From fdf6bc18ddf05d43185f713020f4c816b90ed360 Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Sat, 18 Jun 2016 18:42:34 +0200 Subject: [PATCH] fix(compiler): properly report unresolved dependencies Fixes #9332 Closes #9341 --- .../compiler/src/metadata_resolver.ts | 35 ++++++++++--------- .../compiler/test/metadata_resolver_spec.ts | 34 +++++++++++------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index aa86340a1d..b8366f3239 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -164,21 +164,23 @@ export class CompileMetadataResolver { } } - getTypeMetadata(type: Type, moduleUrl: string): cpl.CompileTypeMetadata { + getTypeMetadata(type: Type, moduleUrl: string, dependencies: any[] = null): + cpl.CompileTypeMetadata { return new cpl.CompileTypeMetadata({ name: this.sanitizeTokenName(type), moduleUrl: moduleUrl, runtime: type, - diDeps: this.getDependenciesMetadata(type, null) + diDeps: this.getDependenciesMetadata(type, dependencies) }); } - getFactoryMetadata(factory: Function, moduleUrl: string): cpl.CompileFactoryMetadata { + getFactoryMetadata(factory: Function, moduleUrl: string, dependencies: any[] = null): + cpl.CompileFactoryMetadata { return new cpl.CompileFactoryMetadata({ name: this.sanitizeTokenName(factory), moduleUrl: moduleUrl, runtime: factory, - diDeps: this.getDependenciesMetadata(factory, null) + diDeps: this.getDependenciesMetadata(factory, dependencies) }); } @@ -229,9 +231,6 @@ export class CompileMetadataResolver { params = []; } let dependenciesMetadata: cpl.CompileDiDependencyMetadata[] = params.map((param) => { - if (isBlank(param)) { - return null; - } let isAttribute = false; let isHost = false; let isSelf = false; @@ -330,21 +329,25 @@ export class CompileMetadataResolver { } getProviderMetadata(provider: Provider): cpl.CompileProviderMetadata { - var compileDeps: any /** TODO #9100 */; + var compileDeps: cpl.CompileDiDependencyMetadata[]; + var compileTypeMetadata: cpl.CompileTypeMetadata = null; + var compileFactoryMetadata: cpl.CompileFactoryMetadata = null; + if (isPresent(provider.useClass)) { - compileDeps = this.getDependenciesMetadata(provider.useClass, provider.dependencies); + compileTypeMetadata = this.getTypeMetadata( + provider.useClass, staticTypeModuleUrl(provider.useClass), provider.dependencies); + compileDeps = compileTypeMetadata.diDeps; } else if (isPresent(provider.useFactory)) { - compileDeps = this.getDependenciesMetadata(provider.useFactory, provider.dependencies); + compileFactoryMetadata = this.getFactoryMetadata( + provider.useFactory, staticTypeModuleUrl(provider.useFactory), provider.dependencies); + compileDeps = compileFactoryMetadata.diDeps; } + return new cpl.CompileProviderMetadata({ token: this.getTokenMetadata(provider.token), - useClass: isPresent(provider.useClass) ? - this.getTypeMetadata(provider.useClass, staticTypeModuleUrl(provider.useClass)) : - null, + useClass: compileTypeMetadata, useValue: convertToCompileValue(provider.useValue), - useFactory: isPresent(provider.useFactory) ? - this.getFactoryMetadata(provider.useFactory, staticTypeModuleUrl(provider.useFactory)) : - null, + useFactory: compileFactoryMetadata, useExisting: isPresent(provider.useExisting) ? this.getTokenMetadata(provider.useExisting) : null, deps: compileDeps, diff --git a/modules/@angular/compiler/test/metadata_resolver_spec.ts b/modules/@angular/compiler/test/metadata_resolver_spec.ts index d7d6492295..9d338be9ab 100644 --- a/modules/@angular/compiler/test/metadata_resolver_spec.ts +++ b/modules/@angular/compiler/test/metadata_resolver_spec.ts @@ -1,14 +1,13 @@ +import {CompilerConfig} from '@angular/compiler/src/config'; +import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, Component, Directive, DoCheck, Injectable, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation} from '@angular/core'; import {LIFECYCLE_HOOKS_VALUES} from '@angular/core/src/metadata/lifecycle_hooks'; import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal'; import {IS_DART, stringify} from '../src/facade/lang'; import {CompileMetadataResolver} from '../src/metadata_resolver'; -import {Component, Directive, ViewEncapsulation, ChangeDetectionStrategy, OnChanges, OnInit, DoCheck, OnDestroy, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, SimpleChanges,} from '@angular/core'; - -import {TEST_PROVIDERS} from './test_bindings'; -import {CompilerConfig} from '@angular/compiler/src/config'; import {MalformedStylesComponent} from './metadata_resolver_fixture'; +import {TEST_PROVIDERS} from './test_bindings'; export function main() { describe('CompileMetadataResolver', () => { @@ -49,18 +48,20 @@ export function main() { it('should throw when metadata is incorrectly typed', inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { - if (!IS_DART) { - expect(() => resolver.getDirectiveMetadata(MalformedStylesComponent)) - .toThrowError(`Expected 'styles' to be an array of strings.`); - } + expect(() => resolver.getDirectiveMetadata(MalformedStylesComponent)) + .toThrowError(`Expected 'styles' to be an array of strings.`); })); it('should throw with descriptive error message when provider token can not be resolved', inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { - if (!IS_DART) { - expect(() => resolver.getDirectiveMetadata(MyBrokenComp1)) - .toThrowError(`Can't resolve all parameters for MyBrokenComp1: (?).`); - } + expect(() => resolver.getDirectiveMetadata(MyBrokenComp1)) + .toThrowError(`Can't resolve all parameters for MyBrokenComp1: (?).`); + })); + + it('should throw with descriptive error message when a param token of a dependency is undefined', + inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { + expect(() => resolver.getDirectiveMetadata(MyBrokenComp2)) + .toThrowError(`Can't resolve all parameters for NonAnnotatedService: (?).`); })); it('should throw an error when the interpolation config has invalid symbols', @@ -152,6 +153,15 @@ class MyBrokenComp1 { constructor(public dependency: any) {} } +class NonAnnotatedService { + constructor(dep: any) {} +} + +@Component({selector: 'my-broken-comp', template: '', providers: [NonAnnotatedService]}) +class MyBrokenComp2 { + constructor(dependency: NonAnnotatedService) {} +} + @Component({selector: 'someSelector', template: '', interpolation: [' ', ' ']}) class ComponentWithInvalidInterpolation1 { }