Skip to content

Commit

Permalink
Fix all x-model highlight flickering (#224415)
Browse files Browse the repository at this point in the history
fix all x-model highlight flickering
  • Loading branch information
Yoyokrazy authored Jul 31, 2024
1 parent 284a605 commit 79327ff
Showing 1 changed file with 31 additions and 16 deletions.
47 changes: 31 additions & 16 deletions src/vs/editor/contrib/wordHighlighter/browser/wordHighlighter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import * as arrays from 'vs/base/common/arrays';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { CancelablePromise, createCancelablePromise, first, timeout } from 'vs/base/common/async';
import { CancelablePromise, createCancelablePromise, Delayer, first, timeout } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { onUnexpectedError, onUnexpectedExternalError } from 'vs/base/common/errors';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
Expand Down Expand Up @@ -267,11 +267,11 @@ class WordHighlighter {
private readonly editor: IActiveCodeEditor;
private readonly providers: LanguageFeatureRegistry<DocumentHighlightProvider>;
private readonly multiDocumentProviders: LanguageFeatureRegistry<MultiDocumentHighlightProvider>;
private occurrencesHighlight: string;
private readonly model: ITextModel;
private readonly decorations: IEditorDecorationsCollection;
private readonly toUnhook = new DisposableStore();
private readonly codeEditorService: ICodeEditorService;
private occurrencesHighlight: string;

private workerRequestTokenId: number = 0;
private workerRequest: IOccurenceAtPositionRequest | null;
Expand All @@ -284,7 +284,9 @@ class WordHighlighter {
private readonly _hasWordHighlights: IContextKey<boolean>;
private _ignorePositionChangeEvent: boolean;

private static storedDecorations: ResourceMap<string[]> = new ResourceMap();
private readonly runDelayer: Delayer<void> = this.toUnhook.add(new Delayer<void>(50));

private static storedDecorationIDs: ResourceMap<string[]> = new ResourceMap();
private static query: IWordHighlighterQuery | null = null;

constructor(editor: IActiveCodeEditor, providers: LanguageFeatureRegistry<DocumentHighlightProvider>, multiProviders: LanguageFeatureRegistry<MultiDocumentHighlightProvider>, contextKeyService: IContextKeyService, @ICodeEditorService codeEditorService: ICodeEditorService) {
Expand All @@ -308,7 +310,7 @@ class WordHighlighter {
return;
}

this._onPositionChanged(e);
this.runDelayer.trigger(() => { this._onPositionChanged(e); });
}));
this.toUnhook.add(editor.onDidFocusEditorText((e) => {
if (this.occurrencesHighlight === 'off') {
Expand All @@ -317,7 +319,7 @@ class WordHighlighter {
}

if (!this.workerRequest) {
this._run();
this.runDelayer.trigger(() => { this._run(); });
}
}));
this.toUnhook.add(editor.onDidChangeModelContent((e) => {
Expand Down Expand Up @@ -345,7 +347,7 @@ class WordHighlighter {
break;
case 'multiFile':
if (WordHighlighter.query) {
this._run();
this._run(true);
}
break;
default:
Expand Down Expand Up @@ -439,13 +441,13 @@ class WordHighlighter {
return;
}

const currentDecorationIDs = WordHighlighter.storedDecorations.get(this.editor.getModel().uri);
const currentDecorationIDs = WordHighlighter.storedDecorationIDs.get(this.editor.getModel().uri);
if (!currentDecorationIDs) {
return;
}

this.editor.removeDecorations(currentDecorationIDs);
WordHighlighter.storedDecorations.delete(this.editor.getModel().uri);
WordHighlighter.storedDecorationIDs.delete(this.editor.getModel().uri);

if (this.decorations.length > 0) {
this.decorations.clear();
Expand All @@ -462,7 +464,7 @@ class WordHighlighter {
continue;
}

const currentDecorationIDs = WordHighlighter.storedDecorations.get(editor.getModel().uri);
const currentDecorationIDs = WordHighlighter.storedDecorationIDs.get(editor.getModel().uri);
if (!currentDecorationIDs) {
continue;
}
Expand All @@ -483,7 +485,7 @@ class WordHighlighter {
}

for (const uri of deleteURI) {
WordHighlighter.storedDecorations.delete(uri);
WordHighlighter.storedDecorationIDs.delete(uri);
}
}

Expand Down Expand Up @@ -639,13 +641,14 @@ class WordHighlighter {
return currentModels;
}

private _run(): void {
private _run(multiFileConfigChange?: boolean): void {

let workerRequestIsValid;
const hasTextFocus = this.editor.hasTextFocus();

if (!hasTextFocus) { // new nb cell scrolled in, didChangeModel fires
if (!WordHighlighter.query) { // no previous query, nothing to highlight off of
this._stopAll();
return;
}
} else { // has text focus
Expand Down Expand Up @@ -705,10 +708,22 @@ class WordHighlighter {
this.renderDecorationsTimer = -1;
this._beginRenderDecorations();
}
} else {
} else if (isEqual(this.editor.getModel().uri, WordHighlighter.query.modelInfo?.model.uri)) { // only trigger new worker requests from the primary model that initiated the query
// case d)
// Stop all previous actions and start fresh
this._stopAll();

// check if the new queried word is contained in the range of a stored decoration for this model
if (!multiFileConfigChange) {
const currentModelDecorationRanges = this.decorations.getRanges();
for (const storedRange of currentModelDecorationRanges) {
if (storedRange.containsPosition(this.editor.getPosition())) {
return;
}
}
}

// stop all previous actions if new word is highlighted
// if we trigger the run off a setting change -> multifile highlighting, we do not want to remove decorations from this model
this._stopAll(multiFileConfigChange ? this.model : undefined);

const myRequestId = ++this.workerRequestTokenId;
this.workerRequestCompleted = false;
Expand Down Expand Up @@ -773,7 +788,7 @@ class WordHighlighter {
const newDecorations: IModelDeltaDecoration[] = [];
const uri = editor.getModel()?.uri;
if (uri && this.workerRequestValue.has(uri)) {
const oldDecorationIDs: string[] | undefined = WordHighlighter.storedDecorations.get(uri);
const oldDecorationIDs: string[] | undefined = WordHighlighter.storedDecorationIDs.get(uri);
const newDocumentHighlights = this.workerRequestValue.get(uri);
if (newDocumentHighlights) {
for (const highlight of newDocumentHighlights) {
Expand All @@ -791,7 +806,7 @@ class WordHighlighter {
editor.changeDecorations((changeAccessor) => {
newDecorationIDs = changeAccessor.deltaDecorations(oldDecorationIDs ?? [], newDecorations);
});
WordHighlighter.storedDecorations = WordHighlighter.storedDecorations.set(uri, newDecorationIDs);
WordHighlighter.storedDecorationIDs = WordHighlighter.storedDecorationIDs.set(uri, newDecorationIDs);

if (newDecorations.length > 0) {
editorHighlighterContrib.wordHighlighter?.decorations.set(newDecorations);
Expand Down

0 comments on commit 79327ff

Please sign in to comment.