mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
fix(migrations): avoid internal modules when generating imports (#48958)
Adds some logic to prefer non-Angular-internal modules when generating imports. This allows us to generate better code for some cases like the `ɵInternalFormsSharedModule` in Forms. Also adds some logic to prefer symbols that are already in the same file. Fixes #48942. PR Close #48958
This commit is contained in:
parent
49a7c9f94a
commit
32cf4e5cb9
2 changed files with 54 additions and 2 deletions
|
|
@ -310,6 +310,7 @@ function findImportLocation(
|
|||
target: Reference<NamedClassDeclaration>, inComponent: Reference<ts.ClassDeclaration>,
|
||||
importMode: PotentialImportMode, typeChecker: TemplateTypeChecker): PotentialImport|null {
|
||||
const importLocations = typeChecker.getPotentialImportsFor(target, inComponent.node, importMode);
|
||||
let firstSameFileImport: PotentialImport|null = null;
|
||||
let firstModuleImport: PotentialImport|null = null;
|
||||
|
||||
for (const location of importLocations) {
|
||||
|
|
@ -318,12 +319,17 @@ function findImportLocation(
|
|||
if (location.kind === PotentialImportKind.Standalone) {
|
||||
return location;
|
||||
}
|
||||
if (location.kind === PotentialImportKind.NgModule && !firstModuleImport) {
|
||||
if (!location.moduleSpecifier && !firstSameFileImport) {
|
||||
firstSameFileImport = location;
|
||||
}
|
||||
if (location.kind === PotentialImportKind.NgModule && !firstModuleImport &&
|
||||
// ɵ is used for some internal Angular modules that we want to skip over.
|
||||
!location.symbolName.startsWith('ɵ')) {
|
||||
firstModuleImport = location;
|
||||
}
|
||||
}
|
||||
|
||||
return firstModuleImport;
|
||||
return firstSameFileImport || firstModuleImport || importLocations[0] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -970,6 +970,52 @@ describe('standalone migration', () => {
|
|||
expect(myCompContent).toContain('imports: [ButtonModule]');
|
||||
});
|
||||
|
||||
it('should not reference internal modules', async () => {
|
||||
writeFile('./should-migrate/module.ts', `
|
||||
import {NgModule} from '@angular/core';
|
||||
import {MyComp} from './comp';
|
||||
import {ɵButtonModule} from '../do-not-migrate/button.module';
|
||||
|
||||
@NgModule({imports: [ɵButtonModule], declarations: [MyComp]})
|
||||
export class Mod {}
|
||||
`);
|
||||
|
||||
writeFile('./should-migrate/comp.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({selector: 'my-comp', template: '<my-button>Hello</my-button>'})
|
||||
export class MyComp {}
|
||||
`);
|
||||
|
||||
writeFile('./do-not-migrate/button.module.ts', `
|
||||
import {NgModule, forwardRef} from '@angular/core';
|
||||
import {MyButton} from './button';
|
||||
|
||||
@NgModule({
|
||||
imports: [forwardRef(() => ɵButtonModule)],
|
||||
exports: [forwardRef(() => ɵButtonModule)]
|
||||
})
|
||||
export class ExporterModule {}
|
||||
|
||||
@NgModule({declarations: [MyButton], exports: [MyButton]})
|
||||
export class ɵButtonModule {}
|
||||
`);
|
||||
|
||||
writeFile('./do-not-migrate/button.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({selector: 'my-button', template: '<ng-content></ng-content>'})
|
||||
export class MyButton {}
|
||||
`);
|
||||
|
||||
await runMigration('convert-to-standalone', './should-migrate');
|
||||
|
||||
const myCompContent = tree.readContent('./should-migrate/comp.ts');
|
||||
expect(myCompContent)
|
||||
.toContain(`import { ExporterModule } from '../do-not-migrate/button.module';`);
|
||||
expect(myCompContent).toContain('imports: [ExporterModule]');
|
||||
});
|
||||
|
||||
it('should migrate tests with a component declared through TestBed', async () => {
|
||||
writeFile('app.spec.ts', `
|
||||
import {NgModule, Component} from '@angular/core';
|
||||
|
|
|
|||
Loading…
Reference in a new issue