Skip to content

Commit f5adc42

Browse files
committed
1 parent 900874f commit f5adc42

File tree

3 files changed

+51
-32
lines changed

3 files changed

+51
-32
lines changed

src/vs/editor/common/model/textModelTokens.ts

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { IdleDeadline, runWhenIdle } from 'vs/base/common/async';
7-
import { onUnexpectedError } from 'vs/base/common/errors';
7+
import { BugIndicatingError, onUnexpectedError } from 'vs/base/common/errors';
88
import { setTimeout0 } from 'vs/base/common/platform';
99
import { StopWatch } from 'vs/base/common/stopwatch';
1010
import { countEOL } from 'vs/editor/common/core/eolCounter';
@@ -25,7 +25,7 @@ const enum Constants {
2525
}
2626

2727
export class TokenizerWithStateStore<TState extends IState = IState> {
28-
private readonly initialState = this.tokenizationSupport.getInitialState();
28+
private readonly initialState = this.tokenizationSupport.getInitialState() as TState;
2929

3030
public readonly store: TrackingTokenizationStateStore<TState>;
3131

@@ -37,10 +37,11 @@ export class TokenizerWithStateStore<TState extends IState = IState> {
3737
}
3838

3939
public getStartState(lineNumber: number): TState | null {
40-
if (lineNumber === 1) {
41-
return this.initialState as TState;
42-
}
43-
return this.store.getEndState(lineNumber - 1);
40+
return this.store.getStartState(lineNumber, this.initialState);
41+
}
42+
43+
public getFirstInvalidLine(): { lineNumber: number; startState: TState } | null {
44+
return this.store.getFirstInvalidLine(this.initialState);
4445
}
4546
}
4647

@@ -58,17 +59,16 @@ export class TokenizerWithStateStoreAndTextModel<TState extends IState = IState>
5859
const languageId = this._textModel.getLanguageId();
5960

6061
while (true) {
61-
const nextLineNumber = this.store.getFirstInvalidEndStateLineNumber();
62-
if (!nextLineNumber || nextLineNumber > lineNumber) {
62+
const lineToTokenize = this.getFirstInvalidLine();
63+
if (!lineToTokenize || lineToTokenize.lineNumber > lineNumber) {
6364
break;
6465
}
6566

66-
const text = this._textModel.getLineContent(nextLineNumber);
67-
const lineStartState = this.getStartState(nextLineNumber);
67+
const text = this._textModel.getLineContent(lineToTokenize.lineNumber);
6868

69-
const r = safeTokenize(this._languageIdCodec, languageId, this.tokenizationSupport, text, true, lineStartState!);
70-
builder.add(nextLineNumber, r.tokens);
71-
this!.store.setEndState(nextLineNumber, r.endState as TState);
69+
const r = safeTokenize(this._languageIdCodec, languageId, this.tokenizationSupport, text, true, lineToTokenize.startState);
70+
builder.add(lineToTokenize.lineNumber, r.tokens);
71+
this!.store.setEndState(lineToTokenize.lineNumber, r.endState as TState);
7272
}
7373
}
7474

@@ -217,12 +217,19 @@ export class TrackingTokenizationStateStore<TState extends IState> {
217217
}
218218

