Skip to content

Commit 7ac60ba

Browse files
fix(migrations): cf migration - improve import declaration handling (#53622)
This should make the import declaration symbol removal a bit more robust and handle more than just CommonModule safely. PR Close #53622
1 parent 7c8a2e1 commit 7ac60ba

File tree

5 files changed

+74
-9
lines changed

5 files changed

+74
-9
lines changed

packages/core/schematics/ng-generate/control-flow-migration/identifier-lookup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
import ts from 'typescript';
1010

1111
export function lookupIdentifiersInSourceFile(
12-
sourceFile: ts.SourceFile, name: string): Set<ts.Identifier> {
12+
sourceFile: ts.SourceFile, names: string[]): Set<ts.Identifier> {
1313
const results = new Set<ts.Identifier>();
1414
const visit = (node: ts.Node): void => {
15-
if (ts.isIdentifier(node) && node.text === name) {
15+
if (ts.isIdentifier(node) && names.includes(node.text)) {
1616
results.add(node);
1717
}
1818
ts.forEachChild(node, visit);

packages/core/schematics/ng-generate/control-flow-migration/migration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export function migrateTemplate(
8282
// and in that case we can't safely remove the common module import.
8383
componentFile.verifyCanRemoveImports();
8484
}
85+
file.verifyCanRemoveImports();
8586

8687
errors = [
8788
...ifResult.errors,

packages/core/schematics/ng-generate/control-flow-migration/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ export const endMarker = '✢';
2323
export const startI18nMarker = '⚈';
2424
export const endI18nMarker = '⚉';
2525

26+
export const importRemovals = [
27+
'NgIf', 'NgIfElse', 'NgIfThenElse', 'NgFor', 'NgForOf', 'NgForTrackBy', 'NgSwitch',
28+
'NgSwitchCase', 'NgSwitchDefault'
29+
];
30+
31+
export const importWithCommonRemovals = [...importRemovals, 'CommonModule'];
32+
2633
function allFormsOf(selector: string): string[] {
2734
return [
2835
selector,
@@ -308,7 +315,7 @@ export class AnalyzedFile {
308315
// skip this check entirely
309316
if (this.removeCommonModule) {
310317
const importDeclaration = this.importRanges.find(r => r.type === 'importDeclaration');
311-
const instances = lookupIdentifiersInSourceFile(this.sourceFile, 'CommonModule');
318+
const instances = lookupIdentifiersInSourceFile(this.sourceFile, importWithCommonRemovals);
312319
let foundImportDeclaration = false;
313320
let count = 0;
314321
for (let range of this.importRanges) {

packages/core/schematics/ng-generate/control-flow-migration/util.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,8 @@ import {Attribute, Element, HtmlParser, Node, ParseTreeResult, visitAll} from '@
1010
import {dirname, join} from 'path';
1111
import ts from 'typescript';
1212

13-
import {AnalyzedFile, CommonCollector, ElementCollector, ElementToMigrate, endI18nMarker, endMarker, i18nCollector, ParseResult, startI18nMarker, startMarker, Template, TemplateCollector} from './types';
13+
import {AnalyzedFile, CommonCollector, ElementCollector, ElementToMigrate, endI18nMarker, endMarker, i18nCollector, importRemovals, importWithCommonRemovals, ParseResult, startI18nMarker, startMarker, Template, TemplateCollector} from './types';
1414

15-
const importRemovals = [
16-
'NgIf', 'NgIfElse', 'NgIfThenElse', 'NgFor', 'NgForOf', 'NgForTrackBy', 'NgSwitch',
17-
'NgSwitchCase', 'NgSwitchDefault'
18-
];
19-
const importWithCommonRemovals = [...importRemovals, 'CommonModule'];
2015
const startMarkerRegex = new RegExp(startMarker, 'gm');
2116
const endMarkerRegex = new RegExp(endMarker, 'gm');
2217
const startI18nMarkerRegex = new RegExp(startI18nMarker, 'gm');

packages/core/schematics/test/control_flow_migration_spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5087,6 +5087,68 @@ describe('control flow migration', () => {
50875087

50885088
expect(actual).toBe(expected);
50895089
});
5090+
5091+
it('should not remove imports when mismatch in counts', async () => {
5092+
writeFile('/comp.ts', [
5093+
`import {CommonModule} from '@angular/common';`,
5094+
`import {Component, NgModule, Pipe, PipeTransform} from '@angular/core';`,
5095+
`@Component({`,
5096+
` selector: 'description',`,
5097+
` template: \`<span>{{getDescription()}}</span>\`,`,
5098+
`})`,
5099+
`export class DescriptionController {`,
5100+
` getDescription(): string {`,
5101+
` return 'stuff';`,
5102+
` }`,
5103+
`}`,
5104+
``,
5105+
`@Pipe({name: 'description'})`,
5106+
`export class DescriptionPipe implements PipeTransform {`,
5107+
` transform(nameString?: string): string {`,
5108+
` return nameString ?? '';`,
5109+
` }`,
5110+
`}`,
5111+
`@NgModule({`,
5112+
` declarations: [DescriptionController, DescriptionPipe],`,
5113+
` imports: [CommonModule],`,
5114+
` providers: [],`,
5115+
` exports: [DescriptionController, DescriptionPipe],`,
5116+
`})`,
5117+
`export class DescriptionModule {}`,
5118+
].join('\n'));
5119+
5120+
await runMigration();
5121+
const actual = tree.readContent('/comp.ts');
5122+
const expected = [
5123+
`import {CommonModule} from '@angular/common';`,
5124+
`import {Component, NgModule, Pipe, PipeTransform} from '@angular/core';`,
5125+
`@Component({`,
5126+
` selector: 'description',`,
5127+
` template: \`<span>{{getDescription()}}</span>\`,`,
5128+
`})`,
5129+
`export class DescriptionController {`,
5130+
` getDescription(): string {`,
5131+
` return 'stuff';`,
5132+
` }`,
5133+
`}`,
5134+
``,
5135+
`@Pipe({name: 'description'})`,
5136+
`export class DescriptionPipe implements PipeTransform {`,
5137+
` transform(nameString?: string): string {`,
5138+
` return nameString ?? '';`,
5139+
` }`,
5140+
`}`,
5141+
`@NgModule({`,
5142+
` declarations: [DescriptionController, DescriptionPipe],`,
5143+
` imports: [CommonModule],`,
5144+
` providers: [],`,
5145+
` exports: [DescriptionController, DescriptionPipe],`,
5146+
`})`,
5147+
`export class DescriptionModule {}`,
5148+
].join('\n');
5149+
5150+
expect(actual).toBe(expected);
5151+
});
50905152
});
50915153

50925154
describe('no migration needed', () => {

0 commit comments

Comments
 (0)