feat: add .ngsummary.ts files to support AOT unit tests

Design doc: https://docs.google.com/document/d/1VmTkz0EbEVSWfEEWEvQ5sXyQXSCvtMOw4t7pKU-jOwc/edit?usp=sharing
This commit is contained in:
Tobias Bosch
2017-04-26 09:24:42 -07:00
committed by Matias Niemelä
parent 2714644528
commit 547c363473
28 changed files with 1187 additions and 197 deletions

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers';
import {CompileMetadataResolver} from '../metadata_resolver';
@ -22,9 +22,9 @@ import {ViewCompiler} from '../view_compiler/view_compiler';
import {AotCompilerHost} from './compiler_host';
import {GeneratedFile} from './generated_file';
import {StaticSymbol} from './static_symbol';
import {StaticSymbolResolver} from './static_symbol_resolver';
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
import {serializeSummaries} from './summary_serializer';
import {ngfactoryFilePath, splitTypescriptSuffix, summaryFileName} from './util';
import {ngfactoryFilePath, splitTypescriptSuffix, summaryFileName, summaryForJitFileName, summaryForJitName} from './util';
export class AotCompiler {
constructor(
@ -59,12 +59,12 @@ export class AotCompiler {
srcFileUrl: string, ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
directives: StaticSymbol[], pipes: StaticSymbol[], ngModules: StaticSymbol[],
injectables: StaticSymbol[]): GeneratedFile[] {
const fileSuffix = splitTypescriptSuffix(srcFileUrl)[1];
const fileSuffix = splitTypescriptSuffix(srcFileUrl, true)[1];
const statements: o.Statement[] = [];
const exportedVars: string[] = [];
const generatedFiles: GeneratedFile[] = [];
generatedFiles.push(this._createSummary(
generatedFiles.push(...this._createSummary(
srcFileUrl, directives, pipes, ngModules, injectables, statements, exportedVars));
// compile all ng modules
@ -101,7 +101,7 @@ export class AotCompiler {
});
if (statements.length > 0) {
const srcModule = this._codegenSourceModule(
srcFileUrl, ngfactoryFilePath(srcFileUrl), statements, exportedVars);
srcFileUrl, ngfactoryFilePath(srcFileUrl, true), statements, exportedVars);
generatedFiles.unshift(srcModule);
}
return generatedFiles;
@ -110,23 +110,45 @@ export class AotCompiler {
private _createSummary(
srcFileUrl: string, directives: StaticSymbol[], pipes: StaticSymbol[],
ngModules: StaticSymbol[], injectables: StaticSymbol[], targetStatements: o.Statement[],
targetExportedVars: string[]): GeneratedFile {
targetExportedVars: string[]): GeneratedFile[] {
const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileUrl)
.map(symbol => this._symbolResolver.resolveSymbol(symbol));
const typeSummaries: CompileTypeSummary[] = [
...ngModules.map(ref => this._metadataResolver.getNgModuleSummary(ref) !),
...directives.map(ref => this._metadataResolver.getDirectiveSummary(ref) !),
...pipes.map(ref => this._metadataResolver.getPipeSummary(ref) !),
...injectables.map(ref => this._metadataResolver.getInjectableSummary(ref) !)
];
const {json, exportAs} = serializeSummaries(
this._summaryResolver, this._symbolResolver, symbolSummaries, typeSummaries);
const typeData: {
summary: CompileTypeSummary,
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
CompileTypeMetadata
}[] =
[
...ngModules.map(ref => ({
summary: this._metadataResolver.getNgModuleSummary(ref) !,
metadata: this._metadataResolver.getNgModuleMetadata(ref) !
})),
...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) !,
metadata: this._metadataResolver.getInjectableSummary(ref) !.type
}))
];
const {json, exportAs, forJit} =
serializeSummaries(this._summaryResolver, this._symbolResolver, symbolSummaries, typeData);
exportAs.forEach((entry) => {
targetStatements.push(
o.variable(entry.exportAs).set(o.importExpr({reference: entry.symbol})).toDeclStmt());
targetExportedVars.push(entry.exportAs);
});
return new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json);
return [
new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json),
this._codegenSourceModule(
srcFileUrl, summaryForJitFileName(srcFileUrl, true), forJit.statements,
forJit.exportedVars)
];
}
private _compileModule(ngModuleType: StaticSymbol, targetStatements: o.Statement[]): string {

View File

@ -35,7 +35,6 @@ import {StaticSymbolResolver} from './static_symbol_resolver';
import {AotSummaryResolver} from './summary_resolver';
/**
* Creates a new AotCompiler based on options and a host.
*/
@ -69,16 +68,10 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
new PipeResolver(staticReflector), summaryResolver, elementSchemaRegistry, normalizer,
console, symbolCache, staticReflector);
// TODO(vicb): do not pass options.i18nFormat here
const importResolver = {
getImportAs: (symbol: StaticSymbol) => symbolResolver.getImportAs(symbol) !,
fileNameToModuleName: (fileName: string, containingFilePath: string) =>
compilerHost.fileNameToModuleName(fileName, containingFilePath),
getTypeArity: (symbol: StaticSymbol) => symbolResolver.getTypeArity(symbol) !
};
const viewCompiler = new ViewCompiler(config, elementSchemaRegistry);
const compiler = new AotCompiler(
config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler,
new NgModuleCompiler(), new TypeScriptEmitter(importResolver), summaryResolver,
new NgModuleCompiler(), new TypeScriptEmitter(symbolResolver), summaryResolver,
options.locale || null, options.i18nFormat || null, options.genFilePreamble || null,
symbolResolver);
return {compiler, reflector: staticReflector};

