Skip to content

Commit 4ad2160

Browse files
author
Zhengbo Li
committed
Merge pull request microsoft#4994 from zhengbli/i4959
Avoid deleting trailing white spaces in templates
2 parents bedeab7 + 16762a4 commit 4ad2160

6 files changed

Lines changed: 77 additions & 35 deletions

File tree

src/services/formatting/formatting.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ namespace ts.formatting {
325325

326326
let lastIndentedLine: number;
327327
let indentationOnLastIndentedLine: number;
328-
328+
329329
let edits: TextChange[] = [];
330330

331331
formattingScanner.advance();
@@ -354,12 +354,12 @@ namespace ts.formatting {
354354
* If list element is in the range - its indentation will be equal
355355
* to inherited indentation from its predecessors.
356356
*/
357-
function tryComputeIndentationForListItem(startPos: number,
358-
endPos: number,
359-
parentStartLine: number,
360-
range: TextRange,
357+
function tryComputeIndentationForListItem(startPos: number,
358+
endPos: number,
359+
parentStartLine: number,
360+
range: TextRange,
361361
inheritedIndentation: number): number {
362-
362+
363363
if (rangeOverlapsWithStartEnd(range, startPos, endPos)) {
364364
if (inheritedIndentation !== Constants.Unknown) {
365365
return inheritedIndentation;
@@ -376,7 +376,7 @@ namespace ts.formatting {
376376

377377
return Constants.Unknown;
378378
}
379-
379+
380380
function computeIndentation(
381381
node: TextRangeWithKind,
382382
startLine: number,
@@ -419,8 +419,8 @@ namespace ts.formatting {
419419
// if node is located on the same line with the parent
420420
// - inherit indentation from the parent
421421
// - push children if either parent of node itself has non-zero delta
422-
indentation = startLine === lastIndentedLine
423-
? indentationOnLastIndentedLine
422+
indentation = startLine === lastIndentedLine
423+
? indentationOnLastIndentedLine
424424
: parentDynamicIndentation.getIndentation();
425425
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
426426
}
@@ -586,7 +586,7 @@ namespace ts.formatting {
586586
if (!rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
587587
return inheritedIndentation;
588588
}
589-
589+
590590
if (child.getFullWidth() === 0) {
591591
return inheritedIndentation;
592592
}
@@ -624,8 +624,8 @@ namespace ts.formatting {
624624
return inheritedIndentation;
625625
}
626626

627-
function processChildNodes(nodes: NodeArray<Node>,
628-
parent: Node,
627+
function processChildNodes(nodes: NodeArray<Node>,
628+
parent: Node,
629629
parentStartLine: number,
630630
parentDynamicIndentation: DynamicIndentation): void {
631631

@@ -751,7 +751,7 @@ namespace ts.formatting {
751751
// indent token only if is it is in target range and does not overlap with any error ranges
752752
if (tokenIndentation !== Constants.Unknown) {
753753
insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
754-
754+
755755
lastIndentedLine = tokenStart.line;
756756
indentationOnLastIndentedLine = tokenIndentation;
757757
}
@@ -772,12 +772,12 @@ namespace ts.formatting {
772772
}
773773
}
774774

775-
function processRange(range: TextRangeWithKind,
776-
rangeStart: LineAndCharacter,
777-
parent: Node,
778-
contextNode: Node,
775+
function processRange(range: TextRangeWithKind,
776+
rangeStart: LineAndCharacter,
777+
parent: Node,
778+
contextNode: Node,
779779
dynamicIndentation: DynamicIndentation): boolean {
780-
780+
781781
let rangeHasError = rangeContainsError(range);
782782
let lineAdded: boolean;
783783
if (!rangeHasError && !previousRangeHasError) {
@@ -787,7 +787,7 @@ namespace ts.formatting {
787787
trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
788788
}
789789
else {
790-
lineAdded =
790+
lineAdded =
791791
processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation)
792792
}
793793
}
@@ -933,8 +933,8 @@ namespace ts.formatting {
933933
let lineStartPosition = getStartPositionOfLine(line, sourceFile);
934934
let lineEndPosition = getEndLinePosition(line, sourceFile);
935935

936-
// do not trim whitespaces in comments
937-
if (range && isComment(range.kind) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
936+
// do not trim whitespaces in comments or template expression
937+
if (range && (isComment(range.kind) || isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
938938
continue;
939939
}
940940

src/services/formatting/smartIndenter.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,7 @@ namespace ts.formatting {
1919
}
2020

2121
// no indentation in string \regex\template literals
22-
let precedingTokenIsLiteral =
23-
precedingToken.kind === SyntaxKind.StringLiteral ||
24-
precedingToken.kind === SyntaxKind.RegularExpressionLiteral ||
25-
precedingToken.kind === SyntaxKind.NoSubstitutionTemplateLiteral ||
26-
precedingToken.kind === SyntaxKind.TemplateHead ||
27-
precedingToken.kind === SyntaxKind.TemplateMiddle ||
28-
precedingToken.kind === SyntaxKind.TemplateTail;
22+
let precedingTokenIsLiteral = isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind);
2923
if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) {
3024
return 0;
3125
}

src/services/utilities.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace ts {
99
export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
1010
Debug.assert(line >= 0);
1111
let lineStarts = sourceFile.getLineStarts();
12-
12+
1313
let lineIndex = line;
1414
if (lineIndex + 1 === lineStarts.length) {
1515
// last line - return EOF
@@ -171,7 +171,7 @@ namespace ts {
171171
case SyntaxKind.VoidExpression:
172172
case SyntaxKind.YieldExpression:
173173
case SyntaxKind.SpreadElementExpression:
174-
let unaryWordExpression = (<TypeOfExpression|DeleteExpression|VoidExpression|YieldExpression|SpreadElementExpression>n);
174+
let unaryWordExpression = (<TypeOfExpression | DeleteExpression | VoidExpression | YieldExpression | SpreadElementExpression>n);
175175
return isCompletedNode(unaryWordExpression.expression, sourceFile);
176176

177177
case SyntaxKind.TaggedTemplateExpression:
@@ -253,7 +253,7 @@ namespace ts {
253253
});
254254

255255
// Either we didn't find an appropriate list, or the list must contain us.
256-
Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node));
256+
Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node));
257257
return syntaxList;
258258
}
259259

@@ -389,7 +389,7 @@ namespace ts {
389389
// if this is the case - then we should assume that token in question is located in previous child.
390390
if (position < child.end && (nodeHasTokens(child) || child.kind === SyntaxKind.JsxText)) {
391391
const start = child.getStart(sourceFile);
392-
const lookInPreviousChild =
392+
const lookInPreviousChild =
393393
(start >= position) || // cursor in the leading trivia
394394
(child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText
395395

@@ -426,7 +426,7 @@ namespace ts {
426426
}
427427
}
428428
}
429-
429+
430430
export function isInString(sourceFile: SourceFile, position: number) {
431431
let token = getTokenAtPosition(sourceFile, position);
432432
return token && token.kind === SyntaxKind.StringLiteral && position > token.getStart();
@@ -474,7 +474,7 @@ namespace ts {
474474
let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos);
475475

476476
return forEach(commentRanges, jsDocPrefix);
477-
477+
478478
function jsDocPrefix(c: CommentRange): boolean {
479479
var text = sourceFile.text;
480480
return text.length >= c.pos + 3 && text[c.pos] === '/' && text[c.pos + 1] === '*' && text[c.pos + 2] === '*';
@@ -563,6 +563,15 @@ namespace ts {
563563
return kind === SyntaxKind.SingleLineCommentTrivia || kind === SyntaxKind.MultiLineCommentTrivia;
564564
}
565565

566+
export function isStringOrRegularExpressionOrTemplateLiteral(kind: SyntaxKind): boolean {
567+
if (kind === SyntaxKind.StringLiteral
568+
|| kind === SyntaxKind.RegularExpressionLiteral
569+
|| isTemplateLiteralKind(kind)) {
570+
return true;
571+
}
572+
return false;
573+
}
574+
566575
export function isPunctuation(kind: SyntaxKind): boolean {
567576
return SyntaxKind.FirstPunctuation <= kind && kind <= SyntaxKind.LastPunctuation;
568577
}
@@ -690,7 +699,7 @@ namespace ts {
690699
}
691700

692701
export function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart {
693-
return <SymbolDisplayPart> {
702+
return <SymbolDisplayPart>{
694703
text: text,
695704
kind: SymbolDisplayPartKind[kind]
696705
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////let noSubTemplate = `/* /*1*/`;
4+
////let templateHead = `/* /*2*/${1 + 2}`;
5+
////let templateMiddle = `/* ${1 + 2 /*3*/}`;
6+
////let templateTail = `/* ${1 + 2} /*4*/`;
7+
8+
goTo.marker('1');
9+
edit.insert("\n");
10+
11+
goTo.marker('2');
12+
edit.insert("\n");
13+
14+
goTo.marker('3');
15+
edit.insert("\n");
16+
17+
goTo.marker('4');
18+
edit.insert("\n");
19+
20+
21+
verify.currentFileContentIs("let noSubTemplate = `/* \n`;\nlet templateHead = `/* \n${1 + 2}`;\nlet templateMiddle = `/* ${1 + 2\n }`;\nlet templateTail = `/* ${1 + 2} \n`;");
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////let t = "foo \
4+
////bar \
5+
////"/*1*/
6+
7+
goTo.marker('1');
8+
edit.insert(";");
9+
10+
verify.currentFileContentIs("let t = \"foo \\\nbar \\ \n\";");
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////var re = /\w+ /*1*//;
4+
5+
goTo.marker('1');
6+
edit.insert("\n");
7+
8+
verify.currentFileContentIs("var re = /\\w+ \n /;");

0 commit comments

Comments
 (0)