From 7764c5c697df8ceddf6e4a177b338ff9b9c7212a Mon Sep 17 00:00:00 2001 From: Chuck Jazdzewski Date: Tue, 4 Apr 2017 08:30:38 -0700 Subject: [PATCH] fix(language-service): avoid throwing exceptions when reporting metadata errors --- packages/compiler/src/metadata_resolver.ts | 8 +++++++- .../language-service/test/diagnostics_spec.ts | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/compiler/src/metadata_resolver.ts b/packages/compiler/src/metadata_resolver.ts index eee5ac8885..b1dfbb132f 100644 --- a/packages/compiler/src/metadata_resolver.ts +++ b/packages/compiler/src/metadata_resolver.ts @@ -529,6 +529,7 @@ export class CompileMetadataResolver { syntaxError( `Can't export ${this._getTypeDescriptor(exportedId.reference)} ${stringifyType(exportedId.reference)} from ${stringifyType(moduleType)} as it was neither declared nor imported!`), moduleType); + return; } }); @@ -627,6 +628,7 @@ export class CompileMetadataResolver { `Please consider moving ${stringifyType(type)} to a higher module that imports ${stringifyType(oldModule)} and ${stringifyType(moduleType)}. ` + `You can also create a new NgModule that exports and includes ${stringifyType(type)} then import that NgModule in ${stringifyType(oldModule)} and ${stringifyType(moduleType)}.`), moduleType); + return; } this._ngModuleOfTypes.set(type, moduleType); } @@ -860,6 +862,7 @@ export class CompileMetadataResolver { } else if (provider === void 0) { this._reportError(syntaxError( `Encountered undefined provider! Usually this means you have a circular dependencies (might be caused by using 'barrel' index.ts files.`)); + return; } else { const providersInfo = (providers.reduce( @@ -879,6 +882,7 @@ export class CompileMetadataResolver { syntaxError( `Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`), type); + return; } if (providerMeta.token === resolveIdentifier(Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS)) { targetEntryComponents.push(...this._getEntryComponentsFromProvider(providerMeta, type)); @@ -1002,8 +1006,10 @@ export class CompileMetadataResolver { syntaxError( `Can't construct a query for the property "${propertyName}" of "${stringifyType(typeOrFunc)}" since the query selector wasn't defined.`), typeOrFunc); + selectors = []; + } else { + selectors = [this._getTokenMetadata(q.selector)]; } - selectors = [this._getTokenMetadata(q.selector)]; } return { diff --git a/packages/language-service/test/diagnostics_spec.ts b/packages/language-service/test/diagnostics_spec.ts index 28b11f7976..07729cebb3 100644 --- a/packages/language-service/test/diagnostics_spec.ts +++ b/packages/language-service/test/diagnostics_spec.ts @@ -201,6 +201,25 @@ describe('diagnostics', () => { expect(diagnostic).toEqual([]); }); + + it('should report an error for invalid providers', () => { + addCode( + ` + @Component({ + template: '', + providers: [null] + }) + export class MyComponent {} + `, + fileName => { + const diagnostics = ngService.getDiagnostics(fileName); + const expected = diagnostics.find(d => d.message.startsWith('Invalid providers for')); + const notExpected = diagnostics.find(d => d.message.startsWith('Cannot read property')); + expect(expected).toBeDefined(); + expect(notExpected).toBeUndefined(); + }); + }); + function addCode(code: string, cb: (fileName: string, content?: string) => void) { const fileName = '/app/app.component.ts'; const originalContent = mockHost.getFileContent(fileName);