fix(ivy): produce ts.Diagnostics for NgModule scope errors (#29191)
Previously, when the NgModule scope resolver discovered semantic errors within a users NgModules, it would throw assertion errors. TODOs in the codebase indicated these should become ts.Diagnostics eventually. Besides producing better-looking errors, there is another reason to make this change asap: these assertions were shadowing actual errors, via an interesting mechanism: 1) a component would produce a ts.Diagnostic during its analyze() step 2) as a result, it wouldn't register component metadata with the scope resolver 3) the NgModule for the component references it in exports, which was detected as an invalid export (no metadata registering it as a component). 4) the resulting assertion error would crash the compiler, hiding the real cause of the problem (an invalid component). This commit should mitigate this problem by converting scoping errors to proper ts.Diagnostics. Additionally, we should consider registering some marker indicating a class is a directive/component/pipe without actually requiring full metadata to be produced for it, which would allow suppression of errors like "invalid export" for such invalid types. PR Close #29191
This commit is contained in:

committed by
Kara Erickson

parent
fc305305e1
commit
c37ec8b255
@ -123,4 +123,7 @@ export interface CompileResult {
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface ResolveResult { reexports?: Reexport[]; }
|
||||
export interface ResolveResult {
|
||||
reexports?: Reexport[];
|
||||
diagnostics?: ts.Diagnostic[];
|
||||
}
|
||||
|
@ -247,15 +247,26 @@ export class IvyCompilation {
|
||||
for (const match of ivyClass.matchedHandlers) {
|
||||
if (match.handler.resolve !== undefined && match.analyzed !== null &&
|
||||
match.analyzed.analysis !== undefined) {
|
||||
const res = match.handler.resolve(node, match.analyzed.analysis);
|
||||
if (res.reexports !== undefined) {
|
||||
const fileName = node.getSourceFile().fileName;
|
||||
if (!this.reexportMap.has(fileName)) {
|
||||
this.reexportMap.set(fileName, new Map<string, [string, string]>());
|
||||
try {
|
||||
const res = match.handler.resolve(node, match.analyzed.analysis);
|
||||
if (res.reexports !== undefined) {
|
||||
const fileName = node.getSourceFile().fileName;
|
||||
if (!this.reexportMap.has(fileName)) {
|
||||
this.reexportMap.set(fileName, new Map<string, [string, string]>());
|
||||
}
|
||||
const fileReexports = this.reexportMap.get(fileName) !;
|
||||
for (const reexport of res.reexports) {
|
||||
fileReexports.set(reexport.asAlias, [reexport.fromModule, reexport.symbolName]);
|
||||
}
|
||||
}
|
||||
const fileReexports = this.reexportMap.get(fileName) !;
|
||||
for (const reexport of res.reexports) {
|
||||
fileReexports.set(reexport.asAlias, [reexport.fromModule, reexport.symbolName]);
|
||||
if (res.diagnostics !== undefined) {
|
||||
this._diagnostics.push(...res.diagnostics);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof FatalDiagnosticError) {
|
||||
this._diagnostics.push(err.toDiagnostic());
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user