mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 03:28:33 -05:00
Merge from master
This commit is contained in:
@@ -2,38 +2,38 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as model from 'vs/editor/common/model';
|
||||
import { LanguageIdentifier, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes';
|
||||
import { EditStack } from 'vs/editor/common/model/editStack';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ModelRawContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelTokensChangedEvent, IModelOptionsChangedEvent, IModelContentChangedEvent, InternalModelContentChangeEvent, ModelRawFlush, ModelRawEOLChanged, ModelRawChange, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/model/textModelEvents';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { IntervalNode, IntervalTree, recomputeMaxEnd, getNodeIsInOverviewRuler } from 'vs/editor/common/model/intervalTree';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions';
|
||||
import { LineTokens } from 'vs/editor/common/core/lineTokens';
|
||||
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 * as model from 'vs/editor/common/model';
|
||||
import { EditStack } from 'vs/editor/common/model/editStack';
|
||||
import { guessIndentation } from 'vs/editor/common/model/indentationGuesser';
|
||||
import { IntervalNode, IntervalTree, getNodeIsInOverviewRuler, recomputeMaxEnd } from 'vs/editor/common/model/intervalTree';
|
||||
import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
|
||||
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, InternalModelContentChangeEvent, ModelRawChange, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/model/textModelEvents';
|
||||
import { SearchData, SearchParams, TextModelSearch } from 'vs/editor/common/model/textModelSearch';
|
||||
import { ModelLinesTokens, ModelTokensChangedEventBuilder } from 'vs/editor/common/model/textModelTokens';
|
||||
import { getWordAtText } from 'vs/editor/common/model/wordHelper';
|
||||
import { IState, LanguageId, LanguageIdentifier, TokenizationRegistry } from 'vs/editor/common/modes';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { NULL_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/nullMode';
|
||||
import { ignoreBracketsInToken } from 'vs/editor/common/modes/supports';
|
||||
import { BracketsUtils, RichEditBrackets, RichEditBracket } from 'vs/editor/common/modes/supports/richEditBrackets';
|
||||
import { Position, IPosition } from 'vs/editor/common/core/position';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
import { LineTokens } from 'vs/editor/common/core/lineTokens';
|
||||
import { getWordAtText } from 'vs/editor/common/model/wordHelper';
|
||||
import { ModelLinesTokens, ModelTokensChangedEventBuilder } from 'vs/editor/common/model/textModelTokens';
|
||||
import { guessIndentation } from 'vs/editor/common/model/indentationGuesser';
|
||||
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions';
|
||||
import { TextModelSearch, SearchParams, SearchData } from 'vs/editor/common/model/textModelSearch';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { BracketsUtils, RichEditBracket, RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets';
|
||||
import { IStringStream, ITextSnapshot } from 'vs/platform/files/common/files';
|
||||
import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
|
||||
import { ITheme, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
const CHEAP_TOKENIZATION_LENGTH_LIMIT = 2048;
|
||||
|
||||
function createTextBufferBuilder() {
|
||||
return new PieceTreeTextBufferBuilder();
|
||||
@@ -45,8 +45,8 @@ export function createTextBufferFactory(text: string): model.ITextBufferFactory
|
||||
return builder.finish();
|
||||
}
|
||||
|
||||
export function createTextBufferFactoryFromStream(stream: IStringStream, filter?: (chunk: string) => string): TPromise<model.ITextBufferFactory> {
|
||||
return new TPromise<model.ITextBufferFactory>((c, e) => {
|
||||
export function createTextBufferFactoryFromStream(stream: IStringStream, filter?: (chunk: string) => string): Promise<model.ITextBufferFactory> {
|
||||
return new Promise<model.ITextBufferFactory>((c, e) => {
|
||||
let done = false;
|
||||
let builder = createTextBufferBuilder();
|
||||
|
||||
@@ -77,7 +77,7 @@ export function createTextBufferFactoryFromStream(stream: IStringStream, filter?
|
||||
export function createTextBufferFactoryFromSnapshot(snapshot: ITextSnapshot): model.ITextBufferFactory {
|
||||
let builder = createTextBufferBuilder();
|
||||
|
||||
let chunk: string;
|
||||
let chunk: string | null;
|
||||
while (typeof (chunk = snapshot.read()) === 'string') {
|
||||
builder.acceptChunk(chunk);
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class TextModelSnapshot implements ITextSnapshot {
|
||||
this._eos = false;
|
||||
}
|
||||
|
||||
public read(): string {
|
||||
public read(): string | null {
|
||||
if (this._eos) {
|
||||
return null;
|
||||
}
|
||||
@@ -152,6 +152,8 @@ class TextModelSnapshot implements ITextSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
const invalidFunc = () => { throw new Error(`Invalid change accessor`); };
|
||||
|
||||
export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
private static readonly MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB
|
||||
@@ -168,7 +170,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
largeFileOptimizations: EDITOR_MODEL_DEFAULTS.largeFileOptimizations,
|
||||
};
|
||||
|
||||
public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier = null, uri: URI = null): TextModel {
|
||||
public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier | null = null, uri: URI | null = null): TextModel {
|
||||
return new TextModel(text, options, languageIdentifier, uri);
|
||||
}
|
||||
|
||||
@@ -244,7 +246,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
private _commandManager: EditStack;
|
||||
private _isUndoing: boolean;
|
||||
private _isRedoing: boolean;
|
||||
private _trimAutoWhitespaceLines: number[];
|
||||
private _trimAutoWhitespaceLines: number[] | null;
|
||||
//#endregion
|
||||
|
||||
//#region Decorations
|
||||
@@ -262,11 +264,11 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
private _languageIdentifier: LanguageIdentifier;
|
||||
private _tokenizationListener: IDisposable;
|
||||
private _languageRegistryListener: IDisposable;
|
||||
private _revalidateTokensTimeout: number;
|
||||
private _revalidateTokensTimeout: any;
|
||||
/*private*/_tokens: ModelLinesTokens;
|
||||
//#endregion
|
||||
|
||||
constructor(source: string | model.ITextBufferFactory, creationOptions: model.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier, associatedResource: URI = null) {
|
||||
constructor(source: string | model.ITextBufferFactory, creationOptions: model.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier | null, associatedResource: URI | null = null) {
|
||||
super();
|
||||
|
||||
// Generate a new unique model id
|
||||
@@ -345,16 +347,11 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
public dispose(): void {
|
||||
this._isDisposing = true;
|
||||
this._onWillDispose.fire();
|
||||
this._commandManager = null;
|
||||
this._decorations = null;
|
||||
this._decorationsTree = null;
|
||||
this._tokenizationListener.dispose();
|
||||
this._languageRegistryListener.dispose();
|
||||
this._clearTimers();
|
||||
this._tokens = null;
|
||||
this._isDisposed = true;
|
||||
// Null out members, such that any use of a disposed model will throw exceptions sooner rather than later
|
||||
this._buffer = null;
|
||||
super.dispose();
|
||||
this._isDisposing = false;
|
||||
}
|
||||
@@ -1108,13 +1105,17 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount);
|
||||
}
|
||||
|
||||
public findNextMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch {
|
||||
public findNextMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch | null {
|
||||
this._assertNotDisposed();
|
||||
const searchStart = this.validatePosition(rawSearchStart);
|
||||
|
||||
if (!isRegex && searchString.indexOf('\n') < 0) {
|
||||
const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators);
|
||||
const searchData = searchParams.parseSearchRequest();
|
||||
if (!searchData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const lineCount = this.getLineCount();
|
||||
let searchRange = new Range(searchStart.lineNumber, searchStart.column, lineCount, this.getLineMaxColumn(lineCount));
|
||||
let ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1);
|
||||
@@ -1136,7 +1137,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
|
||||
}
|
||||
|
||||
public findPreviousMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch {
|
||||
public findPreviousMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch | null {
|
||||
this._assertNotDisposed();
|
||||
const searchStart = this.validatePosition(rawSearchStart);
|
||||
return TextModelSearch.findPreviousMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches);
|
||||
@@ -1165,7 +1166,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] {
|
||||
public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
@@ -1176,7 +1177,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] {
|
||||
private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] | null {
|
||||
if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) {
|
||||
// Go through each saved line number and insert a trim whitespace edit
|
||||
// if it is safe to do so (no conflicts with other edits).
|
||||
@@ -1323,7 +1324,12 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
for (let i = 0, len = contentChanges.length; i < len; i++) {
|
||||
const change = contentChanges[i];
|
||||
const [eolCount, firstLineLength] = TextModel._eolCount(change.text);
|
||||
this._tokens.applyEdits(change.range, eolCount, firstLineLength);
|
||||
try {
|
||||
this._tokens.applyEdits(change.range, eolCount, firstLineLength);
|
||||
} catch (err) {
|
||||
// emergency recovery => reset tokens
|
||||
this._tokens = new ModelLinesTokens(this._tokens.languageIdentifier, this._tokens.tokenizationSupport);
|
||||
}
|
||||
this._onDidChangeDecorations.fire();
|
||||
this._decorationsTree.acceptReplace(change.rangeOffset, change.rangeLength, change.text.length, change.forceMoveMarkers);
|
||||
|
||||
@@ -1391,7 +1397,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return result.reverseEdits;
|
||||
}
|
||||
|
||||
private _undo(): Selection[] {
|
||||
private _undo(): Selection[] | null {
|
||||
this._isUndoing = true;
|
||||
let r = this._commandManager.undo();
|
||||
this._isUndoing = false;
|
||||
@@ -1405,7 +1411,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return r.selections;
|
||||
}
|
||||
|
||||
public undo(): Selection[] {
|
||||
public undo(): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
@@ -1420,7 +1426,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return this._commandManager.canUndo();
|
||||
}
|
||||
|
||||
private _redo(): Selection[] {
|
||||
private _redo(): Selection[] | null {
|
||||
this._isRedoing = true;
|
||||
let r = this._commandManager.redo();
|
||||
this._isRedoing = false;
|
||||
@@ -1434,7 +1440,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return r.selections;
|
||||
}
|
||||
|
||||
public redo(): Selection[] {
|
||||
public redo(): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
@@ -1453,7 +1459,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
//#region Decorations
|
||||
|
||||
public changeDecorations<T>(callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T {
|
||||
public changeDecorations<T>(callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T | null {
|
||||
this._assertNotDisposed();
|
||||
|
||||
try {
|
||||
@@ -1464,7 +1470,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
private _changeDecorations<T>(ownerId: number, callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T): T {
|
||||
private _changeDecorations<T>(ownerId: number, callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T): T | null {
|
||||
let changeAccessor: model.IModelDecorationsChangeAccessor = {
|
||||
addDecoration: (range: IRange, options: model.IModelDecorationOptions): string => {
|
||||
this._onDidChangeDecorations.fire();
|
||||
@@ -1491,17 +1497,18 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
|
||||
}
|
||||
};
|
||||
let result: T = null;
|
||||
let result: T | null = null;
|
||||
try {
|
||||
result = callback(changeAccessor);
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
}
|
||||
// Invalidate change accessor
|
||||
changeAccessor.addDecoration = null;
|
||||
changeAccessor.changeDecoration = null;
|
||||
changeAccessor.removeDecoration = null;
|
||||
changeAccessor.deltaDecorations = null;
|
||||
changeAccessor.addDecoration = invalidFunc;
|
||||
changeAccessor.changeDecoration = invalidFunc;
|
||||
changeAccessor.changeDecorationOptions = invalidFunc;
|
||||
changeAccessor.removeDecoration = invalidFunc;
|
||||
changeAccessor.deltaDecorations = invalidFunc;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1524,11 +1531,13 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
_getTrackedRange(id: string): Range {
|
||||
_getTrackedRange(id: string): Range | null {
|
||||
return this.getDecorationRange(id);
|
||||
}
|
||||
|
||||
_setTrackedRange(id: string, newRange: Range, newStickiness: model.TrackedRangeStickiness): string {
|
||||
_setTrackedRange(id: string | null, newRange: null, newStickiness: model.TrackedRangeStickiness): null;
|
||||
_setTrackedRange(id: string | null, newRange: Range, newStickiness: model.TrackedRangeStickiness): string;
|
||||
_setTrackedRange(id: string | null, newRange: Range | null, newStickiness: model.TrackedRangeStickiness): string | null {
|
||||
const node = (id ? this._decorations[id] : null);
|
||||
|
||||
if (!node) {
|
||||
@@ -1571,7 +1580,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
public getDecorationOptions(decorationId: string): model.IModelDecorationOptions {
|
||||
public getDecorationOptions(decorationId: string): model.IModelDecorationOptions | null {
|
||||
const node = this._decorations[decorationId];
|
||||
if (!node) {
|
||||
return null;
|
||||
@@ -1579,7 +1588,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return node.options;
|
||||
}
|
||||
|
||||
public getDecorationRange(decorationId: string): Range {
|
||||
public getDecorationRange(decorationId: string): Range | null {
|
||||
const node = this._decorations[decorationId];
|
||||
if (!node) {
|
||||
return null;
|
||||
@@ -1671,8 +1680,8 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return;
|
||||
}
|
||||
|
||||
const nodeWasInOverviewRuler = (node.options.overviewRuler.color ? true : false);
|
||||
const nodeIsInOverviewRuler = (options.overviewRuler.color ? true : false);
|
||||
const nodeWasInOverviewRuler = (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
|
||||
const nodeIsInOverviewRuler = (options.overviewRuler && options.overviewRuler.color ? true : false);
|
||||
|
||||
if (nodeWasInOverviewRuler !== nodeIsInOverviewRuler) {
|
||||
// Delete + Insert due to an overview ruler status change
|
||||
@@ -1696,7 +1705,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
let result = new Array<string>(newDecorationsLen);
|
||||
while (oldDecorationIndex < oldDecorationsLen || newDecorationIndex < newDecorationsLen) {
|
||||
|
||||
let node: IntervalNode = null;
|
||||
let node: IntervalNode | null = null;
|
||||
|
||||
if (oldDecorationIndex < oldDecorationsLen) {
|
||||
// (1) get ourselves an old node
|
||||
@@ -1765,9 +1774,9 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
const eventBuilder = new ModelTokensChangedEventBuilder();
|
||||
let nonWhitespaceColumn = this.getLineFirstNonWhitespaceColumn(startLineNumber);
|
||||
let fakeLines = [];
|
||||
let fakeLines: string[] = [];
|
||||
let i = startLineNumber - 1;
|
||||
let initialState = null;
|
||||
let initialState: IState | null = null;
|
||||
if (nonWhitespaceColumn > 0) {
|
||||
while (nonWhitespaceColumn > 0 && i >= 1) {
|
||||
let newNonWhitespaceIndex = this.getLineFirstNonWhitespaceColumn(i);
|
||||
@@ -1847,7 +1856,19 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
|
||||
public isCheapToTokenize(lineNumber: number): boolean {
|
||||
return this._tokens.isCheapToTokenize(lineNumber);
|
||||
if (!this._tokens.isCheapToTokenize(lineNumber)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lineNumber < this._tokens.inValidLineStartIndex + 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.getLineLength(lineNumber) < CHEAP_TOKENIZATION_LENGTH_LIMIT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public tokenizeIfCheap(lineNumber: number): void {
|
||||
@@ -1968,7 +1989,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
// Having tokens allows implementing additional helper methods
|
||||
|
||||
public getWordAtPosition(_position: IPosition): model.IWordAtPosition {
|
||||
public getWordAtPosition(_position: IPosition): model.IWordAtPosition | null {
|
||||
this._assertNotDisposed();
|
||||
const position = this.validatePosition(_position);
|
||||
const lineContent = this.getLineContent(position.lineNumber);
|
||||
@@ -1983,7 +2004,8 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
lineContent.substring(rbStartOffset, rbEndOffset),
|
||||
rbStartOffset
|
||||
);
|
||||
if (rightBiasedWord) {
|
||||
// Make sure the result touches the original passed in position
|
||||
if (rightBiasedWord && rightBiasedWord.startColumn <= _position.column && _position.column <= rightBiasedWord.endColumn) {
|
||||
return rightBiasedWord;
|
||||
}
|
||||
|
||||
@@ -1997,7 +2019,8 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
lineContent.substring(lbStartOffset, lbEndOffset),
|
||||
lbStartOffset
|
||||
);
|
||||
if (leftBiasedWord) {
|
||||
// Make sure the result touches the original passed in position
|
||||
if (leftBiasedWord && leftBiasedWord.startColumn <= _position.column && _position.column <= leftBiasedWord.endColumn) {
|
||||
return leftBiasedWord;
|
||||
}
|
||||
}
|
||||
@@ -2009,13 +2032,13 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
const languageId = lineTokens.getLanguageId(tokenIndex);
|
||||
|
||||
// go left until a different language is hit
|
||||
let startOffset: number;
|
||||
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: number;
|
||||
let endOffset = lineTokens.getLineContent().length;
|
||||
for (let i = tokenIndex, tokenCount = lineTokens.getCount(); i < tokenCount && lineTokens.getLanguageId(i) === languageId; i++) {
|
||||
endOffset = lineTokens.getEndOffset(i);
|
||||
}
|
||||
@@ -2039,7 +2062,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
};
|
||||
}
|
||||
|
||||
public findMatchingBracketUp(_bracket: string, _position: IPosition): Range {
|
||||
public findMatchingBracketUp(_bracket: string, _position: IPosition): Range | null {
|
||||
let bracket = _bracket.toLowerCase();
|
||||
let position = this.validatePosition(_position);
|
||||
|
||||
@@ -2060,11 +2083,11 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return this._findMatchingBracketUp(data, position);
|
||||
}
|
||||
|
||||
public matchBracket(position: IPosition): [Range, Range] {
|
||||
public matchBracket(position: IPosition): [Range, Range] | null {
|
||||
return this._matchBracket(this.validatePosition(position));
|
||||
}
|
||||
|
||||
private _matchBracket(position: Position): [Range, Range] {
|
||||
private _matchBracket(position: Position): [Range, Range] | null {
|
||||
const lineNumber = position.lineNumber;
|
||||
const lineTokens = this._getLineTokens(lineNumber);
|
||||
const lineText = this._buffer.getLineContent(lineNumber);
|
||||
@@ -2084,7 +2107,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
// it might be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets
|
||||
// `bestResult` will contain the most right-side result
|
||||
let bestResult: [Range, Range] = null;
|
||||
let bestResult: [Range, Range] | null = null;
|
||||
while (true) {
|
||||
let foundBracket = BracketsUtils.findNextBracketInToken(currentModeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
|
||||
if (!foundBracket) {
|
||||
@@ -2143,7 +2166,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean): [Range, Range] {
|
||||
private _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean): [Range, Range] | null {
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
@@ -2163,7 +2186,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _findMatchingBracketUp(bracket: RichEditBracket, position: Position): Range {
|
||||
private _findMatchingBracketUp(bracket: RichEditBracket, position: Position): Range | null {
|
||||
// console.log('_findMatchingBracketUp: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));
|
||||
|
||||
const languageId = bracket.languageIdentifier.id;
|
||||
@@ -2224,7 +2247,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _findMatchingBracketDown(bracket: RichEditBracket, position: Position): Range {
|
||||
private _findMatchingBracketDown(bracket: RichEditBracket, position: Position): Range | null {
|
||||
// console.log('_findMatchingBracketDown: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));
|
||||
|
||||
const languageId = bracket.languageIdentifier.id;
|
||||
@@ -2284,11 +2307,11 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
public findPrevBracket(_position: IPosition): model.IFoundBracket {
|
||||
public findPrevBracket(_position: IPosition): model.IFoundBracket | null {
|
||||
const position = this.validatePosition(_position);
|
||||
|
||||
let languageId: LanguageId = -1;
|
||||
let modeBrackets: RichEditBrackets = null;
|
||||
let modeBrackets: RichEditBrackets | null = null;
|
||||
for (let lineNumber = position.lineNumber; lineNumber >= 1; lineNumber--) {
|
||||
const lineTokens = this._getLineTokens(lineNumber);
|
||||
const tokenCount = lineTokens.getCount();
|
||||
@@ -2328,11 +2351,11 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
public findNextBracket(_position: IPosition): model.IFoundBracket {
|
||||
public findNextBracket(_position: IPosition): model.IFoundBracket | null {
|
||||
const position = this.validatePosition(_position);
|
||||
|
||||
let languageId: LanguageId = -1;
|
||||
let modeBrackets: RichEditBrackets = null;
|
||||
let modeBrackets: RichEditBrackets | null = null;
|
||||
for (let lineNumber = position.lineNumber, lineCount = this.getLineCount(); lineNumber <= lineCount; lineNumber++) {
|
||||
const lineTokens = this._getLineTokens(lineNumber);
|
||||
const tokenCount = lineTokens.getCount();
|
||||
@@ -2373,7 +2396,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _toFoundBracket(modeBrackets: RichEditBrackets, r: Range): model.IFoundBracket {
|
||||
private _toFoundBracket(modeBrackets: RichEditBrackets, r: Range): model.IFoundBracket | null {
|
||||
if (!r) {
|
||||
return null;
|
||||
}
|
||||
@@ -2436,7 +2459,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
|
||||
const foldingRules = LanguageConfigurationRegistry.getFoldingRules(this._languageIdentifier.id);
|
||||
const offSide = foldingRules && foldingRules.offSide;
|
||||
const offSide = Boolean(foldingRules && foldingRules.offSide);
|
||||
|
||||
let up_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */
|
||||
let up_aboveContentLineIndent = -1;
|
||||
@@ -2606,7 +2629,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
|
||||
const foldingRules = LanguageConfigurationRegistry.getFoldingRules(this._languageIdentifier.id);
|
||||
const offSide = foldingRules && foldingRules.offSide;
|
||||
const offSide = Boolean(foldingRules && foldingRules.offSide);
|
||||
|
||||
let result: number[] = new Array<number>(endLineNumber - startLineNumber + 1);
|
||||
|
||||
@@ -2778,30 +2801,40 @@ function cleanClassName(className: string): string {
|
||||
export class ModelDecorationOverviewRulerOptions implements model.IModelDecorationOverviewRulerOptions {
|
||||
readonly color: string | ThemeColor;
|
||||
readonly darkColor: string | ThemeColor;
|
||||
readonly hcColor: string | ThemeColor;
|
||||
readonly position: model.OverviewRulerLane;
|
||||
_resolvedColor: string;
|
||||
private _resolvedColor: string | null;
|
||||
|
||||
constructor(options: model.IModelDecorationOverviewRulerOptions) {
|
||||
this.color = strings.empty;
|
||||
this.darkColor = strings.empty;
|
||||
this.hcColor = strings.empty;
|
||||
this.position = model.OverviewRulerLane.Center;
|
||||
this.color = options.color || strings.empty;
|
||||
this.darkColor = options.darkColor || strings.empty;
|
||||
this.position = (typeof options.position === 'number' ? options.position : model.OverviewRulerLane.Center);
|
||||
this._resolvedColor = null;
|
||||
}
|
||||
|
||||
if (options && options.color) {
|
||||
this.color = options.color;
|
||||
public getColor(theme: ITheme): string {
|
||||
if (!this._resolvedColor) {
|
||||
if (theme.type !== 'light' && this.darkColor) {
|
||||
this._resolvedColor = this._resolveColor(this.darkColor, theme);
|
||||
} else {
|
||||
this._resolvedColor = this._resolveColor(this.color, theme);
|
||||
}
|
||||
}
|
||||
if (options && options.darkColor) {
|
||||
this.darkColor = options.darkColor;
|
||||
this.hcColor = options.darkColor;
|
||||
return this._resolvedColor;
|
||||
}
|
||||
|
||||
public invalidateCachedColor(): void {
|
||||
this._resolvedColor = null;
|
||||
}
|
||||
|
||||
private _resolveColor(color: string | ThemeColor, theme: ITheme): string {
|
||||
if (typeof color === 'string') {
|
||||
return color;
|
||||
}
|
||||
if (options && options.hcColor) {
|
||||
this.hcColor = options.hcColor;
|
||||
}
|
||||
if (options && options.hasOwnProperty('position')) {
|
||||
this.position = options.position;
|
||||
let c = color ? theme.getColor(color.id) : null;
|
||||
if (!c) {
|
||||
return strings.empty;
|
||||
}
|
||||
return c.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2819,36 +2852,38 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions {
|
||||
|
||||
readonly stickiness: model.TrackedRangeStickiness;
|
||||
readonly zIndex: number;
|
||||
readonly className: string;
|
||||
readonly hoverMessage: IMarkdownString | IMarkdownString[];
|
||||
readonly glyphMarginHoverMessage: IMarkdownString | IMarkdownString[];
|
||||
readonly className: string | null;
|
||||
readonly hoverMessage: IMarkdownString | IMarkdownString[] | null;
|
||||
readonly glyphMarginHoverMessage: IMarkdownString | IMarkdownString[] | null;
|
||||
readonly isWholeLine: boolean;
|
||||
readonly showIfCollapsed: boolean;
|
||||
readonly overviewRuler: ModelDecorationOverviewRulerOptions;
|
||||
readonly glyphMarginClassName: string;
|
||||
readonly linesDecorationsClassName: string;
|
||||
readonly marginClassName: string;
|
||||
readonly inlineClassName: string;
|
||||
readonly collapseOnReplaceEdit: boolean;
|
||||
readonly overviewRuler: ModelDecorationOverviewRulerOptions | null;
|
||||
readonly glyphMarginClassName: string | null;
|
||||
readonly linesDecorationsClassName: string | null;
|
||||
readonly marginClassName: string | null;
|
||||
readonly inlineClassName: string | null;
|
||||
readonly inlineClassNameAffectsLetterSpacing: boolean;
|
||||
readonly beforeContentClassName: string;
|
||||
readonly afterContentClassName: string;
|
||||
readonly beforeContentClassName: string | null;
|
||||
readonly afterContentClassName: string | null;
|
||||
|
||||
private constructor(options: model.IModelDecorationOptions) {
|
||||
this.stickiness = options.stickiness || model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges;
|
||||
this.zIndex = options.zIndex || 0;
|
||||
this.className = options.className ? cleanClassName(options.className) : strings.empty;
|
||||
this.hoverMessage = options.hoverMessage || [];
|
||||
this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || [];
|
||||
this.className = options.className ? cleanClassName(options.className) : null;
|
||||
this.hoverMessage = options.hoverMessage || null;
|
||||
this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || null;
|
||||
this.isWholeLine = options.isWholeLine || false;
|
||||
this.showIfCollapsed = options.showIfCollapsed || false;
|
||||
this.overviewRuler = new ModelDecorationOverviewRulerOptions(options.overviewRuler);
|
||||
this.glyphMarginClassName = options.glyphMarginClassName ? cleanClassName(options.glyphMarginClassName) : strings.empty;
|
||||
this.linesDecorationsClassName = options.linesDecorationsClassName ? cleanClassName(options.linesDecorationsClassName) : strings.empty;
|
||||
this.marginClassName = options.marginClassName ? cleanClassName(options.marginClassName) : strings.empty;
|
||||
this.inlineClassName = options.inlineClassName ? cleanClassName(options.inlineClassName) : strings.empty;
|
||||
this.collapseOnReplaceEdit = options.collapseOnReplaceEdit || false;
|
||||
this.overviewRuler = options.overviewRuler ? new ModelDecorationOverviewRulerOptions(options.overviewRuler) : null;
|
||||
this.glyphMarginClassName = options.glyphMarginClassName ? cleanClassName(options.glyphMarginClassName) : null;
|
||||
this.linesDecorationsClassName = options.linesDecorationsClassName ? cleanClassName(options.linesDecorationsClassName) : null;
|
||||
this.marginClassName = options.marginClassName ? cleanClassName(options.marginClassName) : null;
|
||||
this.inlineClassName = options.inlineClassName ? cleanClassName(options.inlineClassName) : null;
|
||||
this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false;
|
||||
this.beforeContentClassName = options.beforeContentClassName ? cleanClassName(options.beforeContentClassName) : strings.empty;
|
||||
this.afterContentClassName = options.afterContentClassName ? cleanClassName(options.afterContentClassName) : strings.empty;
|
||||
this.beforeContentClassName = options.beforeContentClassName ? cleanClassName(options.beforeContentClassName) : null;
|
||||
this.afterContentClassName = options.afterContentClassName ? cleanClassName(options.afterContentClassName) : null;
|
||||
}
|
||||
}
|
||||
ModelDecorationOptions.EMPTY = ModelDecorationOptions.register({});
|
||||
@@ -2916,7 +2951,7 @@ export class DidChangeContentEmitter extends Disposable {
|
||||
public readonly slowEvent: Event<InternalModelContentChangeEvent> = this._slowEmitter.event;
|
||||
|
||||
private _deferredCnt: number;
|
||||
private _deferredEvent: InternalModelContentChangeEvent;
|
||||
private _deferredEvent: InternalModelContentChangeEvent | null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
Reference in New Issue
Block a user