@@ -1580,20 +1580,60 @@ namespace ts {
15801580 return isFunctionLike ( n ) || n . kind === SyntaxKind . ModuleDeclaration || n . kind === SyntaxKind . SourceFile ;
15811581 }
15821582
1583- export function cloneEntityName ( node : EntityName ) : EntityName {
1584- if ( node . kind === SyntaxKind . Identifier ) {
1585- const clone = < Identifier > createSynthesizedNode ( SyntaxKind . Identifier ) ;
1586- clone . text = ( < Identifier > node ) . text ;
1587- return clone ;
1583+ /**
1584+ * Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent"
1585+ * properties are excluded by default, and can be provided via the "location", "flags", and
1586+ * "parent" parameters.
1587+ * @param node The node to clone.
1588+ * @param location An optional TextRange to use to supply the new position.
1589+ * @param flags The NodeFlags to use for the cloned node.
1590+ * @param parent The parent for the new node.
1591+ */
1592+ export function cloneNode < T extends Node > ( node : T , location ?: TextRange , flags ?: NodeFlags , parent ?: Node ) : T {
1593+ // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
1594+ // the original node. We also need to exclude specific properties and only include own-
1595+ // properties (to skip members already defined on the shared prototype).
1596+ const clone = location !== undefined
1597+ ? < T > createNode ( node . kind , location . pos , location . end )
1598+ : < T > createSynthesizedNode ( node . kind ) ;
1599+
1600+ for ( const key in node ) {
1601+ if ( clone . hasOwnProperty ( key ) || ! node . hasOwnProperty ( key ) ) {
1602+ continue ;
1603+ }
1604+
1605+ ( < any > clone ) [ key ] = ( < any > node ) [ key ] ;
15881606 }
1589- else {
1590- const clone = < QualifiedName > createSynthesizedNode ( SyntaxKind . QualifiedName ) ;
1591- clone . left = cloneEntityName ( ( < QualifiedName > node ) . left ) ;
1592- clone . left . parent = clone ;
1593- clone . right = < Identifier > cloneEntityName ( ( < QualifiedName > node ) . right ) ;
1594- clone . right . parent = clone ;
1595- return clone ;
1607+
1608+ if ( flags !== undefined ) {
1609+ clone . flags = flags ;
1610+ }
1611+
1612+ if ( parent !== undefined ) {
1613+ clone . parent = parent ;
15961614 }
1615+
1616+ return clone ;
1617+ }
1618+
1619+ /**
1620+ * Creates a deep clone of an EntityName, with new parent pointers.
1621+ * @param node The EntityName to clone.
1622+ * @param parent The parent for the cloned node.
1623+ */
1624+ export function cloneEntityName ( node : EntityName , parent ?: Node ) : EntityName {
1625+ const clone = cloneNode ( node , node , node . flags , parent ) ;
1626+ if ( isQualifiedName ( clone ) ) {
1627+ const { left, right } = clone ;
1628+ clone . left = cloneEntityName ( left , clone ) ;
1629+ clone . right = cloneNode ( right , right , right . flags , parent ) ;
1630+ }
1631+
1632+ return clone ;
1633+ }
1634+
1635+ export function isQualifiedName ( node : Node ) : node is QualifiedName {
1636+ return node . kind === SyntaxKind . QualifiedName ;
15971637 }
15981638
15991639 export function nodeIsSynthesized ( node : Node ) : boolean {
@@ -1936,7 +1976,7 @@ namespace ts {
19361976 const bundledSources = filter ( host . getSourceFiles ( ) ,
19371977 sourceFile => ! isDeclarationFile ( sourceFile ) && // Not a declaration file
19381978 ( ! isExternalModule ( sourceFile ) || // non module file
1939- ( getEmitModuleKind ( options ) && isExternalModule ( sourceFile ) ) ) ) ; // module that can emit - note falsy value from getEmitModuleKind means the module kind that shouldn't be emitted
1979+ ( getEmitModuleKind ( options ) && isExternalModule ( sourceFile ) ) ) ) ; // module that can emit - note falsy value from getEmitModuleKind means the module kind that shouldn't be emitted
19401980 if ( bundledSources . length ) {
19411981 const jsFilePath = options . outFile || options . out ;
19421982 const emitFileNames : EmitFileNames = {
0 commit comments