@@ -212,6 +212,7 @@ namespace ts {
212
212
} = comments ;
213
213
214
214
let currentSourceFile : SourceFile ;
215
+ let statementOffset : number ; // We cache the index of first non prologue so we don't have to recalculate it multiple times like in emitBodyInDirect
215
216
let nodeIdToGeneratedName : string [ ] ; // Map of generated names for specific nodes.
216
217
let autoGeneratedIdToGeneratedName : string [ ] ; // Map of generated names for temp and loop variables.
217
218
let generatedNames : Map < string > ; // Set of names generated by the NameGenerator.
@@ -275,6 +276,7 @@ namespace ts {
275
276
const previousWriter = writer ;
276
277
setWriter ( output ) ;
277
278
emitShebangIfNeeded ( bundle ) ;
279
+ emitPrologueDirectivesIfNeeded ( bundle ) ;
278
280
emitHelpersIndirect ( bundle ) ;
279
281
for ( const sourceFile of bundle . sourceFiles ) {
280
282
print ( EmitHint . SourceFile , sourceFile , sourceFile ) ;
@@ -287,6 +289,7 @@ namespace ts {
287
289
const previousWriter = writer ;
288
290
setWriter ( output ) ;
289
291
emitShebangIfNeeded ( sourceFile ) ;
292
+ emitPrologueDirectivesIfNeeded ( sourceFile ) ;
290
293
print ( EmitHint . SourceFile , sourceFile , sourceFile ) ;
291
294
reset ( ) ;
292
295
writer = previousWriter ;
@@ -309,6 +312,7 @@ namespace ts {
309
312
310
313
function setSourceFile ( sourceFile : SourceFile ) {
311
314
currentSourceFile = sourceFile ;
315
+ statementOffset = getIndexOfFirstNonPrologueDirectives ( sourceFile . statements ) ;
312
316
comments . setSourceFile ( sourceFile ) ;
313
317
if ( onSetSourceFile ) {
314
318
onSetSourceFile ( sourceFile ) ;
@@ -733,7 +737,11 @@ namespace ts {
733
737
}
734
738
735
739
function emitBodyIndirect ( node : Node , elements : NodeArray < Node > , emitCallback : ( node : Node ) => void ) : void {
736
- if ( emitBodyWithDetachedComments ) {
740
+ // If the node is a sourceFile and it has prologueDirective (statmentOffSet is not zero) that is synthesize
741
+ // We will need to emit detached comment here because emitPrologueDirective will not emit comments of such prologue directive
742
+ const shouldEmitDetachedComment = node . kind !== SyntaxKind . SourceFile ? true :
743
+ statementOffset === 0 || nodeIsSynthesized ( ( node as SourceFile ) . statements [ statementOffset - 1 ] ) ;
744
+ if ( emitBodyWithDetachedComments && shouldEmitDetachedComment ) {
737
745
emitBodyWithDetachedComments ( node , elements , emitCallback ) ;
738
746
}
739
747
else {
@@ -2058,7 +2066,6 @@ namespace ts {
2058
2066
2059
2067
function emitSourceFileWorker ( node : SourceFile ) {
2060
2068
const statements = node . statements ;
2061
- const statementOffset = emitPrologueDirectives ( statements ) ;
2062
2069
pushNameGenerationScope ( ) ;
2063
2070
emitHelpersIndirect ( node ) ;
2064
2071
emitList ( node , statements , ListFormat . MultiLine , statementOffset ) ;
@@ -2075,13 +2082,20 @@ namespace ts {
2075
2082
* Emits any prologue directives at the start of a Statement list, returning the
2076
2083
* number of prologue directives written to the output.
2077
2084
*/
2078
- function emitPrologueDirectives ( statements : Node [ ] , startWithNewLine ?: boolean ) : number {
2085
+ function emitPrologueDirectives ( statements : Node [ ] , startWithNewLine ?: boolean , seenPrologueDirectives ?: Map < String > ) : number {
2079
2086
for ( let i = 0 ; i < statements . length ; i ++ ) {
2080
- if ( isPrologueDirective ( statements [ i ] ) ) {
2081
- if ( startWithNewLine || i > 0 ) {
2082
- writeLine ( ) ;
2087
+ const statement = statements [ i ] ;
2088
+ if ( isPrologueDirective ( statement ) ) {
2089
+ const shouldEmitPrologueDirective = seenPrologueDirectives ? ! seenPrologueDirectives . has ( statement . expression . text ) : true ;
2090
+ if ( shouldEmitPrologueDirective ) {
2091
+ if ( startWithNewLine || i > 0 ) {
2092
+ writeLine ( ) ;
2093
+ }
2094
+ emit ( statement ) ;
2095
+ if ( seenPrologueDirectives ) {
2096
+ seenPrologueDirectives . set ( statement . expression . text , statement . expression . text ) ;
2097
+ }
2083
2098
}
2084
- emit ( statements [ i ] ) ;
2085
2099
}
2086
2100
else {
2087
2101
// return index of the first non prologue directive
@@ -2092,9 +2106,19 @@ namespace ts {
2092
2106
return statements . length ;
2093
2107
}
2094
2108
2095
- //
2096
- // Helpers
2097
- //
2109
+ function emitPrologueDirectivesIfNeeded ( sourceFileOrBundle : Bundle | SourceFile ) {
2110
+ if ( sourceFileOrBundle . kind === SyntaxKind . SourceFile ) {
2111
+ setSourceFile ( sourceFileOrBundle as SourceFile ) ;
2112
+ emitPrologueDirectives ( ( sourceFileOrBundle as SourceFile ) . statements ) ;
2113
+ }
2114
+ else {
2115
+ const seenProgolueDirectives = createMap < String > ( ) ;
2116
+ for ( const sourceFile of ( sourceFileOrBundle as Bundle ) . sourceFiles ) {
2117
+ setSourceFile ( sourceFile ) ;
2118
+ emitPrologueDirectives ( sourceFile . statements , /*startWithNewLine*/ true , seenProgolueDirectives ) ;
2119
+ }
2120
+ }
2121
+ }
2098
2122
2099
2123
function emitShebangIfNeeded ( sourceFileOrBundle : Bundle | SourceFile ) {
2100
2124
if ( sourceFileOrBundle . kind === SyntaxKind . SourceFile ) {
@@ -2119,6 +2143,19 @@ namespace ts {
2119
2143
}
2120
2144
}
2121
2145
2146
+ //
2147
+ // Helpers
2148
+ //
2149
+
2150
+ function getIndexOfFirstNonPrologueDirectives ( statements : Statement [ ] ) : number {
2151
+ for ( let i = 0 ; i < statements . length ; i ++ ) {
2152
+ if ( ! isPrologueDirective ( statements [ i ] ) ) {
2153
+ return i ;
2154
+ }
2155
+ }
2156
+ return statements . length ;
2157
+ }
2158
+
2122
2159
function emitModifiers ( node : Node , modifiers : NodeArray < Modifier > ) {
2123
2160
if ( modifiers && modifiers . length ) {
2124
2161
emitList ( node , modifiers , ListFormat . Modifiers ) ;
0 commit comments