Permalink
Browse files

feat(compiler): enabled strict checking of parameters to an `@Injectable

` (#19412)

Added the compiler options `strictInjectionParameters` that defaults
to `false`. If enabled the compiler will report errors for parameters
of an `@Injectable` that cannot be determined instead of generating a
warning.

This is planned to be switched to default to `true` for Angular 6.0.
  • Loading branch information...
chuckjaz authored and vicb committed Sep 26, 2017
1 parent a75040d commit dfb8d21ef424dd3167ac41f0c575833fa119d697
@@ -52,6 +52,14 @@ export interface CompilerOptions extends ts.CompilerOptions {
// Don't produce .ngfactory.ts or .ngstyle.ts files
skipTemplateCodegen?: boolean;
// Always report errors when the type of a parameter supplied whose injection type cannot
// be determined. When this value option is not provided or is `false`, constructor
// parameters of classes marked with `@Injectable` whose type cannot be resolved will
// produce a warning. With this option `true`, they produce an error. When this option is
// not provided is treated as if it were `false`. In Angular 6.0, if this option is not
// provided, it will be treated as `true`.
strictInjectionParameters?: boolean;
// Whether to generate a flat module index of the given name and the corresponding
// flat module metadata. This option is intended to be used when creating flat
// modules similar to how `@angular/core` and `@angular/common` are packaged.
@@ -69,6 +69,7 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
enableLegacyTemplate: options.enableLegacyTemplate === true,
missingTranslation: options.missingTranslation,
preserveWhitespaces: options.preserveWhitespaces,
strictInjectionParameters: options.strictInjectionParameters,
});
const normalizer = new DirectiveNormalizer(
{get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config);
@@ -19,4 +19,5 @@ export interface AotCompilerOptions {
preserveWhitespaces?: boolean;
fullTemplateTypeCheck?: boolean;
allowEmptyCodegenFiles?: boolean;
strictInjectionParameters?: boolean;
}
@@ -21,24 +21,26 @@ export class CompilerConfig {
public jitDevMode: boolean;
public missingTranslation: MissingTranslationStrategy|null;
public preserveWhitespaces: boolean;
public strictInjectionParameters: boolean;
constructor(
{defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, jitDevMode = false,
missingTranslation, enableLegacyTemplate, preserveWhitespaces}: {
missingTranslation, enableLegacyTemplate, preserveWhitespaces, strictInjectionParameters}: {
defaultEncapsulation?: ViewEncapsulation,
useJit?: boolean,
jitDevMode?: boolean,
missingTranslation?: MissingTranslationStrategy,
enableLegacyTemplate?: boolean,
preserveWhitespaces?: boolean,
fullTemplateTypeCheck?: boolean
strictInjectionParameters?: boolean,
} = {}) {
this.defaultEncapsulation = defaultEncapsulation;
this.useJit = !!useJit;
this.jitDevMode = !!jitDevMode;
this.missingTranslation = missingTranslation || null;
this.enableLegacyTemplate = enableLegacyTemplate === true;
this.preserveWhitespaces = preserveWhitespacesDefault(noUndefined(preserveWhitespaces));
this.strictInjectionParameters = strictInjectionParameters === true;
}
}
@@ -886,10 +886,10 @@ export class CompileMetadataResolver {
dependenciesMetadata.map((dep) => dep ? stringifyType(dep.token) : '?').join(', ');
const message =
`Can't resolve all parameters for ${stringifyType(typeOrFunc)}: (${depsTokens}).`;
if (throwOnUnknownDeps) {
if (throwOnUnknownDeps || this._config.strictInjectionParameters) {
this._reportError(syntaxError(message), typeOrFunc);
} else {
this._console.warn(`Warning: ${message} This will become an error in Angular v5.x`);
this._console.warn(`Warning: ${message} This will become an error in Angular v6.x`);
}
}
@@ -205,10 +205,30 @@ describe('compiler (unbundled Angular)', () => {
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 v5.x`);
`Warning: Can't resolve all parameters for MyService in /app/app.ts: (?). This will become an error in Angular v6.x`);
});
it('should error if not all arguments of an @Injectable class can be resolved if strictInjectionParamters is true',
() => {
const FILES: MockDirectory = {
app: {
'app.ts': `
import {Injectable} from '@angular/core';
@Injectable()
export class MyService {
constructor(a: boolean) {}
}
`
}
};
const warnSpy = spyOn(console, 'warn');
expect(() => compile([FILES, angularFiles], {strictInjectionParameters: true}))
.toThrowError(`Can't resolve all parameters for MyService in /app/app.ts: (?).`);
expect(warnSpy).not.toHaveBeenCalled();
});
it('should be able to suppress a null access', () => {
const FILES: MockDirectory = {
app: {

0 comments on commit dfb8d21

Please sign in to comment.