Skip to content

Commit 6225a5a

Browse files
committed
Addesses a number of comment/sourcemap related issues
1 parent d2a7288 commit 6225a5a

7 files changed

Lines changed: 211 additions & 61 deletions

File tree

src/compiler/comments.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ namespace ts {
1313
getTrailingCommentsOfPosition(pos: number): CommentRange[];
1414
emitLeadingComments(range: TextRange, comments: CommentRange[]): void;
1515
emitTrailingComments(range: TextRange, comments: CommentRange[]): void;
16-
emitDetachedComments(range: TextRange): void;
16+
emitLeadingDetachedComments(range: TextRange): void;
17+
emitLeadingDetachedComments(range: TextRange, contextNode: Node, shouldSkipCommentsForNodeCallback: (node: Node) => boolean): void;
18+
emitTrailingDetachedComments(range: TextRange): void;
19+
emitTrailingDetachedComments(range: TextRange, contextNode: Node, shouldSkipCommentsForNodeCallback: (node: Node) => boolean): void;
1720
}
1821

1922
export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter {
@@ -46,10 +49,15 @@ namespace ts {
4649
getTrailingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
4750
emitLeadingComments(range: TextRange, comments: CommentRange[]): void { },
4851
emitTrailingComments(range: TextRange, comments: CommentRange[]): void { },
49-
emitDetachedComments,
52+
emitLeadingDetachedComments,
53+
emitTrailingDetachedComments(node: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void {}
5054
};
5155

52-
function emitDetachedComments(node: TextRange): void {
56+
function emitLeadingDetachedComments(node: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void {
57+
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(contextNode)) {
58+
return;
59+
}
60+
5361
emitDetachedCommentsAndUpdateCommentsInfo(node, /*removeComments*/ true);
5462
}
5563
}
@@ -65,7 +73,8 @@ namespace ts {
6573
getTrailingCommentsOfPosition,
6674
emitLeadingComments,
6775
emitTrailingComments,
68-
emitDetachedComments,
76+
emitLeadingDetachedComments,
77+
emitTrailingDetachedComments
6978
};
7079

7180
function getLeadingComments(range: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): CommentRange[];
@@ -154,10 +163,23 @@ namespace ts {
154163
emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
155164
}
156165

157-
function emitDetachedComments(range: TextRange) {
166+
function emitLeadingDetachedComments(range: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void {
167+
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(contextNode)) {
168+
return;
169+
}
170+
158171
emitDetachedCommentsAndUpdateCommentsInfo(range, /*removeComments*/ false);
159172
}
160173

174+
function emitTrailingDetachedComments(range: TextRange, contextNode?: Node, shouldSkipCommentsForNodeCallback?: (node: Node) => boolean): void {
175+
if (shouldSkipCommentsForNodeCallback && shouldSkipCommentsForNodeCallback(contextNode)) {
176+
return;
177+
}
178+
179+
range = collapseRangeToEnd(range);
180+
emitLeadingComments(range, getLeadingComments(range));
181+
}
182+
161183
function hasConsumedCommentRange(comment: CommentRange) {
162184
return comment.end === consumedCommentRanges[comment.pos];
163185
}

src/compiler/factory.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -651,13 +651,14 @@ namespace ts {
651651

652652
/**
653653
* Creates a synthetic expression to act as a placeholder for a not-emitted expression in
654-
* order to preserve comments.
654+
* order to preserve comments or sourcemap positions.
655655
*
656656
* @param expression The inner expression to emit.
657657
* @param original The original outer expression.
658+
* @param location The location for the expression. Defaults to the positions from "original" if provided.
658659
*/
659-
export function createPartiallyEmittedExpression(expression: Expression, original: Node) {
660-
const node = <PartiallyEmittedExpression>createNode(SyntaxKind.PartiallyEmittedExpression, /*location*/ original);
660+
export function createPartiallyEmittedExpression(expression: Expression, original?: Node, location?: TextRange) {
661+
const node = <PartiallyEmittedExpression>createNode(SyntaxKind.PartiallyEmittedExpression, /*location*/ location || original);
661662
node.expression = expression;
662663
node.original = original;
663664
return node;
@@ -1257,7 +1258,7 @@ namespace ts {
12571258
* The function needs to be called during each transformation step.
12581259
* This function needs to be called whenever we transform the statement
12591260
* list of a source file, namespace, or function-like body.
1260-
*
1261+
*
12611262
* @param target: result statements array
12621263
* @param source: origin statements array
12631264
* @param ensureUseStrict: boolean determining whether the function need to add prologue-directives

src/compiler/printer.ts

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ const _super = (function (geti, seti) {
140140
getTrailingCommentsOfPosition,
141141
emitLeadingComments,
142142
emitTrailingComments,
143-
emitDetachedComments
143+
emitLeadingDetachedComments,
144+
emitTrailingDetachedComments
144145
} = comments;
145146

146147
let context: TransformationContext;
@@ -298,24 +299,45 @@ const _super = (function (geti, seti) {
298299
const leadingComments = getLeadingComments(node, shouldSkipCommentsForNode);
299300
const trailingComments = getTrailingComments(node, shouldSkipCommentsForNode);
300301
emitLeadingComments(node, leadingComments);
301-
emitStart(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
302+
emitStart(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren);
302303
emitWorker(node);
303-
emitEnd(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
304+
emitEnd(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren);
304305
emitTrailingComments(node, trailingComments);
305306
}
306307
}
307308

309+
/**
310+
* Determines whether to skip comment emit for a node.
311+
*
312+
* We do not emit comments for NotEmittedStatement nodes or any node that has
313+
* NodeEmitFlags.NoComments.
314+
*
315+
* @param node A Node.
316+
*/
308317
function shouldSkipCommentsForNode(node: Node) {
309318
return isNotEmittedStatement(node)
310319
|| (getNodeEmitFlags(node) & NodeEmitFlags.NoComments) !== 0;
311320
}
312321

313-
function shouldIgnoreSourceMapForNode(node: Node) {
314-
return isNotEmittedOrPartiallyEmittedNode(node)
322+
/**
323+
* Determines whether to skip source map emit for a node.
324+
*
325+
* We do not emit source maps for NotEmittedStatement nodes or any node that
326+
* has NodeEmitFlags.NoSourceMap.
327+
*
328+
* @param node A Node.
329+
*/
330+
function shouldSkipSourceMapForNode(node: Node) {
331+
return isNotEmittedStatement(node)
315332
|| (getNodeEmitFlags(node) & NodeEmitFlags.NoSourceMap) !== 0;
316333
}
317334

318-
function shouldIgnoreSourceMapForChildren(node: Node) {
335+
/**
336+
* Determines whether to skip source map emit for a node and its children.
337+
*
338+
* We do not emit source maps for a node that has NodeEmitFlags.NoNestedSourceMaps.
339+
*/
340+
function shouldSkipSourceMapForChildren(node: Node) {
319341
return (getNodeEmitFlags(node) & NodeEmitFlags.NoNestedSourceMaps) !== 0;
320342
}
321343

@@ -1064,7 +1086,6 @@ const _super = (function (geti, seti) {
10641086
emitDecorators(node, node.decorators);
10651087
emitModifiers(node, node.modifiers);
10661088
emitSignatureAndBody(node, emitArrowFunctionHead);
1067-
10681089
}
10691090

10701091
function emitArrowFunctionHead(node: ArrowFunction) {
@@ -1375,7 +1396,8 @@ const _super = (function (geti, seti) {
13751396
}
13761397

13771398
function emitDebuggerStatement(node: DebuggerStatement) {
1378-
write("debugger;");
1399+
writeToken(SyntaxKind.DebuggerKeyword, node.pos);
1400+
write(";");
13791401
}
13801402

13811403
//
@@ -1417,9 +1439,7 @@ const _super = (function (geti, seti) {
14171439
tempFlags = 0;
14181440
startLexicalEnvironment();
14191441
emitSignatureHead(node);
1420-
write(" {");
1421-
emitBlockFunctionBody(node, body);
1422-
writeToken(SyntaxKind.CloseBraceToken, node.end)
1442+
emitBlockFunctionBodyAndEndLexicalEnvironment(node, body);
14231443
if (indentedFlag) {
14241444
decreaseIndent();
14251445
}
@@ -1483,10 +1503,12 @@ const _super = (function (geti, seti) {
14831503
return true;
14841504
}
14851505

1486-
function emitBlockFunctionBody(parentNode: Node, body: Block) {
1506+
function emitBlockFunctionBodyAndEndLexicalEnvironment(parentNode: Node, body: Block) {
1507+
write(" {");
1508+
14871509
const startingLine = writer.getLine();
14881510
increaseIndent();
1489-
emitDetachedComments(body.statements);
1511+
emitLeadingDetachedComments(body.statements, body, shouldSkipCommentsForNode);
14901512

14911513
// Emit all the prologue directives (like "use strict").
14921514
const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true);
@@ -1503,10 +1525,9 @@ const _super = (function (geti, seti) {
15031525

15041526
const endingLine = writer.getLine();
15051527
emitLexicalEnvironment(endLexicalEnvironment(), /*newLine*/ startingLine !== endingLine);
1506-
1507-
const range = collapseRangeToEnd(body.statements);
1508-
emitLeadingComments(range, getLeadingComments(range));
1528+
emitTrailingDetachedComments(body.statements, body, shouldSkipCommentsForNode);
15091529
decreaseIndent();
1530+
writeToken(SyntaxKind.CloseBraceToken, body.statements.end);
15101531
}
15111532

15121533
function emitClassDeclaration(node: ClassDeclaration) {
@@ -1882,7 +1903,7 @@ const _super = (function (geti, seti) {
18821903
function emitSourceFile(node: SourceFile) {
18831904
writeLine();
18841905
emitShebang();
1885-
emitDetachedComments(node);
1906+
emitLeadingDetachedComments(node);
18861907

18871908
const statements = node.statements;
18881909
const statementOffset = emitPrologueDirectives(statements);
@@ -1900,7 +1921,7 @@ const _super = (function (geti, seti) {
19001921
tempFlags = savedTempFlags;
19011922
}
19021923

1903-
emitLeadingComments(node.endOfFileToken, getLeadingComments(node.endOfFileToken));
1924+
emitTrailingDetachedComments(node.statements);
19041925
}
19051926

19061927
// Transformation nodes
@@ -2281,6 +2302,7 @@ const _super = (function (geti, seti) {
22812302
}
22822303

22832304
function writeToken(token: SyntaxKind, tokenStartPos: number) {
2305+
tokenStartPos = skipTrivia(currentText, tokenStartPos);
22842306
emitPos(tokenStartPos);
22852307
const tokenEndPos = writeTokenText(token, tokenStartPos);
22862308
emitPos(tokenEndPos);
@@ -2295,9 +2317,9 @@ const _super = (function (geti, seti) {
22952317

22962318
function writeTokenNode(node: Node) {
22972319
if (node) {
2298-
emitStart(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
2320+
emitStart(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren);
22992321
writeTokenText(node.kind);
2300-
emitEnd(node, shouldIgnoreSourceMapForNode, shouldIgnoreSourceMapForChildren);
2322+
emitEnd(node, shouldSkipSourceMapForNode, shouldSkipSourceMapForChildren);
23012323
}
23022324
}
23032325

0 commit comments

Comments
 (0)