@@ -22,7 +22,7 @@ import {ChangesByFile, ChangeTracker, findClassDeclaration, findLiteralProperty,
22
22
* are going to be added to the imports of a component.
23
23
*/
24
24
export type ComponentImportsRemapper =
25
- ( imports : PotentialImport [ ] , component : Reference < ts . ClassDeclaration > ) => PotentialImport [ ] ;
25
+ ( imports : PotentialImport [ ] , component : ts . ClassDeclaration ) => PotentialImport [ ] ;
26
26
27
27
/**
28
28
* Converts all declarations in the specified files to standalone.
@@ -39,9 +39,9 @@ export function toStandalone(
39
39
componentImportRemapper ?: ComponentImportsRemapper ) : ChangesByFile {
40
40
const templateTypeChecker = program . compiler . getTemplateTypeChecker ( ) ;
41
41
const typeChecker = program . getTsProgram ( ) . getTypeChecker ( ) ;
42
- const modulesToMigrate : ts . ClassDeclaration [ ] = [ ] ;
43
- const testObjectsToMigrate : ts . ObjectLiteralExpression [ ] = [ ] ;
44
- const declarations : Reference < ts . ClassDeclaration > [ ] = [ ] ;
42
+ const modulesToMigrate = new Set < ts . ClassDeclaration > ( ) ;
43
+ const testObjectsToMigrate = new Set < ts . ObjectLiteralExpression > ( ) ;
44
+ const declarations = new Set < ts . ClassDeclaration > ( ) ;
45
45
const tracker = new ChangeTracker ( printer , fileImportRemapper ) ;
46
46
47
47
for ( const sourceFile of sourceFiles ) {
@@ -54,12 +54,12 @@ export function toStandalone(
54
54
allModuleDeclarations , module , templateTypeChecker , typeChecker ) ;
55
55
56
56
if ( unbootstrappedDeclarations . length > 0 ) {
57
- modulesToMigrate . push ( module ) ;
58
- declarations . push ( ... unbootstrappedDeclarations ) ;
57
+ modulesToMigrate . add ( module ) ;
58
+ unbootstrappedDeclarations . forEach ( decl => declarations . add ( decl ) ) ;
59
59
}
60
60
}
61
61
62
- testObjectsToMigrate . push ( ... testObjects ) ;
62
+ testObjects . forEach ( obj => testObjectsToMigrate . add ( obj ) ) ;
63
63
}
64
64
65
65
for ( const declaration of declarations ) {
@@ -78,24 +78,23 @@ export function toStandalone(
78
78
79
79
/**
80
80
* Converts a single declaration defined through an NgModule to standalone.
81
- * @param ref References to the declaration being converted.
81
+ * @param decl Declaration being converted.
82
82
* @param tracker Tracker used to track the file changes.
83
83
* @param allDeclarations All the declarations that are being converted as a part of this migration.
84
84
* @param typeChecker
85
85
* @param importRemapper
86
86
*/
87
87
export function convertNgModuleDeclarationToStandalone (
88
- ref : Reference < ts . ClassDeclaration > , allDeclarations : Reference < ts . ClassDeclaration > [ ] ,
89
- tracker : ChangeTracker , typeChecker : TemplateTypeChecker ,
90
- importRemapper ?: ComponentImportsRemapper ) : void {
91
- const directiveMeta = typeChecker . getDirectiveMetadata ( ref . node ) ;
88
+ decl : ts . ClassDeclaration , allDeclarations : Set < ts . ClassDeclaration > , tracker : ChangeTracker ,
89
+ typeChecker : TemplateTypeChecker , importRemapper ?: ComponentImportsRemapper ) : void {
90
+ const directiveMeta = typeChecker . getDirectiveMetadata ( decl ) ;
92
91
93
92
if ( directiveMeta && directiveMeta . decorator && ! directiveMeta . isStandalone ) {
94
93
let decorator = addStandaloneToDecorator ( directiveMeta . decorator ) ;
95
94
96
95
if ( directiveMeta . isComponent ) {
97
- const importsToAdd =
98
- getComponentImportExpressions ( ref , allDeclarations , tracker , typeChecker , importRemapper ) ;
96
+ const importsToAdd = getComponentImportExpressions (
97
+ decl , allDeclarations , tracker , typeChecker , importRemapper ) ;
99
98
100
99
if ( importsToAdd . length > 0 ) {
101
100
decorator = addPropertyToAngularDecorator (
@@ -107,7 +106,7 @@ export function convertNgModuleDeclarationToStandalone(
107
106
108
107
tracker . replaceNode ( directiveMeta . decorator , decorator ) ;
109
108
} else {
110
- const pipeMeta = typeChecker . getPipeMetadata ( ref . node ) ;
109
+ const pipeMeta = typeChecker . getPipeMetadata ( decl ) ;
111
110
112
111
if ( pipeMeta && pipeMeta . decorator && ! pipeMeta . isStandalone ) {
113 112
tracker . replaceNode ( pipeMeta . decorator , addStandaloneToDecorator ( pipeMeta . decorator ) ) ;
@@ -118,26 +117,25 @@ export function convertNgModuleDeclarationToStandalone(
118
117
/**
119
118
* Gets the expressions that should be added to a component's
120
119
* `imports` array based on its template dependencies.
121
- * @param ref Reference to the component class.
120
+ * @param decl Component class declaration .
122
121
* @param allDeclarations All the declarations that are being converted as a part of this migration.
123
122
* @param tracker
124
123
* @param typeChecker
125
124
* @param importRemapper
126
125
*/
127
126
function getComponentImportExpressions (
128
- ref : Reference < ts . ClassDeclaration > , allDeclarations : Reference < ts . ClassDeclaration > [ ] ,
129
- tracker : ChangeTracker , typeChecker : TemplateTypeChecker ,
130
- importRemapper ?: ComponentImportsRemapper ) : ts . Expression [ ] {
131
- const templateDependencies = findTemplateDependencies ( ref , typeChecker ) ;
132
- const usedDependenciesInMigration = new Set ( templateDependencies . filter (
133
- dep => allDeclarations . find ( current => current . node === dep . node ) ) ) ;
127
+ decl : ts . ClassDeclaration , allDeclarations : Set < ts . ClassDeclaration > , tracker : ChangeTracker ,
128
+ typeChecker : TemplateTypeChecker , importRemapper ?: ComponentImportsRemapper ) : ts . Expression [ ] {
129
+ const templateDependencies = findTemplateDependencies ( decl , typeChecker ) ;
130
+ const usedDependenciesInMigration =
131
+ new Set ( templateDependencies . filter ( dep => allDeclarations . has ( dep . node ) ) ) ;
134
132
const imports : ts . Expression [ ] = [ ] ;
135
133
const seenImports = new Set < string > ( ) ;
136
134
const resolvedDependencies : PotentialImport [ ] = [ ] ;
137
135
138
136
for ( const dep of templateDependencies ) {
139
137
const importLocation = findImportLocation (
140
- dep as Reference < NamedClassDeclaration > , ref ,
138
+ dep as Reference < NamedClassDeclaration > , decl ,
141
139
usedDependenciesInMigration . has ( dep ) ? PotentialImportMode . ForceDirect :
142
140
PotentialImportMode . Normal ,
143
141
typeChecker ) ;
@@ -149,19 +147,19 @@ function getComponentImportExpressions(
149
147
}
150
148
151
149
const processedDependencies =
152
- importRemapper ? importRemapper ( resolvedDependencies , ref ) : resolvedDependencies ;
150
+ importRemapper ? importRemapper ( resolvedDependencies , decl ) : resolvedDependencies ;
153
151
154
152
for ( const importLocation of processedDependencies ) {
155
153
if ( importLocation . moduleSpecifier ) {
156
154
const identifier = tracker . addImport (
157
- ref . node . getSourceFile ( ) , importLocation . symbolName , importLocation . moduleSpecifier ) ;
155
+ decl . getSourceFile ( ) , importLocation . symbolName , importLocation . moduleSpecifier ) ;
158
156
imports . push ( identifier ) ;
159
157
} else {
160
158
const identifier = ts . factory . createIdentifier ( importLocation . symbolName ) ;
161
159
162
160
if ( importLocation . isForwardReference ) {
163
161
const forwardRefExpression =
164
- tracker . addImport ( ref . node . getSourceFile ( ) , 'forwardRef' , '@angular/core' ) ;
162
+ tracker . addImport ( decl . getSourceFile ( ) , 'forwardRef' , '@angular/core' ) ;
165
163
const arrowFunction = ts . factory . createArrowFunction (
166
164
undefined , undefined , [ ] , undefined , undefined , identifier ) ;
167
165
imports . push (
@@ -184,15 +182,13 @@ function getComponentImportExpressions(
184
182
* @param templateTypeChecker
185
183
*/
186
184
function migrateNgModuleClass (
187
- node : ts . ClassDeclaration , allDeclarations : Reference < ts . ClassDeclaration > [ ] ,
188
- tracker : ChangeTracker , typeChecker : ts . TypeChecker , templateTypeChecker : TemplateTypeChecker ) {
185
+ node : ts . ClassDeclaration , allDeclarations : Set < ts . ClassDeclaration > , tracker : ChangeTracker ,
186
+ typeChecker : ts . TypeChecker , templateTypeChecker : TemplateTypeChecker ) {
189
187
const decorator = templateTypeChecker . getNgModuleMetadata ( node ) ?. decorator ;
190
188
const metadata = decorator ? extractMetadataLiteral ( decorator ) : null ;
191
189
192
190
if ( metadata ) {
193
- moveDeclarationsToImports (
194
- metadata , allDeclarations . map ( decl => decl . node ) , typeChecker , templateTypeChecker ,
195
- tracker ) ;
191
+ moveDeclarationsToImports ( metadata , allDeclarations , typeChecker , templateTypeChecker , tracker ) ;
196
192
}
197
193
}
198
194
@@ -205,7 +201,7 @@ function migrateNgModuleClass(
205
201
* @param tracker
206
202
*/
207
203
function moveDeclarationsToImports (
208
- literal : ts . ObjectLiteralExpression , allDeclarations : ts . ClassDeclaration [ ] ,
204
+ literal : ts . ObjectLiteralExpression , allDeclarations : Set < ts . ClassDeclaration > ,
209
205
typeChecker : ts . TypeChecker , templateTypeChecker : TemplateTypeChecker ,
210
206
tracker : ChangeTracker ) : void {
211
207
const declarationsProp = findLiteralProperty ( literal , 'declarations' ) ;
@@ -347,9 +343,9 @@ function isNamedPropertyAssignment(node: ts.Node): node is ts.PropertyAssignment
347
343
* @param typeChecker
348
344
*/
349
345
function findImportLocation (
350
- target : Reference < NamedClassDeclaration > , inComponent : Reference < ts . ClassDeclaration > ,
346
+ target : Reference < NamedClassDeclaration > , inComponent : ts . ClassDeclaration ,
351
347
importMode : PotentialImportMode , typeChecker : TemplateTypeChecker ) : PotentialImport | null {
352
- const importLocations = typeChecker . getPotentialImportsFor ( target , inComponent . node , importMode ) ;
348
+ const importLocations = typeChecker . getPotentialImportsFor ( target , inComponent , importMode ) ;
353
349
let firstSameFileImport : PotentialImport | null = null ;
354
350
let firstModuleImport : PotentialImport | null = null ;
355
351
@@ -439,15 +435,14 @@ export function findTestObjectsToMigrate(sourceFile: ts.SourceFile, typeChecker:
439
435
440
436
/**
441
437
* Finds the classes corresponding to dependencies used in a component's template.
442
- * @param ref Component in whose template we're looking for dependencies.
438
+ * @param decl Component in whose template we're looking for dependencies.
443
439
* @param typeChecker
444
440
*/
445
- function findTemplateDependencies (
446
- ref : Reference < ts . ClassDeclaration > ,
447
- typeChecker : TemplateTypeChecker ) : Reference < NamedClassDeclaration > [ ] {
441
+ function findTemplateDependencies ( decl : ts . ClassDeclaration , typeChecker : TemplateTypeChecker ) :
442
+ Reference < NamedClassDeclaration > [ ] {
448
443
const results : Reference < NamedClassDeclaration > [ ] = [ ] ;
449
- const usedDirectives = typeChecker . getUsedDirectives ( ref . node ) ;
450
- const usedPipes = typeChecker . getUsedPipes ( ref . node ) ;
444
+ const usedDirectives = typeChecker . getUsedDirectives ( decl ) ;
445
+ const usedPipes = typeChecker . getUsedPipes ( decl ) ;
451
446
452
447
if ( usedDirectives !== null ) {
453
448
for ( const dir of usedDirectives ) {
@@ -458,7 +453,7 @@ function findTemplateDependencies(
458
453
}
459
454
460
455
if ( usedPipes !== null ) {
461
- const potentialPipes = typeChecker . getPotentialPipes ( ref . node ) ;
456
+ const potentialPipes = typeChecker . getPotentialPipes ( decl ) ;
462
457
463
458
for ( const pipe of potentialPipes ) {
464
459
if ( ts . isClassDeclaration ( pipe . ref . node ) &&
@@ -480,7 +475,7 @@ function findTemplateDependencies(
480
475
* @param typeChecker
481
476
*/
482
477
function filterNonBootstrappedDeclarations (
483
- declarations : Reference < ts . ClassDeclaration > [ ] , ngModule : ts . ClassDeclaration ,
478
+ declarations : ts . ClassDeclaration [ ] , ngModule : ts . ClassDeclaration ,
484
479
templateTypeChecker : TemplateTypeChecker , typeChecker : ts . TypeChecker ) {
485
480
const metadata = templateTypeChecker . getNgModuleMetadata ( ngModule ) ;
486
481
const metaLiteral =
@@ -513,7 +508,7 @@ function filterNonBootstrappedDeclarations(
513
508
}
514
509
}
515
510
516
- return declarations . filter ( ref => ! bootstrappedClasses . has ( ref . node ) ) ;
511
+ return declarations . filter ( ref => ! bootstrappedClasses . has ( ref ) ) ;
517
512
}
518
513
519
514
/**
@@ -523,10 +518,10 @@ function filterNonBootstrappedDeclarations(
523
518
*/
524
519
export function extractDeclarationsFromModule (
525
520
ngModule : ts . ClassDeclaration ,
526
- templateTypeChecker : TemplateTypeChecker ) : Reference < ts . ClassDeclaration > [ ] {
521
+ templateTypeChecker : TemplateTypeChecker ) : ts . ClassDeclaration [ ] {
527
522
const metadata = templateTypeChecker . getNgModuleMetadata ( ngModule ) ;
528
- return metadata ? metadata . declarations . filter ( decl => ts . isClassDeclaration ( decl . node ) ) as
529
- Reference < ts . ClassDeclaration > [ ] :
523
+ return metadata ? metadata . declarations . filter ( decl => ts . isClassDeclaration ( decl . node ) )
524
+ . map ( decl => decl . node ) as ts . ClassDeclaration [ ] :
530
525
[ ] ;
531
526
}
532
527
@@ -539,12 +534,11 @@ export function extractDeclarationsFromModule(
539
534
* @param typeChecker
540
535
*/
541
536
export function migrateTestDeclarations (
542
- testObjects : ts . ObjectLiteralExpression [ ] ,
543
- declarationsOutsideOfTestFiles : Reference < ts . ClassDeclaration > [ ] , tracker : ChangeTracker ,
537
+ testObjects : Set < ts . ObjectLiteralExpression > ,
538
+ declarationsOutsideOfTestFiles : Set < ts . ClassDeclaration > , tracker : ChangeTracker ,
544
539
templateTypeChecker : TemplateTypeChecker , typeChecker : ts . TypeChecker ) {
545
540
const { decorators, componentImports} = analyzeTestingModules ( testObjects , typeChecker ) ;
546
- const allDeclarations : ts . ClassDeclaration [ ] =
547
- declarationsOutsideOfTestFiles . map ( ref => ref . node ) ;
541
+ const allDeclarations = new Set ( declarationsOutsideOfTestFiles ) ;
548
542
549
543
for ( const decorator of decorators ) {
550
544
const closestClass = closestNode ( decorator . node , ts . isClassDeclaration ) ;
@@ -553,14 +547,14 @@ export function migrateTestDeclarations(
553
547
tracker . replaceNode ( decorator . node , addStandaloneToDecorator ( decorator . node ) ) ;
554
548
555
549
if ( closestClass ) {
556
- allDeclarations . push ( closestClass ) ;
550
+ allDeclarations . add ( closestClass ) ;
557
551
}
558
552
} else if ( decorator . name === 'Component' ) {
559
553
const newDecorator = addStandaloneToDecorator ( decorator . node ) ;
560
554
const importsToAdd = componentImports . get ( decorator . node ) ;
561
555
562
556
if ( closestClass ) {
563
- allDeclarations . push ( closestClass ) ;
557
+ allDeclarations . add ( closestClass ) ;
564
558
}
565
559
566
560
if ( importsToAdd && importsToAdd . size > 0 ) {
@@ -588,7 +582,7 @@ export function migrateTestDeclarations(
588
582
* @param testObjects Object literals that should be analyzed.
589
583
*/
590
584
function analyzeTestingModules (
591
- testObjects : ts . ObjectLiteralExpression [ ] , typeChecker : ts . TypeChecker ) {
585
+ testObjects : Set < ts . ObjectLiteralExpression > , typeChecker : ts . TypeChecker ) {
592
586
const seenDeclarations = new Set < ts . Declaration > ( ) ;
593
587
const decorators : NgDecorator [ ] = [ ] ;
594
588
const componentImports = new Map < ts . Decorator , Set < ts . Expression > > ( ) ;
@@ -685,9 +679,9 @@ function extractMetadataLiteral(decorator: ts.Decorator): ts.ObjectLiteralExpres
685
679
* @param templateTypeChecker
686
680
*/
687
681
function isStandaloneDeclaration (
688
- node : ts . ClassDeclaration , declarationsInMigration : ts . ClassDeclaration [ ] ,
682
+ node : ts . ClassDeclaration , declarationsInMigration : Set < ts . ClassDeclaration > ,
689
683
templateTypeChecker : TemplateTypeChecker ): boolean {
690
- if ( declarationsInMigration . includes ( node ) ) {
684
+ if ( declarationsInMigration . has ( node ) ) {
691
685
return true ;
692
686
}
693
687
0 commit comments