Fall back to a full result when previousResult gets an unknown id - #1858
Open
Ngo Quoc Viet (NgoQuocViet2001) wants to merge 1 commit into
Open
Conversation
previousResult() only assigns _prevData when the id matches, and initialize() deliberately leaves _prevData alone, so a mismatch left the builder holding an older generation's data. canBuildEdits() then reported true and buildEdits() returned edits computed against that generation, labelled with a freshly generated resultId. A SemanticTokensDelta carries no field naming its baseline -- the client takes it to be the previousResultId it sent -- so those edits are applied to a different array and the highlighting drifts, silently and persistently. Clear _prevData on a mismatch; buildEdits() already returns a full result in that case.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
previousResultis the builder's only channel for learning which token set the client currently holds:There is no
else. On a mismatch_prevDatakeeps whatever generation it was left holding —initialize()resets_id,_data,_dataNonDelta,_dataLenand the_prevLine/_prevCharcursors, but deliberately not_prevData.canBuildEdits()then reportstrueeven though the builder has no baseline for the id it was given, andbuildEdits()returns edits diffed against that older generation under a freshly generatedresultId.Effect
Measured against the built
SemanticTokensBuilder(public API viaserver/src/common/api.ts):A
SemanticTokensDeltahas no field naming its baseline — the client takes it to be thepreviousResultIdit sent — so the client applies edits computed against a different array. Token offsets, lengths and types drift out of alignment, and because each later delta chains off the already-wrong state, the highlighting stays wrong until something forces a full request. There is no error and no log line, and a server author who checkscanBuildEdits()first is told the wrong thing by the very guard meant to prevent this.The one-generation-behind case happens to line up by luck, which is presumably why it has gone unnoticed — the damage starts once the client is two or more generations behind, e.g. after a cancelled delta request or a
workspace/semanticTokens/refresh.The documented usage pattern passes the client id straight through, as this repo's own testbed does:
Fix
Clear
_prevDatawhen the id does not match.buildEdits()already returnsthis.build()when_prevDataisundefined, so the fallback path needs no change andcanBuildEdits()becomes truthful for free.Test plan
An unknown previousResultId falls back to a full resulttoserver/src/node/test/sematicTokens.test.ts.semanticTokens.tsfails the new test.No protocol type changes, so
protocol/metaModel.jsonand its schema are untouched.