Files
angular/packages/compiler-cli/ngcc/src/analysis/private_declarations_analyzer.ts
2020-04-06 09:26:58 -07:00

74 lines
2.8 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript';
import {absoluteFromSourceFile, AbsoluteFsPath} from '../../../src/ngtsc/file_system';
import {ConcreteDeclaration} from '../../../src/ngtsc/reflection';
import {NgccReflectionHost} from '../host/ngcc_host';
import {hasNameIdentifier, isDefined} from '../utils';
import {NgccReferencesRegistry} from './ngcc_references_registry';
export interface ExportInfo {
identifier: string;
from: AbsoluteFsPath;
dtsFrom?: AbsoluteFsPath|null;
}
export type PrivateDeclarationsAnalyses = ExportInfo[];
/**
* This class will analyze a program to find all the declared classes
* (i.e. on an NgModule) that are not publicly exported via an entry-point.
*/
export class PrivateDeclarationsAnalyzer {
constructor(
private host: NgccReflectionHost, private referencesRegistry: NgccReferencesRegistry) {}
analyzeProgram(program: ts.Program): PrivateDeclarationsAnalyses {
const rootFiles = this.getRootFiles(program);
return this.getPrivateDeclarations(rootFiles, this.referencesRegistry.getDeclarationMap());
}
private getRootFiles(program: ts.Program): ts.SourceFile[] {
return program.getRootFileNames().map(f => program.getSourceFile(f)).filter(isDefined);
}
private getPrivateDeclarations(
rootFiles: ts.SourceFile[],
declarations: Map<ts.Identifier, ConcreteDeclaration>): PrivateDeclarationsAnalyses {
const privateDeclarations: Map<ts.Identifier, ConcreteDeclaration> = new Map(declarations);
rootFiles.forEach(f => {
const exports = this.host.getExportsOfModule(f);
if (exports) {
exports.forEach((declaration, exportedName) => {
if (declaration.node !== null && hasNameIdentifier(declaration.node)) {
if (privateDeclarations.has(declaration.node.name)) {
const privateDeclaration = privateDeclarations.get(declaration.node.name)!;
if (privateDeclaration.node !== declaration.node) {
throw new Error(`${declaration.node.name.text} is declared multiple times.`);
}
// This declaration is public so we can remove it from the list
privateDeclarations.delete(declaration.node.name);
}
}
});
}
});
return Array.from(privateDeclarations.keys()).map(id => {
const from = absoluteFromSourceFile(id.getSourceFile());
const declaration = privateDeclarations.get(id)!;
const dtsDeclaration = this.host.getDtsDeclaration(declaration.node);
const dtsFrom = dtsDeclaration && absoluteFromSourceFile(dtsDeclaration.getSourceFile());
return {identifier: id.text, from, dtsFrom};
});
}
}