refactor(compiler): remove old ngtools api and add listLazyRoutes to new api (#19836)

Usages of `NgTools_InternalApi_NG_2` from `@angular/compiler-cli` will now
throw an error.

Adds `listLazyRoutes` to `@angular/compiler-cli/ngtools2.ts` for getting
the lazy routes of a `ng.Program`.
PR Close #19836
This commit is contained in:
Tobias Bosch
2017-10-20 09:46:41 -07:00
committed by Matias Niemelä
parent 5da96c75a2
commit 8d45fefc31
41 changed files with 1128 additions and 1837 deletions

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileStylesheetMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, flatten, identifierName, templateSourceUrl} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileStylesheetMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, flatten, identifierName, templateSourceUrl, tokenReference} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {ViewEncapsulation} from '../core';
import {MessageBundle} from '../i18n/message_bundle';
@ -29,6 +29,7 @@ import {ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler';
import {AotCompilerHost} from './compiler_host';
import {AotCompilerOptions} from './compiler_options';
import {GeneratedFile} from './generated_file';
import {LazyRoute, listLazyRoutes, parseLazyRoute} from './lazy_routes';
import {StaticReflector} from './static_reflector';
import {StaticSymbol} from './static_symbol';
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
@ -500,13 +501,13 @@ export class AotCompiler {
}
const arity = this._symbolResolver.getTypeArity(symbol) || 0;
const {filePath, name, members} = this._symbolResolver.getImportAs(symbol) || symbol;
const importModule = this._symbolResolver.fileNameToModuleName(filePath, genFilePath);
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._symbolResolver.fileNameToModuleName(genFilePath, genFilePath);
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
@ -527,6 +528,12 @@ export class AotCompiler {
return {statements: [], genFilePath, importExpr};
}
private _fileNameToModuleName(importedFilePath: string, containingFilePath: string): string {
return this._summaryResolver.getKnownModuleName(importedFilePath) ||
this._symbolResolver.getKnownModuleName(importedFilePath) ||
this._host.fileNameToModuleName(importedFilePath, containingFilePath);
}
private _codegenStyles(
srcFileUrl: string, compMeta: CompileDirectiveMetadata,
stylesheetMetadata: CompileStylesheetMetadata, isShimmed: boolean,
@ -542,6 +549,43 @@ export class AotCompiler {
private _codegenSourceModule(srcFileUrl: string, ctx: OutputContext): GeneratedFile {
return new GeneratedFile(srcFileUrl, ctx.genFilePath, ctx.statements);
}
listLazyRoutes(entryRoute?: string, analyzedModules?: NgAnalyzedModules): LazyRoute[] {
const self = this;
if (entryRoute) {
const symbol = parseLazyRoute(entryRoute, this._reflector).referencedModule;
return visitLazyRoute(symbol);
} else if (analyzedModules) {
const allLazyRoutes: LazyRoute[] = [];
for (const ngModule of analyzedModules.ngModules) {
const lazyRoutes = listLazyRoutes(ngModule, this._reflector);
for (const lazyRoute of lazyRoutes) {
allLazyRoutes.push(lazyRoute);
}
}
return allLazyRoutes;
} else {
throw new Error(`Either route or analyzedModules has to be specified!`);
}
function visitLazyRoute(
symbol: StaticSymbol, seenRoutes = new Set<StaticSymbol>(),
allLazyRoutes: LazyRoute[] = []): LazyRoute[] {
// Support pointing to default exports, but stop recursing there,
// as the StaticReflector does not yet support default exports.
if (seenRoutes.has(symbol) || !symbol.name) {
return allLazyRoutes;
}
seenRoutes.add(symbol);
const lazyRoutes = listLazyRoutes(
self._metadataResolver.getNgModuleMetadata(symbol, true) !, self._reflector);
for (const lazyRoute of lazyRoutes) {
allLazyRoutes.push(lazyRoute);
visitLazyRoute(lazyRoute.referencedModule, seenRoutes, allLazyRoutes);
}
return allLazyRoutes;
}
}
}
function _createEmptyStub(outputCtx: OutputContext) {

View File

@ -52,15 +52,18 @@ export function createAotUrlResolver(host: {
/**
* Creates a new AotCompiler based on options and a host.
*/
export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCompilerOptions):
{compiler: AotCompiler, reflector: StaticReflector} {
export function createAotCompiler(
compilerHost: AotCompilerHost, options: AotCompilerOptions,
errorCollector: (error: any, type?: any) =>
void): {compiler: AotCompiler, reflector: StaticReflector} {
let translations: string = options.translations || '';
const urlResolver = createAotUrlResolver(compilerHost);
const symbolCache = new StaticSymbolCache();
const summaryResolver = new AotSummaryResolver(compilerHost, symbolCache);
const symbolResolver = new StaticSymbolResolver(compilerHost, symbolCache, summaryResolver);
const staticReflector = new StaticReflector(summaryResolver, symbolResolver);
const staticReflector =
new StaticReflector(summaryResolver, symbolResolver, [], [], errorCollector);
const htmlParser = new I18NHtmlParser(
new HtmlParser(), translations, options.i18nFormat, options.missingTranslation, console);
const config = new CompilerConfig({
@ -80,7 +83,7 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
const resolver = new CompileMetadataResolver(
config, htmlParser, new NgModuleResolver(staticReflector),
new DirectiveResolver(staticReflector), new PipeResolver(staticReflector), summaryResolver,
elementSchemaRegistry, normalizer, console, symbolCache, staticReflector);
elementSchemaRegistry, normalizer, console, symbolCache, staticReflector, errorCollector);
// TODO(vicb): do not pass options.i18nFormat here
const viewCompiler = new ViewCompiler(staticReflector);
const typeCheckCompiler = new TypeCheckCompiler(options, staticReflector);

View File

@ -14,6 +14,13 @@ import {AotSummaryResolverHost} from './summary_resolver';
* services and from underlying file systems.
*/
export interface AotCompilerHost extends StaticSymbolResolverHost, AotSummaryResolverHost {
/**
* Converts a file path to a module name that can be used as an `import.
* I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`.
*
* See ImportResolver.
*/
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string;
/**
* Converts a path that refers to a resource into an absolute filePath
* that can be later on used for loading the resource via `loadResource.

View File

@ -0,0 +1,62 @@
/**
* @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 {CompileNgModuleMetadata, tokenReference} from '../compile_metadata';
import {Route} from '../core';
import {CompileMetadataResolver} from '../metadata_resolver';
import {AotCompilerHost} from './compiler_host';
import {StaticReflector} from './static_reflector';
import {StaticSymbol} from './static_symbol';
export interface LazyRoute {
module: StaticSymbol;
route: string;
referencedModule: StaticSymbol;
}
export function listLazyRoutes(
moduleMeta: CompileNgModuleMetadata, reflector: StaticReflector): LazyRoute[] {
const allLazyRoutes: LazyRoute[] = [];
for (const {provider, module} of moduleMeta.transitiveModule.providers) {
if (tokenReference(provider.token) === reflector.ROUTES) {
const loadChildren = _collectLoadChildren(provider.useValue);
for (const route of loadChildren) {
allLazyRoutes.push(parseLazyRoute(route, reflector, module.reference));
}
}
}
return allLazyRoutes;
}
function _collectLoadChildren(routes: string | Route | Route[], target: string[] = []): string[] {
if (typeof routes === 'string') {
target.push(routes);
} else if (Array.isArray(routes)) {
for (const route of routes) {
_collectLoadChildren(route, target);
}
} else if (routes.loadChildren) {
_collectLoadChildren(routes.loadChildren, target);
} else if (routes.children) {
_collectLoadChildren(routes.children, target);
}
return target;
}
export function parseLazyRoute(
route: string, reflector: StaticReflector, module?: StaticSymbol): LazyRoute {
const [routePath, routeName] = route.split('#');
const referencedModule = reflector.resolveExternalReference(
{
moduleName: routePath,
name: routeName,
},
module ? module.filePath : undefined);
return {route: route, module: module || referencedModule, referencedModule};
}

View File

@ -45,7 +45,7 @@ export class StaticReflector implements CompileReflector {
private conversionMap = new Map<StaticSymbol, (context: StaticSymbol, args: any[]) => any>();
private injectionToken: StaticSymbol;
private opaqueToken: StaticSymbol;
private ROUTES: StaticSymbol;
ROUTES: StaticSymbol;
private ANALYZE_FOR_ENTRY_COMPONENTS: StaticSymbol;
private annotationForParentClassWithSummaryKind =
new Map<CompileSummaryKind, MetadataFactory<any>[]>();
@ -76,8 +76,9 @@ export class StaticReflector implements CompileReflector {
return this.symbolResolver.getResourcePath(staticSymbol);
}
resolveExternalReference(ref: o.ExternalReference): StaticSymbol {
const refSymbol = this.symbolResolver.getSymbolByModule(ref.moduleName !, ref.name !);
resolveExternalReference(ref: o.ExternalReference, containingFile?: string): StaticSymbol {
const refSymbol =
this.symbolResolver.getSymbolByModule(ref.moduleName !, ref.name !, containingFile);
const declarationSymbol = this.findSymbolDeclaration(refSymbol);
this.symbolResolver.recordModuleNameForFileName(refSymbol.filePath, ref.moduleName !);
this.symbolResolver.recordImportAs(declarationSymbol, refSymbol);

View File

@ -39,13 +39,6 @@ export interface StaticSymbolResolverHost {
* `path/to/containingFile.ts` containing `import {...} from 'module-name'`.
*/
moduleNameToFileName(moduleName: string, containingFile?: string): string|null;
/**
* Converts a file path to a module name that can be used as an `import.
* I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`.
*
* See ImportResolver.
*/
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string;
}
const SUPPORTED_SCHEMA_VERSION = 4;
@ -160,15 +153,6 @@ export class StaticSymbolResolver {
return (resolvedSymbol && resolvedSymbol.metadata && resolvedSymbol.metadata.arity) || null;
}
/**
* Converts a file path to a module name that can be used as an `import`.
*/
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string {
return this.summaryResolver.getKnownModuleName(importedFilePath) ||
this.knownFileNameToModuleNames.get(importedFilePath) ||
this.host.fileNameToModuleName(importedFilePath, containingFilePath);
}
getKnownModuleName(filePath: string): string|null {
return this.knownFileNameToModuleNames.get(filePath) || null;
}
@ -498,9 +482,8 @@ export class StaticSymbolResolver {
const filePath = this.resolveModule(module, containingFile);
if (!filePath) {
this.reportError(
new Error(`Could not resolve module ${module}${containingFile ? ` relative to $ {
containingFile
} `: ''}`));
new Error(`Could not resolve module ${module}${containingFile ? ' relative to ' +
containingFile : ''}`));
return this.getStaticSymbol(`ERROR:${module}`, symbolName);
}
return this.getStaticSymbol(filePath, symbolName);

View File

@ -39,6 +39,7 @@ export * from './aot/static_reflector';
export * from './aot/static_symbol';
export * from './aot/static_symbol_resolver';
export * from './aot/summary_resolver';
export {LazyRoute} from './aot/lazy_routes';
export * from './ast_path';
export * from './summary_resolver';
export {Identifiers} from './identifiers';

View File

@ -260,3 +260,8 @@ function makeMetadataFactory<T>(name: string, props?: (...args: any[]) => T): Me
factory.ngMetadataName = name;
return factory;
}
export interface Route {
children?: Route[];
loadChildren?: string|Type|any;
}