From 60f21d95258e1611d9cda450e303d126ccdcc560 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Thu, 1 Jul 2021 10:42:19 +0200 Subject: [PATCH] Caches ghost text to improve performance. --- .../inlineCompletions/ghostTextModel.ts | 12 +++++++++++- .../inlineCompletions/ghostTextWidget.ts | 6 +++--- .../inlineCompletionsModel.ts | 19 +++++++++++++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/vs/editor/contrib/inlineCompletions/ghostTextModel.ts b/src/vs/editor/contrib/inlineCompletions/ghostTextModel.ts index f86ff46952d..25ff2d76792 100644 --- a/src/vs/editor/contrib/inlineCompletions/ghostTextModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/ghostTextModel.ts @@ -18,21 +18,31 @@ export abstract class DelegatingModel extends Disposable implements GhostTextWid private readonly onDidChangeEmitter = new Emitter(); public readonly onDidChange = this.onDidChangeEmitter.event; + private hasCachedGhostText = false; + private cachedGhostText: GhostText | undefined; + private readonly currentModelRef = this._register(new MutableDisposable>()); protected get targetModel(): GhostTextWidgetModel | undefined { return this.currentModelRef.value?.object; } protected setTargetModel(model: GhostTextWidgetModel | undefined): void { + this.currentModelRef.clear(); this.currentModelRef.value = model ? createDisposableRef(model, model.onDidChange(() => { + this.hasCachedGhostText = false; this.onDidChangeEmitter.fire(); })) : undefined; + this.hasCachedGhostText = false; this.onDidChangeEmitter.fire(); } public get ghostText(): GhostText | undefined { - return this.targetModel?.ghostText; + if (!this.hasCachedGhostText) { + this.cachedGhostText = this.currentModelRef.value?.object?.ghostText; + this.hasCachedGhostText = true; + } + return this.cachedGhostText; } public setExpanded(expanded: boolean): void { diff --git a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts index fbc08982840..cff08300855 100644 --- a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts +++ b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts @@ -75,14 +75,14 @@ export class GhostTextWidget extends Disposable { } private update(): void { - if (!this.editor.hasModel() || !this.model.ghostText || this.disposed) { + const ghostText = this.model.ghostText; + + if (!this.editor.hasModel() || !ghostText || this.disposed) { this.partsWidget.clear(); this.additionalLinesWidget.clear(); return; } - const ghostText = this.model.ghostText; - const inlineTexts = new Array(); const additionalLines = new Array(); diff --git a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts index 8e461548b7c..459af1ed358 100644 --- a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts @@ -20,7 +20,7 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions'; import { MutableDisposable } from 'vs/editor/contrib/inlineCompletions/utils'; import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; -import { stringDiff } from 'vs/base/common/diff/diff'; +import { IDiffChange, stringDiff } from 'vs/base/common/diff/diff'; import { GhostTextWidgetModel, GhostText, BaseGhostTextWidgetModel, GhostTextPart } from 'vs/editor/contrib/inlineCompletions/ghostText'; export class InlineCompletionsModel extends Disposable implements GhostTextWidgetModel { @@ -499,7 +499,7 @@ export function inlineCompletionToGhostText(inlineCompletion: NormalizedInlineCo // This is a single line string const valueToBeReplaced = textModel.getValueInRange(inlineCompletion.range); - const changes = stringDiff(valueToBeReplaced, inlineCompletion.text, false); + const changes = cachingDiff(valueToBeReplaced, inlineCompletion.text); const lineNumber = inlineCompletion.range.startLineNumber; @@ -540,6 +540,21 @@ export function inlineCompletionToGhostText(inlineCompletion: NormalizedInlineCo return new GhostText(lineNumber, parts, 0); } +let lastRequest: { originalValue: string, newValue: string, changes: IDiffChange[] } | undefined = undefined; +function cachingDiff(originalValue: string, newValue: string): readonly IDiffChange[] { + if (lastRequest?.originalValue === originalValue && lastRequest?.newValue === newValue) { + return lastRequest?.changes; + } else { + const changes = stringDiff(originalValue, newValue, false); + lastRequest = { + originalValue, + newValue, + changes + }; + return changes; + } +} + export interface LiveInlineCompletion extends NormalizedInlineCompletion { sourceProvider: InlineCompletionsProvider; sourceInlineCompletion: InlineCompletion;