mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-13 06:20:23 -06:00
Merge pull request #9420 from Microsoft/formatting_loc
Do not scan nodes preceding formatted region, just skip over them
This commit is contained in:
commit
1102fa6bae
@ -7686,7 +7686,7 @@ const _super = (function (geti, seti) {
|
||||
}
|
||||
firstNonWhitespace = -1;
|
||||
}
|
||||
else if (!isWhiteSpace(c)) {
|
||||
else if (!isWhiteSpaceSingleLine(c)) {
|
||||
lastNonWhitespace = i;
|
||||
if (firstNonWhitespace === -1) {
|
||||
firstNonWhitespace = i;
|
||||
|
||||
@ -31,6 +31,7 @@ namespace ts {
|
||||
scanJsxToken(): SyntaxKind;
|
||||
scanJSDocToken(): SyntaxKind;
|
||||
scan(): SyntaxKind;
|
||||
getText(): string;
|
||||
// Sets the text for the scanner to scan. An optional subrange starting point and length
|
||||
// can be provided to have the scanner only scan a portion of the text.
|
||||
setText(text: string, start?: number, length?: number): void;
|
||||
@ -365,6 +366,11 @@ namespace ts {
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
export function isWhiteSpace(ch: number): boolean {
|
||||
return isWhiteSpaceSingleLine(ch) || isLineBreak(ch);
|
||||
}
|
||||
|
||||
/** Does not include line breaks. For that, see isWhiteSpaceLike. */
|
||||
export function isWhiteSpaceSingleLine(ch: number): boolean {
|
||||
// Note: nextLine is in the Zs space, and should be considered to be a whitespace.
|
||||
// It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript.
|
||||
return ch === CharacterCodes.space ||
|
||||
@ -505,7 +511,7 @@ namespace ts {
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) {
|
||||
if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch))) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
@ -658,7 +664,7 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) {
|
||||
if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch))) {
|
||||
if (result && result.length && isLineBreak(ch)) {
|
||||
lastOrUndefined(result).hasTrailingNewLine = true;
|
||||
}
|
||||
@ -763,6 +769,7 @@ namespace ts {
|
||||
scanJsxToken,
|
||||
scanJSDocToken,
|
||||
scan,
|
||||
getText,
|
||||
setText,
|
||||
setScriptTarget,
|
||||
setLanguageVariant,
|
||||
@ -1202,7 +1209,7 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
while (pos < end && isWhiteSpace(text.charCodeAt(pos))) {
|
||||
while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
return token = SyntaxKind.WhitespaceTrivia;
|
||||
@ -1520,7 +1527,7 @@ namespace ts {
|
||||
}
|
||||
return token = getIdentifierToken();
|
||||
}
|
||||
else if (isWhiteSpace(ch)) {
|
||||
else if (isWhiteSpaceSingleLine(ch)) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
@ -1689,7 +1696,7 @@ namespace ts {
|
||||
let ch = text.charCodeAt(pos);
|
||||
while (pos < end) {
|
||||
ch = text.charCodeAt(pos);
|
||||
if (isWhiteSpace(ch)) {
|
||||
if (isWhiteSpaceSingleLine(ch)) {
|
||||
pos++;
|
||||
}
|
||||
else {
|
||||
@ -1789,6 +1796,10 @@ namespace ts {
|
||||
return speculationHelper(callback, /*isLookahead*/ false);
|
||||
}
|
||||
|
||||
function getText(): string {
|
||||
return text;
|
||||
}
|
||||
|
||||
function setText(newText: string, start: number, length: number) {
|
||||
text = newText || "";
|
||||
end = length === undefined ? text.length : start + length;
|
||||
|
||||
@ -2605,7 +2605,7 @@ namespace ts {
|
||||
|
||||
function calculateIndent(text: string, pos: number, end: number) {
|
||||
let currentLineIndent = 0;
|
||||
for (; pos < end && isWhiteSpace(text.charCodeAt(pos)); pos++) {
|
||||
for (; pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos)); pos++) {
|
||||
if (text.charCodeAt(pos) === CharacterCodes.tab) {
|
||||
// Tabs = TabSize = indent size and go to next tabStop
|
||||
currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
|
||||
|
||||
@ -78,7 +78,7 @@ namespace ts.formatting {
|
||||
// 1. the end of the previous line
|
||||
// 2. the last non-whitespace character in the current line
|
||||
let endOfFormatSpan = getEndLinePosition(line, sourceFile);
|
||||
while (isWhiteSpace(sourceFile.text.charCodeAt(endOfFormatSpan)) && !isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) {
|
||||
while (isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) {
|
||||
endOfFormatSpan--;
|
||||
}
|
||||
// if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to
|
||||
@ -599,6 +599,9 @@ namespace ts.formatting {
|
||||
|
||||
// child node is outside the target range - do not dive inside
|
||||
if (!rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
|
||||
if (child.end < originalRange.pos) {
|
||||
formattingScanner.skipToEndOf(child);
|
||||
}
|
||||
return inheritedIndentation;
|
||||
}
|
||||
|
||||
@ -963,7 +966,7 @@ namespace ts.formatting {
|
||||
|
||||
const whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition);
|
||||
if (whitespaceStart !== -1) {
|
||||
Debug.assert(whitespaceStart === lineStartPosition || !isWhiteSpace(sourceFile.text.charCodeAt(whitespaceStart - 1)));
|
||||
Debug.assert(whitespaceStart === lineStartPosition || !isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1)));
|
||||
recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart);
|
||||
}
|
||||
}
|
||||
@ -975,7 +978,7 @@ namespace ts.formatting {
|
||||
*/
|
||||
function getTrailingWhitespaceStartPosition(start: number, end: number) {
|
||||
let pos = end;
|
||||
while (pos >= start && isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
|
||||
while (pos >= start && isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) {
|
||||
pos--;
|
||||
}
|
||||
if (pos !== end) {
|
||||
|
||||
@ -17,6 +17,7 @@ namespace ts.formatting {
|
||||
readTokenInfo(n: Node): TokenInfo;
|
||||
getCurrentLeadingTrivia(): TextRangeWithKind[];
|
||||
lastTrailingTriviaWasNewLine(): boolean;
|
||||
skipToEndOf(node: Node): void;
|
||||
close(): void;
|
||||
}
|
||||
|
||||
@ -36,12 +37,12 @@ namespace ts.formatting {
|
||||
scanner.setTextPos(startPos);
|
||||
|
||||
let wasNewLine = true;
|
||||
let leadingTrivia: TextRangeWithKind[];
|
||||
let trailingTrivia: TextRangeWithKind[];
|
||||
let leadingTrivia: TextRangeWithKind[] | undefined;
|
||||
let trailingTrivia: TextRangeWithKind[] | undefined;
|
||||
|
||||
let savedPos: number;
|
||||
let lastScanAction: ScanAction;
|
||||
let lastTokenInfo: TokenInfo;
|
||||
let lastScanAction: ScanAction | undefined;
|
||||
let lastTokenInfo: TokenInfo | undefined;
|
||||
|
||||
return {
|
||||
advance,
|
||||
@ -49,6 +50,7 @@ namespace ts.formatting {
|
||||
isOnToken,
|
||||
getCurrentLeadingTrivia: () => leadingTrivia,
|
||||
lastTrailingTriviaWasNewLine: () => wasNewLine,
|
||||
skipToEndOf,
|
||||
close: () => {
|
||||
Debug.assert(scanner !== undefined);
|
||||
|
||||
@ -278,5 +280,15 @@ namespace ts.formatting {
|
||||
}
|
||||
return tokenInfo;
|
||||
}
|
||||
|
||||
function skipToEndOf(node: Node): void {
|
||||
scanner.setTextPos(node.end);
|
||||
savedPos = scanner.getStartPos();
|
||||
lastScanAction = undefined;
|
||||
lastTokenInfo = undefined;
|
||||
wasNewLine = false;
|
||||
leadingTrivia = undefined;
|
||||
trailingTrivia = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,7 +42,7 @@ namespace ts.formatting {
|
||||
let current = position;
|
||||
while (current > 0) {
|
||||
const char = sourceFile.text.charCodeAt(current);
|
||||
if (!isWhiteSpace(char) && !isLineBreak(char)) {
|
||||
if (!isWhiteSpace(char)) {
|
||||
break;
|
||||
}
|
||||
current--;
|
||||
@ -406,7 +406,7 @@ namespace ts.formatting {
|
||||
let column = 0;
|
||||
for (let pos = startPos; pos < endPos; pos++) {
|
||||
const ch = sourceFile.text.charCodeAt(pos);
|
||||
if (!isWhiteSpace(ch)) {
|
||||
if (!isWhiteSpaceSingleLine(ch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -474,8 +474,7 @@ namespace ts {
|
||||
|
||||
for (; pos < end; pos++) {
|
||||
const ch = sourceFile.text.charCodeAt(pos);
|
||||
if (!isWhiteSpace(ch) || isLineBreak(ch)) {
|
||||
// Either found lineBreak or non whiteSpace
|
||||
if (!isWhiteSpaceSingleLine(ch)) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
@ -494,8 +493,7 @@ namespace ts {
|
||||
function isName(pos: number, end: number, sourceFile: SourceFile, name: string) {
|
||||
return pos + name.length < end &&
|
||||
sourceFile.text.substr(pos, name.length) === name &&
|
||||
(isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)) ||
|
||||
isLineBreak(sourceFile.text.charCodeAt(pos + name.length)));
|
||||
isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length));
|
||||
}
|
||||
|
||||
function isParamTag(pos: number, end: number, sourceFile: SourceFile) {
|
||||
@ -690,7 +688,7 @@ namespace ts {
|
||||
return paramDocComments;
|
||||
|
||||
function consumeWhiteSpaces(pos: number) {
|
||||
while (pos < end && isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
|
||||
while (pos < end && isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
@ -5727,7 +5725,7 @@ namespace ts {
|
||||
|
||||
// Avoid recalculating getStart() by iterating backwards.
|
||||
for (let j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
|
||||
if (!isWhiteSpace(sourceFile.text.charCodeAt(j))) {
|
||||
if (!isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) {
|
||||
shouldCombindElseAndIf = false;
|
||||
break;
|
||||
}
|
||||
|
||||
9
tests/cases/fourslash/formattingTemplatesWithNewline.ts
Normal file
9
tests/cases/fourslash/formattingTemplatesWithNewline.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////`${1}`;
|
||||
////`
|
||||
////`;/**/1
|
||||
|
||||
goTo.marker();
|
||||
edit.insert('\n');
|
||||
verify.currentLineContentIs("1");
|
||||
Loading…
x
Reference in New Issue
Block a user