diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b978c3dbc4e..d7c00dbcc14 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -483,7 +483,8 @@ namespace ts { return node.pos; } - if (isJSDocNode(node)) { + if (isJSDocNode(node) || node.kind === SyntaxKind.JsxText) { + // JsxText cannot actually contain comments, even though the scanner will think it sees comments return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 7907a18e7bf..424dd2e8957 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -720,6 +720,9 @@ namespace ts.formatting { // proceed any parent tokens that are located prior to child.getStart() const tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end > childStartPos) { + if (tokenInfo.token.pos > childStartPos) { + formattingScanner.skipToStartOf(child); + } // stop when formatting scanner advances past the beginning of the child break; } @@ -731,13 +734,15 @@ namespace ts.formatting { return inheritedIndentation; } - // JSX text shouldn't affect indenting - if (isToken(child) && child.kind !== SyntaxKind.JsxText) { + if (isToken(child)) { // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules const tokenInfo = formattingScanner.readTokenInfo(child); - Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); - consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); - return inheritedIndentation; + // JSX text shouldn't affect indenting + if (child.kind !== SyntaxKind.JsxText) { + Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); + consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); + return inheritedIndentation; + } } const effectiveParentStartLine = child.kind === SyntaxKind.Decorator ? childStartLine : undecoratedParentStartLine; diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index 64e257f4a08..5a6013c4e75 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -12,6 +12,7 @@ namespace ts.formatting { getCurrentLeadingTrivia(): TextRangeWithKind[] | undefined; lastTrailingTriviaWasNewLine(): boolean; skipToEndOf(node: Node): void; + skipToStartOf(node: Node): void; } const enum ScanAction { @@ -47,6 +48,7 @@ namespace ts.formatting { getCurrentLeadingTrivia: () => leadingTrivia, lastTrailingTriviaWasNewLine: () => wasNewLine, skipToEndOf, + skipToStartOf, }); lastTokenInfo = undefined; @@ -298,5 +300,15 @@ namespace ts.formatting { leadingTrivia = undefined; trailingTrivia = undefined; } + + function skipToStartOf(node: Node): void { + scanner.setTextPos(node.pos); + savedPos = scanner.getStartPos(); + lastScanAction = undefined; + lastTokenInfo = undefined; + wasNewLine = false; + leadingTrivia = undefined; + trailingTrivia = undefined; + } } } diff --git a/tests/cases/fourslash/formatTSXWithInlineComment.ts b/tests/cases/fourslash/formatTSXWithInlineComment.ts new file mode 100644 index 00000000000..426e795e4a4 --- /dev/null +++ b/tests/cases/fourslash/formatTSXWithInlineComment.ts @@ -0,0 +1,10 @@ +/// +// @Filename: foo.tsx +////const a =
+//// // +////
+ +format.document(); +verify.currentFileContentIs(`const a =
+ // +
`);