diff --git a/src/vs/editor/common/services/semanticTokensProviderStyling.ts b/src/vs/editor/common/services/semanticTokensProviderStyling.ts index ca9026d66fe6d..63a7409c4a284 100644 --- a/src/vs/editor/common/services/semanticTokensProviderStyling.ts +++ b/src/vs/editor/common/services/semanticTokensProviderStyling.ts @@ -22,6 +22,7 @@ export class SemanticTokensProviderStyling { private _hasWarnedOverlappingTokens = false; private _hasWarnedInvalidLengthTokens = false; private _hasWarnedInvalidEditStart = false; + private _hasWarnedInvalidEditDeleteCount = false; constructor( private readonly _legend: SemanticTokensLegend, @@ -125,6 +126,13 @@ export class SemanticTokensProviderStyling { } } + public warnInvalidEditDeleteCount(previousResultId: string | undefined, resultId: string | undefined, srcLength: number, deltaLength: number): void { + if (!this._hasWarnedInvalidEditDeleteCount) { + this._hasWarnedInvalidEditDeleteCount = true; + this._logService.warn(`Invalid semantic tokens edit detected (previousResultId: ${previousResultId}, resultId: ${resultId}): The edits delete more tokens than the previous data contains (previous length ${srcLength}, computed length ${srcLength + deltaLength}).`); + } + } + } const enum SemanticColoringConstants { diff --git a/src/vs/editor/contrib/semanticTokens/browser/documentSemanticTokens.ts b/src/vs/editor/contrib/semanticTokens/browser/documentSemanticTokens.ts index 95348d44230af..44eaf3edc7ede 100644 --- a/src/vs/editor/contrib/semanticTokens/browser/documentSemanticTokens.ts +++ b/src/vs/editor/contrib/semanticTokens/browser/documentSemanticTokens.ts @@ -341,7 +341,14 @@ class ModelSemanticColoring extends Disposable { } const srcData = currentResponse.data; - const destData = new Uint32Array(srcData.length + deltaLength); + const destDataLength = srcData.length + deltaLength; + if (destDataLength < 0) { + styling.warnInvalidEditDeleteCount(currentResponse.resultId, tokens.resultId, srcData.length, deltaLength); + // The edits delete more tokens than the previous result contains and there's no way to recover + this._model.tokenization.setSemanticTokens(null, true); + return; + } + const destData = new Uint32Array(destDataLength); let srcLastStart = srcData.length; let destLastStart = destData.length;