Skip to content

Commit 10326b4

Browse files
committed
Fixes #2663 better debouncing of text change events
1 parent 0a15c72 commit 10326b4

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
4242

4343
### Fixed
4444

45+
- Fixes [#2663](https://github.com/gitkraken/vscode-gitlens/issues/2663) - Debounce bug: file blame isn't cleared when editing document while text in output window changes
4546
- Fixes [#3050](https://github.com/gitkraken/vscode-gitlens/issues/3050) - Opening revision of a renamed file is broken
4647
- Fixes [#3019](https://github.com/gitkraken/vscode-gitlens/issues/3019) - Commits Views not working
4748
- Fixes [#3026](https://github.com/gitkraken/vscode-gitlens/issues/3026) - Gitlens stopped working in sub-repositories

src/system/function.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ interface PropOfValue {
1212
value: string | undefined;
1313
}
1414

15-
export function debounce<T extends (...args: any[]) => ReturnType<T>>(fn: T, wait: number): Deferrable<T> {
15+
export function debounce<T extends (...args: any[]) => ReturnType<T>>(
16+
fn: T,
17+
wait: number,
18+
aggregator?: (prevArgs: Parameters<T>, nextArgs: Parameters<T>) => Parameters<T>,
19+
): Deferrable<T> {
1620
let lastArgs: Parameters<T>;
1721
let lastCallTime: number | undefined;
1822
let lastThis: ThisType<T>;
@@ -77,7 +81,12 @@ export function debounce<T extends (...args: any[]) => ReturnType<T>>(fn: T, wai
7781
const time = Date.now();
7882
const isInvoking = shouldInvoke(time);
7983

80-
lastArgs = args;
84+
if (aggregator != null && lastArgs) {
85+
lastArgs = aggregator(lastArgs, args);
86+
} else {
87+
lastArgs = args;
88+
}
89+
8190
// eslint-disable-next-line @typescript-eslint/no-this-alias
8291
lastThis = this;
8392
lastCallTime = time;

src/trackers/documentTracker.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ export class DocumentTracker<T> implements Disposable {
7777
once(container.onReady)(this.onReady, this),
7878
configuration.onDidChange(this.onConfigurationChanged, this),
7979
window.onDidChangeActiveTextEditor(this.onActiveTextEditorChanged, this),
80-
// window.onDidChangeVisibleTextEditors(debounce(this.onVisibleEditorsChanged, 5000), this),
81-
workspace.onDidChangeTextDocument(debounce(this.onTextDocumentChanged, 50), this),
80+
workspace.onDidChangeTextDocument(this.onTextDocumentChanged, this),
8281
workspace.onDidCloseTextDocument(this.onTextDocumentClosed, this),
8382
workspace.onDidSaveTextDocument(this.onTextDocumentSaved, this),
8483
this.container.git.onDidChangeRepositories(this.onRepositoriesChanged, this),
@@ -170,10 +169,39 @@ export class DocumentTracker<T> implements Disposable {
170169
}
171170
}
172171

173-
private async onTextDocumentChanged(e: TextDocumentChangeEvent) {
172+
private debouncedTextDocumentChanges = new WeakMap<
173+
TextDocument,
174+
Deferrable<Parameters<typeof workspace.onDidChangeTextDocument>[0]>
175+
>();
176+
177+
private onTextDocumentChanged(e: TextDocumentChangeEvent) {
174178
const { scheme } = e.document.uri;
175179
if (!this.container.git.supportedSchemes.has(scheme)) return;
176180

181+
let debouncedChange = this.debouncedTextDocumentChanges.get(e.document);
182+
if (debouncedChange == null) {
183+
debouncedChange = debounce(
184+
e => this.onTextDocumentChangedCore(e),
185+
50,
186+
([prev]: [TextDocumentChangeEvent], [next]: [TextDocumentChangeEvent]) => {
187+
return [
188+
{
189+
...next,
190+
// Aggregate content changes
191+
contentChanges: [...prev.contentChanges, ...next.contentChanges],
192+
} satisfies TextDocumentChangeEvent,
193+
];
194+
},
195+
);
196+
this.debouncedTextDocumentChanges.set(e.document, debouncedChange);
197+
}
198+
199+
debouncedChange(e);
200+
}
201+
202+
private async onTextDocumentChangedCore(e: TextDocumentChangeEvent) {
203+
this.debouncedTextDocumentChanges.delete(e.document);
204+
177205
const doc = await (this._documentMap.get(e.document) ?? this.addCore(e.document));
178206
doc.refresh('doc-changed');
179207

0 commit comments

Comments
 (0)