Skip to content

Commit d2ea675

Browse files
Merge pull request microsoft#2406 from Microsoft/pinnedComments
Simplify code for emitting comments.
2 parents 17f3e14 + 63e4420 commit d2ea675

File tree

6 files changed

+122
-91
lines changed

6 files changed

+122
-91
lines changed

src/compiler/emitter.ts

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,25 +1594,12 @@ module ts {
15941594
/** write emitted output to disk*/
15951595
let writeEmittedFiles = writeJavaScriptFile;
15961596

1597-
/** Emit leading comments of the node */
1598-
let emitLeadingComments = compilerOptions.removeComments ? (node: Node) => { } : emitLeadingDeclarationComments;
1599-
1600-
/** Emit Trailing comments of the node */
1601-
let emitTrailingComments = compilerOptions.removeComments ? (node: Node) => { } : emitTrailingDeclarationComments;
1602-
1603-
let emitLeadingCommentsOfPosition = compilerOptions.removeComments ? (pos: number) => { } : emitLeadingCommentsOfLocalPosition;
1604-
16051597
let detachedCommentsInfo: { nodePos: number; detachedCommentEndPos: number }[];
16061598

1607-
/** Emit detached comments of the node */
1608-
let emitDetachedComments = compilerOptions.removeComments ? (node: TextRange) => { } : emitDetachedCommentsAtPosition;
1609-
16101599
let writeComment = writeCommentRange;
16111600

16121601
/** Emit a node */
1613-
let emitNodeWithoutSourceMap = compilerOptions.removeComments ? emitNodeWithoutSourceMapWithoutComments : emitNodeWithoutSourceMapWithComments;
16141602
let emit = emitNodeWithoutSourceMap;
1615-
let emitWithoutComments = emitNodeWithoutSourceMapWithoutComments;
16161603

16171604
/** Called just before starting emit of a node */
16181605
let emitStart = function (node: Node) { };
@@ -2091,17 +2078,8 @@ module ts {
20912078
}
20922079
}
20932080

