fix(CompilerCli): assert that all pipes and directives are declared by a module
This commit is contained in:
parent
02f1222a8d
commit
7221632228
|
@ -11,7 +11,7 @@
|
||||||
* Intended to be used in a build step.
|
* Intended to be used in a build step.
|
||||||
*/
|
*/
|
||||||
import * as compiler from '@angular/compiler';
|
import * as compiler from '@angular/compiler';
|
||||||
import {Directive, NgModule, ViewEncapsulation} from '@angular/core';
|
import {ViewEncapsulation} from '@angular/core';
|
||||||
import {AngularCompilerOptions, NgcCliOptions} from '@angular/tsc-wrapped';
|
import {AngularCompilerOptions, NgcCliOptions} from '@angular/tsc-wrapped';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
@ -35,65 +35,11 @@ const PREAMBLE = `/**
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class CodeGeneratorModuleCollector {
|
|
||||||
constructor(
|
|
||||||
private staticReflector: StaticReflector, private reflectorHost: StaticReflectorHost,
|
|
||||||
private program: ts.Program, private options: AngularCompilerOptions) {}
|
|
||||||
|
|
||||||
getModuleSymbols(): StaticSymbol[] {
|
|
||||||
// Compare with false since the default should be true
|
|
||||||
const skipFileNames =
|
|
||||||
this.options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : GENERATED_FILES;
|
|
||||||
|
|
||||||
const ngModules: StaticSymbol[] = [];
|
|
||||||
|
|
||||||
this.program.getSourceFiles()
|
|
||||||
.filter(sourceFile => !skipFileNames.test(sourceFile.fileName))
|
|
||||||
.forEach(sourceFile => {
|
|
||||||
const absSrcPath = this.reflectorHost.getCanonicalFileName(sourceFile.fileName);
|
|
||||||
|
|
||||||
const moduleMetadata = this.staticReflector.getModuleMetadata(absSrcPath);
|
|
||||||
if (!moduleMetadata) {
|
|
||||||
console.log(`WARNING: no metadata found for ${absSrcPath}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const metadata = moduleMetadata['metadata'];
|
|
||||||
|
|
||||||
if (!metadata) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const symbol of Object.keys(metadata)) {
|
|
||||||
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
|
|
||||||
// Ignore symbols that are only included to record error information.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const staticType = this.reflectorHost.findDeclaration(absSrcPath, symbol, absSrcPath);
|
|
||||||
const annotations = this.staticReflector.annotations(staticType);
|
|
||||||
annotations.some((annotation) => {
|
|
||||||
if (annotation instanceof NgModule) {
|
|
||||||
ngModules.push(staticType);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ngModules;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CodeGenerator {
|
export class CodeGenerator {
|
||||||
private moduleCollector: CodeGeneratorModuleCollector;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private options: AngularCompilerOptions, private program: ts.Program,
|
private options: AngularCompilerOptions, private program: ts.Program,
|
||||||
public host: ts.CompilerHost, private staticReflector: StaticReflector,
|
public host: ts.CompilerHost, private staticReflector: StaticReflector,
|
||||||
private compiler: compiler.OfflineCompiler, private reflectorHost: StaticReflectorHost) {
|
private compiler: compiler.OfflineCompiler, private reflectorHost: StaticReflectorHost) {}
|
||||||
this.moduleCollector =
|
|
||||||
new CodeGeneratorModuleCollector(staticReflector, reflectorHost, program, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write codegen in a directory structure matching the sources.
|
// Write codegen in a directory structure matching the sources.
|
||||||
private calculateEmitPath(filePath: string): string {
|
private calculateEmitPath(filePath: string): string {
|
||||||
|
@ -118,10 +64,11 @@ export class CodeGenerator {
|
||||||
return path.join(this.options.genDir, relativePath);
|
return path.join(this.options.genDir, relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen(): Promise<any> {
|
codegen(options: {transitiveModules: boolean}): Promise<any> {
|
||||||
const ngModules = this.moduleCollector.getModuleSymbols();
|
const staticSymbols =
|
||||||
|
extractProgramSymbols(this.program, this.staticReflector, this.reflectorHost, this.options);
|
||||||
|
|
||||||
return this.compiler.compileModules(ngModules).then(generatedModules => {
|
return this.compiler.compileModules(staticSymbols, options).then(generatedModules => {
|
||||||
generatedModules.forEach(generatedModule => {
|
generatedModules.forEach(generatedModule => {
|
||||||
const sourceFile = this.program.getSourceFile(generatedModule.fileUrl);
|
const sourceFile = this.program.getSourceFile(generatedModule.fileUrl);
|
||||||
const emitPath = this.calculateEmitPath(generatedModule.moduleUrl);
|
const emitPath = this.calculateEmitPath(generatedModule.moduleUrl);
|
||||||
|
@ -194,3 +141,41 @@ export class CodeGenerator {
|
||||||
options, program, compilerHost, staticReflector, offlineCompiler, reflectorHost);
|
options, program, compilerHost, staticReflector, offlineCompiler, reflectorHost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function extractProgramSymbols(
|
||||||
|
program: ts.Program, staticReflector: StaticReflector, reflectorHost: StaticReflectorHost,
|
||||||
|
options: AngularCompilerOptions): StaticSymbol[] {
|
||||||
|
// Compare with false since the default should be true
|
||||||
|
const skipFileNames =
|
||||||
|
options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : GENERATED_FILES;
|
||||||
|
|
||||||
|
const staticSymbols: StaticSymbol[] = [];
|
||||||
|
|
||||||
|
program.getSourceFiles()
|
||||||
|
.filter(sourceFile => !skipFileNames.test(sourceFile.fileName))
|
||||||
|
.forEach(sourceFile => {
|
||||||
|
const absSrcPath = reflectorHost.getCanonicalFileName(sourceFile.fileName);
|
||||||
|
|
||||||
|
const moduleMetadata = staticReflector.getModuleMetadata(absSrcPath);
|
||||||
|
if (!moduleMetadata) {
|
||||||
|
console.log(`WARNING: no metadata found for ${absSrcPath}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const metadata = moduleMetadata['metadata'];
|
||||||
|
|
||||||
|
if (!metadata) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const symbol of Object.keys(metadata)) {
|
||||||
|
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
|
||||||
|
// Ignore symbols that are only included to record error information.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
staticSymbols.push(reflectorHost.findDeclaration(absSrcPath, symbol, absSrcPath));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return staticSymbols;
|
||||||
|
}
|
|
@ -9,23 +9,20 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract i18n messages from source code
|
* Extract i18n messages from source code
|
||||||
*
|
|
||||||
* TODO(vicb): factorize code with the CodeGenerator
|
|
||||||
*/
|
*/
|
||||||
// Must be imported first, because angular2 decorators throws on load.
|
// Must be imported first, because angular2 decorators throws on load.
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
|
|
||||||
import * as compiler from '@angular/compiler';
|
import * as compiler from '@angular/compiler';
|
||||||
import {Component, NgModule, ViewEncapsulation} from '@angular/core';
|
import {ViewEncapsulation} from '@angular/core';
|
||||||
import * as tsc from '@angular/tsc-wrapped';
|
import * as tsc from '@angular/tsc-wrapped';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ReflectorHost, ReflectorHostContext} from './reflector_host';
|
import {extractProgramSymbols} from './codegen';
|
||||||
|
import {ReflectorHost} from './reflector_host';
|
||||||
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
|
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
|
||||||
import {StaticReflector, StaticSymbol} from './static_reflector';
|
import {StaticReflector, StaticSymbol} from './static_reflector';
|
||||||
|
|
||||||
const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/;
|
|
||||||
|
|
||||||
export class Extractor {
|
export class Extractor {
|
||||||
constructor(
|
constructor(
|
||||||
private options: tsc.AngularCompilerOptions, private program: ts.Program,
|
private options: tsc.AngularCompilerOptions, private program: ts.Program,
|
||||||
|
@ -34,48 +31,13 @@ export class Extractor {
|
||||||
private metadataResolver: compiler.CompileMetadataResolver,
|
private metadataResolver: compiler.CompileMetadataResolver,
|
||||||
private directiveNormalizer: compiler.DirectiveNormalizer) {}
|
private directiveNormalizer: compiler.DirectiveNormalizer) {}
|
||||||
|
|
||||||
private readModuleSymbols(absSourcePath: string): StaticSymbol[] {
|
|
||||||
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
|
|
||||||
const modSymbols: StaticSymbol[] = [];
|
|
||||||
if (!moduleMetadata) {
|
|
||||||
console.log(`WARNING: no metadata found for ${absSourcePath}`);
|
|
||||||
return modSymbols;
|
|
||||||
}
|
|
||||||
|
|
||||||
const metadata = moduleMetadata['metadata'];
|
|
||||||
const symbols = metadata && Object.keys(metadata);
|
|
||||||
if (!symbols || !symbols.length) {
|
|
||||||
return modSymbols;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const symbol of symbols) {
|
|
||||||
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
|
|
||||||
// Ignore symbols that are only included to record error information.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const staticType = this.reflectorHost.findDeclaration(absSourcePath, symbol, absSourcePath);
|
|
||||||
const annotations = this.staticReflector.annotations(staticType);
|
|
||||||
|
|
||||||
annotations.some(a => {
|
|
||||||
if (a instanceof NgModule) {
|
|
||||||
modSymbols.push(staticType);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return modSymbols;
|
|
||||||
}
|
|
||||||
|
|
||||||
extract(): Promise<compiler.MessageBundle> {
|
extract(): Promise<compiler.MessageBundle> {
|
||||||
const filePaths =
|
const programSymbols: StaticSymbol[] =
|
||||||
this.program.getSourceFiles().map(sf => sf.fileName).filter(f => !GENERATED_FILES.test(f));
|
extractProgramSymbols(this.program, this.staticReflector, this.reflectorHost, this.options);
|
||||||
const ngModules: StaticSymbol[] = [];
|
|
||||||
|
|
||||||
filePaths.forEach((filePath) => ngModules.push(...this.readModuleSymbols(filePath)));
|
const files =
|
||||||
|
compiler.analyzeNgModules(programSymbols, {transitiveModules: true}, this.metadataResolver)
|
||||||
const files = compiler.analyzeNgModules(ngModules, this.metadataResolver).files;
|
.files;
|
||||||
const errors: compiler.ParseError[] = [];
|
const errors: compiler.ParseError[] = [];
|
||||||
const filePromises: Promise<any>[] = [];
|
const filePromises: Promise<any>[] = [];
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@ import {CodeGenerator} from './codegen';
|
||||||
function codegen(
|
function codegen(
|
||||||
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions, program: ts.Program,
|
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.NgcCliOptions, program: ts.Program,
|
||||||
host: ts.CompilerHost) {
|
host: ts.CompilerHost) {
|
||||||
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen();
|
return CodeGenerator.create(ngOptions, cliOptions, program, host).codegen({
|
||||||
|
transitiveModules: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLI entry point
|
// CLI entry point
|
||||||
|
|
|
@ -29,56 +29,81 @@ export class SourceModule {
|
||||||
|
|
||||||
// Returns all the source files and a mapping from modules to directives
|
// Returns all the source files and a mapping from modules to directives
|
||||||
export function analyzeNgModules(
|
export function analyzeNgModules(
|
||||||
ngModules: StaticSymbol[], metadataResolver: CompileMetadataResolver): {
|
programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean},
|
||||||
ngModuleByDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
metadataResolver: CompileMetadataResolver): {
|
||||||
|
ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
||||||
files: Array<{srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}>
|
files: Array<{srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}>
|
||||||
} {
|
} {
|
||||||
|
const {
|
||||||
|
ngModules: programNgModules,
|
||||||
|
pipesAndDirectives: programPipesOrDirectives,
|
||||||
|
} = _extractModulesAndPipesOrDirectives(programStaticSymbols, metadataResolver);
|
||||||
|
|
||||||
const moduleMetasByRef = new Map<any, CompileNgModuleMetadata>();
|
const moduleMetasByRef = new Map<any, CompileNgModuleMetadata>();
|
||||||
|
|
||||||
|
programNgModules.forEach(modMeta => {
|
||||||
|
if (options.transitiveModules) {
|
||||||
// For every input modules add the list of transitively included modules
|
// For every input modules add the list of transitively included modules
|
||||||
ngModules.forEach(ngModule => {
|
|
||||||
const modMeta = metadataResolver.getNgModuleMetadata(ngModule);
|
|
||||||
modMeta.transitiveModule.modules.forEach(
|
modMeta.transitiveModule.modules.forEach(
|
||||||
modMeta => { moduleMetasByRef.set(modMeta.type.reference, modMeta); });
|
modMeta => { moduleMetasByRef.set(modMeta.type.reference, modMeta); });
|
||||||
|
} else {
|
||||||
|
moduleMetasByRef.set(modMeta.type.reference, modMeta);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const ngModuleMetas = MapWrapper.values(moduleMetasByRef);
|
const ngModuleMetas = MapWrapper.values(moduleMetasByRef);
|
||||||
const ngModuleByDirective = new Map<StaticSymbol, CompileNgModuleMetadata>();
|
const ngModuleByPipeOrDirective = new Map<StaticSymbol, CompileNgModuleMetadata>();
|
||||||
const ngModulesByFile = new Map<string, StaticSymbol[]>();
|
const ngModulesByFile = new Map<string, StaticSymbol[]>();
|
||||||
const ngDirectivesByFile = new Map<string, StaticSymbol[]>();
|
const ngDirectivesByFile = new Map<string, StaticSymbol[]>();
|
||||||
const srcFileUrls = new Set<string>();
|
const filePaths = new Set<string>();
|
||||||
|
|
||||||
// Looping over all modules to construct:
|
// Looping over all modules to construct:
|
||||||
// - a map from files to modules `ngModulesByFile`,
|
// - a map from file to modules `ngModulesByFile`,
|
||||||
// - a map from files to directives `ngDirectivesByFile`,
|
// - a map from file to directives `ngDirectivesByFile`,
|
||||||
// - a map from modules to directives `ngModuleByDirective`.
|
// - a map from directive/pipe to module `ngModuleByPipeOrDirective`.
|
||||||
ngModuleMetas.forEach((ngModuleMeta) => {
|
ngModuleMetas.forEach((ngModuleMeta) => {
|
||||||
const srcFileUrl = ngModuleMeta.type.reference.filePath;
|
const srcFileUrl = ngModuleMeta.type.reference.filePath;
|
||||||
srcFileUrls.add(srcFileUrl);
|
filePaths.add(srcFileUrl);
|
||||||
ngModulesByFile.set(
|
ngModulesByFile.set(
|
||||||
srcFileUrl, (ngModulesByFile.get(srcFileUrl) || []).concat(ngModuleMeta.type.reference));
|
srcFileUrl, (ngModulesByFile.get(srcFileUrl) || []).concat(ngModuleMeta.type.reference));
|
||||||
|
|
||||||
ngModuleMeta.declaredDirectives.forEach((dirMeta: CompileDirectiveMetadata) => {
|
ngModuleMeta.declaredDirectives.forEach((dirMeta: CompileDirectiveMetadata) => {
|
||||||
const fileUrl = dirMeta.type.reference.filePath;
|
const fileUrl = dirMeta.type.reference.filePath;
|
||||||
srcFileUrls.add(fileUrl);
|
filePaths.add(fileUrl);
|
||||||
ngDirectivesByFile.set(
|
ngDirectivesByFile.set(
|
||||||
fileUrl, (ngDirectivesByFile.get(fileUrl) || []).concat(dirMeta.type.reference));
|
fileUrl, (ngDirectivesByFile.get(fileUrl) || []).concat(dirMeta.type.reference));
|
||||||
ngModuleByDirective.set(dirMeta.type.reference, ngModuleMeta);
|
ngModuleByPipeOrDirective.set(dirMeta.type.reference, ngModuleMeta);
|
||||||
|
});
|
||||||
|
|
||||||
|
ngModuleMeta.declaredPipes.forEach((pipeMeta: CompilePipeMetadata) => {
|
||||||
|
const fileUrl = pipeMeta.type.reference.filePath;
|
||||||
|
filePaths.add(fileUrl);
|
||||||
|
ngModuleByPipeOrDirective.set(pipeMeta.type.reference, ngModuleMeta);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Throw an error if any of the program pipe or directives is not declared by a module
|
||||||
|
const symbolsMissingModule =
|
||||||
|
programPipesOrDirectives.filter(s => !ngModuleByPipeOrDirective.has(s));
|
||||||
|
|
||||||
|
if (symbolsMissingModule.length) {
|
||||||
|
const messages = symbolsMissingModule.map(
|
||||||
|
s => `Cannot determine the module for class ${s.name} in ${s.filePath}!`);
|
||||||
|
throw new Error(messages.join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
const files: {srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}[] = [];
|
const files: {srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}[] = [];
|
||||||
|
|
||||||
srcFileUrls.forEach((srcUrl) => {
|
filePaths.forEach((srcUrl) => {
|
||||||
const directives = ngDirectivesByFile.get(srcUrl) || [];
|
const directives = ngDirectivesByFile.get(srcUrl) || [];
|
||||||
const ngModules = ngModulesByFile.get(srcUrl) || [];
|
const ngModules = ngModulesByFile.get(srcUrl) || [];
|
||||||
files.push({srcUrl, directives, ngModules});
|
files.push({srcUrl, directives, ngModules});
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// map from modules to declared directives
|
// map directive/pipe to module
|
||||||
ngModuleByDirective,
|
ngModuleByPipeOrDirective,
|
||||||
// list of modules and directives for every source file
|
// list modules and directives for every source file
|
||||||
files,
|
files,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -100,19 +125,21 @@ export class OfflineCompiler {
|
||||||
this._metadataResolver.clearCache();
|
this._metadataResolver.clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
compileModules(ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
compileModules(staticSymbols: StaticSymbol[], options: {transitiveModules: boolean}):
|
||||||
const {ngModuleByDirective, files} = analyzeNgModules(ngModules, this._metadataResolver);
|
Promise<SourceModule[]> {
|
||||||
|
const {ngModuleByPipeOrDirective, files} =
|
||||||
|
analyzeNgModules(staticSymbols, options, this._metadataResolver);
|
||||||
|
|
||||||
const sourceModules = files.map(
|
const sourceModules = files.map(
|
||||||
file => this._compileSrcFile(
|
file => this._compileSrcFile(
|
||||||
file.srcUrl, ngModuleByDirective, file.directives, file.ngModules));
|
file.srcUrl, ngModuleByPipeOrDirective, file.directives, file.ngModules));
|
||||||
|
|
||||||
return Promise.all(sourceModules)
|
return Promise.all(sourceModules)
|
||||||
.then((modules: SourceModule[][]) => ListWrapper.flatten(modules));
|
.then((modules: SourceModule[][]) => ListWrapper.flatten(modules));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _compileSrcFile(
|
private _compileSrcFile(
|
||||||
srcFileUrl: string, ngModuleByDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
srcFileUrl: string, ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
||||||
directives: StaticSymbol[], ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
directives: StaticSymbol[], ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||||
const fileSuffix = _splitTypescriptSuffix(srcFileUrl)[1];
|
const fileSuffix = _splitTypescriptSuffix(srcFileUrl)[1];
|
||||||
const statements: o.Statement[] = [];
|
const statements: o.Statement[] = [];
|
||||||
|
@ -134,9 +161,10 @@ export class OfflineCompiler {
|
||||||
if (!compMeta.isComponent) {
|
if (!compMeta.isComponent) {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
const ngModule = ngModuleByDirective.get(dirType);
|
const ngModule = ngModuleByPipeOrDirective.get(dirType);
|
||||||
if (!ngModule) {
|
if (!ngModule) {
|
||||||
throw new Error(`Cannot determine the module for component ${compMeta.type.name}!`);
|
throw new Error(
|
||||||
|
`Internal Error: cannot determine the module for component ${compMeta.type.name}!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise
|
return Promise
|
||||||
|
@ -330,3 +358,28 @@ function _splitTypescriptSuffix(path: string): string[] {
|
||||||
|
|
||||||
return [path, ''];
|
return [path, ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Group the symbols by types:
|
||||||
|
// - NgModules,
|
||||||
|
// - Pipes and Directives.
|
||||||
|
function _extractModulesAndPipesOrDirectives(
|
||||||
|
programStaticSymbols: StaticSymbol[], metadataResolver: CompileMetadataResolver) {
|
||||||
|
const ngModules: CompileNgModuleMetadata[] = [];
|
||||||
|
const pipesAndDirectives: StaticSymbol[] = [];
|
||||||
|
|
||||||
|
programStaticSymbols.forEach(staticSymbol => {
|
||||||
|
const ngModule = metadataResolver.getNgModuleMetadata(staticSymbol, false);
|
||||||
|
const directive = metadataResolver.getDirectiveMetadata(staticSymbol, false);
|
||||||
|
const pipe = metadataResolver.getPipeMetadata(<any>staticSymbol, false);
|
||||||
|
|
||||||
|
if (ngModule) {
|
||||||
|
ngModules.push(ngModule);
|
||||||
|
} else if (directive) {
|
||||||
|
pipesAndDirectives.push(staticSymbol);
|
||||||
|
} else if (pipe) {
|
||||||
|
pipesAndDirectives.push(staticSymbol);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {ngModules, pipesAndDirectives};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue