Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)

* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998

* fix pipelines

* fix strict-null-checks

* add missing files
This commit is contained in:
Anthony Dresser
2019-10-21 22:12:22 -07:00
committed by GitHub
parent 7c9be74970
commit 1e22f47304
913 changed files with 18898 additions and 16536 deletions

View File

@@ -726,6 +726,11 @@ export class TextModel extends Disposable implements model.ITextModel {
return this._buffer.getValueLengthInRange(this.validateRange(rawRange), eol);
}
public getCharacterCountInRange(rawRange: IRange, eol: model.EndOfLinePreference = model.EndOfLinePreference.TextDefined): number {
this._assertNotDisposed();
return this._buffer.getCharacterCountInRange(this.validateRange(rawRange), eol);
}
public getLineCount(): number {
this._assertNotDisposed();
return this._buffer.getLineCount();
@@ -1910,7 +1915,7 @@ export class TextModel extends Disposable implements model.ITextModel {
const lineTokens = this._getLineTokens(lineNumber);
const lineText = this._buffer.getLineContent(lineNumber);
let tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
const tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
if (tokenIndex < 0) {
return null;
}
@@ -1919,15 +1924,15 @@ export class TextModel extends Disposable implements model.ITextModel {
// check that the token is not to be ignored
if (currentModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex))) {
// limit search to not go before `maxBracketLength`
let searchStartOffset = Math.max(lineTokens.getStartOffset(tokenIndex), position.column - 1 - currentModeBrackets.maxBracketLength);
let searchStartOffset = Math.max(0, position.column - 1 - currentModeBrackets.maxBracketLength);
// limit search to not go after `maxBracketLength`
const searchEndOffset = Math.min(lineTokens.getEndOffset(tokenIndex), position.column - 1 + currentModeBrackets.maxBracketLength);
const searchEndOffset = Math.min(lineText.length, position.column - 1 + currentModeBrackets.maxBracketLength);
// it might be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets
// `bestResult` will contain the most right-side result
let bestResult: [Range, Range] | null = null;
while (true) {
let foundBracket = BracketsUtils.findNextBracketInToken(currentModeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
const foundBracket = BracketsUtils.findNextBracketInRange(currentModeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (!foundBracket) {
// there are no more brackets in this text
break;
@@ -1935,12 +1940,8 @@ 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) {
let foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1);
foundBracketText = foundBracketText.toLowerCase();
let r = this._matchFoundBracket(foundBracket, currentModeBrackets.textIsBracket[foundBracketText], currentModeBrackets.textIsOpenBracket[foundBracketText]);
// check that we can actually match this bracket
const foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();
const r = this._matchFoundBracket(foundBracket, currentModeBrackets.textIsBracket[foundBracketText], currentModeBrackets.textIsOpenBracket[foundBracketText]);
if (r) {
bestResult = r;
}
@@ -1956,24 +1957,20 @@ export class TextModel extends Disposable implements model.ITextModel {
// If position is in between two tokens, try also looking in the previous token
if (tokenIndex > 0 && lineTokens.getStartOffset(tokenIndex) === position.column - 1) {
const searchEndOffset = lineTokens.getStartOffset(tokenIndex);
tokenIndex--;
const prevModeBrackets = LanguageConfigurationRegistry.getBracketsSupport(lineTokens.getLanguageId(tokenIndex));
const prevTokenIndex = tokenIndex - 1;
const prevModeBrackets = LanguageConfigurationRegistry.getBracketsSupport(lineTokens.getLanguageId(prevTokenIndex));
// check that previous token is not to be ignored
if (prevModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex))) {
if (prevModeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(prevTokenIndex))) {
// limit search in case previous token is very large, there's no need to go beyond `maxBracketLength`
const searchStartOffset = Math.max(lineTokens.getStartOffset(tokenIndex), position.column - 1 - prevModeBrackets.maxBracketLength);
const foundBracket = BracketsUtils.findPrevBracketInToken(prevModeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
const searchStartOffset = Math.max(0, position.column - 1 - prevModeBrackets.maxBracketLength);
const searchEndOffset = Math.min(lineText.length, position.column - 1 + prevModeBrackets.maxBracketLength);
const foundBracket = BracketsUtils.findPrevBracketInRange(prevModeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
// check that we didn't hit a bracket too far away from position
if (foundBracket && foundBracket.startColumn <= position.column && position.column <= foundBracket.endColumn) {
let foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1);
foundBracketText = foundBracketText.toLowerCase();
let r = this._matchFoundBracket(foundBracket, prevModeBrackets.textIsBracket[foundBracketText], prevModeBrackets.textIsOpenBracket[foundBracketText]);
// check that we can actually match this bracket
const foundBracketText = lineText.substring(foundBracket.startColumn - 1, foundBracket.endColumn - 1).toLowerCase();
const r = this._matchFoundBracket(foundBracket, prevModeBrackets.textIsBracket[foundBracketText], prevModeBrackets.textIsOpenBracket[foundBracketText]);
if (r) {
return r;
}
@@ -2011,54 +2008,76 @@ export class TextModel extends Disposable implements model.ITextModel {
const reversedBracketRegex = bracket.reversedRegex;
let count = -1;
const searchPrevMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null => {
while (true) {
const r = BracketsUtils.findPrevBracketInRange(reversedBracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (!r) {
break;
}
const hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();
if (bracket.isOpen(hitText)) {
count++;
} else if (bracket.isClose(hitText)) {
count--;
}
if (count === 0) {
return r;
}
searchEndOffset = r.startColumn - 1;
}
return null;
};
for (let lineNumber = position.lineNumber; lineNumber >= 1; lineNumber--) {
const lineTokens = this._getLineTokens(lineNumber);
const tokenCount = lineTokens.getCount();
const lineText = this._buffer.getLineContent(lineNumber);
let tokenIndex = tokenCount - 1;
let searchStopOffset = -1;
let searchStartOffset = lineText.length;
let searchEndOffset = lineText.length;
if (lineNumber === position.lineNumber) {
tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
searchStopOffset = position.column - 1;
searchStartOffset = position.column - 1;
searchEndOffset = position.column - 1;
}
let prevSearchInToken = true;
for (; tokenIndex >= 0; tokenIndex--) {
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
const tokenType = lineTokens.getStandardTokenType(tokenIndex);
const tokenStartOffset = lineTokens.getStartOffset(tokenIndex);
const tokenEndOffset = lineTokens.getEndOffset(tokenIndex);
const searchInToken = (lineTokens.getLanguageId(tokenIndex) === languageId && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));
if (searchStopOffset === -1) {
searchStopOffset = tokenEndOffset;
}
if (tokenLanguageId === languageId && !ignoreBracketsInToken(tokenType)) {
while (true) {
let r = BracketsUtils.findPrevBracketInToken(reversedBracketRegex, lineNumber, lineText, tokenStartOffset, searchStopOffset);
if (!r) {
break;
}
let hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1);
hitText = hitText.toLowerCase();
if (hitText === bracket.open) {
count++;
} else if (hitText === bracket.close) {
count--;
}
if (count === 0) {
if (searchInToken) {
// this token should be searched
if (prevSearchInToken) {
// the previous token should be searched, simply extend searchStartOffset
searchStartOffset = lineTokens.getStartOffset(tokenIndex);
} else {
// the previous token should not be searched
searchStartOffset = lineTokens.getStartOffset(tokenIndex);
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
}
} else {
// this token should not be searched
if (prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = searchPrevMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return r;
}
searchStopOffset = r.startColumn - 1;
}
}
searchStopOffset = -1;
prevSearchInToken = searchInToken;
}
if (prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = searchPrevMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return r;
}
}
}
@@ -2072,53 +2091,77 @@ export class TextModel extends Disposable implements model.ITextModel {
const bracketRegex = bracket.forwardRegex;
let count = 1;
for (let lineNumber = position.lineNumber, lineCount = this.getLineCount(); lineNumber <= lineCount; lineNumber++) {
const searchNextMatchingBracketInRange = (lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): Range | null => {
while (true) {
const r = BracketsUtils.findNextBracketInRange(bracketRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (!r) {
break;
}
const hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();
if (bracket.isOpen(hitText)) {
count++;
} else if (bracket.isClose(hitText)) {
count--;
}
if (count === 0) {
return r;
}
searchStartOffset = r.endColumn - 1;
}
return null;
};
const lineCount = this.getLineCount();
for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {
const lineTokens = this._getLineTokens(lineNumber);
const tokenCount = lineTokens.getCount();
const lineText = this._buffer.getLineContent(lineNumber);
let tokenIndex = 0;
let searchStartOffset = 0;
let searchEndOffset = 0;
if (lineNumber === position.lineNumber) {
tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
searchStartOffset = position.column - 1;
searchEndOffset = position.column - 1;
}
let prevSearchInToken = true;
for (; tokenIndex < tokenCount; tokenIndex++) {
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
const tokenType = lineTokens.getStandardTokenType(tokenIndex);
const tokenStartOffset = lineTokens.getStartOffset(tokenIndex);
const tokenEndOffset = lineTokens.getEndOffset(tokenIndex);
const searchInToken = (lineTokens.getLanguageId(tokenIndex) === languageId && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));
if (searchStartOffset === 0) {
searchStartOffset = tokenStartOffset;
}
if (tokenLanguageId === languageId && !ignoreBracketsInToken(tokenType)) {
while (true) {
let r = BracketsUtils.findNextBracketInToken(bracketRegex, lineNumber, lineText, searchStartOffset, tokenEndOffset);
if (!r) {
break;
}
let hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1);
hitText = hitText.toLowerCase();
if (hitText === bracket.open) {
count++;
} else if (hitText === bracket.close) {
count--;
}
if (count === 0) {
if (searchInToken) {
// this token should be searched
if (prevSearchInToken) {
// the previous token should be searched, simply extend searchEndOffset
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
} else {
// the previous token should not be searched
searchStartOffset = lineTokens.getStartOffset(tokenIndex);
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
}
} else {
// this token should not be searched
if (prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = searchNextMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return r;
}
searchStartOffset = r.endColumn - 1;
}
}
searchStartOffset = 0;
prevSearchInToken = searchInToken;
}
if (prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = searchNextMatchingBracketInRange(lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return r;
}
}
}
@@ -2136,33 +2179,66 @@ export class TextModel extends Disposable implements model.ITextModel {
const lineText = this._buffer.getLineContent(lineNumber);
let tokenIndex = tokenCount - 1;
let searchStopOffset = -1;
let searchStartOffset = lineText.length;
let searchEndOffset = lineText.length;
if (lineNumber === position.lineNumber) {
tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
searchStopOffset = position.column - 1;
}
for (; tokenIndex >= 0; tokenIndex--) {
searchStartOffset = position.column - 1;
searchEndOffset = position.column - 1;
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
const tokenType = lineTokens.getStandardTokenType(tokenIndex);
const tokenStartOffset = lineTokens.getStartOffset(tokenIndex);
const tokenEndOffset = lineTokens.getEndOffset(tokenIndex);
if (searchStopOffset === -1) {
searchStopOffset = tokenEndOffset;
}
if (languageId !== tokenLanguageId) {
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
}
if (modeBrackets && !ignoreBracketsInToken(tokenType)) {
let r = BracketsUtils.findPrevBracketInToken(modeBrackets.reversedRegex, lineNumber, lineText, tokenStartOffset, searchStopOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
let prevSearchInToken = true;
for (; tokenIndex >= 0; tokenIndex--) {
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
if (languageId !== tokenLanguageId) {
// language id change!
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
prevSearchInToken = false;
}
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
}
const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));
if (searchInToken) {
// this token should be searched
if (prevSearchInToken) {
// the previous token should be searched, simply extend searchStartOffset
searchStartOffset = lineTokens.getStartOffset(tokenIndex);
} else {
// the previous token should not be searched
searchStartOffset = lineTokens.getStartOffset(tokenIndex);
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
}
} else {
// this token should not be searched
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
}
}
searchStopOffset = -1;
prevSearchInToken = searchInToken;
}
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = BracketsUtils.findPrevBracketInRange(modeBrackets.reversedRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
}
}
@@ -2171,43 +2247,187 @@ export class TextModel extends Disposable implements model.ITextModel {
public findNextBracket(_position: IPosition): model.IFoundBracket | null {
const position = this.validatePosition(_position);
const lineCount = this.getLineCount();
let languageId: LanguageId = -1;
let modeBrackets: RichEditBrackets | null = null;
for (let lineNumber = position.lineNumber, lineCount = this.getLineCount(); lineNumber <= lineCount; lineNumber++) {
for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {
const lineTokens = this._getLineTokens(lineNumber);
const tokenCount = lineTokens.getCount();
const lineText = this._buffer.getLineContent(lineNumber);
let tokenIndex = 0;
let searchStartOffset = 0;
let searchEndOffset = 0;
if (lineNumber === position.lineNumber) {
tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
searchStartOffset = position.column - 1;
}
for (; tokenIndex < tokenCount; tokenIndex++) {
searchEndOffset = position.column - 1;
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
const tokenType = lineTokens.getStandardTokenType(tokenIndex);
const tokenStartOffset = lineTokens.getStartOffset(tokenIndex);
const tokenEndOffset = lineTokens.getEndOffset(tokenIndex);
if (searchStartOffset === 0) {
searchStartOffset = tokenStartOffset;
}
if (languageId !== tokenLanguageId) {
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
}
if (modeBrackets && !ignoreBracketsInToken(tokenType)) {
let r = BracketsUtils.findNextBracketInToken(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, tokenEndOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
let prevSearchInToken = true;
for (; tokenIndex < tokenCount; tokenIndex++) {
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
if (languageId !== tokenLanguageId) {
// language id change!
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
prevSearchInToken = false;
}
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
}
const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));
if (searchInToken) {
// this token should be searched
if (prevSearchInToken) {
// the previous token should be searched, simply extend searchEndOffset
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
} else {
// the previous token should not be searched
searchStartOffset = lineTokens.getStartOffset(tokenIndex);
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
}
} else {
// this token should not be searched
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
}
}
searchStartOffset = 0;
prevSearchInToken = searchInToken;
}
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return this._toFoundBracket(modeBrackets, r);
}
}
}
return null;
}
public findEnclosingBrackets(_position: IPosition): [Range, Range] | null {
const position = this.validatePosition(_position);
const lineCount = this.getLineCount();
let counts: number[] = [];
const resetCounts = (modeBrackets: RichEditBrackets | null) => {
counts = [];
for (let i = 0, len = modeBrackets ? modeBrackets.brackets.length : 0; i < len; i++) {
counts[i] = 0;
}
};
const searchInRange = (modeBrackets: RichEditBrackets, lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): [Range, Range] | null => {
while (true) {
const r = BracketsUtils.findNextBracketInRange(modeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (!r) {
break;
}
const hitText = lineText.substring(r.startColumn - 1, r.endColumn - 1).toLowerCase();
const bracket = modeBrackets.textIsBracket[hitText];
if (bracket) {
if (bracket.isOpen(hitText)) {
counts[bracket.index]++;
} else if (bracket.isClose(hitText)) {
counts[bracket.index]--;
}
if (counts[bracket.index] === -1) {
return this._matchFoundBracket(r, bracket, false);
}
}
searchStartOffset = r.endColumn - 1;
}
return null;
};
let languageId: LanguageId = -1;
let modeBrackets: RichEditBrackets | null = null;
for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {
const lineTokens = this._getLineTokens(lineNumber);
const tokenCount = lineTokens.getCount();
const lineText = this._buffer.getLineContent(lineNumber);
let tokenIndex = 0;
let searchStartOffset = 0;
let searchEndOffset = 0;
if (lineNumber === position.lineNumber) {
tokenIndex = lineTokens.findTokenIndexAtOffset(position.column - 1);
searchStartOffset = position.column - 1;
searchEndOffset = position.column - 1;
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
if (languageId !== tokenLanguageId) {
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
resetCounts(modeBrackets);
}
}
let prevSearchInToken = true;
for (; tokenIndex < tokenCount; tokenIndex++) {
const tokenLanguageId = lineTokens.getLanguageId(tokenIndex);
if (languageId !== tokenLanguageId) {
// language id change!
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return r;
}
prevSearchInToken = false;
}
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
resetCounts(modeBrackets);
}
const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));
if (searchInToken) {
// this token should be searched
if (prevSearchInToken) {
// the previous token should be searched, simply extend searchEndOffset
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
} else {
// the previous token should not be searched
searchStartOffset = lineTokens.getStartOffset(tokenIndex);
searchEndOffset = lineTokens.getEndOffset(tokenIndex);
}
} else {
// this token should not be searched
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return r;
}
}
}
prevSearchInToken = searchInToken;
}
if (modeBrackets && prevSearchInToken && searchStartOffset !== searchEndOffset) {
const r = searchInRange(modeBrackets, lineNumber, lineText, searchStartOffset, searchEndOffset);
if (r) {
return r;
}
}
}