From d0280a03350a804950e941bd0d06fa8bca64cc26 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Thu, 7 May 2020 21:35:54 +0200 Subject: [PATCH] fix(compiler): remove outdated and invalid warning for unresolved DI parameters (#36985) In past versions of the View Engine compiler, we added a warning that is printed whenever the compiler comes across an Angular declaration with a constructor that does not match suitable DI tokens. The warning mentioned that in `v6.x` it will turn into an actual error. This actually happened as expected for most cases. e.g. the constructor of `@NgModule`, `@Component`'s, `@Pipe`'s etc will be checked and an error will be reported if constructor is not DI compatible. The warning has never been removed though as it was still relevant for unprovided injectables, or injectables serialized into summaries of the Angular compiler. As of version 10, classes that use Angular features need an Angular decorator. This includes base classes of services that use the lifecycles Angular feature. Due to this being a common pattern now, we can remove the warning in View Engine. The warning is not correct, and also quite confusing as it mentions the planned removal in `v6.x`. Resolves FW-2147. PR Close #36985 --- packages/compiler/src/metadata_resolver.ts | 2 - packages/compiler/test/aot/compiler_spec.ts | 63 +++++++++++++++++---- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/packages/compiler/src/metadata_resolver.ts b/packages/compiler/src/metadata_resolver.ts index ff85eb216c..2fc245af37 100644 --- a/packages/compiler/src/metadata_resolver.ts +++ b/packages/compiler/src/metadata_resolver.ts @@ -989,8 +989,6 @@ export class CompileMetadataResolver { `Can't resolve all parameters for ${stringifyType(typeOrFunc)}: (${depsTokens}).`; if (throwOnUnknownDeps || this._config.strictInjectionParameters) { this._reportError(syntaxError(message), typeOrFunc); - } else { - this._console.warn(`Warning: ${message} This will become an error in Angular v6.x`); } } diff --git a/packages/compiler/test/aot/compiler_spec.ts b/packages/compiler/test/aot/compiler_spec.ts index 3084b9d390..c960a38e0a 100644 --- a/packages/compiler/test/aot/compiler_spec.ts +++ b/packages/compiler/test/aot/compiler_spec.ts @@ -190,23 +190,64 @@ describe('compiler (unbundled Angular)', () => { }); describe('errors', () => { - it('should only warn if not all arguments of an @Injectable class can be resolved', () => { + it('should not error or warn if an unprovided @Injectable with DI-incompatible ' + + 'constructor is discovered', + () => { + const FILES: MockDirectory = { + app: { + 'app.ts': ` + import {Injectable, NgModule} from '@angular/core'; + + // This injectable is not provided. It is used as a base class for another + // service but is not directly provided. It's allowed for such classes to + // have a decorator applied as they use Angular features. + @Injectable() + export class ServiceBase { + constructor(a: boolean) {} + + ngOnDestroy() {} + } + + @Injectable() + export class MyService extends ServiceBase { + constructor() { + super(true); + } + } + + @NgModule({providers: [MyService]}) + export class AppModule {} + ` + } + }; + + spyOn(console, 'error'); + spyOn(console, 'warn'); + expect(() => compile([FILES, angularFiles])).not.toThrowError(); + expect(console.warn).toHaveBeenCalledTimes(0); + expect(console.error).toHaveBeenCalledTimes(0); + }); + + it('should error if parameters of a provided @Injectable class cannot be resolved', () => { const FILES: MockDirectory = { app: { 'app.ts': ` - import {Injectable} from '@angular/core'; + import {Injectable, NgModule} from '@angular/core'; - @Injectable() - export class MyService { - constructor(a: boolean) {} - } - ` + @Injectable() + export class MyService { + constructor(a: boolean) {} + } + + @NgModule({ + providers: [MyService], + }) + export class MyModule {} + ` } }; - const warnSpy = spyOn(console, 'warn'); - compile([FILES, angularFiles]); - expect(warnSpy).toHaveBeenCalledWith( - `Warning: Can't resolve all parameters for MyService in /app/app.ts: (?). This will become an error in Angular v6.x`); + expect(() => compile([FILES, angularFiles])) + .toThrowError(`Can't resolve all parameters for MyService in /app/app.ts: (?).`); }); it('should error if not all arguments of an @Injectable class can be resolved if strictInjectionParameters is true',