Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/vs/editor/common/model/textModel.ts')
-rw-r--r--src/vs/editor/common/model/textModel.ts406
1 files changed, 56 insertions, 350 deletions
diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts
index 78f17dd2669..8aa71a280d5 100644
--- a/src/vs/editor/common/model/textModel.ts
+++ b/src/vs/editor/common/model/textModel.ts
@@ -5,7 +5,6 @@
import { ArrayQueue, pushMany } from 'vs/base/common/arrays';
import { VSBuffer, VSBufferReadableStream } from 'vs/base/common/buffer';
-import { CharCode } from 'vs/base/common/charCode';
import { Color } from 'vs/base/common/color';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
@@ -15,39 +14,35 @@ import { listenStream } from 'vs/base/common/stream';
import * as strings from 'vs/base/common/strings';
import { Constants } from 'vs/base/common/uint';
import { URI } from 'vs/base/common/uri';
-import { LineTokens } from 'vs/editor/common/tokens/lineTokens';
+import { ISingleEditOperation } from 'vs/editor/common/core/editOperation';
+import { countEOL } from 'vs/editor/common/core/eolCounter';
+import { normalizeIndentation } from 'vs/editor/common/core/indentation';
import { IPosition, Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
+import { TextChange } from 'vs/editor/common/core/textChange';
+import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/core/textModelDefaults';
+import { IWordAtPosition } from 'vs/editor/common/core/wordHelper';
+import { FormattingOptions } from 'vs/editor/common/languages';
+import { ILanguageService } from 'vs/editor/common/languages/language';
+import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import * as model from 'vs/editor/common/model';
-import { IBracketPairsTextModelPart } from 'vs/editor/common/textModelBracketPairs';
import { BracketPairsTextModelPart } from 'vs/editor/common/model/bracketPairsTextModelPart/bracketPairsImpl';
import { ColorizedBracketPairsDecorationProvider } from 'vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider';
import { EditStack } from 'vs/editor/common/model/editStack';
import { GuidesTextModelPart } from 'vs/editor/common/model/guidesTextModelPart';
-import { IGuidesTextModelPart } from 'vs/editor/common/textModelGuides';
import { guessIndentation } from 'vs/editor/common/model/indentationGuesser';
import { IntervalNode, IntervalTree, recomputeMaxEnd } from 'vs/editor/common/model/intervalTree';
import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer';
import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
-import { TextChange } from 'vs/editor/common/core/textChange';
-import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, InternalModelContentChangeEvent, LineInjectedText, ModelInjectedTextChangedEvent, ModelRawChange, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/textModelEvents';
import { SearchParams, TextModelSearch } from 'vs/editor/common/model/textModelSearch';
-import { TextModelTokenization } from 'vs/editor/common/model/textModelTokens';
-import { countEOL } from 'vs/editor/common/core/eolCounter';
-import { ContiguousMultilineTokens } from 'vs/editor/common/tokens/contiguousMultilineTokens';
-import { SparseMultilineTokens } from 'vs/editor/common/tokens/sparseMultilineTokens';
-import { ContiguousTokensStore } from 'vs/editor/common/tokens/contiguousTokensStore';
-import { SparseTokensStore } from 'vs/editor/common/tokens/sparseTokensStore';
-import { getWordAtText, IWordAtPosition } from 'vs/editor/common/core/wordHelper';
-import { FormattingOptions, StandardTokenType } from 'vs/editor/common/languages';
-import { ILanguageConfigurationService, ResolvedLanguageConfiguration } from 'vs/editor/common/languages/languageConfigurationRegistry';
-import { ILanguageService } from 'vs/editor/common/languages/language';
+import { TokenizationTextModelPart } from 'vs/editor/common/model/tokenizationTextModelPart';
+import { IBracketPairsTextModelPart } from 'vs/editor/common/textModelBracketPairs';
+import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelOptionsChangedEvent, InternalModelContentChangeEvent, LineInjectedText, ModelInjectedTextChangedEvent, ModelRawChange, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/textModelEvents';
+import { IGuidesTextModelPart } from 'vs/editor/common/textModelGuides';
+import { ITokenizationTextModelPart } from 'vs/editor/common/tokenizationTextModelPart';
import { IColorTheme, ThemeColor } from 'vs/platform/theme/common/themeService';
import { IUndoRedoService, ResourceEditStackSnapshot } from 'vs/platform/undoRedo/common/undoRedo';
-import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/core/textModelDefaults';
-import { normalizeIndentation } from 'vs/editor/common/core/indentation';
-import { ISingleEditOperation } from 'vs/editor/common/core/editOperation';
function createTextBufferBuilder() {
return new PieceTreeTextBufferBuilder();
@@ -172,12 +167,6 @@ const enum StringOffsetValidationType {
SurrogatePairs = 1,
}
-export const enum BackgroundTokenizationState {
- Uninitialized = 0,
- InProgress = 1,
- Completed = 2,
-}
-
export class TextModel extends Disposable implements model.ITextModel, IDecorationsTreesHost {
private static readonly MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB
@@ -227,14 +216,9 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
private readonly _onDidChangeDecorations: DidChangeDecorationsEmitter = this._register(new DidChangeDecorationsEmitter(affectedInjectedTextLines => this.handleBeforeFireDecorationsChangedEvent(affectedInjectedTextLines)));
public readonly onDidChangeDecorations: Event<IModelDecorationsChangedEvent> = this._onDidChangeDecorations.event;
- private readonly _onDidChangeLanguage: Emitter<IModelLanguageChangedEvent> = this._register(new Emitter<IModelLanguageChangedEvent>());
- public readonly onDidChangeLanguage: Event<IModelLanguageChangedEvent> = this._onDidChangeLanguage.event;
-
- private readonly _onDidChangeLanguageConfiguration: Emitter<IModelLanguageConfigurationChangedEvent> = this._register(new Emitter<IModelLanguageConfigurationChangedEvent>());
- public readonly onDidChangeLanguageConfiguration: Event<IModelLanguageConfigurationChangedEvent> = this._onDidChangeLanguageConfiguration.event;
-
- private readonly _onDidChangeTokens: Emitter<IModelTokensChangedEvent> = this._register(new Emitter<IModelTokensChangedEvent>());
- public readonly onDidChangeTokens: Event<IModelTokensChangedEvent> = this._onDidChangeTokens.event;
+ public get onDidChangeLanguage() { return this._tokenizationTextModelPart.onDidChangeLanguage; }
+ public get onDidChangeLanguageConfiguration() { return this._tokenizationTextModelPart.onDidChangeLanguageConfiguration; }
+ public get onDidChangeTokens() { return this._tokenizationTextModelPart.onDidChangeTokens; }
private readonly _onDidChangeOptions: Emitter<IModelOptionsChangedEvent> = this._register(new Emitter<IModelOptionsChangedEvent>());
public readonly onDidChangeOptions: Event<IModelOptionsChangedEvent> = this._onDidChangeOptions.event;
@@ -265,7 +249,8 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
private _options: model.TextModelResolvedOptions;
private _isDisposed: boolean;
- private _isDisposing: boolean;
+ private __isDisposing: boolean;
+ public _isDisposing(): boolean { return this.__isDisposing; }
private _versionId: number;
/**
* Unlike, versionId, this can go down (via undo) or go to previous values (via redo)
@@ -294,40 +279,15 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
private readonly _decorationProvider: ColorizedBracketPairsDecorationProvider;
//#endregion
- //#region Tokenization
- private _languageId: string;
- private readonly _languageRegistryListener: IDisposable;
- private readonly _tokens: ContiguousTokensStore;
- private readonly _semanticTokens: SparseTokensStore;
- private readonly _tokenization: TextModelTokenization;
- //#endregion
+ private readonly _tokenizationTextModelPart: TokenizationTextModelPart;
+ public get tokenization(): ITokenizationTextModelPart { return this._tokenizationTextModelPart; }
- private readonly _bracketPairColorizer: BracketPairsTextModelPart;
- public get bracketPairs(): IBracketPairsTextModelPart { return this._bracketPairColorizer; }
+ private readonly _bracketPairs: BracketPairsTextModelPart;
+ public get bracketPairs(): IBracketPairsTextModelPart { return this._bracketPairs; }
private readonly _guidesTextModelPart: GuidesTextModelPart;
public get guides(): IGuidesTextModelPart { return this._guidesTextModelPart; }
- private _backgroundTokenizationState = BackgroundTokenizationState.Uninitialized;
- public get backgroundTokenizationState(): BackgroundTokenizationState {
- return this._backgroundTokenizationState;
- }
- private handleTokenizationProgress(completed: boolean) {
- if (this._backgroundTokenizationState === BackgroundTokenizationState.Completed) {
- // We already did a full tokenization and don't go back to progressing.
- return;
- }
- const newState = completed ? BackgroundTokenizationState.Completed : BackgroundTokenizationState.InProgress;
- if (this._backgroundTokenizationState !== newState) {
- this._backgroundTokenizationState = newState;
- this._bracketPairColorizer.handleDidChangeBackgroundTokenizationState();
- this._onBackgroundTokenizationStateChanged.fire();
- }
- }
-
- private readonly _onBackgroundTokenizationStateChanged = this._register(new Emitter<void>());
- public readonly onBackgroundTokenizationStateChanged: Event<void> = this._onBackgroundTokenizationStateChanged.event;
-
constructor(
source: string | model.ITextBufferFactory,
languageId: string,
@@ -356,6 +316,17 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
this._options = TextModel.resolveOptions(this._buffer, creationOptions);
+ this._bracketPairs = this._register(new BracketPairsTextModelPart(this, this._languageConfigurationService));
+ this._guidesTextModelPart = this._register(new GuidesTextModelPart(this, this._languageConfigurationService));
+ this._decorationProvider = this._register(new ColorizedBracketPairsDecorationProvider(this));
+ this._tokenizationTextModelPart = new TokenizationTextModelPart(
+ this._languageService,
+ this._languageConfigurationService,
+ this,
+ this._bracketPairs,
+ languageId
+ );
+
const bufferLineCount = this._buffer.getLineCount();
const bufferTextLength = this._buffer.getValueLengthInRange(new Range(1, 1, bufferLineCount, this._buffer.getLineLength(bufferLineCount) + 1), model.EndOfLinePreference.TextDefined);
@@ -378,17 +349,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
this._initialUndoRedoSnapshot = null;
this._isDisposed = false;
- this._isDisposing = false;
-
- this._languageId = languageId;
-
- this._languageRegistryListener = this._languageConfigurationService.onDidChange(
- e => {
- if (e.affects(this._languageId)) {
- this._onDidChangeLanguageConfiguration.fire({});
- }
- }
- );
+ this.__isDisposing = false;
this._instanceId = strings.singleLetterHash(MODEL_ID);
this._lastDecorationId = 0;
@@ -400,13 +361,6 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
this._isRedoing = false;
this._trimAutoWhitespaceLines = null;
- this._tokens = new ContiguousTokensStore(this._languageService.languageIdCodec);
- this._semanticTokens = new SparseTokensStore(this._languageService.languageIdCodec);
- this._tokenization = new TextModelTokenization(this, this._languageService.languageIdCodec);
-
- this._bracketPairColorizer = this._register(new BracketPairsTextModelPart(this, this._languageConfigurationService));
- this._guidesTextModelPart = this._register(new GuidesTextModelPart(this, this._languageConfigurationService));
- this._decorationProvider = this._register(new ColorizedBracketPairsDecorationProvider(this));
this._register(this._decorationProvider.onDidChange(() => {
this._onDidChangeDecorations.beginDeferredEmit();
@@ -416,14 +370,13 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
}
public override dispose(): void {
- this._isDisposing = true;
+ this.__isDisposing = true;
this._onWillDispose.fire();
- this._languageRegistryListener.dispose();
- this._tokenization.dispose();
+ this._tokenizationTextModelPart.dispose();
this._isDisposed = true;
super.dispose();
this._bufferDisposable.dispose();
- this._isDisposing = false;
+ this.__isDisposing = false;
// Manually release reference to previous text buffer to avoid large leaks
// in case someone leaks a TextModel reference
const emptyDisposedTextBuffer = new PieceTreeTextBuffer([], '', '\n', false, false, true, true);
@@ -436,14 +389,11 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
return (
this._onWillDispose.hasListeners()
|| this._onDidChangeDecorations.hasListeners()
- || this._onDidChangeLanguage.hasListeners()
- || this._onDidChangeLanguageConfiguration.hasListeners()
- || this._onDidChangeTokens.hasListeners()
+ || this._tokenizationTextModelPart._hasListeners()
|| this._onDidChangeOptions.hasListeners()
|| this._onDidChangeAttached.hasListeners()
|| this._onDidChangeInjectedText.hasListeners()
|| this._eventEmitter.hasListeners()
- || this._onBackgroundTokenizationStateChanged.hasListeners()
);
}
@@ -464,12 +414,12 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
}
private _emitContentChangedEvent(rawChange: ModelRawContentChangedEvent, change: IModelContentChangedEvent): void {
- if (this._isDisposing) {
+ if (this.__isDisposing) {
// Do not confuse listeners by emitting any event after disposing
return;
}
- this._bracketPairColorizer.handleDidChangeContent(change);
- this._tokenization.handleDidChangeContent(change);
+ this._tokenizationTextModelPart.handleDidChangeContent(change);
+ this._bracketPairs.handleDidChangeContent(change);
this._eventEmitter.fire(new InternalModelContentChangeEvent(rawChange, change));
}
@@ -513,8 +463,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
this._increaseVersionId();
// Flush all tokens
- this._tokens.flush();
- this._semanticTokens.flush();
+ this._tokenizationTextModelPart.flush();
// Destroy all my decorations
this._decorations = Object.create(null);
@@ -600,7 +549,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
public onBeforeAttached(): void {
this._attachedEditorCount++;
if (this._attachedEditorCount === 1) {
- this._tokenization.handleDidChangeAttached();
+ this._tokenizationTextModelPart.handleDidChangeAttached();
this._onDidChangeAttached.fire(undefined);
}
}
@@ -608,7 +557,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
public onBeforeDetached(): void {
this._attachedEditorCount--;
if (this._attachedEditorCount === 0) {
- this._tokenization.handleDidChangeAttached();
+ this._tokenizationTextModelPart.handleDidChangeAttached();
this._onDidChangeAttached.fire(undefined);
}
}
@@ -697,7 +646,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
const e = this._options.createChangeEvent(newOpts);
this._options = newOpts;
- this._bracketPairColorizer.handleDidChangeOptions(e);
+ this._bracketPairs.handleDidChangeOptions(e);
this._decorationProvider.handleDidChangeOptions(e);
this._onDidChangeOptions.fire(e);
}
@@ -1463,8 +1412,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
for (let i = 0, len = contentChanges.length; i < len; i++) {
const change = contentChanges[i];
const [eolCount, firstLineLength, lastLineLength] = countEOL(change.text);
- this._tokens.acceptEdit(change.range, eolCount, firstLineLength);
- this._semanticTokens.acceptEdit(change.range, eolCount, firstLineLength, lastLineLength, change.text.length > 0 ? change.text.charCodeAt(0) : CharCode.Null);
+ this._tokenizationTextModelPart.acceptEdit(change.range, change.text, eolCount, firstLineLength, lastLineLength);
this._decorationsTree.acceptReplace(change.rangeOffset, change.rangeLength, change.text.length, change.forceMoveMarkers);
}
@@ -1944,270 +1892,28 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
//#region Tokenization
- public setLineTokens(lineNumber: number, tokens: Uint32Array | ArrayBuffer | null): void {
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
-
- this._tokens.setTokens(this._languageId, lineNumber - 1, this._buffer.getLineLength(lineNumber), tokens, false);
- }
-
- public setTokens(tokens: ContiguousMultilineTokens[], backgroundTokenizationCompleted: boolean = false): void {
- if (tokens.length !== 0) {
- const ranges: { fromLineNumber: number; toLineNumber: number }[] = [];
-
- for (let i = 0, len = tokens.length; i < len; i++) {
- const element = tokens[i];
- let minChangedLineNumber = 0;
- let maxChangedLineNumber = 0;
- let hasChange = false;
- for (let lineNumber = element.startLineNumber; lineNumber <= element.endLineNumber; lineNumber++) {
- if (hasChange) {
- this._tokens.setTokens(this._languageId, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.getLineTokens(lineNumber), false);
- maxChangedLineNumber = lineNumber;
- } else {
- const lineHasChange = this._tokens.setTokens(this._languageId, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.getLineTokens(lineNumber), true);
- if (lineHasChange) {
- hasChange = true;
- minChangedLineNumber = lineNumber;
- maxChangedLineNumber = lineNumber;
- }
- }
- }
- if (hasChange) {
- ranges.push({ fromLineNumber: minChangedLineNumber, toLineNumber: maxChangedLineNumber });
- }
- }
-
- if (ranges.length > 0) {
- this._emitModelTokensChangedEvent({
- tokenizationSupportChanged: false,
- semanticTokensApplied: false,
- ranges: ranges
- });
- }
- }
- this.handleTokenizationProgress(backgroundTokenizationCompleted);
- }
-
- public setSemanticTokens(tokens: SparseMultilineTokens[] | null, isComplete: boolean): void {
- this._semanticTokens.set(tokens, isComplete);
-
- this._emitModelTokensChangedEvent({
- tokenizationSupportChanged: false,
- semanticTokensApplied: tokens !== null,
- ranges: [{ fromLineNumber: 1, toLineNumber: this.getLineCount() }]
- });
- }
-
- public hasCompleteSemanticTokens(): boolean {
- return this._semanticTokens.isComplete();
- }
-
- public hasSomeSemanticTokens(): boolean {
- return !this._semanticTokens.isEmpty();
- }
-
- public setPartialSemanticTokens(range: Range, tokens: SparseMultilineTokens[]): void {
- if (this.hasCompleteSemanticTokens()) {
- return;
- }
- const changedRange = this.validateRange(this._semanticTokens.setPartial(range, tokens));
-
- this._emitModelTokensChangedEvent({
- tokenizationSupportChanged: false,
- semanticTokensApplied: true,
- ranges: [{ fromLineNumber: changedRange.startLineNumber, toLineNumber: changedRange.endLineNumber }]
- });
- }
-
- public tokenizeViewport(startLineNumber: number, endLineNumber: number): void {
- startLineNumber = Math.max(1, startLineNumber);
- endLineNumber = Math.min(this._buffer.getLineCount(), endLineNumber);
- this._tokenization.tokenizeViewport(startLineNumber, endLineNumber);
- }
-
- public clearTokens(): void {
- this._tokens.flush();
- this._emitModelTokensChangedEvent({
- tokenizationSupportChanged: true,
- semanticTokensApplied: false,
- ranges: [{
- fromLineNumber: 1,
- toLineNumber: this._buffer.getLineCount()
- }]
- });
- }
-
- public clearSemanticTokens(): void {
- this._semanticTokens.flush();
-
- this._emitModelTokensChangedEvent({
- tokenizationSupportChanged: false,
- semanticTokensApplied: false,
- ranges: [{ fromLineNumber: 1, toLineNumber: this.getLineCount() }]
- });
- }
-
- private _emitModelTokensChangedEvent(e: IModelTokensChangedEvent): void {
- if (!this._isDisposing) {
- this._bracketPairColorizer.handleDidChangeTokens(e);
- this._onDidChangeTokens.fire(e);
- }
- }
-
- public resetTokenization(): void {
- this._tokenization.reset();
- }
-
- public forceTokenization(lineNumber: number): void {
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
-
- this._tokenization.forceTokenization(lineNumber);
- }
-
- public isCheapToTokenize(lineNumber: number): boolean {
- return this._tokenization.isCheapToTokenize(lineNumber);
- }
-
- public tokenizeIfCheap(lineNumber: number): void {
- if (this.isCheapToTokenize(lineNumber)) {
- this.forceTokenization(lineNumber);
- }
- }
-
- public getLineTokens(lineNumber: number): LineTokens {
- if (lineNumber < 1 || lineNumber > this.getLineCount()) {
- throw new Error('Illegal value for lineNumber');
- }
-
- return this._getLineTokens(lineNumber);
- }
-
- private _getLineTokens(lineNumber: number): LineTokens {
- const lineText = this.getLineContent(lineNumber);
- const syntacticTokens = this._tokens.getTokens(this._languageId, lineNumber - 1, lineText);
- return this._semanticTokens.addSparseTokens(lineNumber, syntacticTokens);
- }
-
+ // TODO move them to the tokenization part.
public getLanguageId(): string {
- return this._languageId;
+ return this.tokenization.getLanguageId();
}
public setMode(languageId: string): void {
- if (this._languageId === languageId) {
- // There's nothing to do
- return;
- }
-
- const e: IModelLanguageChangedEvent = {
- oldLanguage: this._languageId,
- newLanguage: languageId
- };
-
- this._languageId = languageId;
-
- this._bracketPairColorizer.handleDidChangeLanguage(e);
- this._tokenization.handleDidChangeLanguage(e);
- this._onDidChangeLanguage.fire(e);
- this._onDidChangeLanguageConfiguration.fire({});
+ this.tokenization.setLanguageId(languageId);
}
public getLanguageIdAtPosition(lineNumber: number, column: number): string {
- const position = this.validatePosition(new Position(lineNumber, column));
- const lineTokens = this.getLineTokens(position.lineNumber);
- return lineTokens.getLanguageId(lineTokens.findTokenIndexAtOffset(position.column - 1));
+ return this.tokenization.getLanguageIdAtPosition(lineNumber, column);
}
-
- public getTokenTypeIfInsertingCharacter(lineNumber: number, column: number, character: string): StandardTokenType {
- const position = this.validatePosition(new Position(lineNumber, column));
- return this._tokenization.getTokenTypeIfInsertingCharacter(position, character);
- }
-
- tokenizeLineWithEdit(position: IPosition, length: number, newText: string): LineTokens | null {
- const validatedPosition = this.validatePosition(position);
- return this._tokenization.tokenizeLineWithEdit(validatedPosition, length, newText);
- }
-
- private getLanguageConfiguration(languageId: string): ResolvedLanguageConfiguration {
- return this._languageConfigurationService.getLanguageConfiguration(languageId);
- }
-
- // Having tokens allows implementing additional helper methods
-
- public getWordAtPosition(_position: IPosition): IWordAtPosition | null {
- this._assertNotDisposed();
- const position = this.validatePosition(_position);
- const lineContent = this.getLineContent(position.lineNumber);
- const lineTokens = this._getLineTokens(position.lineNumber);
- const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
-
- // (1). First try checking right biased word
- const [rbStartOffset, rbEndOffset] = TextModel._findLanguageBoundaries(lineTokens, tokenIndex);
- const rightBiasedWord = getWordAtText(
- position.column,
- this.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex)).getWordDefinition(),
- lineContent.substring(rbStartOffset, rbEndOffset),
- rbStartOffset
- );
- // Make sure the result touches the original passed in position
- if (rightBiasedWord && rightBiasedWord.startColumn <= _position.column && _position.column <= rightBiasedWord.endColumn) {
- return rightBiasedWord;
- }
-
- // (2). Else, if we were at a language boundary, check the left biased word
- if (tokenIndex > 0 && rbStartOffset === position.column - 1) {
- // edge case, where `position` sits between two tokens belonging to two different languages
- const [lbStartOffset, lbEndOffset] = TextModel._findLanguageBoundaries(lineTokens, tokenIndex - 1);
- const leftBiasedWord = getWordAtText(
- position.column,
- this.getLanguageConfiguration(lineTokens.getLanguageId(tokenIndex - 1)).getWordDefinition(),
- lineContent.substring(lbStartOffset, lbEndOffset),
- lbStartOffset
- );
- // Make sure the result touches the original passed in position
- if (leftBiasedWord && leftBiasedWord.startColumn <= _position.column && _position.column <= leftBiasedWord.endColumn) {
- return leftBiasedWord;
- }
- }
-
- return null;
+ public setLineTokens(lineNumber: number, tokens: Uint32Array | ArrayBuffer | null): void {
+ this._tokenizationTextModelPart.setLineTokens(lineNumber, tokens);
}
- private static _findLanguageBoundaries(lineTokens: LineTokens, tokenIndex: number): [number, number] {
- const languageId = lineTokens.getLanguageId(tokenIndex);
-
- // go left until a different language is hit
- let startOffset = 0;
- for (let i = tokenIndex; i >= 0 && lineTokens.getLanguageId(i) === languageId; i--) {
- startOffset = lineTokens.getStartOffset(i);
- }
-
- // go right until a different language is hit
- let endOffset = lineTokens.getLineContent().length;
- for (let i = tokenIndex, tokenCount = lineTokens.getCount(); i < tokenCount && lineTokens.getLanguageId(i) === languageId; i++) {
- endOffset = lineTokens.getEndOffset(i);
- }
-
- return [startOffset, endOffset];
+ public getWordAtPosition(position: IPosition): IWordAtPosition | null {
+ return this._tokenizationTextModelPart.getWordAtPosition(position);
}
public getWordUntilPosition(position: IPosition): IWordAtPosition {
- const wordAtPosition = this.getWordAtPosition(position);
- if (!wordAtPosition) {
- return {
- word: '',
- startColumn: position.column,
- endColumn: position.column
- };
- }
- return {
- word: wordAtPosition.word.substr(0, position.column - wordAtPosition.startColumn),
- startColumn: wordAtPosition.startColumn,
- endColumn: position.column
- };
+ return this._tokenizationTextModelPart.getWordUntilPosition(position);
}
//#endregion