fix(language-service): tolerate errors in decorators (#14634)

Fixes #14631
This commit is contained in:
Chuck Jazdzewski
2017-03-01 13:23:34 -08:00
committed by Igor Minar
parent 7a66a4115b
commit 6bae7378b1
8 changed files with 88 additions and 38 deletions

View File

@ -1,2 +1 @@
Tests in this directory are excluded from running in the browser and only running
in node.
Tests in this directory are excluded from running in the browser and only run in node.

View File

@ -8,6 +8,7 @@
import {StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, StaticSymbolResolverHost} from '@angular/compiler';
import {HostListener, Inject, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
import {CollectorOptions} from '@angular/tsc-wrapped';
import {MockStaticSymbolResolverHost, MockSummaryResolver} from './static_symbol_resolver_spec';
@ -19,11 +20,13 @@ describe('StaticReflector', () => {
function init(
testData: {[key: string]: any} = DEFAULT_TEST_DATA,
decorators: {name: string, filePath: string, ctor: any}[] = []) {
decorators: {name: string, filePath: string, ctor: any}[] = [],
errorRecorder?: (error: any, fileName: string) => void, collectorOptions?: CollectorOptions) {
const symbolCache = new StaticSymbolCache();
host = new MockStaticSymbolResolverHost(testData);
symbolResolver = new StaticSymbolResolver(host, symbolCache, new MockSummaryResolver([]));
reflector = new StaticReflector(symbolResolver, decorators);
host = new MockStaticSymbolResolverHost(testData, collectorOptions);
symbolResolver =
new StaticSymbolResolver(host, symbolCache, new MockSummaryResolver([]), errorRecorder);
reflector = new StaticReflector(symbolResolver, decorators, [], errorRecorder);
noContext = reflector.getStaticSymbol('', '');
}
@ -492,6 +495,31 @@ describe('StaticReflector', () => {
expect(() => reflector.propMetadata(appComponent)).not.toThrow();
});
it('should produce a annotation even if it contains errors', () => {
const data = Object.create(DEFAULT_TEST_DATA);
const file = '/tmp/src/invalid-component.ts';
data[file] = `
import {Component} from '@angular/core';
@Component({
selector: 'tmp',
template: () => {},
providers: [1, 2, (() => {}), 3, !(() => {}), 4, 5, (() => {}) + (() => {}), 6, 7]
})
export class BadComponent {
}
`;
init(data, [], () => {}, {verboseInvalidExpression: true});
const badComponent = reflector.getStaticSymbol(file, 'BadComponent');
const annotations = reflector.annotations(badComponent);
const annotation = annotations[0];
expect(annotation.selector).toEqual('tmp');
expect(annotation.template).toBeUndefined();
expect(annotation.providers).toEqual([1, 2, 3, 4, 5, 6, 7]);
});
describe('inheritance', () => {
class ClassDecorator {
constructor(public value: any) {}
@ -1264,5 +1292,5 @@ const DEFAULT_TEST_DATA: {[key: string]: any} = {
export class Dep {
@Input f: Forward;
}
`,
`
};

View File

@ -7,11 +7,10 @@
*/
import {StaticSymbol, StaticSymbolCache, StaticSymbolResolver, StaticSymbolResolverHost, Summary, SummaryResolver} from '@angular/compiler';
import {MetadataCollector} from '@angular/tsc-wrapped';
import {CollectorOptions, MetadataCollector} from '@angular/tsc-wrapped';
import * as ts from 'typescript';
// This matches .ts files but not .d.ts files.
const TS_EXT = /(^.|(?!\.d)..)\.ts$/;
@ -366,9 +365,11 @@ export class MockSummaryResolver implements SummaryResolver<StaticSymbol> {
}
export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
private collector = new MetadataCollector();
private collector: MetadataCollector;
constructor(private data: {[key: string]: any}) {}
constructor(private data: {[key: string]: any}, collectorOptions?: CollectorOptions) {
this.collector = new MetadataCollector(collectorOptions);
}
// In tests, assume that symbols are not re-exported
moduleNameToFileName(modulePath: string, containingFile?: string): string {