mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 27ada910e121e23a6d95ecca9cae595fb98ab568
This commit is contained in:
@@ -34,7 +34,6 @@ import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { VSBufferReadableStream, VSBuffer } from 'vs/base/common/buffer';
|
||||
import { TokensStore, MultilineTokens, countEOL, MultilineTokens2, TokensStore2 } from 'vs/editor/common/model/tokensStore';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Constants } from 'vs/base/common/uint';
|
||||
import { EditorTheme } from 'vs/editor/common/view/viewContext';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { TextChange } from 'vs/editor/common/model/textChange';
|
||||
@@ -172,6 +171,21 @@ const enum StringOffsetValidationType {
|
||||
SurrogatePairs = 1,
|
||||
}
|
||||
|
||||
type ContinueBracketSearchPredicate = null | (() => boolean);
|
||||
|
||||
class BracketSearchCanceled {
|
||||
public static INSTANCE = new BracketSearchCanceled();
|
||||
_searchCanceledBrand = undefined;
|
||||
private constructor() { }
|
||||
}
|
||||
|
||||
function stripBracketSearchCanceled<T>(result: T | null | BracketSearchCanceled): T | null {
|
||||
if (result instanceof BracketSearchCanceled) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
private static readonly MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB
|
||||
@@ -2014,7 +2028,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._findMatchingBracketUp(data, position);
|
||||
return stripBracketSearchCanceled(this._findMatchingBracketUp(data, position, null));
|
||||
}
|
||||
|
||||
public matchBracket(position: IPosition): [Range, Range] | null {
|
||||
@@ -2062,8 +2076,11 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
// check that we didn't hit a bracket too far away from position
|
||||
if (foundBracket.startColumn <= position.column && position.column <= foundBracket.endColumn) {
|
||||
const foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();
|
||||
const r = this._matchFoundBracket(foundBracket, currentModeBrackets.textIsBracket[foundBracketText], currentModeBrackets.textIsOpenBracket[foundBracketText]);
|
||||
const r = this._matchFoundBracket(foundBracket, currentModeBrackets.textIsBracket[foundBracketText], currentModeBrackets.textIsOpenBracket[foundBracketText], null);
|
||||
if (r) {
|
||||
if (r instanceof BracketSearchCanceled) {
|
||||
return null;
|
||||
}
|
||||
bestResult = r;
|
||||
}
|
||||
}
|
||||
@@ -2100,8 +2117,11 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
// check that we didn't hit a bracket too far away from position
|
||||
if (foundBracket && foundBracket.startColumn <= position.column && position.column <= foundBracket.endColumn) {
|
||||
const foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();
|
||||
const r = this._matchFoundBracket(foundBracket, prevModeBrackets.textIsBracket[foundBracketText], prevModeBrackets.textIsOpenBracket[foundBracketText]);
|
||||
const r = this._matchFoundBracket(foundBracket, prevModeBrackets.textIsBracket[foundBracketText], prevModeBrackets.textIsOpenBracket[foundBracketText], null);
|
||||
if (r) {
|
||||
if (r instanceof BracketSearchCanceled) {
|
||||
return null;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -2111,35 +2131,41 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean): [Range, Range] | null {
|
||||
private _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean, continueSearchPredicate: ContinueBracketSearchPredicate): [Range, Range] | null | BracketSearchCanceled {
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isOpen) {
|
||||
let matched = this._findMatchingBracketDown(data, foundBracket.getEndPosition());
|
||||
if (matched) {
|
||||
return [foundBracket, matched];
|
||||
}
|
||||
} else {
|
||||
let matched = this._findMatchingBracketUp(data, foundBracket.getStartPosition());
|
||||
if (matched) {
|
||||
return [foundBracket, matched];
|
||||
}
|
||||
const matched = (
|
||||
isOpen
|
||||
? this._findMatchingBracketDown(data, foundBracket.getEndPosition(), continueSearchPredicate)
|
||||
: this._findMatchingBracketUp(data, foundBracket.getStartPosition(), continueSearchPredicate)
|
||||
);
|
||||
|
||||
if (!matched) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
if (matched instanceof BracketSearchCanceled) {
|
||||
return matched;
|
||||
}
|
||||
|
||||
return [foundBracket, matched];
|
||||
}
|
||||
|
||||
private _findMatchingBracketUp(bracket: RichEditBracket, position: Position): Range | null {
|
||||
private _findMatchingBracketUp(bracket: RichEditBracket, position: Position, continueSearchPredicate: ContinueBracketSearchPredicate): Range | null | BracketSearchCanceled {
|
||||
// console.log('_findMatchingBracketUp: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));
|
||||
|
||||
const languageId = bracket.languageIdentifier.id;
|
||||
const reversedBracketRegex = bracket.reversedRegex;
|
||||
let count = -1;
|
||||
|
||||
const searchPrevMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null => {
|
||||
let totalCallCount = 0;
|
||||
const searchPrevMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null | BracketSearchCanceled => {
|
||||
while (true) {
|
||||
if (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {
|
||||
return BracketSearchCanceled.INSTANCE;
|
||||
}
|
||||
const r = BracketsUtils.findPrevBracketInRange(reversedBracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
|
||||
if (!r) {
|
||||
break;
|
||||
@@ -2214,15 +2240,19 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _findMatchingBracketDown(bracket: RichEditBracket, position: Position): Range | null {
|
||||
private _findMatchingBracketDown(bracket: RichEditBracket, position: Position, continueSearchPredicate: ContinueBracketSearchPredicate): Range | null | BracketSearchCanceled {
|
||||
// console.log('_findMatchingBracketDown: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position));
|
||||
|
||||
const languageId = bracket.languageIdentifier.id;
|
||||
const bracketRegex = bracket.forwardRegex;
|
||||
let count = 1;
|
||||
|
||||
const searchNextMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null => {
|
||||
let totalCallCount = 0;
|
||||
const searchNextMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null | BracketSearchCanceled => {
|
||||
while (true) {
|
||||
if (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {
|
||||
return BracketSearchCanceled.INSTANCE;
|
||||
}
|
||||
const r = BracketsUtils.findNextBracketInRange(bracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
|
||||
if (!r) {
|
||||
break;
|
||||
@@ -2452,7 +2482,16 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
public findEnclosingBrackets(_position: IPosition, maxDuration = Constants.MAX_SAFE_SMALL_INTEGER): [Range, Range] | null {
|
||||
public findEnclosingBrackets(_position: IPosition, maxDuration?: number): [Range, Range] | null {
|
||||
let continueSearchPredicate: ContinueBracketSearchPredicate;
|
||||
if (typeof maxDuration === 'undefined') {
|
||||
continueSearchPredicate = null;
|
||||
} else {
|
||||
const startTime = Date.now();
|
||||
continueSearchPredicate = () => {
|
||||
return (Date.now() - startTime <= maxDuration);
|
||||
};
|
||||
}
|
||||
const position = this.validatePosition(_position);
|
||||
const lineCount = this.getLineCount();
|
||||
const savedCounts = new Map<number, number[]>();
|
||||
@@ -2468,8 +2507,13 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
counts = savedCounts.get(languageId)!;
|
||||
};
|
||||
const searchInRange = (modeBrackets: RichEditBrackets, lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): [Range, Range] | null => {
|
||||
|
||||
let totalCallCount = 0;
|
||||
const searchInRange = (modeBrackets: RichEditBrackets, lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): [Range, Range] | null | BracketSearchCanceled => {
|
||||
while (true) {
|
||||
if (continueSearchPredicate && (++totalCallCount) % 100 === 0 && !continueSearchPredicate()) {
|
||||
return BracketSearchCanceled.INSTANCE;
|
||||
}
|
||||
const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
|
||||
if (!r) {
|
||||
break;
|
||||
@@ -2485,7 +2529,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
|
||||
if (counts[bracket.index] === -1) {
|
||||
return this._matchFoundBracket(r, bracket, false);
|
||||
return this._matchFoundBracket(r, bracket, false, continueSearchPredicate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2496,12 +2540,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
let languageId: LanguageId = -1;
|
||||
let modeBrackets: RichEditBrackets | null = null;
|
||||
const startTime = Date.now();
|
||||
for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {
|
||||
const elapsedTime = Date.now() - startTime;
|
||||
if (elapsedTime > maxDuration) {
|
||||
return null;
|
||||
}
|
||||
const lineTokens = this._getLineTokens(lineNumber);
|
||||
const tokenCount = lineTokens.getCount();
|
||||
const lineText = this._buffer.getLineContent(lineNumber);
|
||||
@@ -2530,7 +2569,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
|
||||
const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);
|
||||
if (r) {
|
||||
return r;
|
||||
return stripBracketSearchCanceled(r);
|
||||
}
|
||||
prevSearchInToken = false;
|
||||
}
|
||||
@@ -2555,7 +2594,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
|
||||
const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);
|
||||
if (r) {
|
||||
return r;
|
||||
return stripBracketSearchCanceled(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2566,7 +2605,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
|
||||
const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);
|
||||
if (r) {
|
||||
return r;
|
||||
return stripBracketSearchCanceled(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user