diff --git a/integration/ng_update_migrations/src/app/migration-tests/providers-test-module.ts b/integration/ng_update_migrations/src/app/migration-tests/providers-test-module.ts index cf35d63f11ac8e..392072d6d77970 100644 --- a/integration/ng_update_migrations/src/app/migration-tests/providers-test-module.ts +++ b/integration/ng_update_migrations/src/app/migration-tests/providers-test-module.ts @@ -8,7 +8,7 @@ export class ComponentProvider2 {} @Component({ template: '', viewProviders: [ComponentTypeProvider, [ - {provide: ComponentDontNeedCase, useExisting: ComponentProvider}] + {provide: ComponentDontNeedCase, useClass: ComponentProvider}] ], providers: [ComponentProvider2] }) @@ -21,7 +21,7 @@ export class DirectiveProvider {} @Directive({ selector: 'test-dir', providers: [DirectiveTypeProvider, [ - {provide: DirectiveDontNeedCase, useExisting: DirectiveProvider}] + {provide: DirectiveDontNeedCase, useClass: DirectiveProvider}] ], }) export class ProvidersTestDirective {} diff --git a/integration/ng_update_migrations/src/app/migration-tests/providers-test-module_expected.ts b/integration/ng_update_migrations/src/app/migration-tests/providers-test-module_expected.ts index c25fba964a6550..6daf48c87fb40b 100644 --- a/integration/ng_update_migrations/src/app/migration-tests/providers-test-module_expected.ts +++ b/integration/ng_update_migrations/src/app/migration-tests/providers-test-module_expected.ts @@ -11,7 +11,7 @@ export class ComponentProvider2 {} @Component({ template: '', viewProviders: [ComponentTypeProvider, [ - {provide: ComponentDontNeedCase, useExisting: ComponentProvider}] + {provide: ComponentDontNeedCase, useClass: ComponentProvider}] ], providers: [ComponentProvider2] }) @@ -26,7 +26,7 @@ export class DirectiveProvider {} @Directive({ selector: 'test-dir', providers: [DirectiveTypeProvider, [ - {provide: DirectiveDontNeedCase, useExisting: DirectiveProvider}] + {provide: DirectiveDontNeedCase, useClass: DirectiveProvider}] ], }) export class ProvidersTestDirective {} diff --git a/packages/core/schematics/migrations/missing-injectable/transform.ts b/packages/core/schematics/migrations/missing-injectable/transform.ts index 12a9c324a48e11..8a1fd27d33cc38 100644 --- a/packages/core/schematics/migrations/missing-injectable/transform.ts +++ b/packages/core/schematics/migrations/missing-injectable/transform.ts @@ -169,12 +169,11 @@ export class MissingInjectableTransform { if (value instanceof Reference && ts.isClassDeclaration(value.node)) { this.migrateProviderClass(value.node, module); } else if (value instanceof Map) { - if (!value.has('provide') || value.has('useValue') || value.has('useFactory')) { + if (!value.has('provide') || value.has('useValue') || value.has('useFactory') || + value.has('useExisting')) { return []; } - if (value.has('useExisting')) { - return this._visitProviderResolvedValue(value.get('useExisting') !, module); - } else if (value.has('useClass')) { + if (value.has('useClass')) { return this._visitProviderResolvedValue(value.get('useClass') !, module); } else { return this._visitProviderResolvedValue(value.get('provide') !, module); diff --git a/packages/core/schematics/test/google3/missing_injectable_rule_spec.ts b/packages/core/schematics/test/google3/missing_injectable_rule_spec.ts index a3fc1afc30d303..c1be822baa865b 100644 --- a/packages/core/schematics/test/google3/missing_injectable_rule_spec.ts +++ b/packages/core/schematics/test/google3/missing_injectable_rule_spec.ts @@ -151,7 +151,7 @@ describe('Google3 missing injectable tslint rule', () => { expect(getFile('/index.ts')).toMatch(/@Injectable\(\)\s+export class MyServiceB/); expect(getFile('/index.ts')).toMatch(/@Injectable\(\)\s+export class MyServiceC/); expect(getFile('/index.ts')).toMatch(/@Injectable\(\)\s+export class MyServiceD/); - expect(getFile('/index.ts')).toMatch(/@Injectable\(\)\s+export class MyServiceE/); + expect(getFile('/index.ts')).toMatch(/MyServiceD {}\s+export class MyServiceE/); expect(getFile('/index.ts')).toMatch(/MyServiceE {}\s+export class MyServiceF/); expect(getFile('/index.ts')).toMatch(/MyServiceF {}\s+export class MyServiceG/); }); diff --git a/packages/core/schematics/test/missing_injectable_migration_spec.ts b/packages/core/schematics/test/missing_injectable_migration_spec.ts index 3f9ba6b6bb45d2..75dbe9b86ce80a 100644 --- a/packages/core/schematics/test/missing_injectable_migration_spec.ts +++ b/packages/core/schematics/test/missing_injectable_migration_spec.ts @@ -189,24 +189,24 @@ describe('Missing injectable migration', () => { expect(tree.readContent('/index.ts')).not.toContain('@Injectable'); }); - it(`should migrate object literal provider with "useExisting" in ${type}`, async() => { + it(`should not migrate object literal provider with "useExisting" in ${type}`, async() => { writeFile('/index.ts', ` import {${type}} from '@angular/core'; export class MyService {} export class MyToken {} - @${type}({${propName}: [{provide: MyToken, useExisting: MyService}]}) + @${type}({${propName}: [ + {provide: MyService: useValue: null}, + {provide: MyToken, useExisting: MyService}, + ]}) export class TestClass {} `); await runMigration(); expect(warnOutput.length).toBe(0); - expect(tree.readContent('/index.ts')).toMatch(/@Injectable\(\)\s+export class MyService/); - expect(tree.readContent('/index.ts')).toMatch(/MyService {}\s+export class MyToken/); - expect(tree.readContent('/index.ts')) - .toContain(`{ ${type}, Injectable } from '@angular/core`); + expect(tree.readContent('/index.ts')).not.toContain('@Injectable'); }); it(`should migrate object literal provider with "useClass" in ${type}`, async() => { @@ -229,6 +229,41 @@ describe('Missing injectable migration', () => { .toContain(`{ ${type}, Injectable } from '@angular/core`); }); + it(`should not migrate references for providers with "useExisting" in ${type}, but migrate ` + + `existing token if declared in other ${type}`, + async() => { + writeFile('/index.ts', ` + import {${type}} from '@angular/core'; + + export class MyService {} + export class MyToken {} + + @${type}({ + ${propName}: [ + {provide: MyToken, useExisting: MyService}, + ], + }) + export class TestClass {} + `); + + writeFile('/other.ts', ` + import {${type} from '@angular/core'; + import {MyService} from './index'; + + export @${type}({ + ${propName}: [{provide: MyService}], + }) + export class OtherClass {} + `); + + await runMigration(); + + expect(warnOutput.length).toBe(0); + expect(tree.readContent('/index.ts')) + .toMatch(/@angular\/core';\s+@Injectable\(\)\s+export class MyService/); + expect(tree.readContent('/index.ts')).toMatch(/MyService {}\s+export class MyToken/); + }); + it('should not migrate provider which is already decorated with @Injectable', async() => { writeFile('/index.ts', ` import {Injectable, ${type}} from '@angular/core';