2094-
function emitNodeWithSourceMapWithoutComments(node: Node) {
2095-
if (node) {
2096-
recordEmitNodeStartSpan(node);
2097-
emitNodeWithoutSourceMapWithoutComments(node);
2098-
recordEmitNodeEndSpan(node);
2099-
}
2100-
}
2101-
21022081
writeEmittedFiles = writeJavaScriptAndSourceMapFile;
21032082
emit = emitNodeWithSourceMap;
2104-
emitWithoutComments = emitNodeWithSourceMapWithoutComments;
21052083
emitStart = recordEmitNodeStartSpan;
21062084
emitEnd = recordEmitNodeEndSpan;
21072085
emitToken = writeTextWithSpanRecord;
@@ -4365,7 +4343,7 @@ module ts {
43654343

43664344
function emitFunctionDeclaration(node: FunctionLikeDeclaration) {
43674345
if (nodeIsMissing(node.body)) {
4368-
return emitPinnedOrTripleSlashComments(node);
4346+
return emitOnlyPinnedOrTripleSlashComments(node);
43694347
}
43704348

43714349
if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
@@ -4521,10 +4499,7 @@ module ts {
45214499
write(" ");
45224500
emitStart(body);
45234501
write("return ");
4524-
4525-
// Don't emit comments on this body. We'll have already taken care of it above
4526-
// when we called emitDetachedComments.
4527-
emitWithoutComments(body);
4502+
emit(body);
45284503
emitEnd(body);
45294504
write(";");
45304505
emitTempDeclarations(/*newLine*/ false);
@@ -4535,10 +4510,7 @@ module ts {
45354510
writeLine();
45364511
emitLeadingComments(node.body);
45374512
write("return ");
4538-
4539-
// Don't emit comments on this body. We'll have already taken care of it above
4540-
// when we called emitDetachedComments.
4541-
emitWithoutComments(node.body);
4513+
emit(body);
45424514
write(";");
45434515
emitTrailingComments(node.body);
45444516

@@ -4670,7 +4642,7 @@ module ts {
46704642
forEach(node.members, member => {
46714643
if (member.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) {
46724644
if (!(<MethodDeclaration>member).body) {
4673-
return emitPinnedOrTripleSlashComments(member);
4645+
return emitOnlyPinnedOrTripleSlashComments(member);
46744646
}
46754647

46764648
writeLine();
@@ -4745,7 +4717,7 @@ module ts {
47454717
function emitMemberFunctionsForES6AndHigher(node: ClassDeclaration) {
47464718
for (let member of node.members) {
47474719
if ((member.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && !(<MethodDeclaration>member).body) {
4748-
emitPinnedOrTripleSlashComments(member);
4720+
emitOnlyPinnedOrTripleSlashComments(member);
47494721
}
47504722
else if (member.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) {
47514723
writeLine();
@@ -4786,7 +4758,7 @@ module ts {
47864758
// Emit the constructor overload pinned comments
47874759
forEach(node.members, member => {
47884760
if (member.kind === SyntaxKind.Constructor && !(<ConstructorDeclaration>member).body) {
4789-
emitPinnedOrTripleSlashComments(member);
4761+
emitOnlyPinnedOrTripleSlashComments(member);
47904762
}
47914763
// Check if there is any non-static property assignment
47924764
if (member.kind === SyntaxKind.PropertyDeclaration && (<PropertyDeclaration>member).initializer && (member.flags & NodeFlags.Static) === 0) {
@@ -5001,7 +4973,7 @@ module ts {
50014973
}
50024974

50034975
function emitInterfaceDeclaration(node: InterfaceDeclaration) {
5004-
emitPinnedOrTripleSlashComments(node);
4976+
emitOnlyPinnedOrTripleSlashComments(node);
50054977
}
50064978

50074979
function shouldEmitEnumDeclaration(node: EnumDeclaration) {
@@ -5109,7 +5081,7 @@ module ts {
51095081
let shouldEmit = shouldEmitModuleDeclaration(node);
51105082

51115083
if (!shouldEmit) {
5112-
return emitPinnedOrTripleSlashComments(node);
5084+
return emitOnlyPinnedOrTripleSlashComments(node);
51135085
}
51145086

51155087
emitStart(node);
@@ -5703,13 +5675,13 @@ module ts {
57035675
emitLeadingComments(node.endOfFileToken);
57045676
}
57055677

5706-
function emitNodeWithoutSourceMapWithComments(node: Node, allowGeneratedIdentifiers?: boolean): void {
5678+
function emitNodeWithoutSourceMap(node: Node, allowGeneratedIdentifiers?: boolean): void {
57075679
if (!node) {
57085680
return;
57095681
}
57105682

57115683
if (node.flags & NodeFlags.Ambient) {
5712-
return emitPinnedOrTripleSlashComments(node);
5684+
return emitOnlyPinnedOrTripleSlashComments(node);
57135685
}
57145686

57155687
let emitComments = shouldEmitLeadingAndTrailingComments(node);
@@ -5724,18 +5696,6 @@ module ts {
57245696
}
57255697
}
57265698

5727-
function emitNodeWithoutSourceMapWithoutComments(node: Node, allowGeneratedIdentifiers?: boolean): void {
5728-
if (!node) {
5729-
return;
5730-
}
5731-
5732-
if (node.flags & NodeFlags.Ambient) {
5733-
return emitPinnedOrTripleSlashComments(node);
5734-
}
5735-
5736-
emitJavaScriptWorker(node, allowGeneratedIdentifiers);
5737-
}
5738-
57395699
function shouldEmitLeadingAndTrailingComments(node: Node) {
57405700
switch (node.kind) {
57415701
// All of these entities are emitted in a specialized fashion. As such, we allow
@@ -5759,6 +5719,19 @@ module ts {
57595719
return shouldEmitEnumDeclaration(<EnumDeclaration>node);
57605720
}
57615721

5722+
// If this is the expression body of an arrow function that we're downleveling,
5723+
// then we don't want to emit comments when we emit the body. It will have already
5724+
// been taken care of when we emitted the 'return' statement for the function
5725+
// expression body.
5726+
if (node.kind !== SyntaxKind.Block &&
5727+
node.parent &&
5728+
node.parent.kind === SyntaxKind.ArrowFunction &&
5729+
(<ArrowFunction>node.parent).body === node &&
5730+
compilerOptions.target <= ScriptTarget.ES5) {
5731+
5732+
return false;
5733+
}
5734+
57625735
// Emit comments for everything else.
57635736
return true;
57645737
}
@@ -5928,7 +5901,8 @@ module ts {
59285901

59295902
function getLeadingCommentsWithoutDetachedComments() {
59305903
// get the leading comments from detachedPos
5931-
let leadingComments = getLeadingCommentRanges(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
5904+
let leadingComments = getLeadingCommentRanges(currentSourceFile.text,
5905+
detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
59325906
if (detachedCommentsInfo.length - 1) {
59335907
detachedCommentsInfo.pop();
59345908
}
@@ -5952,30 +5926,59 @@ module ts {
59525926
// get the leading comments from the node
59535927
leadingComments = getLeadingCommentRangesOfNode(node, currentSourceFile);
59545928
}
5929+
59555930
return leadingComments;
59565931
}
59575932
}
59585933
}
59595934

5960-
function emitLeadingDeclarationComments(node: Node) {
5961-
let leadingComments = getLeadingCommentsToEmit(node);
5935+
function filterComments(ranges: CommentRange[], onlyPinnedOrTripleSlashComments: boolean): CommentRange[]{
5936+
// If we're removing comments, then we want to strip out all but the pinned or
5937+
// triple slash comments.
5938+
if (ranges && onlyPinnedOrTripleSlashComments) {
5939+
ranges = filter(ranges, isPinnedOrTripleSlashComment);
5940+
if (ranges.length === 0) {
5941+
return undefined;
5942+
}
5943+
}
5944+
5945+
return ranges;
5946+
}
5947+
5948+
function emitOnlyPinnedOrTripleSlashComments(node: Node) {
5949+
emitLeadingCommentsWorker(node, /*onlyPinnedOrTripleSlashComments:*/ true);
5950+
}
5951+
5952+
function emitLeadingComments(node: Node) {
5953+
return emitLeadingCommentsWorker(node, /*onlyPinnedOrTripleSlashComments:*/ compilerOptions.removeComments);
5954+
}
5955+
5956+
function emitLeadingCommentsWorker(node: Node, onlyPinnedOrTripleSlashComments: boolean) {
5957+
// If the caller only wants pinned or triple slash comments, then always filter
5958+
// down to that set. Otherwise, filter based on the current compiler options.
5959+
let leadingComments = filterComments(getLeadingCommentsToEmit(node), onlyPinnedOrTripleSlashComments);
5960+
59625961
emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
5962+
59635963
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
59645964
emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
59655965
}
59665966

5967-
function emitTrailingDeclarationComments(node: Node) {
5967+
function emitTrailingComments(node: Node) {
59685968
// Emit the trailing comments only if the parent's end doesn't match
59695969
if (node.parent) {
59705970
if (node.parent.kind === SyntaxKind.SourceFile || node.end !== node.parent.end) {
5971-
let trailingComments = getTrailingCommentRanges(currentSourceFile.text, node.end);
5971+
let trailingComments = filterComments(
5972+
getTrailingCommentRanges(currentSourceFile.text, node.end),
5973+
/*emitOnlyPinnedOrTripleSlashComments:*/ compilerOptions.removeComments);
5974+
59725975
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
59735976
emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
59745977
}
59755978
}
59765979
}
59775980

5978-
function emitLeadingCommentsOfLocalPosition(pos: number) {
5981+
function emitLeadingCommentsOfPosition(pos: number) {
59795982
let leadingComments: CommentRange[];
59805983
if (hasDetachedComments(pos)) {
59815984
// get comments without detached comments
@@ -5985,12 +5988,15 @@ module ts {
59855988
// get the leading comments from the node
59865989
leadingComments = getLeadingCommentRanges(currentSourceFile.text, pos);
59875990
}
5991+
5992+
leadingComments = filterComments(leadingComments, compilerOptions.removeComments);
59885993
emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments);
5994+
59895995
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
59905996
emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
59915997
}
59925998

5993-
function emitDetachedCommentsAtPosition(node: TextRange) {
5999+
function emitDetachedComments(node: TextRange) {
59946000
let leadingComments = getLeadingCommentRanges(currentSourceFile.text, node.pos);
59956001
if (leadingComments) {
59966002
let detachedComments: CommentRange[] = [];
@@ -6035,27 +6041,18 @@ module ts {
60356041
}
60366042
}
60376043

6038-
/** Emits /// or pinned which is comment starting with /*! comments */
6039-
function emitPinnedOrTripleSlashComments(node: Node) {
6040-
let pinnedComments = ts.filter(getLeadingCommentsToEmit(node), isPinnedOrTripleSlashComment);
6041-
6042-
function isPinnedOrTripleSlashComment(comment: CommentRange) {
6043-
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
6044-
return currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
6045-
}
6046-
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
6047-
// so that we don't end up computing comment string and doing match for all // comments
6048-
else if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
6049-
comment.pos + 2 < comment.end &&
6050-
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.slash &&
6051-
currentSourceFile.text.substring(comment.pos, comment.end).match(fullTripleSlashReferencePathRegEx)) {
6052-
return true;
6053-
}
6044+
function isPinnedOrTripleSlashComment(comment: CommentRange) {
6045+
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
6046+
return currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
6047+
}
6048+
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
6049+
// so that we don't end up computing comment string and doing match for all // comments
6050+
else if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
6051+
comment.pos + 2 < comment.end &&
6052+
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.slash &&
6053+
currentSourceFile.text.substring(comment.pos, comment.end).match(fullTripleSlashReferencePathRegEx)) {
6054+
return true;
60546055
}
6055-
6056-
emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, pinnedComments);
6057-
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
6058-
emitComments(currentSourceFile, writer, pinnedComments, /*trailingSeparator*/ true, newLine, writeComment);
60596056
}
60606057
}
60616058

src/compiler/scanner.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -455,19 +455,23 @@ module ts {
455455
return pos;
456456
}
457457

458-
// Extract comments from the given source text starting at the given position. If trailing is false, whitespace is skipped until
459-
// the first line break and comments between that location and the next token are returned. If trailing is true, comments occurring
460-
// between the given position and the next line break are returned. The return value is an array containing a TextRange for each
461-
// comment. Single-line comment ranges include the beginning '//' characters but not the ending line break. Multi-line comment
462-
// ranges include the beginning '/* and ending '*/' characters. The return value is undefined if no comments were found.
458+
// Extract comments from the given source text starting at the given position. If trailing is
459+
// false, whitespace is skipped until the first line break and comments between that location
460+
// and the next token are returned.If trailing is true, comments occurring between the given
461+
// position and the next line break are returned.The return value is an array containing a
462+
// TextRange for each comment. Single-line comment ranges include the beginning '//' characters
463+
// but not the ending line break. Multi - line comment ranges include the beginning '/* and
464+
// ending '*/' characters.The return value is undefined if no comments were found.
463465
function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] {
464466
let result: CommentRange[];
465467
let collecting = trailing || pos === 0;
466468
while (true) {
467469
let ch = text.charCodeAt(pos);
468470
switch (ch) {
469471
case CharacterCodes.carriageReturn:
470-
if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) pos++;
472+
if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
473+
pos++;
474+
}
471475
case CharacterCodes.lineFeed:
472476
pos++;
473477
if (trailing) {
@@ -509,7 +513,10 @@ module ts {
509513
}
510514
}
511515
if (collecting) {
512-
if (!result) result = [];
516+
if (!result) {
517+
result = [];
518+
}
519+
513520
result.push({ pos: startPos, end: pos, hasTrailingNewLine: hasTrailingNewLine });
514521
}
515522
continue;

0 commit comments

Comments
 (0)