@@ -336,6 +336,9 @@ module ts {
336
336
/** Emit detached comments of the node */
337
337
var emitDetachedComments = compilerOptions . removeComments ? ( node : TextRange ) => { } : emitDetachedCommentsAtPosition ;
338
338
339
+ /** Emits /// or pinned which is comment starting with /*! comments */
340
+ var emitPinnedOrTripleSlashComments = compilerOptions . removeComments ? ( node : Node ) => { } : emitPinnedOrTripleSlashCommentsOfNode ;
341
+
339
342
var writeComment = writeCommentRange ;
340
343
341
344
/** Emit a node */
@@ -1318,7 +1321,10 @@ module ts {
1318
1321
}
1319
1322
1320
1323
function emitFunctionDeclaration ( node : FunctionDeclaration ) {
1321
- if ( ! node . body ) return ;
1324
+ if ( ! node . body ) {
1325
+ return emitPinnedOrTripleSlashComments ( node ) ;
1326
+ }
1327
+
1322
1328
if ( node . kind !== SyntaxKind . Method ) {
1323
1329
// Methods will emit the comments as part of emitting method declaration
1324
1330
emitLeadingComments ( node ) ;
@@ -1488,7 +1494,10 @@ module ts {
1488
1494
function emitMemberFunctions ( node : ClassDeclaration ) {
1489
1495
forEach ( node . members , member => {
1490
1496
if ( member . kind === SyntaxKind . Method ) {
1491
- if ( ! ( < MethodDeclaration > member ) . body ) return ;
1497
+ if ( ! ( < MethodDeclaration > member ) . body ) {
1498
+ return emitPinnedOrTripleSlashComments ( member ) ;
1499
+ }
1500
+
1492
1501
writeLine ( ) ;
1493
1502
emitLeadingComments ( member ) ;
1494
1503
emitStart ( member ) ;
@@ -1611,6 +1620,13 @@ module ts {
1611
1620
emitTrailingComments ( node ) ;
1612
1621
1613
1622
function emitConstructorOfClass ( ) {
1623
+ // Emit the constructor overload pinned comments
1624
+ forEach ( node . members , member => {
1625
+ if ( member . kind === SyntaxKind . Constructor && ! ( < ConstructorDeclaration > member ) . body ) {
1626
+ emitPinnedOrTripleSlashComments ( member ) ;
1627
+ }
1628
+ } ) ;
1629
+
1614
1630
var ctor = getFirstConstructorWithBody ( node ) ;
1615
1631
if ( ctor ) {
1616
1632
emitLeadingComments ( ctor ) ;
@@ -1666,6 +1682,10 @@ module ts {
1666
1682
}
1667
1683
}
1668
1684
1685
+ function emitInterfaceDeclaration ( node : InterfaceDeclaration ) {
1686
+ emitPinnedOrTripleSlashComments ( node ) ;
1687
+ }
1688
+
1669
1689
function emitEnumDeclaration ( node : EnumDeclaration ) {
1670
1690
emitLeadingComments ( node ) ;
1671
1691
if ( ! ( node . flags & NodeFlags . Export ) ) {
@@ -1741,7 +1761,10 @@ module ts {
1741
1761
}
1742
1762
1743
1763
function emitModuleDeclaration ( node : ModuleDeclaration ) {
1744
- if ( ! isInstantiated ( node ) ) return ;
1764
+ if ( ! isInstantiated ( node ) ) {
1765
+ return emitPinnedOrTripleSlashComments ( node ) ;
1766
+ }
1767
+
1745
1768
emitLeadingComments ( node ) ;
1746
1769
if ( ! ( node . flags & NodeFlags . Export ) ) {
1747
1770
emitStart ( node ) ;
@@ -1969,7 +1992,14 @@ module ts {
1969
1992
}
1970
1993
1971
1994
function emitNode ( node : Node ) {
1972
- if ( ! node || node . flags & NodeFlags . Ambient ) return ;
1995
+ if ( ! node ) {
1996
+ return ;
1997
+ }
1998
+
1999
+ if ( node . flags & NodeFlags . Ambient ) {
2000
+ return emitPinnedOrTripleSlashComments ( node ) ;
2001
+ }
2002
+
1973
2003
switch ( node . kind ) {
1974
2004
case SyntaxKind . Identifier :
1975
2005
return emitIdentifier ( < Identifier > node ) ;
@@ -2073,6 +2103,8 @@ module ts {
2073
2103
return emitVariableDeclaration ( < VariableDeclaration > node ) ;
2074
2104
case SyntaxKind . ClassDeclaration :
2075
2105
return emitClassDeclaration ( < ClassDeclaration > node ) ;
2106
+ case SyntaxKind . InterfaceDeclaration :
2107
+ return emitInterfaceDeclaration ( < InterfaceDeclaration > node ) ;
2076
2108
case SyntaxKind . EnumDeclaration :
2077
2109
return emitEnumDeclaration ( < EnumDeclaration > node ) ;
2078
2110
case SyntaxKind . ModuleDeclaration :
@@ -2101,7 +2133,7 @@ module ts {
2101
2133
return leadingComments ;
2102
2134
}
2103
2135
2104
- function emitLeadingDeclarationComments ( node : Node ) {
2136
+ function getLeadingCommentsToEmit ( node : Node ) {
2105
2137
// Emit the leading comments only if the parent's pos doesnt match because parent should take care of emitting these comments
2106
2138
if ( node . parent . kind === SyntaxKind . SourceFile || node . pos !== node . parent . pos ) {
2107
2139
var leadingComments : Comment [ ] ;
@@ -2113,12 +2145,17 @@ module ts {
2113
2145
// get the leading comments from the node
2114
2146
leadingComments = getLeadingCommentsOfNode ( node , currentSourceFile ) ;
2115
2147
}
2116
- emitNewLineBeforeLeadingComments ( node , leadingComments , writer ) ;
2117
- // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
2118
- emitComments ( leadingComments , /*trailingSeparator*/ true , writer , writeComment ) ;
2148
+ return leadingComments ;
2119
2149
}
2120
2150
}
2121
2151
2152
+ function emitLeadingDeclarationComments ( node : Node ) {
2153
+ var leadingComments = getLeadingCommentsToEmit ( node ) ;
2154
+ emitNewLineBeforeLeadingComments ( node , leadingComments , writer ) ;
2155
+ // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
2156
+ emitComments ( leadingComments , /*trailingSeparator*/ true , writer , writeComment ) ;
2157
+ }
2158
+
2122
2159
function emitTrailingDeclarationComments ( node : Node ) {
2123
2160
// Emit the trailing comments only if the parent's end doesnt match
2124
2161
if ( node . parent . kind === SyntaxKind . SourceFile || node . end !== node . parent . end ) {
@@ -2166,7 +2203,7 @@ module ts {
2166
2203
lastComment = comment ;
2167
2204
} ) ;
2168
2205
2169
- if ( detachedComments && detachedComments . length ) {
2206
+ if ( detachedComments . length ) {
2170
2207
// All comments look like they could have been part of the copyright header. Make
2171
2208
// sure there is at least one blank line between it and the node. If not, it's not
2172
2209
// a copyright header.
@@ -2188,6 +2225,28 @@ module ts {
2188
2225
}
2189
2226
}
2190
2227
2228
+ function emitPinnedOrTripleSlashCommentsOfNode ( node : Node ) {
2229
+ var pinnedComments = ts . filter ( getLeadingCommentsToEmit ( node ) , isPinnedOrTripleSlashComment ) ;
2230
+
2231
+ function isPinnedOrTripleSlashComment ( comment : Comment ) {
2232
+ if ( currentSourceFile . text . charCodeAt ( comment . pos + 1 ) === CharacterCodes . asterisk ) {
2233
+ return currentSourceFile . text . charCodeAt ( comment . pos + 2 ) === CharacterCodes . exclamation ;
2234
+ }
2235
+ // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
2236
+ // so that we dont end up computing comment string and doing match for all // comments
2237
+ else if ( currentSourceFile . text . charCodeAt ( comment . pos + 1 ) === CharacterCodes . slash &&
2238
+ comment . pos + 2 < comment . end &&
2239
+ currentSourceFile . text . charCodeAt ( comment . pos + 2 ) === CharacterCodes . slash &&
2240
+ currentSourceFile . text . substring ( comment . pos , comment . end ) . match ( fullTripleSlashReferencePathRegEx ) ) {
2241
+ return true ;
2242
+ }
2243
+ }
2244
+
2245
+ emitNewLineBeforeLeadingComments ( node , pinnedComments , writer ) ;
2246
+ // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
2247
+ emitComments ( pinnedComments , /*trailingSeparator*/ true , writer , writeComment ) ;
2248
+ }
2249
+
2191
2250
if ( compilerOptions . sourceMap ) {
2192
2251
initializeEmitterWithSourceMaps ( ) ;
2193
2252
}
0 commit comments