219219
public setEndState(lineNumber: number, state: TState): boolean {
220+
if (!state) {
221+
throw new BugIndicatingError('Cannot set null/undefined state');
222+
}
223+
if (lineNumber > 1 && !this.tokenizationStateStore.getEndState(lineNumber - 1)) {
224+
throw new BugIndicatingError('Cannot set state before setting previous state');
225+
}
226+
220227
while (true) {
221228
const min = this._invalidEndStatesLineNumbers.min;
222-
if (min !== null && min <= lineNumber) {
223-
this._invalidEndStatesLineNumbers.removeMin();
224-
} else {
229+
if (min === null || min > lineNumber) {
225230
break;
231+
} else {
232+
this._invalidEndStatesLineNumbers.removeMin();
226233
}
227234
}
228235

@@ -263,6 +270,21 @@ export class TrackingTokenizationStateStore<TState extends IState> {
263270
public isTokenizationComplete(): boolean {
264271
return this._invalidEndStatesLineNumbers.min === null;
265272
}
273+
274+
public getStartState(lineNumber: number, initialState: TState): TState | null {
275+
if (lineNumber === 1) {
276+
return initialState;
277+
}
278+
return this.getEndState(lineNumber - 1);
279+
}
280+
281+
public getFirstInvalidLine(initialState: TState): { lineNumber: number; startState: TState } | null {
282+
const lineNumber = this.getFirstInvalidEndStateLineNumber();
283+
if (lineNumber === null) {
284+
return null;
285+
}
286+
return { lineNumber, startState: this.getStartState(lineNumber, initialState)! };
287+
}
266288
}
267289

268290
export class TokenizationStateStore<TState extends IState> {

src/vs/editor/common/model/tokenizationTextModelPart.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -449,12 +449,10 @@ class GrammarTokens extends Disposable {
449449
this._onDidChangeBackgroundTokenizationState.fire();
450450
},
451451
setEndState: (lineNumber, state) => {
452-
if (!state) {
453-
throw new BugIndicatingError();
454-
}
455-
const firstInvalidEndStateLineNumber = this._tokenizer?.store.getFirstInvalidEndStateLineNumber() ?? undefined;
456-
if (firstInvalidEndStateLineNumber !== undefined && lineNumber >= firstInvalidEndStateLineNumber) {
457-
// Don't accept states for definitely valid states
452+
if (!this._tokenizer) { return; }
453+
const firstInvalidEndStateLineNumber = this._tokenizer.store.getFirstInvalidEndStateLineNumber();
454+
// Don't accept states for definitely valid states, the renderer is ahead of the worker!
455+
if (firstInvalidEndStateLineNumber !== null && lineNumber >= firstInvalidEndStateLineNumber) {
458456
this._tokenizer?.store.setEndState(lineNumber, state);
459457
}
460458
},

src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,25 +125,24 @@ export class TextMateWorkerTokenizer extends MirrorTextModel {
125125
const stateDeltaBuilder = new StateDeltaBuilder();
126126

127127
while (true) {
128-
const lineNumberToTokenize = this._tokenizerWithStateStore.store.getFirstInvalidEndStateLineNumber();
129-
if (lineNumberToTokenize === null || tokenizedLines > 200) {
128+
const lineToTokenize = this._tokenizerWithStateStore.getFirstInvalidLine();
129+
if (lineToTokenize === null || tokenizedLines > 200) {
130130
break;
131131
}
132132

133133
tokenizedLines++;
134134

135-
const text = this._lines[lineNumberToTokenize - 1];
136-
const lineStartState = this._tokenizerWithStateStore.getStartState(lineNumberToTokenize)!;
137-
const r = this._tokenizerWithStateStore.tokenizationSupport.tokenizeEncoded(text, true, lineStartState);
138-
if (this._tokenizerWithStateStore.store.setEndState(lineNumberToTokenize, r.endState as StateStack)) {
139-
const delta = this._diffStateStacksRefEqFn(lineStartState, r.endState as StateStack);
140-
stateDeltaBuilder.setState(lineNumberToTokenize, delta);
135+
const text = this._lines[lineToTokenize.lineNumber - 1];
136+
const r = this._tokenizerWithStateStore.tokenizationSupport.tokenizeEncoded(text, true, lineToTokenize.startState);
137+
if (this._tokenizerWithStateStore.store.setEndState(lineToTokenize.lineNumber, r.endState as StateStack)) {
138+
const delta = this._diffStateStacksRefEqFn(lineToTokenize.startState, r.endState as StateStack);
139+
stateDeltaBuilder.setState(lineToTokenize.lineNumber, delta);
141140
} else {
142-
stateDeltaBuilder.setState(lineNumberToTokenize, null);
141+
stateDeltaBuilder.setState(lineToTokenize.lineNumber, null);
143142
}
144143

145144
LineTokens.convertToEndOffset(r.tokens, text.length);
146-
tokenBuilder.add(lineNumberToTokenize, r.tokens);
145+
tokenBuilder.add(lineToTokenize.lineNumber, r.tokens);
147146

148147
const deltaMs = new Date().getTime() - startTime;
149148
if (deltaMs > 20) {

0 commit comments

Comments
 (0)