View File

@ -14,14 +14,6 @@ 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|null;
/**
* Loads a resource (e.g. html / css)
*/

View File

@ -10,7 +10,7 @@ import {SummaryResolver} from '../summary_resolver';
import {ValueTransformer, visitValue} from '../util';
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
import {isNgFactoryFile} from './util';
import {isGeneratedFile, stripSummaryForJitFileSuffix, stripSummaryForJitNameSuffix, summaryForJitFileName, summaryForJitName} from './util';
export class ResolvedStaticSymbol {
constructor(public symbol: StaticSymbol, public metadata: any) {}
@ -39,6 +39,13 @@ 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|null;
}
const SUPPORTED_SCHEMA_VERSION = 3;
@ -60,6 +67,7 @@ export class StaticSymbolResolver {
private importAs = new Map<StaticSymbol, StaticSymbol>();
private symbolResourcePaths = new Map<StaticSymbol, string>();
private symbolFromFile = new Map<string, StaticSymbol[]>();
private knownFileNameToModuleNames = new Map<string, string>();
constructor(
private host: StaticSymbolResolverHost, private staticSymbolCache: StaticSymbolCache,
@ -103,6 +111,18 @@ export class StaticSymbolResolver {
this.getStaticSymbol(baseImportAs.filePath, baseImportAs.name, staticSymbol.members) :
null;
}
const summarizedFileName = stripSummaryForJitFileSuffix(staticSymbol.filePath);
if (summarizedFileName !== staticSymbol.filePath) {
const summarizedName = stripSummaryForJitNameSuffix(staticSymbol.name);
const baseSymbol =
this.getStaticSymbol(summarizedFileName, summarizedName, staticSymbol.members);
const baseImportAs = this.getImportAs(baseSymbol);
return baseImportAs ?
this.getStaticSymbol(
summaryForJitFileName(baseImportAs.filePath), summaryForJitName(baseImportAs.name),
baseSymbol.members) :
null;
}
let result = this.summaryResolver.getImportAs(staticSymbol);
if (!result) {
result = this.importAs.get(staticSymbol) !;
@ -124,11 +144,11 @@ export class StaticSymbolResolver {
* has. If the symbol is not a type the result is null.
*/
getTypeArity(staticSymbol: StaticSymbol): number|null {
// If the file is a factory file, don't resolve the symbol as doing so would
// cause the metadata for an factory file to be loaded which doesn't exist.
// If the file is a factory/ngsummary file, don't resolve the symbol as doing so would
// cause the metadata for an factory/ngsummary file to be loaded which doesn't exist.
// All references to generated classes must include the correct arity whenever
// generating code.
if (isNgFactoryFile(staticSymbol.filePath)) {
if (isGeneratedFile(staticSymbol.filePath)) {
return null;
}
let resolvedSymbol = this.resolveSymbol(staticSymbol);
@ -138,6 +158,17 @@ 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|null {
if (importedFilePath === containingFilePath) {
return null;
}
return this.knownFileNameToModuleNames.get(importedFilePath) ||
this.host.fileNameToModuleName(importedFilePath, containingFilePath);
}
recordImportAs(sourceSymbol: StaticSymbol, targetSymbol: StaticSymbol) {
sourceSymbol.assertNoMembers();
targetSymbol.assertNoMembers();
@ -226,6 +257,11 @@ export class StaticSymbolResolver {
this.resolvedFilePaths.add(filePath);
const resolvedSymbols: ResolvedStaticSymbol[] = [];
const metadata = this.getModuleMetadata(filePath);
if (metadata['importAs']) {
// Index bundle indices should use the importAs module name defined
// in the bundle.
this.knownFileNameToModuleNames.set(filePath, metadata['importAs']);
}
if (metadata['metadata']) {
// handle direct declarations of the symbol
const topLevelSymbolNames =
@ -236,13 +272,6 @@ export class StaticSymbolResolver {
const name = unescapeIdentifier(metadataKey);
const symbol = this.getStaticSymbol(filePath, name);
let importSymbol: StaticSymbol|undefined = undefined;
if (metadata['importAs']) {
// Index bundle indexes should use the importAs module name instead of a reference
// to the .d.ts file directly.
importSymbol = this.getStaticSymbol(metadata['importAs'], name);
this.recordImportAs(symbol, importSymbol);
}
const origin = origins.hasOwnProperty(metadataKey) && origins[metadataKey];
if (origin) {

View File

@ -10,7 +10,7 @@ import {Summary, SummaryResolver} from '../summary_resolver';
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
import {deserializeSummaries} from './summary_serializer';
import {ngfactoryFilePath, stripNgFactory, summaryFileName} from './util';
import {ngfactoryFilePath, stripGeneratedFileSuffix, summaryFileName} from './util';
export interface AotSummaryResolverHost {
/**
@ -43,7 +43,7 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
// Note: We need to strip the .ngfactory. file path,
// so this method also works for generated files
// (for which host.isSourceFile will always return false).
return !this.host.isSourceFile(stripNgFactory(filePath));
return !this.host.isSourceFile(stripGeneratedFileSuffix(filePath));
}
getLibraryFileName(filePath: string) { return this.host.getOutputFileName(filePath); }
@ -68,6 +68,8 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
return this.importAs.get(staticSymbol) !;
}
addSummary(summary: Summary<StaticSymbol>) { this.summaryCache.set(summary.symbol, summary); }
private _loadSummaryFile(filePath: string) {
if (this.loadedFilePaths.has(filePath)) {
return;

View File

@ -5,31 +5,40 @@
* 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 {CompileNgModuleSummary, CompileSummaryKind, CompileTypeSummary} from '../compile_metadata';
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary} from '../compile_metadata';
import * as o from '../output/output_ast';
import {Summary, SummaryResolver} from '../summary_resolver';
import {ValueTransformer, visitValue} from '../util';
import {ValueTransformer, ValueVisitor, visitValue} from '../util';
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
import {summaryForJitFileName, summaryForJitName} from './util';
export function serializeSummaries(
summaryResolver: SummaryResolver<StaticSymbol>, symbolResolver: StaticSymbolResolver,
symbols: ResolvedStaticSymbol[], types: CompileTypeSummary[]):
{json: string, exportAs: {symbol: StaticSymbol, exportAs: string}[]} {
const serializer = new Serializer(symbolResolver, summaryResolver);
symbols: ResolvedStaticSymbol[], types: {
summary: CompileTypeSummary,
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
CompileTypeMetadata
}[]): {
json: string,
exportAs: {symbol: StaticSymbol, exportAs: string}[],
forJit: {statements: o.Statement[], exportedVars: string[]}
} {
const toJsonSerializer = new ToJsonSerializer(symbolResolver, summaryResolver);
const forJitSerializer = new ForJitSerializer(symbolResolver);
// for symbols, we use everything except for the class metadata itself
// (we keep the statics though), as the class metadata is contained in the
// CompileTypeSummary.
symbols.forEach(
(resolvedSymbol) => serializer.addOrMergeSummary(
(resolvedSymbol) => toJsonSerializer.addOrMergeSummary(
{symbol: resolvedSymbol.symbol, metadata: resolvedSymbol.metadata}));
// Add summaries that are referenced by the given symbols (transitively)
// Note: the serializer.symbols array might be growing while
// we execute the loop!
for (let processedIndex = 0; processedIndex < serializer.symbols.length; processedIndex++) {
const symbol = serializer.symbols[processedIndex];
for (let processedIndex = 0; processedIndex < toJsonSerializer.symbols.length; processedIndex++) {
const symbol = toJsonSerializer.symbols[processedIndex];
if (summaryResolver.isLibraryFile(symbol.filePath)) {
let summary = summaryResolver.resolveSummary(symbol);
if (!summary) {
@ -42,7 +51,10 @@ export function serializeSummaries(
}
}
if (summary) {
serializer.addOrMergeSummary(summary);
if (summary.type) {
forJitSerializer.addLibType(summary.type);
}
toJsonSerializer.addOrMergeSummary(summary);
}
}
}
@ -51,32 +63,35 @@ export function serializeSummaries(
// Note: We don't add the summaries of all referenced symbols as for the ResolvedSymbols,
// as the type summaries already contain the transitive data that they require
// (in a minimal way).
types.forEach((typeSummary) => {
serializer.addOrMergeSummary(
{symbol: typeSummary.type.reference, metadata: null, type: typeSummary});
if (typeSummary.summaryKind === CompileSummaryKind.NgModule) {
const ngModuleSummary = <CompileNgModuleSummary>typeSummary;
types.forEach(({summary, metadata}) => {
forJitSerializer.addSourceType(summary, metadata);
toJsonSerializer.addOrMergeSummary(
{symbol: summary.type.reference, metadata: null, type: summary});
if (summary.summaryKind === CompileSummaryKind.NgModule) {
const ngModuleSummary = <CompileNgModuleSummary>summary;
ngModuleSummary.exportedDirectives.concat(ngModuleSummary.exportedPipes).forEach((id) => {
const symbol: StaticSymbol = id.reference;
if (summaryResolver.isLibraryFile(symbol.filePath)) {
const summary = summaryResolver.resolveSummary(symbol);
if (summary) {
serializer.addOrMergeSummary(summary);
toJsonSerializer.addOrMergeSummary(summary);
}
}
});
}
});
return serializer.serialize();
const {json, exportAs} = toJsonSerializer.serialize();
const {statements, exportedVars} = forJitSerializer.serialize(exportAs);
return {json, forJit: {statements, exportedVars}, exportAs};
}
export function deserializeSummaries(symbolCache: StaticSymbolCache, json: string):
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
const deserializer = new Deserializer(symbolCache);
const deserializer = new FromJsonDeserializer(symbolCache);
return deserializer.deserialize(json);
}
class Serializer extends ValueTransformer {
class ToJsonSerializer extends ValueTransformer {
// Note: This only contains symbols without members.
symbols: StaticSymbol[] = [];
private indexBySymbol = new Map<StaticSymbol, number>();
@ -169,7 +184,132 @@ class Serializer extends ValueTransformer {
}
}
class Deserializer extends ValueTransformer {
class ForJitSerializer {
private data = new Map<StaticSymbol, {
summary: CompileTypeSummary,
metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|CompilePipeMetadata|
CompileTypeMetadata|null,
isLibrary: boolean
}>();
constructor(private symbolResolver: StaticSymbolResolver) {}
addSourceType(
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|
CompilePipeMetadata|CompileTypeMetadata) {
this.data.set(summary.type.reference, {summary, metadata, isLibrary: false});
}
addLibType(summary: CompileTypeSummary) {
this.data.set(summary.type.reference, {summary, metadata: null, isLibrary: true});
}
serialize(exportAs: {symbol: StaticSymbol, exportAs: string}[]):
{statements: o.Statement[], exportedVars: string[]} {
const statements: o.Statement[] = [];
const exportedVars: string[] = [];
const ngModuleSymbols = new Set<StaticSymbol>();
Array.from(this.data.values()).forEach(({summary, metadata, isLibrary}) => {
if (summary.summaryKind === CompileSummaryKind.NgModule) {
// collect the symbols that refer to NgModule classes.
// Note: we can't just rely on `summary.type.summaryKind` to determine this as
// we don't add the summaries of all referenced symbols when we serialize type summaries.
// See serializeSummaries for details.
ngModuleSymbols.add(summary.type.reference);
const modSummary = <CompileNgModuleSummary>summary;
modSummary.modules.forEach((mod) => { ngModuleSymbols.add(mod.reference); });
}
if (!isLibrary) {
const fnName = summaryForJitName(summary.type.reference.name);
statements.push(
o.fn([], [new o.ReturnStatement(this.serializeSummaryWithDeps(summary, metadata !))],
new o.ArrayType(o.DYNAMIC_TYPE))
.toDeclStmt(fnName, [o.StmtModifier.Final]));
exportedVars.push(fnName);
}
});
exportAs.forEach((entry) => {
const symbol = entry.symbol;
if (ngModuleSymbols.has(symbol)) {
const jitExportAsName = summaryForJitName(entry.exportAs);
statements.push(
o.variable(jitExportAsName).set(this.serializeSummaryRef(symbol)).toDeclStmt());
exportedVars.push(jitExportAsName);
}
});
return {statements, exportedVars};
}
private serializeSummaryWithDeps(
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|
CompilePipeMetadata|CompileTypeMetadata): o.Expression {
const expressions: o.Expression[] = [this.serializeSummary(summary)];
let providers: CompileProviderMetadata[] = [];
if (metadata instanceof CompileNgModuleMetadata) {
expressions.push(...
// For directives / pipes, we only add the declared ones,
// and rely on transitively importing NgModules to get the transitive
// summaries.
metadata.declaredDirectives.concat(metadata.declaredPipes)
.map(type => type.reference)
// For modules,
// we also add the summaries for modules
// from libraries.
// This is ok as we produce reexports for all transitive modules.
.concat(metadata.transitiveModule.modules.map(type => type.reference)
.filter(ref => ref !== metadata.type.reference))
.map((ref) => this.serializeSummaryRef(ref)));
// Note: We don't use `NgModuleSummary.providers`, as that one is transitive,
// and we already have transitive modules.
providers = metadata.providers;
} else if (summary.summaryKind === CompileSummaryKind.Directive) {
const dirSummary = <CompileDirectiveSummary>summary;
providers = dirSummary.providers.concat(dirSummary.viewProviders);
}
// Note: We can't just refer to the `ngsummary.ts` files for `useClass` providers (as we do for
// declaredDirectives / declaredPipes), as we allow
// providers without ctor arguments to skip the `@Injectable` decorator,
// i.e. we didn't generate .ngsummary.ts files for these.
expressions.push(
...providers.filter(provider => !!provider.useClass).map(provider => this.serializeSummary({
summaryKind: CompileSummaryKind.Injectable, type: provider.useClass
} as CompileTypeSummary)));
return o.literalArr(expressions);
}
private serializeSummaryRef(typeSymbol: StaticSymbol): o.Expression {
const jitImportedSymbol = this.symbolResolver.getStaticSymbol(
summaryForJitFileName(typeSymbol.filePath), summaryForJitName(typeSymbol.name));
return o.importExpr({reference: jitImportedSymbol});
}
private serializeSummary(data: {[key: string]: any}): o.Expression {
class Transformer implements ValueVisitor {
visitArray(arr: any[], context: any): any {
return o.literalArr(arr.map(entry => visitValue(entry, this, context)));
}
visitStringMap(map: {[key: string]: any}, context: any): any {
return new o.LiteralMapExpr(Object.keys(map).map(
(key) => new o.LiteralMapEntry(key, visitValue(map[key], this, context))));
}
visitPrimitive(value: any, context: any): any { return o.literal(value); }
visitOther(value: any, context: any): any {
if (value instanceof StaticSymbol) {
return o.importExpr({reference: value});
} else {
throw new Error(`Illegal State: Encountered value ${value}`);
}
}
}
return visitValue(data, new Transformer(), null);
}
}
class FromJsonDeserializer extends ValueTransformer {
private symbols: StaticSymbol[];
constructor(private symbolCache: StaticSymbolCache) { super(); }

View File

@ -7,24 +7,27 @@
*/
const STRIP_SRC_FILE_SUFFIXES = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
const NG_FACTORY = /\.ngfactory\./;
const GENERATED_FILE = /\.ngfactory\.|\.ngsummary\./;
const GENERATED_MODULE = /\.ngfactory$|\.ngsummary$/;
const JIT_SUMMARY_FILE = /\.ngsummary\./;
const JIT_SUMMARY_NAME = /NgSummary$/;
export function ngfactoryFilePath(filePath: string): string {
const urlWithSuffix = splitTypescriptSuffix(filePath);
export function ngfactoryFilePath(filePath: string, forceSourceFile = false): string {
const urlWithSuffix = splitTypescriptSuffix(filePath, forceSourceFile);
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
}
export function stripNgFactory(filePath: string): string {
return filePath.replace(NG_FACTORY, '.');
export function stripGeneratedFileSuffix(filePath: string): string {
return filePath.replace(GENERATED_FILE, '.');
}
export function isNgFactoryFile(filePath: string): boolean {
return NG_FACTORY.test(filePath);
export function isGeneratedFile(filePath: string): boolean {
return GENERATED_FILE.test(filePath);
}
export function splitTypescriptSuffix(path: string): string[] {
export function splitTypescriptSuffix(path: string, forceSourceFile = false): string[] {
if (path.endsWith('.d.ts')) {
return [path.slice(0, -5), '.ts'];
return [path.slice(0, -5), forceSourceFile ? '.ts' : '.d.ts'];
}
const lastDot = path.lastIndexOf('.');
@ -40,3 +43,20 @@ export function summaryFileName(fileName: string): string {
const fileNameWithoutSuffix = fileName.replace(STRIP_SRC_FILE_SUFFIXES, '');
return `${fileNameWithoutSuffix}.ngsummary.json`;
}
export function summaryForJitFileName(fileName: string, forceSourceFile = false): string {
const urlWithSuffix = splitTypescriptSuffix(stripGeneratedFileSuffix(fileName), forceSourceFile);
return `${urlWithSuffix[0]}.ngsummary${urlWithSuffix[1]}`;
}
export function stripSummaryForJitFileSuffix(filePath: string): string {
return filePath.replace(JIT_SUMMARY_FILE, '.');
}
export function summaryForJitName(symbolName: string): string {
return `${symbolName}NgSummary`;
}
export function stripSummaryForJitNameSuffix(symbolName: string): string {
return symbolName.replace(JIT_SUMMARY_NAME, '');
}