fix(language-service): avoid throwing exceptions when reporting metadata errors

This commit is contained in:
Chuck Jazdzewski 2017-04-04 08:30:38 -07:00 committed by Alex Rickabaugh
parent c6917d9d4f
commit 7764c5c697
2 changed files with 26 additions and 1 deletions

View File

@ -529,6 +529,7 @@ export class CompileMetadataResolver {
syntaxError( syntaxError(
`Can't export ${this._getTypeDescriptor(exportedId.reference)} ${stringifyType(exportedId.reference)} from ${stringifyType(moduleType)} as it was neither declared nor imported!`), `Can't export ${this._getTypeDescriptor(exportedId.reference)} ${stringifyType(exportedId.reference)} from ${stringifyType(moduleType)} as it was neither declared nor imported!`),
moduleType); 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)}. ` + `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)}.`), `You can also create a new NgModule that exports and includes ${stringifyType(type)} then import that NgModule in ${stringifyType(oldModule)} and ${stringifyType(moduleType)}.`),
moduleType); moduleType);
return;
} }
this._ngModuleOfTypes.set(type, moduleType); this._ngModuleOfTypes.set(type, moduleType);
} }
@ -860,6 +862,7 @@ export class CompileMetadataResolver {
} else if (provider === void 0) { } else if (provider === void 0) {
this._reportError(syntaxError( this._reportError(syntaxError(
`Encountered undefined provider! Usually this means you have a circular dependencies (might be caused by using 'barrel' index.ts files.`)); `Encountered undefined provider! Usually this means you have a circular dependencies (might be caused by using 'barrel' index.ts files.`));
return;
} else { } else {
const providersInfo = const providersInfo =
(<string[]>providers.reduce( (<string[]>providers.reduce(
@ -879,6 +882,7 @@ export class CompileMetadataResolver {
syntaxError( syntaxError(
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`), `Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`),
type); type);
return;
} }
if (providerMeta.token === resolveIdentifier(Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS)) { if (providerMeta.token === resolveIdentifier(Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS)) {
targetEntryComponents.push(...this._getEntryComponentsFromProvider(providerMeta, type)); targetEntryComponents.push(...this._getEntryComponentsFromProvider(providerMeta, type));
@ -1002,8 +1006,10 @@ export class CompileMetadataResolver {
syntaxError( syntaxError(
`Can't construct a query for the property "${propertyName}" of "${stringifyType(typeOrFunc)}" since the query selector wasn't defined.`), `Can't construct a query for the property "${propertyName}" of "${stringifyType(typeOrFunc)}" since the query selector wasn't defined.`),
typeOrFunc); typeOrFunc);
selectors = [];
} else {
selectors = [this._getTokenMetadata(q.selector)];
} }
selectors = [this._getTokenMetadata(q.selector)];
} }
return { return {

View File

@ -201,6 +201,25 @@ describe('diagnostics', () => {
expect(diagnostic).toEqual([]); 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) { function addCode(code: string, cb: (fileName: string, content?: string) => void) {
const fileName = '/app/app.component.ts'; const fileName = '/app/app.component.ts';
const originalContent = mockHost.getFileContent(fileName); const originalContent = mockHost.getFileContent(fileName);