fix(ivy): process separate declarations and exports for summaries (#29193)

ngsummary files were generated with an export for each class declaration.
However, some Angular code declares classes (class Foo) and exports them
(export {Foo}) separately, which was causing incomplete summary files.

This commit expands the set of symbol names for which summary exports will
be generated, fixing this issue.

PR Close #29193
This commit is contained in:
Alex Rickabaugh
2019-03-08 13:18:32 -08:00
committed by Kara Erickson
parent 3a6ba00286
commit 49dccf4bfc
2 changed files with 43 additions and 10 deletions

View File

@ -34,16 +34,31 @@ export class SummaryGenerator implements ShimGenerator {
// to semantically understand which decorators are Angular decorators. It's okay to output an
// overly broad set of summary exports as the exports are no-ops anyway, and summaries are a
// compatibility layer which will be removed after Ivy is enabled.
const symbolNames = original
.statements
// Pick out top level class declarations...
.filter(ts.isClassDeclaration)
// which are named, exported, and have decorators.
.filter(
decl => isExported(decl) && decl.decorators !== undefined &&
decl.name !== undefined)
// Grab the symbol name.
.map(decl => decl.name !.text);
const symbolNames: string[] = [];
for (const stmt of original.statements) {
if (ts.isClassDeclaration(stmt)) {
// If the class isn't exported, or if it's not decorated, then skip it.
if (!isExported(stmt) || stmt.decorators === undefined || stmt.name === undefined) {
continue;
}
symbolNames.push(stmt.name.text);
} else if (ts.isExportDeclaration(stmt)) {
// Look for an export statement of the form "export {...};". If it doesn't match that, then
// skip it.
if (stmt.exportClause === undefined || stmt.moduleSpecifier !== undefined) {
continue;
}
for (const specifier of stmt.exportClause.elements) {
// At this point, there is no guarantee that specifier here refers to a class declaration,
// but that's okay.
// Use specifier.name as that's guaranteed to be the exported name, regardless of whether
// specifier.propertyName is set.
symbolNames.push(specifier.name.text);
}
}
}
const varLines = symbolNames.map(name => `export const ${name}NgSummary: any = null;`);