2016-11-29 15:36:33 -08:00
|
|
|
/**
|
|
|
|
|
* @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
|
|
|
|
|
*/
|
2016-12-02 10:08:46 -08:00
|
|
|
import {CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleSummary, CompilePipeSummary, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, identifierModuleUrl, identifierName} from '../compile_metadata';
|
2016-11-29 15:36:33 -08:00
|
|
|
import {SummaryResolver} from '../summary_resolver';
|
|
|
|
|
|
|
|
|
|
import {GeneratedFile} from './generated_file';
|
|
|
|
|
import {StaticReflector} from './static_reflector';
|
2016-12-05 13:26:12 -08:00
|
|
|
import {StaticSymbol} from './static_symbol';
|
2016-11-29 15:36:33 -08:00
|
|
|
import {filterFileByPatterns} from './utils';
|
|
|
|
|
|
|
|
|
|
const STRIP_SRC_FILE_SUFFIXES = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
|
|
|
|
|
|
|
|
|
|
export interface AotSummaryResolverHost {
|
|
|
|
|
/**
|
|
|
|
|
* Loads an NgModule/Directive/Pipe summary file
|
|
|
|
|
*/
|
|
|
|
|
loadSummary(filePath: string): string;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the output file path of a source file.
|
|
|
|
|
* E.g.
|
|
|
|
|
* `some_file.ts` -> `some_file.d.ts`
|
|
|
|
|
*/
|
|
|
|
|
getOutputFileName(sourceFilePath: string): string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface AotSummaryResolverOptions {
|
|
|
|
|
includeFilePattern?: RegExp;
|
|
|
|
|
excludeFilePattern?: RegExp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class AotSummaryResolver implements SummaryResolver {
|
2016-12-02 10:08:46 -08:00
|
|
|
private summaryCache: {[cacheKey: string]: CompileTypeSummary} = {};
|
2016-11-29 15:36:33 -08:00
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
private host: AotSummaryResolverHost, private staticReflector: StaticReflector,
|
|
|
|
|
private options: AotSummaryResolverOptions) {}
|
|
|
|
|
|
|
|
|
|
serializeSummaries(srcFileUrl: string, summaries: CompileTypeSummary[]): GeneratedFile {
|
|
|
|
|
const jsonReplacer = (key: string, value: any) => {
|
2016-12-05 13:35:24 -08:00
|
|
|
if (value instanceof StaticSymbol) {
|
2016-11-29 15:36:33 -08:00
|
|
|
// We convert the source filenames into output filenames,
|
|
|
|
|
// as the generated summary file will be used when the current
|
|
|
|
|
// compilation unit is used as a library
|
|
|
|
|
return {
|
|
|
|
|
'__symbolic__': 'symbol',
|
|
|
|
|
'name': value.name,
|
|
|
|
|
'path': this.host.getOutputFileName(value.filePath),
|
|
|
|
|
'members': value.members
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
};
|
2016-12-02 10:08:46 -08:00
|
|
|
const allSummaries = summaries.slice();
|
|
|
|
|
summaries.forEach((summary) => {
|
|
|
|
|
if (summary.summaryKind === CompileSummaryKind.NgModule) {
|
|
|
|
|
const moduleMeta = <CompileNgModuleSummary>summary;
|
|
|
|
|
moduleMeta.exportedDirectives.concat(moduleMeta.exportedPipes).forEach((id) => {
|
|
|
|
|
if (!filterFileByPatterns(id.reference.filePath, this.options)) {
|
|
|
|
|
allSummaries.push(this.resolveSummary(id.reference));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
2016-11-29 15:36:33 -08:00
|
|
|
|
|
|
|
|
return new GeneratedFile(
|
2016-12-02 10:08:46 -08:00
|
|
|
srcFileUrl, summaryFileName(srcFileUrl), JSON.stringify(allSummaries, jsonReplacer));
|
2016-11-29 15:36:33 -08:00
|
|
|
}
|
|
|
|
|
|
2016-12-02 10:08:46 -08:00
|
|
|
private _cacheKey(symbol: StaticSymbol) { return `${symbol.filePath}|${symbol.name}`; }
|
|
|
|
|
|
2016-11-29 15:36:33 -08:00
|
|
|
resolveSummary(staticSymbol: StaticSymbol): any {
|
|
|
|
|
const filePath = staticSymbol.filePath;
|
|
|
|
|
const name = staticSymbol.name;
|
2016-12-02 10:08:46 -08:00
|
|
|
const cacheKey = this._cacheKey(staticSymbol);
|
2016-11-29 15:36:33 -08:00
|
|
|
if (!filterFileByPatterns(filePath, this.options)) {
|
2016-12-02 10:08:46 -08:00
|
|
|
let summary = this.summaryCache[cacheKey];
|
2016-11-29 15:36:33 -08:00
|
|
|
const summaryFilePath = summaryFileName(filePath);
|
2016-12-02 10:08:46 -08:00
|
|
|
if (!summary) {
|
2016-11-29 15:36:33 -08:00
|
|
|
try {
|
|
|
|
|
const jsonReviver = (key: string, value: any) => {
|
2016-12-05 13:35:24 -08:00
|
|
|
if (value && value['__symbolic__'] === 'symbol') {
|
2016-11-29 15:36:33 -08:00
|
|
|
// Note: We can't use staticReflector.findDeclaration here:
|
|
|
|
|
// Summary files can contain symbols of transitive compilation units
|
|
|
|
|
// (via the providers), and findDeclaration needs .metadata.json / .d.ts files,
|
|
|
|
|
// but we don't want to depend on these for transitive dependencies.
|
|
|
|
|
return this.staticReflector.getStaticSymbol(
|
|
|
|
|
value['path'], value['name'], value['members']);
|
|
|
|
|
} else {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
};
|
2016-12-02 10:08:46 -08:00
|
|
|
const readSummaries: CompileTypeSummary[] =
|
|
|
|
|
JSON.parse(this.host.loadSummary(summaryFilePath), jsonReviver);
|
|
|
|
|
readSummaries.forEach((summary) => {
|
|
|
|
|
const filePath = summary.type.reference.filePath;
|
|
|
|
|
this.summaryCache[this._cacheKey(summary.type.reference)] = summary;
|
|
|
|
|
});
|
|
|
|
|
summary = this.summaryCache[cacheKey];
|
2016-11-29 15:36:33 -08:00
|
|
|
} catch (e) {
|
|
|
|
|
console.error(`Error loading summary file ${summaryFilePath}`);
|
|
|
|
|
throw e;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-12-02 10:08:46 -08:00
|
|
|
if (!summary) {
|
2016-11-29 15:36:33 -08:00
|
|
|
throw new Error(
|
|
|
|
|
`Could not find the symbol ${name} in the summary file ${summaryFilePath}!`);
|
|
|
|
|
}
|
2016-12-02 10:08:46 -08:00
|
|
|
return summary;
|
2016-11-29 15:36:33 -08:00
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function summaryFileName(fileName: string): string {
|
|
|
|
|
const fileNameWithoutSuffix = fileName.replace(STRIP_SRC_FILE_SUFFIXES, '');
|
|
|
|
|
return `${fileNameWithoutSuffix}.ngsummary.json`;
|
|
|
|
|
}
|