diff --git a/modules/@angular/compiler-cli/src/static_reflector.ts b/modules/@angular/compiler-cli/src/static_reflector.ts index dec1799bfc..80b9affa9e 100644 --- a/modules/@angular/compiler-cli/src/static_reflector.ts +++ b/modules/@angular/compiler-cli/src/static_reflector.ts @@ -516,6 +516,8 @@ export class StaticReflector implements ReflectorReader { if (expression['line']) { message = `${message} (position ${expression['line']+1}:${expression['character']+1} in the original .ts file)`; + throw positionalError( + message, context.filePath, expression['line'], expression['character']); } throw new Error(message); } @@ -529,7 +531,11 @@ export class StaticReflector implements ReflectorReader { try { return simplify(value); } catch (e) { - throw new Error(`${e.message}, resolving symbol ${context.name} in ${context.filePath}`); + const message = `${e.message}, resolving symbol ${context.name} in ${context.filePath}`; + if (e.fileName) { + throw positionalError(message, e.fileName, e.line, e.column); + } + throw new Error(message); } } @@ -659,3 +665,11 @@ function sameSymbol(a: StaticSymbol, b: StaticSymbol): boolean { function shouldIgnore(value: any): boolean { return value && value.__symbolic == 'ignore'; } + +function positionalError(message: string, fileName: string, line: number, column: number): Error { + const result = new Error(message); + (result as any).fileName = fileName; + (result as any).line = line; + (result as any).column = column; + return result; +} \ No newline at end of file diff --git a/modules/@angular/compiler-cli/test/static_reflector_spec.ts b/modules/@angular/compiler-cli/test/static_reflector_spec.ts index 536008b959..036f3a112d 100644 --- a/modules/@angular/compiler-cli/test/static_reflector_spec.ts +++ b/modules/@angular/compiler-cli/test/static_reflector_spec.ts @@ -337,6 +337,25 @@ describe('StaticReflector', () => { 'Recursion not supported, resolving symbol recursive in /tmp/src/function-recursive.d.ts, resolving symbol recursion in /tmp/src/function-reference.ts, resolving symbol in /tmp/src/function-reference.ts')); }); + it('should record data about the error in the exception', () => { + let threw = false; + try { + const metadata = host.getMetadataFor('/tmp/src/invalid-metadata.ts'); + expect(metadata).toBeDefined(); + if (!Array.isArray(metadata)) { + const moduleMetadata: any = metadata['metadata']; + expect(moduleMetadata).toBeDefined(); + const classData: any = moduleMetadata['InvalidMetadata']; + expect(classData).toBeDefined(); + simplify(new StaticSymbol('/tmp/src/invalid-metadata.ts', ''), classData.decorators[0]); + } + } catch (e) { + expect(e.fileName).toBe('/tmp/src/invalid-metadata.ts'); + threw = true; + } + expect(threw).toBe(true); + }); + it('should error on indirect recursive calls', () => { expect( () => simplify( @@ -1040,6 +1059,14 @@ class MockReflectorHost implements StaticReflectorHost { export class MethodReference { } + `, + '/tmp/src/invalid-metadata.ts': ` + import {Component} from 'angular2/src/core/metadata'; + + @Component({ + providers: [ { provider: 'a', useValue: (() => 1)() }] + }) + export class InvalidMetadata {} ` }; @@ -1047,7 +1074,8 @@ class MockReflectorHost implements StaticReflectorHost { if (data[moduleId] && moduleId.match(TS_EXT)) { let text = data[moduleId]; if (typeof text === 'string') { - let sf = ts.createSourceFile(moduleId, data[moduleId], ts.ScriptTarget.ES5); + let sf = ts.createSourceFile( + moduleId, data[moduleId], ts.ScriptTarget.ES5, /* setParentNodes */ true); let diagnostics: ts.Diagnostic[] = (sf).parseDiagnostics; if (diagnostics && diagnostics.length) { throw Error(`Error encountered during parse of file ${moduleId}`);