diff --git a/packages/core/schematics/migrations/missing-injectable/transform.ts b/packages/core/schematics/migrations/missing-injectable/transform.ts index aad21c9d12..f49f34b120 100644 --- a/packages/core/schematics/migrations/missing-injectable/transform.ts +++ b/packages/core/schematics/migrations/missing-injectable/transform.ts @@ -18,10 +18,14 @@ import {ResolvedDirective, ResolvedNgModule} from './definition_collector'; import {ProviderLiteral, ProvidersEvaluator} from './providers_evaluator'; import {UpdateRecorder} from './update_recorder'; - - -/** Name of decorators which imply that a given class does not need to be migrated. */ -const NO_MIGRATE_DECORATORS = ['Injectable', 'Directive', 'Component', 'Pipe']; +/** + * Name of decorators which imply that a given class does not need to be migrated. + * - `@Injectable`, `@Directive`, `@Component` and `@Pipe` instruct the compiler + * to generate a factory definition. + * - `@NgModule` instructs the compiler to generate a provider definition that holds + * the factory function. + */ +const NO_MIGRATE_DECORATORS = ['Injectable', 'Directive', 'Component', 'Pipe', 'NgModule']; export interface AnalysisFailure { node: ts.Node; diff --git a/packages/core/schematics/test/missing_injectable_migration_spec.ts b/packages/core/schematics/test/missing_injectable_migration_spec.ts index f07027a538..28e6787710 100644 --- a/packages/core/schematics/test/missing_injectable_migration_spec.ts +++ b/packages/core/schematics/test/missing_injectable_migration_spec.ts @@ -350,6 +350,24 @@ describe('Missing injectable migration', () => { expect(tree.readContent('/index.ts')).not.toContain('@Injectable'); }); + it('should not migrate provider which is already decorated with @NgModule', async () => { + const importedSymbols = type !== 'NgModule' ? ['NgModule', type] : ['NgModule']; + writeFile('/index.ts', ` + import {${importedSymbols.join(', ')}} from '@angular/core'; + + @NgModule() + export class MyOtherModule {} + + @${type}({${propName}: [MyOtherModule]}) + export class TestClass {} + `); + + await runMigration(); + + expect(warnOutput.length).toBe(0); + expect(tree.readContent('/index.ts')).not.toContain('@Injectable'); + }); + it(`should migrate multiple providers in same ${type}`, async () => { writeFile('/index.ts', ` import {${type}} from '@angular/core';