@@ -1580,20 +1580,66 @@ 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 "pos", "end", "flags", and "parent" properties
1585+ * are excluded by default, and can be provided via the "location", "flags", and "parent" parameters.
1586+ * @param node The node to clone.
1587+ * @param location An optional TextRange to use to supply the new position.
1588+ * @param flags The NodeFlags to use for the cloned node.
1589+ * @param parent The parent for the new node.
1590+ */
1591+ export function cloneNode < T extends Node > ( node : T , location ?: TextRange , flags ?: NodeFlags , parent ?: Node ) : T {
1592+ // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
1593+ // the original node. We also need to exclude specific properties and only include own-
1594+ // properties (to skip members already defined on the shared prototype).
1595+ const clone = location !== undefined
1596+ ? < T > createNode ( node . kind , location . pos , location . end )
1597+ : < T > createSynthesizedNode ( node . kind ) ;
1598+
1599+ for ( const key in node ) {
1600+ if ( isExcludedPropertyForClone ( key ) || ! node . hasOwnProperty ( key ) ) {
1601+ continue ;
1602+ }
1603+
1604+ ( < any > clone ) [ key ] = ( < any > node ) [ key ] ;
15881605 }
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 ;
1606+
1607+ if ( flags !== undefined ) {
1608+ clone . flags = flags ;
15961609 }
1610+
1611+ if ( parent !== undefined ) {
1612+ clone . parent = parent ;
1613+ }
1614+
1615+ return clone ;
1616+ }
1617+
1618+ function isExcludedPropertyForClone ( property : string ) {
1619+ return property === "pos"
1620+ || property === "end"
1621+ || property === "flags"
1622+ || property === "parent" ;
1623+ }
1624+
1625+ /**
1626+ * Creates a deep clone of an EntityName, with new parent pointers.
1627+ * @param node The EntityName to clone.
1628+ * @param parent The parent for the cloned node.
1629+ */
1630+ export function cloneEntityName ( node : EntityName , parent ?: Node ) : EntityName {
1631+ const clone = cloneNode ( node , node , node . flags , parent ) ;
1632+ if ( isQualifiedName ( clone ) ) {
1633+ const { left, right } = clone ;
1634+ clone . left = cloneEntityName ( left , clone ) ;
1635+ clone . right = cloneNode ( right , right , right . flags , parent ) ;
1636+ }
1637+
1638+ return clone ;
1639+ }
1640+
1641+ export function isQualifiedName ( node : Node ) : node is QualifiedName {
1642+ return node . kind === SyntaxKind . QualifiedName ;
15971643 }
15981644
15991645 export function nodeIsSynthesized ( node : Node ) : boolean {
@@ -1936,7 +1982,7 @@ namespace ts {
19361982 const bundledSources = filter ( host . getSourceFiles ( ) ,
19371983 sourceFile => ! isDeclarationFile ( sourceFile ) && // Not a declaration file
19381984 ( ! 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
1985+ ( getEmitModuleKind ( options ) && isExternalModule ( sourceFile ) ) ) ) ; // module that can emit - note falsy value from getEmitModuleKind means the module kind that shouldn't be emitted
19401986 if ( bundledSources . length ) {
19411987 const jsFilePath = options . outFile || options . out ;
19421988 const emitFileNames : EmitFileNames = {
0 commit comments