Skip to content

Commit 4c8dd31

Browse files
committed
fix(material/schematics): migrate components selectively bug
Fixes mdc-migration to migrate only the selected components. Fixes #26426
1 parent 1564880 commit 4c8dd31

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

src/material/schematics/ng-generate/mdc-migration/rules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,5 @@ export const PERMANENT_MIGRATORS: ComponentMigrator[] = [
203203
styles: new TypographyHierarchyStylesMigrator(),
204204
},
205205
];
206+
207+
export const CORE_COMPONENTS = ['option', 'optgroup'];

src/material/schematics/ng-generate/mdc-migration/rules/ts-migration/runtime-migration.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import {Migration, getPropertyNameText} from '@angular/cdk/schematics';
1010
import {SchematicContext} from '@angular-devkit/schematics';
11-
import {ComponentMigrator, LEGACY_MODULES} from '../index';
11+
import {ComponentMigrator, CORE_COMPONENTS, LEGACY_MODULES} from '../index';
1212
import * as ts from 'typescript';
1313
import {ThemingStylesMigration} from '../theming-styles';
1414
import {TemplateMigration} from '../template-migration';
@@ -65,6 +65,16 @@ export class RuntimeCodeMigration extends Migration<ComponentMigrator[], Schemat
6565
});
6666
}
6767

68+
private _importPathHasComponentToMigrate(importTextPath: string): boolean {
69+
const lastImportName = importTextPath.split('/').slice(-1)[0];
70+
return !!this.upgradeData.find(componentMigrator => {
71+
return (
72+
lastImportName.includes(componentMigrator.component) ||
73+
(lastImportName === 'legacy-core' && CORE_COMPONENTS.includes(componentMigrator.component))
74+
);
75+
});
76+
}
77+
6878
/** Finds the imported symbols in a file that need to be migrated. */
6979
private _findImportsToMigrate(sourceFile: ts.SourceFile) {
7080
const importSpecifiersToNewNames = new Map<ts.ImportSpecifier, string>();
@@ -77,7 +87,8 @@ export class RuntimeCodeMigration extends Migration<ComponentMigrator[], Schemat
7787
ts.isStringLiteral(statement.moduleSpecifier) &&
7888
statement.importClause?.namedBindings &&
7989
ts.isNamedImports(statement.importClause.namedBindings) &&
80-
LEGACY_MODULES.has(statement.moduleSpecifier.text)
90+
LEGACY_MODULES.has(statement.moduleSpecifier.text) &&
91+
this._importPathHasComponentToMigrate(statement.moduleSpecifier.text)
8192
) {
8293
statement.importClause.namedBindings.elements.forEach(element => {
8394
const oldName = (element.propertyName || element.name).text;

src/material/schematics/ng-generate/mdc-migration/rules/ts-migration/runtime-migrator.spec.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,78 @@ describe('runtime code migration', () => {
385385
);
386386
});
387387

388+
it('should not replace imports from non selected components', async () => {
389+
declareLibrarySymbols('legacy-button', 'export declare class MatLegacyButtonModule {};');
390+
declareLibrarySymbols('legacy-checkbox', 'export declare class MatLegacyCheckboxModule {};');
391+
392+
await runMigrationTest(
393+
`
394+
import {NgModule} from '@angular/core';
395+
import {MatLegacyButtonModule} from '@angular/material/legacy-button';
396+
import {MatLegacyCheckboxModule} from '@angular/material/legacy-checkbox';
397+
398+
@NgModule({imports: [MatLegacyButtonModule, MatLegacyCheckboxModule]})
399+
export class AppModule {}
400+
`,
401+
`
402+
import {NgModule} from '@angular/core';
403+
import {MatButtonModule} from '@angular/material/button';
404+
import {MatLegacyCheckboxModule} from '@angular/material/legacy-checkbox';
405+
406+
@NgModule({imports: [MatButtonModule, MatLegacyCheckboxModule]})
407+
export class AppModule {}
408+
`,
409+
);
410+
});
411+
412+
it('should migrate legacy-core symbols when option or optgroup is choosen for migration', async () => {
413+
declareLibrarySymbols('legacy-select', 'export declare class MatLegacySelectModule {};');
414+
415+
async function runMigrationSelectTest(oldFileContent: string, newFileContent: string) {
416+
cliAppTree.overwrite(APP_MODULE_FILE, oldFileContent);
417+
const tree = await migrateComponents(['select'], runner, cliAppTree);
418+
expect(tree.readContent(APP_MODULE_FILE)).toBe(newFileContent);
419+
}
420+
421+
await runMigrationSelectTest(
422+
`
423+
import {NgModule} from '@angular/core';
424+
import {MatLegacySelectModule as MatSelectModule} from '@angular/material/legacy-select';
425+
import {MatLegacyOptionModule as MatOptionModule, LEGACY_VERSION as VERSION} from '@angular/material/legacy-core';
426+
427+
@NgModule({imports: [MatSelectModule, MatOptionModule]})
428+
export class AppModule {}
429+
`,
430+
`
431+
import {NgModule} from '@angular/core';
432+
import {MatSelectModule} from '@angular/material/select';
433+
import {MatOptionModule, VERSION} from '@angular/material/core';
434+
435+
@NgModule({imports: [MatSelectModule, MatOptionModule]})
436+
export class AppModule {}
437+
`,
438+
);
439+
});
440+
441+
it('should not migrate legacy-core symbols when option or optgroup are not choosen for migration', async () => {
442+
await runMigrationTest(
443+
`
444+
import {NgModule} from '@angular/core';
445+
import {MatLegacyOptionModule as MatOptionModule, LEGACY_VERSION as VERSION} from '@angular/material/legacy-core';
446+
447+
@NgModule({imports: [MatOptionModule]})
448+
export class AppModule {}
449+
`,
450+
`
451+
import {NgModule} from '@angular/core';
452+
import {MatLegacyOptionModule as MatOptionModule, LEGACY_VERSION as VERSION} from '@angular/material/legacy-core';
453+
454+
@NgModule({imports: [MatOptionModule]})
455+
export class AppModule {}
456+
`,
457+
);
458+
});
459+
388460
it('should migrate styles for a component', async () => {
389461
await runMigrationTest(
390462
`

0 commit comments

Comments
 (0)