@angular/compiler
Version:
Angular - the compiler library
657 lines • 128 kB
JavaScript
/**
* @license
* Copyright Google LLC 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 { componentFactoryName, flatten, templateSourceUrl } from '../compile_metadata';
import { ConstantPool } from '../constant_pool';
import { ViewEncapsulation } from '../core';
import { MessageBundle } from '../i18n/message_bundle';
import { createTokenForExternalReference, Identifiers } from '../identifiers';
import { HtmlParser } from '../ml_parser/html_parser';
import { InterpolationConfig } from '../ml_parser/interpolation_config';
import * as o from '../output/output_ast';
import { identifierName, syntaxError } from '../parse_util';
import { newArray, visitValue } from '../util';
import { GeneratedFile } from './generated_file';
import { StaticSymbol } from './static_symbol';
import { createForJitStub, serializeSummaries } from './summary_serializer';
import { ngfactoryFilePath, normalizeGenFileSuffix, splitTypescriptSuffix, summaryFileName, summaryForJitFileName } from './util';
export class AotCompiler {
constructor(_config, _options, _host, reflector, _metadataResolver, _templateParser, _styleCompiler, _viewCompiler, _typeCheckCompiler, _ngModuleCompiler, _injectableCompiler, _outputEmitter, _summaryResolver, _symbolResolver) {
this._config = _config;
this._options = _options;
this._host = _host;
this.reflector = reflector;
this._metadataResolver = _metadataResolver;
this._templateParser = _templateParser;
this._styleCompiler = _styleCompiler;
this._viewCompiler = _viewCompiler;
this._typeCheckCompiler = _typeCheckCompiler;
this._ngModuleCompiler = _ngModuleCompiler;
this._injectableCompiler = _injectableCompiler;
this._outputEmitter = _outputEmitter;
this._summaryResolver = _summaryResolver;
this._symbolResolver = _symbolResolver;
this._templateAstCache = new Map();
this._analyzedFiles = new Map();
this._analyzedFilesForInjectables = new Map();
}
clearCache() {
this._metadataResolver.clearCache();
}
analyzeModulesSync(rootFiles) {
const analyzeResult = analyzeAndValidateNgModules(rootFiles, this._host, this._symbolResolver, this._metadataResolver);
analyzeResult.ngModules.forEach(ngModule => this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, true));
return analyzeResult;
}
analyzeModulesAsync(rootFiles) {
const analyzeResult = analyzeAndValidateNgModules(rootFiles, this._host, this._symbolResolver, this._metadataResolver);
return Promise
.all(analyzeResult.ngModules.map(ngModule => this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, false)))
.then(() => analyzeResult);
}
_analyzeFile(fileName) {
let analyzedFile = this._analyzedFiles.get(fileName);
if (!analyzedFile) {
analyzedFile =
analyzeFile(this._host, this._symbolResolver, this._metadataResolver, fileName);
this._analyzedFiles.set(fileName, analyzedFile);
}
return analyzedFile;
}
_analyzeFileForInjectables(fileName) {
let analyzedFile = this._analyzedFilesForInjectables.get(fileName);
if (!analyzedFile) {
analyzedFile = analyzeFileForInjectables(this._host, this._symbolResolver, this._metadataResolver, fileName);
this._analyzedFilesForInjectables.set(fileName, analyzedFile);
}
return analyzedFile;
}
findGeneratedFileNames(fileName) {
const genFileNames = [];
const file = this._analyzeFile(fileName);
// Make sure we create a .ngfactory if we have a injectable/directive/pipe/NgModule
// or a reference to a non source file.
// Note: This is overestimating the required .ngfactory files as the real calculation is harder.
// Only do this for StubEmitFlags.Basic, as adding a type check block
// does not change this file (as we generate type check blocks based on NgModules).
if (this._options.allowEmptyCodegenFiles || file.directives.length || file.pipes.length ||
file.injectables.length || file.ngModules.length || file.exportsNonSourceFiles) {
genFileNames.push(ngfactoryFilePath(file.fileName, true));
if (this._options.enableSummariesForJit) {
genFileNames.push(summaryForJitFileName(file.fileName, true));
}
}
const fileSuffix = normalizeGenFileSuffix(splitTypescriptSuffix(file.fileName, true)[1]);
file.directives.forEach((dirSymbol) => {
const compMeta = this._metadataResolver.getNonNormalizedDirectiveMetadata(dirSymbol).metadata;
if (!compMeta.isComponent) {
return;
}
// Note: compMeta is a component and therefore template is non null.
compMeta.template.styleUrls.forEach((styleUrl) => {
const normalizedUrl = this._host.resourceNameToFileName(styleUrl, file.fileName);
if (!normalizedUrl) {
throw syntaxError(`Couldn't resolve resource ${styleUrl} relative to ${file.fileName}`);
}
const needsShim = (compMeta.template.encapsulation ||
this._config.defaultEncapsulation) === ViewEncapsulation.Emulated;
genFileNames.push(_stylesModuleUrl(normalizedUrl, needsShim, fileSuffix));
if (this._options.allowEmptyCodegenFiles) {
genFileNames.push(_stylesModuleUrl(normalizedUrl, !needsShim, fileSuffix));
}
});
});
return genFileNames;
}
emitBasicStub(genFileName, originalFileName) {
const outputCtx = this._createOutputContext(genFileName);
if (genFileName.endsWith('.ngfactory.ts')) {
if (!originalFileName) {
throw new Error(`Assertion error: require the original file for .ngfactory.ts stubs. File: ${genFileName}`);
}
const originalFile = this._analyzeFile(originalFileName);
this._createNgFactoryStub(outputCtx, originalFile, 1 /* Basic */);
}
else if (genFileName.endsWith('.ngsummary.ts')) {
if (this._options.enableSummariesForJit) {
if (!originalFileName) {
throw new Error(`Assertion error: require the original file for .ngsummary.ts stubs. File: ${genFileName}`);
}
const originalFile = this._analyzeFile(originalFileName);
_createEmptyStub(outputCtx);
originalFile.ngModules.forEach(ngModule => {
// create exports that user code can reference
createForJitStub(outputCtx, ngModule.type.reference);
});
}
}
else if (genFileName.endsWith('.ngstyle.ts')) {
_createEmptyStub(outputCtx);
}
// Note: for the stubs, we don't need a property srcFileUrl,
// as later on in emitAllImpls we will create the proper GeneratedFiles with the
// correct srcFileUrl.
// This is good as e.g. for .ngstyle.ts files we can't derive
// the url of components based on the genFileUrl.
return this._codegenSourceModule('unknown', outputCtx);
}
emitTypeCheckStub(genFileName, originalFileName) {
const originalFile = this._analyzeFile(originalFileName);
const outputCtx = this._createOutputContext(genFileName);
if (genFileName.endsWith('.ngfactory.ts')) {
this._createNgFactoryStub(outputCtx, originalFile, 2 /* TypeCheck */);
}
return outputCtx.statements.length > 0 ?
this._codegenSourceModule(originalFile.fileName, outputCtx) :
null;
}
loadFilesAsync(fileNames, tsFiles) {
const files = fileNames.map(fileName => this._analyzeFile(fileName));
const loadingPromises = [];
files.forEach(file => file.ngModules.forEach(ngModule => loadingPromises.push(this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, false))));
const analyzedInjectables = tsFiles.map(tsFile => this._analyzeFileForInjectables(tsFile));
return Promise.all(loadingPromises).then(_ => ({
analyzedModules: mergeAndValidateNgFiles(files),
analyzedInjectables: analyzedInjectables,
}));
}
loadFilesSync(fileNames, tsFiles) {
const files = fileNames.map(fileName => this._analyzeFile(fileName));
files.forEach(file => file.ngModules.forEach(ngModule => this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(ngModule.type.reference, true)));
const analyzedInjectables = tsFiles.map(tsFile => this._analyzeFileForInjectables(tsFile));
return {
analyzedModules: mergeAndValidateNgFiles(files),
analyzedInjectables: analyzedInjectables,
};
}
_createNgFactoryStub(outputCtx, file, emitFlags) {
let componentId = 0;
file.ngModules.forEach((ngModuleMeta, ngModuleIndex) => {
// Note: the code below needs to executed for StubEmitFlags.Basic and StubEmitFlags.TypeCheck,
// so we don't change the .ngfactory file too much when adding the type-check block.
// create exports that user code can reference
this._ngModuleCompiler.createStub(outputCtx, ngModuleMeta.type.reference);
// add references to the symbols from the metadata.
// These can be used by the type check block for components,
// and they also cause TypeScript to include these files into the program too,
// which will make them part of the analyzedFiles.
const externalReferences = [
// Add references that are available from all the modules and imports.
...ngModuleMeta.transitiveModule.directives.map(d => d.reference),
...ngModuleMeta.transitiveModule.pipes.map(d => d.reference),
...ngModuleMeta.importedModules.map(m => m.type.reference),
...ngModuleMeta.exportedModules.map(m => m.type.reference),
// Add references that might be inserted by the template compiler.
...this._externalIdentifierReferences([Identifiers.TemplateRef, Identifiers.ElementRef]),
];
const externalReferenceVars = new Map();
externalReferences.forEach((ref, typeIndex) => {
externalReferenceVars.set(ref, `_decl${ngModuleIndex}_${typeIndex}`);
});
externalReferenceVars.forEach((varName, reference) => {
outputCtx.statements.push(o.variable(varName)
.set(o.NULL_EXPR.cast(o.DYNAMIC_TYPE))
.toDeclStmt(o.expressionType(outputCtx.importExpr(reference, /* typeParams */ null, /* useSummaries */ false))));
});
if (emitFlags & 2 /* TypeCheck */) {
// add the type-check block for all components of the NgModule
ngModuleMeta.declaredDirectives.forEach((dirId) => {
const compMeta = this._metadataResolver.getDirectiveMetadata(dirId.reference);
if (!compMeta.isComponent) {
return;
}
componentId++;
this._createTypeCheckBlock(outputCtx, `${compMeta.type.reference.name}_Host_${componentId}`, ngModuleMeta, this._metadataResolver.getHostComponentMetadata(compMeta), [compMeta.type], externalReferenceVars);
this._createTypeCheckBlock(outputCtx, `${compMeta.type.reference.name}_${componentId}`, ngModuleMeta, compMeta, ngModuleMeta.transitiveModule.directives, externalReferenceVars);
});
}
});
if (outputCtx.statements.length === 0) {
_createEmptyStub(outputCtx);
}
}
_externalIdentifierReferences(references) {
const result = [];
for (let reference of references) {
const token = createTokenForExternalReference(this.reflector, reference);
if (token.identifier) {
result.push(token.identifier.reference);
}
}
return result;
}
_createTypeCheckBlock(ctx, componentId, moduleMeta, compMeta, directives, externalReferenceVars) {
const { template: parsedTemplate, pipes: usedPipes } = this._parseTemplate(compMeta, moduleMeta, directives);
ctx.statements.push(...this._typeCheckCompiler.compileComponent(componentId, compMeta, parsedTemplate, usedPipes, externalReferenceVars, ctx));
}
emitMessageBundle(analyzeResult, locale) {
const errors = [];
const htmlParser = new HtmlParser();
// TODO(vicb): implicit tags & attributes
const messageBundle = new MessageBundle(htmlParser, [], {}, locale);
analyzeResult.files.forEach(file => {
const compMetas = [];
file.directives.forEach(directiveType => {
const dirMeta = this._metadataResolver.getDirectiveMetadata(directiveType);
if (dirMeta && dirMeta.isComponent) {
compMetas.push(dirMeta);
}
});
compMetas.forEach(compMeta => {
const html = compMeta.template.template;
// Template URL points to either an HTML or TS file depending on whether
// the file is used with `templateUrl:` or `template:`, respectively.
const templateUrl = compMeta.template.templateUrl;
const interpolationConfig = InterpolationConfig.fromArray(compMeta.template.interpolation);
errors.push(...messageBundle.updateFromTemplate(html, templateUrl, interpolationConfig));
});
});
if (errors.length) {
throw new Error(errors.map(e => e.toString()).join('\n'));
}
return messageBundle;
}
emitAllPartialModules2(files) {
// Using reduce like this is a select many pattern (where map is a select pattern)
return files.reduce((r, file) => {
r.push(...this._emitPartialModule2(file.fileName, file.injectables));
return r;
}, []);
}
_emitPartialModule2(fileName, injectables) {
const context = this._createOutputContext(fileName);
injectables.forEach(injectable => this._injectableCompiler.compile(injectable, context));
if (context.statements && context.statements.length > 0) {
return [{ fileName, statements: [...context.constantPool.statements, ...context.statements] }];
}
return [];
}
emitAllImpls(analyzeResult) {
const { ngModuleByPipeOrDirective, files } = analyzeResult;
const sourceModules = files.map(file => this._compileImplFile(file.fileName, ngModuleByPipeOrDirective, file.directives, file.pipes, file.ngModules, file.injectables));
return flatten(sourceModules);
}
_compileImplFile(srcFileUrl, ngModuleByPipeOrDirective, directives, pipes, ngModules, injectables) {
const fileSuffix = normalizeGenFileSuffix(splitTypescriptSuffix(srcFileUrl, true)[1]);
const generatedFiles = [];
const outputCtx = this._createOutputContext(ngfactoryFilePath(srcFileUrl, true));
generatedFiles.push(...this._createSummary(srcFileUrl, directives, pipes, ngModules, injectables, outputCtx));
// compile all ng modules
ngModules.forEach((ngModuleMeta) => this._compileModule(outputCtx, ngModuleMeta));
// compile components
directives.forEach((dirType) => {
const compMeta = this._metadataResolver.getDirectiveMetadata(dirType);
if (!compMeta.isComponent) {
return;
}
const ngModule = ngModuleByPipeOrDirective.get(dirType);
if (!ngModule) {
throw new Error(`Internal Error: cannot determine the module for component ${identifierName(compMeta.type)}!`);
}
// compile styles
const componentStylesheet = this._styleCompiler.compileComponent(outputCtx, compMeta);
// Note: compMeta is a component and therefore template is non null.
compMeta.template.externalStylesheets.forEach((stylesheetMeta) => {
// Note: fill non shim and shim style files as they might
// be shared by component with and without ViewEncapsulation.
const shim = this._styleCompiler.needsStyleShim(compMeta);
generatedFiles.push(this._codegenStyles(srcFileUrl, compMeta, stylesheetMeta, shim, fileSuffix));
if (this._options.allowEmptyCodegenFiles) {
generatedFiles.push(this._codegenStyles(srcFileUrl, compMeta, stylesheetMeta, !shim, fileSuffix));
}
});
// compile components
const compViewVars = this._compileComponent(outputCtx, compMeta, ngModule, ngModule.transitiveModule.directives, componentStylesheet, fileSuffix);
this._compileComponentFactory(outputCtx, compMeta, ngModule, fileSuffix);
});
if (outputCtx.statements.length > 0 || this._options.allowEmptyCodegenFiles) {
const srcModule = this._codegenSourceModule(srcFileUrl, outputCtx);
generatedFiles.unshift(srcModule);
}
return generatedFiles;
}
_createSummary(srcFileName, directives, pipes, ngModules, injectables, ngFactoryCtx) {
const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileName)
.map(symbol => this._symbolResolver.resolveSymbol(symbol));
const typeData = [
...ngModules.map(meta => ({
summary: this._metadataResolver.getNgModuleSummary(meta.type.reference),
metadata: this._metadataResolver.getNgModuleMetadata(meta.type.reference)
})),
...directives.map(ref => ({
summary: this._metadataResolver.getDirectiveSummary(ref),
metadata: this._metadataResolver.getDirectiveMetadata(ref)
})),
...pipes.map(ref => ({
summary: this._metadataResolver.getPipeSummary(ref),
metadata: this._metadataResolver.getPipeMetadata(ref)
})),
...injectables.map(ref => ({
summary: this._metadataResolver.getInjectableSummary(ref.symbol),
metadata: this._metadataResolver.getInjectableSummary(ref.symbol).type
}))
];
const forJitOutputCtx = this._options.enableSummariesForJit ?
this._createOutputContext(summaryForJitFileName(srcFileName, true)) :
null;
const { json, exportAs } = serializeSummaries(srcFileName, forJitOutputCtx, this._summaryResolver, this._symbolResolver, symbolSummaries, typeData, this._options.createExternalSymbolFactoryReexports);
exportAs.forEach((entry) => {
ngFactoryCtx.statements.push(o.variable(entry.exportAs).set(ngFactoryCtx.importExpr(entry.symbol)).toDeclStmt(null, [
o.StmtModifier.Exported
]));
});
const summaryJson = new GeneratedFile(srcFileName, summaryFileName(srcFileName), json);
const result = [summaryJson];
if (forJitOutputCtx) {
result.push(this._codegenSourceModule(srcFileName, forJitOutputCtx));
}
return result;
}
_compileModule(outputCtx, ngModule) {
const providers = [];
if (this._options.locale) {
const normalizedLocale = this._options.locale.replace(/_/g, '-');
providers.push({
token: createTokenForExternalReference(this.reflector, Identifiers.LOCALE_ID),
useValue: normalizedLocale,
});
}
if (this._options.i18nFormat) {
providers.push({
token: createTokenForExternalReference(this.reflector, Identifiers.TRANSLATIONS_FORMAT),
useValue: this._options.i18nFormat
});
}
this._ngModuleCompiler.compile(outputCtx, ngModule, providers);
}
_compileComponentFactory(outputCtx, compMeta, ngModule, fileSuffix) {
const hostMeta = this._metadataResolver.getHostComponentMetadata(compMeta);
const hostViewFactoryVar = this._compileComponent(outputCtx, hostMeta, ngModule, [compMeta.type], null, fileSuffix)
.viewClassVar;
const compFactoryVar = componentFactoryName(compMeta.type.reference);
const inputsExprs = [];
for (let propName in compMeta.inputs) {
const templateName = compMeta.inputs[propName];
// Don't quote so that the key gets minified...
inputsExprs.push(new o.LiteralMapEntry(propName, o.literal(templateName), false));
}
const outputsExprs = [];
for (let propName in compMeta.outputs) {
const templateName = compMeta.outputs[propName];
// Don't quote so that the key gets minified...
outputsExprs.push(new o.LiteralMapEntry(propName, o.literal(templateName), false));
}
outputCtx.statements.push(o.variable(compFactoryVar)
.set(o.importExpr(Identifiers.createComponentFactory).callFn([
o.literal(compMeta.selector), outputCtx.importExpr(compMeta.type.reference),
o.variable(hostViewFactoryVar), new o.LiteralMapExpr(inputsExprs),
new o.LiteralMapExpr(outputsExprs),
o.literalArr(compMeta.template.ngContentSelectors.map(selector => o.literal(selector)))
]))
.toDeclStmt(o.importType(Identifiers.ComponentFactory, [o.expressionType(outputCtx.importExpr(compMeta.type.reference))], [o.TypeModifier.Const]), [o.StmtModifier.Final, o.StmtModifier.Exported]));
}
_compileComponent(outputCtx, compMeta, ngModule, directiveIdentifiers, componentStyles, fileSuffix) {
const { template: parsedTemplate, pipes: usedPipes } = this._parseTemplate(compMeta, ngModule, directiveIdentifiers);
const stylesExpr = componentStyles ? o.variable(componentStyles.stylesVar) : o.literalArr([]);
const viewResult = this._viewCompiler.compileComponent(outputCtx, compMeta, parsedTemplate, stylesExpr, usedPipes);
if (componentStyles) {
_resolveStyleStatements(this._symbolResolver, componentStyles, this._styleCompiler.needsStyleShim(compMeta), fileSuffix);
}
return viewResult;
}
_parseTemplate(compMeta, ngModule, directiveIdentifiers) {
if (this._templateAstCache.has(compMeta.type.reference)) {
return this._templateAstCache.get(compMeta.type.reference);
}
const preserveWhitespaces = compMeta.template.preserveWhitespaces;
const directives = directiveIdentifiers.map(dir => this._metadataResolver.getDirectiveSummary(dir.reference));
const pipes = ngModule.transitiveModule.pipes.map(pipe => this._metadataResolver.getPipeSummary(pipe.reference));
const result = this._templateParser.parse(compMeta, compMeta.template.htmlAst, directives, pipes, ngModule.schemas, templateSourceUrl(ngModule.type, compMeta, compMeta.template), preserveWhitespaces);
this._templateAstCache.set(compMeta.type.reference, result);
return result;
}
_createOutputContext(genFilePath) {
const importExpr = (symbol, typeParams = null, useSummaries = true) => {
if (!(symbol instanceof StaticSymbol)) {
throw new Error(`Internal error: unknown identifier ${JSON.stringify(symbol)}`);
}
const arity = this._symbolResolver.getTypeArity(symbol) || 0;
const { filePath, name, members } = this._symbolResolver.getImportAs(symbol, useSummaries) || symbol;
const importModule = this._fileNameToModuleName(filePath, genFilePath);
// It should be good enough to compare filePath to genFilePath and if they are equal
// there is a self reference. However, ngfactory files generate to .ts but their
// symbols have .d.ts so a simple compare is insufficient. They should be canonical
// and is tracked by #17705.
const selfReference = this._fileNameToModuleName(genFilePath, genFilePath);
const moduleName = importModule === selfReference ? null : importModule;
// If we are in a type expression that refers to a generic type then supply
// the required type parameters. If there were not enough type parameters
// supplied, supply any as the type. Outside a type expression the reference
// should not supply type parameters and be treated as a simple value reference
// to the constructor function itself.
const suppliedTypeParams = typeParams || [];
const missingTypeParamsCount = arity - suppliedTypeParams.length;
const allTypeParams = suppliedTypeParams.concat(newArray(missingTypeParamsCount, o.DYNAMIC_TYPE));
return members.reduce((expr, memberName) => expr.prop(memberName), o.importExpr(new o.ExternalReference(moduleName, name, null), allTypeParams));
};
return { statements: [], genFilePath, importExpr, constantPool: new ConstantPool() };
}
_fileNameToModuleName(importedFilePath, containingFilePath) {
return this._summaryResolver.getKnownModuleName(importedFilePath) ||
this._symbolResolver.getKnownModuleName(importedFilePath) ||
this._host.fileNameToModuleName(importedFilePath, containingFilePath);
}
_codegenStyles(srcFileUrl, compMeta, stylesheetMetadata, isShimmed, fileSuffix) {
const outputCtx = this._createOutputContext(_stylesModuleUrl(stylesheetMetadata.moduleUrl, isShimmed, fileSuffix));
const compiledStylesheet = this._styleCompiler.compileStyles(outputCtx, compMeta, stylesheetMetadata, isShimmed);
_resolveStyleStatements(this._symbolResolver, compiledStylesheet, isShimmed, fileSuffix);
return this._codegenSourceModule(srcFileUrl, outputCtx);
}
_codegenSourceModule(srcFileUrl, ctx) {
return new GeneratedFile(srcFileUrl, ctx.genFilePath, ctx.statements);
}
}
function _createEmptyStub(outputCtx) {
// Note: We need to produce at least one import statement so that
// TypeScript knows that the file is an es6 module. Otherwise our generated
// exports / imports won't be emitted properly by TypeScript.
outputCtx.statements.push(o.importExpr(Identifiers.ComponentFactory).toStmt());
}
function _resolveStyleStatements(symbolResolver, compileResult, needsShim, fileSuffix) {
compileResult.dependencies.forEach((dep) => {
dep.setValue(symbolResolver.getStaticSymbol(_stylesModuleUrl(dep.moduleUrl, needsShim, fileSuffix), dep.name));
});
}
function _stylesModuleUrl(stylesheetUrl, shim, suffix) {
return `${stylesheetUrl}${shim ? '.shim' : ''}.ngstyle${suffix}`;
}
export function analyzeNgModules(fileNames, host, staticSymbolResolver, metadataResolver) {
const files = _analyzeFilesIncludingNonProgramFiles(fileNames, host, staticSymbolResolver, metadataResolver);
return mergeAnalyzedFiles(files);
}
export function analyzeAndValidateNgModules(fileNames, host, staticSymbolResolver, metadataResolver) {
return validateAnalyzedModules(analyzeNgModules(fileNames, host, staticSymbolResolver, metadataResolver));
}
function validateAnalyzedModules(analyzedModules) {
if (analyzedModules.symbolsMissingModule && analyzedModules.symbolsMissingModule.length) {
const messages = analyzedModules.symbolsMissingModule.map(s => `Cannot determine the module for class ${s.name} in ${s.filePath}! Add ${s.name} to the NgModule to fix it.`);
throw syntaxError(messages.join('\n'));
}
return analyzedModules;
}
// Analyzes all of the program files,
// including files that are not part of the program
// but are referenced by an NgModule.
function _analyzeFilesIncludingNonProgramFiles(fileNames, host, staticSymbolResolver, metadataResolver) {
const seenFiles = new Set();
const files = [];
const visitFile = (fileName) => {
if (seenFiles.has(fileName) || !host.isSourceFile(fileName)) {
return false;
}
seenFiles.add(fileName);
const analyzedFile = analyzeFile(host, staticSymbolResolver, metadataResolver, fileName);
files.push(analyzedFile);
analyzedFile.ngModules.forEach(ngModule => {
ngModule.transitiveModule.modules.forEach(modMeta => visitFile(modMeta.reference.filePath));
});
};
fileNames.forEach((fileName) => visitFile(fileName));
return files;
}
export function analyzeFile(host, staticSymbolResolver, metadataResolver, fileName) {
const abstractDirectives = [];
const directives = [];
const pipes = [];
const injectables = [];
const ngModules = [];
const hasDecorators = staticSymbolResolver.hasDecorators(fileName);
let exportsNonSourceFiles = false;
const isDeclarationFile = fileName.endsWith('.d.ts');
// Don't analyze .d.ts files that have no decorators as a shortcut
// to speed up the analysis. This prevents us from
// resolving the references in these files.
// Note: exportsNonSourceFiles is only needed when compiling with summaries,
// which is not the case when .d.ts files are treated as input files.
if (!isDeclarationFile || hasDecorators) {
staticSymbolResolver.getSymbolsOf(fileName).forEach((symbol) => {
const resolvedSymbol = staticSymbolResolver.resolveSymbol(symbol);
const symbolMeta = resolvedSymbol.metadata;
if (!symbolMeta || symbolMeta.__symbolic === 'error') {
return;
}
let isNgSymbol = false;
if (symbolMeta.__symbolic === 'class') {
if (metadataResolver.isDirective(symbol)) {
isNgSymbol = true;
// This directive either has a selector or doesn't. Selector-less directives get tracked
// in abstractDirectives, not directives. The compiler doesn't deal with selector-less
// directives at all, really, other than to persist their metadata. This is done so that
// apps will have an easier time migrating to Ivy, which requires the selector-less
// annotations to be applied.
if (!metadataResolver.isAbstractDirective(symbol)) {
// The directive is an ordinary directive.
directives.push(symbol);
}
else {
// The directive has no selector and is an "abstract" directive, so track it
// accordingly.
abstractDirectives.push(symbol);
}
}
else if (metadataResolver.isPipe(symbol)) {
isNgSymbol = true;
pipes.push(symbol);
}
else if (metadataResolver.isNgModule(symbol)) {
const ngModule = metadataResolver.getNgModuleMetadata(symbol, false);
if (ngModule) {
isNgSymbol = true;
ngModules.push(ngModule);
}
}
else if (metadataResolver.isInjectable(symbol)) {
isNgSymbol = true;
const injectable = metadataResolver.getInjectableMetadata(symbol, null, false);
if (injectable) {
injectables.push(injectable);
}
}
}
if (!isNgSymbol) {
exportsNonSourceFiles =
exportsNonSourceFiles || isValueExportingNonSourceFile(host, symbolMeta);
}
});
}
return {
fileName,
directives,
abstractDirectives,
pipes,
ngModules,
injectables,
exportsNonSourceFiles,
};
}
export function analyzeFileForInjectables(host, staticSymbolResolver, metadataResolver, fileName) {
const injectables = [];
const shallowModules = [];
if (staticSymbolResolver.hasDecorators(fileName)) {
staticSymbolResolver.getSymbolsOf(fileName).forEach((symbol) => {
const resolvedSymbol = staticSymbolResolver.resolveSymbol(symbol);
const symbolMeta = resolvedSymbol.metadata;
if (!symbolMeta || symbolMeta.__symbolic === 'error') {
return;
}
if (symbolMeta.__symbolic === 'class') {
if (metadataResolver.isInjectable(symbol)) {
const injectable = metadataResolver.getInjectableMetadata(symbol, null, false);
if (injectable) {
injectables.push(injectable);
}
}
else if (metadataResolver.isNgModule(symbol)) {
const module = metadataResolver.getShallowModuleMetadata(symbol);
if (module) {
shallowModules.push(module);
}
}
}
});
}
return { fileName, injectables, shallowModules };
}
function isValueExportingNonSourceFile(host, metadata) {
let exportsNonSourceFiles = false;
class Visitor {
visitArray(arr, context) {
arr.forEach(v => visitValue(v, this, context));
}
visitStringMap(map, context) {
Object.keys(map).forEach((key) => visitValue(map[key], this, context));
}
visitPrimitive(value, context) { }
visitOther(value, context) {
if (value instanceof StaticSymbol && !host.isSourceFile(value.filePath)) {
exportsNonSourceFiles = true;
}
}
}
visitValue(metadata, new Visitor(), null);
return exportsNonSourceFiles;
}
export function mergeAnalyzedFiles(analyzedFiles) {
const allNgModules = [];
const ngModuleByPipeOrDirective = new Map();
const allPipesAndDirectives = new Set();
analyzedFiles.forEach(af => {
af.ngModules.forEach(ngModule => {
allNgModules.push(ngModule);
ngModule.declaredDirectives.forEach(d => ngModuleByPipeOrDirective.set(d.reference, ngModule));
ngModule.declaredPipes.forEach(p => ngModuleByPipeOrDirective.set(p.reference, ngModule));
});
af.directives.forEach(d => allPipesAndDirectives.add(d));
af.pipes.forEach(p => allPipesAndDirectives.add(p));
});
const symbolsMissingModule = [];
allPipesAndDirectives.forEach(ref => {
if (!ngModuleByPipeOrDirective.has(ref)) {
symbolsMissingModule.push(ref);
}
});
return {
ngModules: allNgModules,
ngModuleByPipeOrDirective,
symbolsMissingModule,
files: analyzedFiles
};
}
function mergeAndValidateNgFiles(files) {
return validateAnalyzedModules(mergeAnalyzedFiles(files));
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGlsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvYW90L2NvbXBpbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBbVAsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLGlCQUFpQixFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFFdlUsT0FBTyxFQUFDLFlBQVksRUFBZ0IsTUFBTSxrQkFBa0IsQ0FBQztBQUM3RCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxTQUFTLENBQUM7QUFDMUMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBQywrQkFBK0IsRUFBRSxXQUFXLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUc1RSxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDcEQsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sbUNBQW1DLENBQUM7QUFHdEUsT0FBTyxLQUFLLENBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUMxQyxPQUFPLEVBQTRCLGNBQWMsRUFBYyxXQUFXLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFLakcsT0FBTyxFQUFDLFFBQVEsRUFBZ0IsVUFBVSxFQUFDLE1BQU0sU0FBUyxDQUFDO0FBTTNELE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUcvQyxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFN0MsT0FBTyxFQUFDLGdCQUFnQixFQUFFLGtCQUFrQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDMUUsT0FBTyxFQUFDLGlCQUFpQixFQUFFLHNCQUFzQixFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxxQkFBcUIsRUFBQyxNQUFNLFFBQVEsQ0FBQztBQVFoSSxNQUFNLE9BQU8sV0FBVztJQU10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