From 659816653e6bd1b102aaa0f46c63a9d024227492 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 17 Feb 2020 15:25:48 +0100 Subject: [PATCH] Emit a tokens change event only if there are changed tokens --- src/vs/editor/common/model/textModel.ts | 32 ++++++++++++++++++----- src/vs/editor/common/model/tokensStore.ts | 27 ++++++++++++++++++- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 2c1fcc8f248..bfd6c4b9e6a 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -1713,7 +1713,7 @@ export class TextModel extends Disposable implements model.ITextModel { throw new Error('Illegal value for lineNumber'); } - this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), tokens); + this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), tokens, false); } public setTokens(tokens: MultilineTokens[]): void { @@ -1725,16 +1725,34 @@ export class TextModel extends Disposable implements model.ITextModel { for (let i = 0, len = tokens.length; i < len; i++) { const element = tokens[i]; - ranges.push({ fromLineNumber: element.startLineNumber, toLineNumber: element.startLineNumber + element.tokens.length - 1 }); + let minChangedLineNumber = 0; + let maxChangedLineNumber = 0; + let hasChange = false; for (let j = 0, lenJ = element.tokens.length; j < lenJ; j++) { - this.setLineTokens(element.startLineNumber + j, element.tokens[j]); + const lineNumber = element.startLineNumber + j; + if (hasChange) { + this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.tokens[j], false); + maxChangedLineNumber = lineNumber; + } else { + const lineHasChange = this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.tokens[j], true); + if (lineHasChange) { + hasChange = true; + minChangedLineNumber = lineNumber; + maxChangedLineNumber = lineNumber; + } + } + } + if (hasChange) { + ranges.push({ fromLineNumber: minChangedLineNumber, toLineNumber: maxChangedLineNumber }); } } - this._emitModelTokensChangedEvent({ - tokenizationSupportChanged: false, - ranges: ranges - }); + if (ranges.length > 0) { + this._emitModelTokensChangedEvent({ + tokenizationSupportChanged: false, + ranges: ranges + }); + } } public setSemanticTokens(tokens: MultilineTokens2[] | null): void { diff --git a/src/vs/editor/common/model/tokensStore.ts b/src/vs/editor/common/model/tokensStore.ts index e396aa054a2..c662f820c9c 100644 --- a/src/vs/editor/common/model/tokensStore.ts +++ b/src/vs/editor/common/model/tokensStore.ts @@ -964,10 +964,35 @@ export class TokensStore { this._len += insertCount; } - public setTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null): void { + public setTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null, checkEquality: boolean): boolean { const tokens = TokensStore._massageTokens(topLevelLanguageId, lineTextLength, _tokens); this._ensureLine(lineIndex); + const oldTokens = this._lineTokens[lineIndex]; this._lineTokens[lineIndex] = tokens; + + if (checkEquality) { + return !TokensStore._equals(oldTokens, tokens); + } + return false; + } + + private static _equals(_a: Uint32Array | ArrayBuffer | null, _b: Uint32Array | ArrayBuffer | null) { + if (!_a || !_b) { + return !_a && !_b; + } + + const a = toUint32Array(_a); + const b = toUint32Array(_b); + + if (a.length !== b.length) { + return false; + } + for (let i = 0, len = a.length; i < len; i++) { + if (a[i] !== b[i]) { + return false; + } + } + return true; } //#region Editing -- GitLab