@@ -121,7 +121,6 @@ const _super = (function (geti, seti) {
121121 const writer = createTextWriter ( newLine ) ;
122122 const {
123123 write,
124- writeTextOfNode,
125124 writeLine,
126125 increaseIndent,
127126 decreaseIndent
@@ -154,11 +153,12 @@ const _super = (function (geti, seti) {
154153 let identifierSubstitution : ( node : Identifier ) => Identifier ;
155154 let onBeforeEmitNode : ( node : Node ) => void ;
156155 let onAfterEmitNode : ( node : Node ) => void ;
157- let isUniqueName : ( name : string ) => boolean ;
158- let temporaryVariables : string [ ] = [ ] ;
156+ let nodeToGeneratedName : string [ ] ;
157+ let generatedNameSet : Map < string > ;
159158 let tempFlags : TempFlags ;
160159 let currentSourceFile : SourceFile ;
161160 let currentText : string ;
161+ let currentFileIdentifiers : Map < string > ;
162162 let extendsEmitted : boolean ;
163163 let decorateEmitted : boolean ;
164164 let paramEmitted : boolean ;
@@ -169,6 +169,8 @@ const _super = (function (geti, seti) {
169169
170170 function doPrint ( jsFilePath : string , sourceMapFilePath : string , sourceFiles : SourceFile [ ] , isBundledEmit : boolean ) {
171171 sourceMap . initialize ( jsFilePath , sourceMapFilePath , sourceFiles , isBundledEmit ) ;
172+ nodeToGeneratedName = [ ] ;
173+ generatedNameSet = { } ;
172174 isOwnFileEmit = ! isBundledEmit ;
173175
174176 // Emit helpers from all the files
@@ -213,8 +215,6 @@ const _super = (function (geti, seti) {
213215 identifierSubstitution = undefined ;
214216 onBeforeEmitNode = undefined ;
215217 onAfterEmitNode = undefined ;
216- isUniqueName = undefined ;
217- temporaryVariables = undefined ;
218218 tempFlags = TempFlags . Auto ;
219219 currentSourceFile = undefined ;
220220 currentText = undefined ;
@@ -236,13 +236,13 @@ const _super = (function (geti, seti) {
236236 identifierSubstitution = context . identifierSubstitution ;
237237 onBeforeEmitNode = context . onBeforeEmitNode ;
238238 onAfterEmitNode = context . onAfterEmitNode ;
239- isUniqueName = context . isUniqueName ;
240239 return printSourceFile ;
241240 }
242241
243242 function printSourceFile ( node : SourceFile ) {
244243 currentSourceFile = node ;
245244 currentText = node . text ;
245+ currentFileIdentifiers = node . identifiers ;
246246 sourceMap . setSourceFile ( node ) ;
247247 comments . setSourceFile ( node ) ;
248248 emitWorker ( node ) ;
@@ -659,22 +659,11 @@ const _super = (function (geti, seti) {
659659 //
660660
661661 function emitIdentifier ( node : Identifier ) {
662- if ( node . text === undefined ) {
663- // Emit a temporary variable name for this node.
664- const nodeId = getOriginalNodeId ( node ) ;
665- const text = temporaryVariables [ nodeId ] || ( temporaryVariables [ nodeId ] = makeTempVariableName ( tempKindToFlags ( node . tempKind ) ) ) ;
666- write ( text ) ;
667- }
668- else if ( nodeIsSynthesized ( node ) || ! node . parent ) {
669- if ( getNodeEmitFlags ( node ) & NodeEmitFlags . UMDDefine ) {
670- writeLines ( umdHelper ) ;
671- }
672- else {
673- write ( node . text ) ;
674- }
662+ if ( getNodeEmitFlags ( node ) && NodeEmitFlags . UMDDefine ) {
663+ writeLines ( umdHelper ) ;
675664 }
676665 else {
677- writeTextOfNode ( currentText , node ) ;
666+ write ( getTextOfNode ( node , /*includeTrivia*/ false ) ) ;
678667 }
679668 }
680669
@@ -1720,7 +1709,6 @@ const _super = (function (geti, seti) {
17201709 emitExpression ( node . expression ) ;
17211710 write ( ":" ) ;
17221711
1723- debugger ;
17241712 emitCaseOrDefaultClauseStatements ( node , node . statements ) ;
17251713 }
17261714
@@ -1763,14 +1751,14 @@ const _super = (function (geti, seti) {
17631751 function emitPropertyAssignment ( node : PropertyAssignment ) {
17641752 emit ( node . name ) ;
17651753 write ( ": " ) ;
1766- // // This is to ensure that we emit comment in the following case:
1767- // // For example:
1768- // // obj = {
1769- // // id: /*comment1*/ ()=>void
1770- // / / }
1771- // // "comment1" is not considered to be leading comment for node.initializer
1772- // // but rather a trailing comment on the previous node.
1773- // emitTrailingCommentsOfPosition( node.initializer.pos );
1754+ // This is to ensure that we emit comment in the following case:
1755+ // For example:
1756+ // obj = {
1757+ // id: /*comment1*/ ()=>void
1758+ // }
1759+ // "comment1" is not considered to be leading comment for node.initializer
1760+ // but rather a trailing comment on the previous node.
1761+ emitLeadingComments ( node . initializer , getTrailingComments ( collapseTextRange ( node . initializer , TextRangeCollapse . CollapseToStart ) ) ) ;
17741762 emitExpression ( node . initializer ) ;
17751763 }
17761764
@@ -1951,11 +1939,8 @@ const _super = (function (geti, seti) {
19511939 }
19521940
19531941 function emitModifiers ( node : Node , modifiers : ModifiersArray ) {
1954- const startingPos = writer . getTextPos ( ) ;
1955- emitList ( node , modifiers , ListFormat . SingleLine ) ;
1956-
1957- const endingPos = writer . getTextPos ( ) ;
1958- if ( startingPos !== endingPos ) {
1942+ if ( modifiers && modifiers . length ) {
1943+ emitList ( node , modifiers , ListFormat . SingleLine ) ;
19591944 write ( " " ) ;
19601945 }
19611946 }
@@ -2345,7 +2330,15 @@ const _super = (function (geti, seti) {
23452330 }
23462331
23472332 function getTextOfNode ( node : Node , includeTrivia ?: boolean ) {
2348- if ( nodeIsSynthesized ( node ) && ( isLiteralExpression ( node ) || isIdentifier ( node ) ) ) {
2333+ if ( isIdentifier ( node ) ) {
2334+ if ( node . autoGenerateKind ) {
2335+ return getGeneratedIdentifier ( node ) ;
2336+ }
2337+ else if ( nodeIsSynthesized ( node ) || ! node . parent ) {
2338+ return node . text ;
2339+ }
2340+ }
2341+ else if ( isLiteralExpression ( node ) && ( nodeIsSynthesized ( node ) || ! node . parent ) ) {
23492342 return node . text ;
23502343 }
23512344
@@ -2368,10 +2361,22 @@ const _super = (function (geti, seti) {
23682361 && rangeEndIsOnSameLineAsRangeStart ( block , block ) ;
23692362 }
23702363
2371- function tempKindToFlags ( kind : TempVariableKind ) {
2372- return kind === TempVariableKind . Loop
2373- ? TempFlags . _i
2374- : TempFlags . Auto ;
2364+ function isUniqueName ( name : string ) : boolean {
2365+ return ! resolver . hasGlobalName ( name ) &&
2366+ ! hasProperty ( currentFileIdentifiers , name ) &&
2367+ ! hasProperty ( generatedNameSet , name ) ;
2368+ }
2369+
2370+ function isUniqueLocalName ( name : string , container : Node ) : boolean {
2371+ for ( let node = container ; isNodeDescendentOf ( node , container ) ; node = node . nextContainer ) {
2372+ if ( node . locals && hasProperty ( node . locals , name ) ) {
2373+ // We conservatively include alias symbols to cover cases where they're emitted as locals
2374+ if ( node . locals [ name ] . flags & ( SymbolFlags . Value | SymbolFlags . ExportValue | SymbolFlags . Alias ) ) {
2375+ return false ;
2376+ }
2377+ }
2378+ }
2379+ return true ;
23752380 }
23762381
23772382 /**
@@ -2401,6 +2406,85 @@ const _super = (function (geti, seti) {
24012406 }
24022407 }
24032408 }
2409+
2410+ // Generate a name that is unique within the current file and doesn't conflict with any names
2411+ // in global scope. The name is formed by adding an '_n' suffix to the specified base name,
2412+ // where n is a positive integer. Note that names generated by makeTempVariableName and
2413+ // makeUniqueName are guaranteed to never conflict.
2414+ function makeUniqueName ( baseName : string ) : string {
2415+ // Find the first unique 'name_n', where n is a positive number
2416+ if ( baseName . charCodeAt ( baseName . length - 1 ) !== CharacterCodes . _ ) {
2417+ baseName += "_" ;
2418+ }
2419+ let i = 1 ;
2420+ while ( true ) {
2421+ const generatedName = baseName + i ;
2422+ if ( isUniqueName ( generatedName ) ) {
2423+ return generatedNameSet [ generatedName ] = generatedName ;
2424+ }
2425+ i ++ ;
2426+ }
2427+ }
2428+
2429+ function generateNameForModuleOrEnum ( node : ModuleDeclaration | EnumDeclaration ) {
2430+ const name = node . name . text ;
2431+ // Use module/enum name itself if it is unique, otherwise make a unique variation
2432+ return isUniqueLocalName ( name , node ) ? name : makeUniqueName ( name ) ;
2433+ }
2434+
2435+ function generateNameForImportOrExportDeclaration ( node : ImportDeclaration | ExportDeclaration ) {
2436+ const expr = getExternalModuleName ( node ) ;
2437+ const baseName = expr . kind === SyntaxKind . StringLiteral ?
2438+ escapeIdentifier ( makeIdentifierFromModuleName ( ( < LiteralExpression > expr ) . text ) ) : "module" ;
2439+ return makeUniqueName ( baseName ) ;
2440+ }
2441+
2442+ function generateNameForExportDefault ( ) {
2443+ return makeUniqueName ( "default" ) ;
2444+ }
2445+
2446+ function generateNameForClassExpression ( ) {
2447+ return makeUniqueName ( "class" ) ;
2448+ }
2449+
2450+ function generateNameForNode ( node : Node ) {
2451+ switch ( node . kind ) {
2452+ case SyntaxKind . Identifier :
2453+ return makeUniqueName ( ( < Identifier > node ) . text ) ;
2454+ case SyntaxKind . ModuleDeclaration :
2455+ case SyntaxKind . EnumDeclaration :
2456+ return generateNameForModuleOrEnum ( < ModuleDeclaration | EnumDeclaration > node ) ;
2457+ case SyntaxKind . ImportDeclaration :
2458+ case SyntaxKind . ExportDeclaration :
2459+ return generateNameForImportOrExportDeclaration ( < ImportDeclaration | ExportDeclaration > node ) ;
2460+ case SyntaxKind . FunctionDeclaration :
2461+ case SyntaxKind . ClassDeclaration :
2462+ case SyntaxKind . ExportAssignment :
2463+ return generateNameForExportDefault ( ) ;
2464+ case SyntaxKind . ClassExpression :
2465+ return generateNameForClassExpression ( ) ;
2466+ default :
2467+ return makeTempVariableName ( TempFlags . Auto ) ;
2468+ }
2469+ }
2470+
2471+ function generateIdentifier ( node : Identifier ) {
2472+ switch ( node . autoGenerateKind ) {
2473+ case GeneratedIdentifierKind . Auto :
2474+ return makeTempVariableName ( TempFlags . Auto ) ;
2475+ case GeneratedIdentifierKind . Loop :
2476+ return makeTempVariableName ( TempFlags . _i ) ;
2477+ case GeneratedIdentifierKind . Unique :
2478+ return makeUniqueName ( node . text ) ;
2479+ case GeneratedIdentifierKind . Node :
2480+ return generateNameForNode ( getOriginalNode ( node ) ) ;
2481+ }
2482+ }
2483+
2484+ function getGeneratedIdentifier ( node : Identifier ) {
2485+ const id = getOriginalNodeId ( node ) ;
2486+ return nodeToGeneratedName [ id ] || ( nodeToGeneratedName [ id ] = unescapeIdentifier ( generateIdentifier ( node ) ) ) ;
2487+ }
24042488 }
24052489 }
24062490
0 commit comments