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:

committed by
Matias Niemelä

parent
5da96c75a2
commit
8d45fefc31
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
62
packages/compiler/src/aot/lazy_routes.ts
Normal file
62
packages/compiler/src/aot/lazy_routes.ts
Normal 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};
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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';
|
||||
|
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user