feat(compiler): make `.ngsummary.json` files portable
This also allows to customize the filePaths in `.ngsummary.json` file via the new methods `toSummaryFileName` and `fromSummaryFileName` on the `CompilerHost`.
This commit is contained in:
parent
6a1ab61cce
commit
2572bf508f
|
@ -42,6 +42,10 @@ export abstract class BaseAotCompilerHost<C extends BaseAotCompilerHostContext>
|
||||||
|
|
||||||
abstract fileNameToModuleName(importedFile: string, containingFile: string): string|null;
|
abstract fileNameToModuleName(importedFile: string, containingFile: string): string|null;
|
||||||
|
|
||||||
|
abstract toSummaryFileName(fileName: string, referringSrcFileName: string): string;
|
||||||
|
|
||||||
|
abstract fromSummaryFileName(fileName: string, referringLibFileName: string): string;
|
||||||
|
|
||||||
protected getSourceFile(filePath: string): ts.SourceFile {
|
protected getSourceFile(filePath: string): ts.SourceFile {
|
||||||
const sf = this.program.getSourceFile(filePath);
|
const sf = this.program.getSourceFile(filePath);
|
||||||
if (!sf) {
|
if (!sf) {
|
||||||
|
@ -144,10 +148,6 @@ export abstract class BaseAotCompilerHost<C extends BaseAotCompilerHostContext>
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputFileName(sourceFilePath: string): string {
|
|
||||||
return sourceFilePath.replace(EXT, '') + '.d.ts';
|
|
||||||
}
|
|
||||||
|
|
||||||
isSourceFile(filePath: string): boolean {
|
isSourceFile(filePath: string): boolean {
|
||||||
const excludeRegex =
|
const excludeRegex =
|
||||||
this.options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : GENERATED_FILES;
|
this.options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : GENERATED_FILES;
|
||||||
|
@ -268,6 +268,12 @@ export class CompilerHost extends BaseAotCompilerHost<CompilerHostContext> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toSummaryFileName(fileName: string, referringSrcFileName: string): string {
|
||||||
|
return fileName.replace(EXT, '') + '.d.ts';
|
||||||
|
}
|
||||||
|
|
||||||
|
fromSummaryFileName(fileName: string, referringLibFileName: string): string { return fileName; }
|
||||||
|
|
||||||
calculateEmitPath(filePath: string): string {
|
calculateEmitPath(filePath: string): string {
|
||||||
// Write codegen in a directory structure matching the sources.
|
// Write codegen in a directory structure matching the sources.
|
||||||
let root = this.options.basePath !;
|
let root = this.options.basePath !;
|
||||||
|
|
|
@ -130,6 +130,20 @@ export interface CompilerHost extends ts.CompilerHost {
|
||||||
* See ImportResolver.
|
* See ImportResolver.
|
||||||
*/
|
*/
|
||||||
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null;
|
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null;
|
||||||
|
/**
|
||||||
|
* Converts a file name into a representation that should be stored in a summary file.
|
||||||
|
* This has to include changing the suffix as well.
|
||||||
|
* E.g.
|
||||||
|
* `some_file.ts` -> `some_file.d.ts`
|
||||||
|
*
|
||||||
|
* @param referringSrcFileName the soure file that refers to fileName
|
||||||
|
*/
|
||||||
|
toSummaryFileName(fileName: string, referringSrcFileName: string): string;
|
||||||
|
/**
|
||||||
|
* Converts a fileName that was processed by `toSummaryFileName` back into a real fileName
|
||||||
|
* given the fileName of the library that is referrig to it.
|
||||||
|
*/
|
||||||
|
fromSummaryFileName(fileName: string, referringLibFileName: string): string;
|
||||||
/**
|
/**
|
||||||
* Load a referenced resource either statically or asynchronously. If the host returns a
|
* Load a referenced resource either statically or asynchronously. If the host returns a
|
||||||
* `Promise<string>` it is assumed the user of the corresponding `Program` will call
|
* `Promise<string>` it is assumed the user of the corresponding `Program` will call
|
||||||
|
|
|
@ -24,6 +24,8 @@ export function createCompilerHost(
|
||||||
|
|
||||||
host.moduleNameToFileName = mixin.moduleNameToFileName.bind(mixin);
|
host.moduleNameToFileName = mixin.moduleNameToFileName.bind(mixin);
|
||||||
host.fileNameToModuleName = mixin.fileNameToModuleName.bind(mixin);
|
host.fileNameToModuleName = mixin.fileNameToModuleName.bind(mixin);
|
||||||
|
host.toSummaryFileName = mixin.toSummaryFileName.bind(mixin);
|
||||||
|
host.fromSummaryFileName = mixin.fromSummaryFileName.bind(mixin);
|
||||||
|
|
||||||
// Make sure we do not `host.realpath()` from TS as we do not want to resolve symlinks.
|
// Make sure we do not `host.realpath()` from TS as we do not want to resolve symlinks.
|
||||||
// https://github.com/Microsoft/TypeScript/issues/9552
|
// https://github.com/Microsoft/TypeScript/issues/9552
|
||||||
|
@ -109,9 +111,15 @@ class CompilerHostMixin {
|
||||||
|
|
||||||
let moduleName: string;
|
let moduleName: string;
|
||||||
if (importedFilePackagName === containingFilePackageName) {
|
if (importedFilePackagName === containingFilePackageName) {
|
||||||
moduleName = dotRelative(
|
const rootedContainingFile = stripRootDir(this.rootDirs, containingFile);
|
||||||
path.dirname(stripRootDir(this.rootDirs, containingFile)),
|
const rootedImportedFile = stripRootDir(this.rootDirs, importedFile);
|
||||||
stripRootDir(this.rootDirs, importedFile));
|
|
||||||
|
if (rootedContainingFile !== containingFile && rootedImportedFile !== importedFile) {
|
||||||
|
// if both files are contained in the `rootDirs`, then strip the rootDirs
|
||||||
|
containingFile = rootedContainingFile;
|
||||||
|
importedFile = rootedImportedFile;
|
||||||
|
}
|
||||||
|
moduleName = dotRelative(path.dirname(containingFile), importedFile);
|
||||||
} else if (importedFilePackagName) {
|
} else if (importedFilePackagName) {
|
||||||
moduleName = stripNodeModulesPrefix(importedFile);
|
moduleName = stripNodeModulesPrefix(importedFile);
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,6 +128,18 @@ class CompilerHostMixin {
|
||||||
}
|
}
|
||||||
return moduleName;
|
return moduleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toSummaryFileName(fileName: string, referringSrcFileName: string): string {
|
||||||
|
return this.fileNameToModuleName(fileName, referringSrcFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
fromSummaryFileName(fileName: string, referringLibFileName: string): string {
|
||||||
|
const resolved = this.moduleNameToFileName(fileName, referringLibFileName);
|
||||||
|
if (!resolved) {
|
||||||
|
throw new Error(`Could not resolve ${fileName} from ${referringLibFileName}`);
|
||||||
|
}
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ModuleFilenameResolutionHost extends ts.ModuleResolutionHost {
|
interface ModuleFilenameResolutionHost extends ts.ModuleResolutionHost {
|
||||||
|
@ -189,6 +209,11 @@ function stripNodeModulesPrefix(filePath: string): string {
|
||||||
return filePath.replace(/.*node_modules\//, '');
|
return filePath.replace(/.*node_modules\//, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNodeModulesPrefix(filePath: string): string|null {
|
||||||
|
const match = /.*node_modules\//.exec(filePath);
|
||||||
|
return match ? match[1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizePath(p: string): string {
|
function normalizePath(p: string): string {
|
||||||
return path.normalize(path.join(p, '.')).replace(/\\/g, '/');
|
return path.normalize(path.join(p, '.')).replace(/\\/g, '/');
|
||||||
}
|
}
|
|
@ -314,6 +314,14 @@ class AotCompilerHostImpl extends BaseAotCompilerHost<CompilerHost> {
|
||||||
fileNameToModuleName(importedFile: string, containingFile: string): string|null {
|
fileNameToModuleName(importedFile: string, containingFile: string): string|null {
|
||||||
return this.context.fileNameToModuleName(importedFile, containingFile);
|
return this.context.fileNameToModuleName(importedFile, containingFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toSummaryFileName(fileName: string, referringSrcFileName: string): string {
|
||||||
|
return this.context.toSummaryFileName(fileName, referringSrcFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
fromSummaryFileName(fileName: string, referringLibFileName: string): string {
|
||||||
|
return this.context.fromSummaryFileName(fileName, referringLibFileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createProgram(
|
export function createProgram(
|
||||||
|
|
|
@ -105,7 +105,8 @@ const summaryResolver = new AotSummaryResolver(
|
||||||
{
|
{
|
||||||
loadSummary(filePath: string) { return null; },
|
loadSummary(filePath: string) { return null; },
|
||||||
isSourceFile(sourceFilePath: string) { return true; },
|
isSourceFile(sourceFilePath: string) { return true; },
|
||||||
getOutputFileName(sourceFilePath: string) { return sourceFilePath; }
|
toSummaryFileName(sourceFilePath: string) { return sourceFilePath; },
|
||||||
|
fromSummaryFileName(filePath: string): string{return filePath;},
|
||||||
},
|
},
|
||||||
staticSymbolCache);
|
staticSymbolCache);
|
||||||
|
|
||||||
|
|
|
@ -67,8 +67,13 @@ describe('NgCompilerHost', () => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// both files are in the rootDirs
|
||||||
expect(ngHostWithMultipleRoots.fileNameToModuleName('/tmp/src/b/b.ts', '/tmp/src/a/a.ts'))
|
expect(ngHostWithMultipleRoots.fileNameToModuleName('/tmp/src/b/b.ts', '/tmp/src/a/a.ts'))
|
||||||
.toBe('./b');
|
.toBe('./b');
|
||||||
|
|
||||||
|
// one file is not in the rootDirs
|
||||||
|
expect(ngHostWithMultipleRoots.fileNameToModuleName('/tmp/src/c/c.ts', '/tmp/src/a/a.ts'))
|
||||||
|
.toBe('../c/c');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should error if accessing a source file from a package', () => {
|
it('should error if accessing a source file from a package', () => {
|
||||||
|
|
|
@ -207,10 +207,10 @@ export class AotCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createSummary(
|
private _createSummary(
|
||||||
srcFileUrl: string, directives: StaticSymbol[], pipes: StaticSymbol[],
|
srcFileName: string, directives: StaticSymbol[], pipes: StaticSymbol[],
|
||||||
ngModules: StaticSymbol[], injectables: StaticSymbol[],
|
ngModules: StaticSymbol[], injectables: StaticSymbol[],
|
||||||
ngFactoryCtx: OutputContext): GeneratedFile[] {
|
ngFactoryCtx: OutputContext): GeneratedFile[] {
|
||||||
const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileUrl)
|
const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileName)
|
||||||
.map(symbol => this._symbolResolver.resolveSymbol(symbol));
|
.map(symbol => this._symbolResolver.resolveSymbol(symbol));
|
||||||
const typeData: {
|
const typeData: {
|
||||||
summary: CompileTypeSummary,
|
summary: CompileTypeSummary,
|
||||||
|
@ -235,18 +235,19 @@ export class AotCompiler {
|
||||||
metadata: this._metadataResolver.getInjectableSummary(ref) !.type
|
metadata: this._metadataResolver.getInjectableSummary(ref) !.type
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
const forJitOutputCtx = this._createOutputContext(summaryForJitFileName(srcFileUrl, true));
|
const forJitOutputCtx = this._createOutputContext(summaryForJitFileName(srcFileName, true));
|
||||||
const {json, exportAs} = serializeSummaries(
|
const {json, exportAs} = serializeSummaries(
|
||||||
forJitOutputCtx, this._summaryResolver, this._symbolResolver, symbolSummaries, typeData);
|
srcFileName, forJitOutputCtx, this._summaryResolver, this._symbolResolver, symbolSummaries,
|
||||||
|
typeData);
|
||||||
exportAs.forEach((entry) => {
|
exportAs.forEach((entry) => {
|
||||||
ngFactoryCtx.statements.push(
|
ngFactoryCtx.statements.push(
|
||||||
o.variable(entry.exportAs).set(ngFactoryCtx.importExpr(entry.symbol)).toDeclStmt(null, [
|
o.variable(entry.exportAs).set(ngFactoryCtx.importExpr(entry.symbol)).toDeclStmt(null, [
|
||||||
o.StmtModifier.Exported
|
o.StmtModifier.Exported
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
const summaryJson = new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json);
|
const summaryJson = new GeneratedFile(srcFileName, summaryFileName(srcFileName), json);
|
||||||
if (this._enableSummariesForJit) {
|
if (this._enableSummariesForJit) {
|
||||||
return [summaryJson, this._codegenSourceModule(srcFileUrl, forJitOutputCtx)];
|
return [summaryJson, this._codegenSourceModule(srcFileName, forJitOutputCtx)];
|
||||||
};
|
};
|
||||||
|
|
||||||
return [summaryJson];
|
return [summaryJson];
|
||||||
|
|
|
@ -23,11 +23,20 @@ export interface AotSummaryResolverHost {
|
||||||
*/
|
*/
|
||||||
isSourceFile(sourceFilePath: string): boolean;
|
isSourceFile(sourceFilePath: string): boolean;
|
||||||
/**
|
/**
|
||||||
* Returns the output file path of a source file.
|
* Converts a file name into a representation that should be stored in a summary file.
|
||||||
|
* This has to include changing the suffix as well.
|
||||||
* E.g.
|
* E.g.
|
||||||
* `some_file.ts` -> `some_file.d.ts`
|
* `some_file.ts` -> `some_file.d.ts`
|
||||||
|
*
|
||||||
|
* @param referringSrcFileName the soure file that refers to fileName
|
||||||
*/
|
*/
|
||||||
getOutputFileName(sourceFilePath: string): string;
|
toSummaryFileName(fileName: string, referringSrcFileName: string): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a fileName that was processed by `toSummaryFileName` back into a real fileName
|
||||||
|
* given the fileName of the library that is referrig to it.
|
||||||
|
*/
|
||||||
|
fromSummaryFileName(fileName: string, referringLibFileName: string): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
|
export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
|
||||||
|
@ -46,7 +55,13 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
|
||||||
return !this.host.isSourceFile(stripGeneratedFileSuffix(filePath));
|
return !this.host.isSourceFile(stripGeneratedFileSuffix(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
getLibraryFileName(filePath: string) { return this.host.getOutputFileName(filePath); }
|
toSummaryFileName(filePath: string, referringSrcFileName: string) {
|
||||||
|
return this.host.toSummaryFileName(filePath, referringSrcFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
fromSummaryFileName(fileName: string, referringLibFileName: string) {
|
||||||
|
return this.host.fromSummaryFileName(fileName, referringLibFileName);
|
||||||
|
}
|
||||||
|
|
||||||
resolveSummary(staticSymbol: StaticSymbol): Summary<StaticSymbol> {
|
resolveSummary(staticSymbol: StaticSymbol): Summary<StaticSymbol> {
|
||||||
staticSymbol.assertNoMembers();
|
staticSymbol.assertNoMembers();
|
||||||
|
@ -85,7 +100,8 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
const {summaries, importAs} = deserializeSummaries(this.staticSymbolCache, json);
|
const {summaries, importAs} =
|
||||||
|
deserializeSummaries(this.staticSymbolCache, this, filePath, json);
|
||||||
summaries.forEach((summary) => this.summaryCache.set(summary.symbol, summary));
|
summaries.forEach((summary) => this.summaryCache.set(summary.symbol, summary));
|
||||||
importAs.forEach((importAs) => {
|
importAs.forEach((importAs) => {
|
||||||
this.importAs.set(
|
this.importAs.set(
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolv
|
||||||
import {summaryForJitFileName, summaryForJitName} from './util';
|
import {summaryForJitFileName, summaryForJitName} from './util';
|
||||||
|
|
||||||
export function serializeSummaries(
|
export function serializeSummaries(
|
||||||
forJitCtx: OutputContext, summaryResolver: SummaryResolver<StaticSymbol>,
|
srcFileName: string, forJitCtx: OutputContext, summaryResolver: SummaryResolver<StaticSymbol>,
|
||||||
symbolResolver: StaticSymbolResolver, symbols: ResolvedStaticSymbol[], types: {
|
symbolResolver: StaticSymbolResolver, symbols: ResolvedStaticSymbol[], types: {
|
||||||
summary: CompileTypeSummary,
|
summary: CompileTypeSummary,
|
||||||
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
|
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
|
||||||
|
@ -76,15 +76,17 @@ export function serializeSummaries(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const {json, exportAs} = toJsonSerializer.serialize();
|
const {json, exportAs} = toJsonSerializer.serialize(srcFileName);
|
||||||
forJitSerializer.serialize(exportAs);
|
forJitSerializer.serialize(exportAs);
|
||||||
return {json, exportAs};
|
return {json, exportAs};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deserializeSummaries(symbolCache: StaticSymbolCache, json: string):
|
export function deserializeSummaries(
|
||||||
|
symbolCache: StaticSymbolCache, summaryResolver: SummaryResolver<StaticSymbol>,
|
||||||
|
libraryFileName: string, json: string):
|
||||||
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
|
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
|
||||||
const deserializer = new FromJsonDeserializer(symbolCache);
|
const deserializer = new FromJsonDeserializer(symbolCache, summaryResolver);
|
||||||
return deserializer.deserialize(json);
|
return deserializer.deserialize(libraryFileName, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createForJitStub(outputCtx: OutputContext, reference: StaticSymbol) {
|
export function createForJitStub(outputCtx: OutputContext, reference: StaticSymbol) {
|
||||||
|
@ -151,7 +153,8 @@ class ToJsonSerializer extends ValueTransformer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize(): {json: string, exportAs: {symbol: StaticSymbol, exportAs: string}[]} {
|
serialize(srcFileName: string):
|
||||||
|
{json: string, exportAs: {symbol: StaticSymbol, exportAs: string}[]} {
|
||||||
const exportAs: {symbol: StaticSymbol, exportAs: string}[] = [];
|
const exportAs: {symbol: StaticSymbol, exportAs: string}[] = [];
|
||||||
const json = JSON.stringify({
|
const json = JSON.stringify({
|
||||||
summaries: this.processedSummaries,
|
summaries: this.processedSummaries,
|
||||||
|
@ -165,10 +168,7 @@ class ToJsonSerializer extends ValueTransformer {
|
||||||
return {
|
return {
|
||||||
__symbol: index,
|
__symbol: index,
|
||||||
name: symbol.name,
|
name: symbol.name,
|
||||||
// We convert the source filenames tinto output filenames,
|
filePath: this.summaryResolver.toSummaryFileName(symbol.filePath, srcFileName),
|
||||||
// as the generated summary file will be used when the current
|
|
||||||
// compilation unit is used as a library
|
|
||||||
filePath: this.summaryResolver.getLibraryFileName(symbol.filePath),
|
|
||||||
importAs: importAs
|
importAs: importAs
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
@ -317,15 +317,21 @@ class ForJitSerializer {
|
||||||
class FromJsonDeserializer extends ValueTransformer {
|
class FromJsonDeserializer extends ValueTransformer {
|
||||||
private symbols: StaticSymbol[];
|
private symbols: StaticSymbol[];
|
||||||
|
|
||||||
constructor(private symbolCache: StaticSymbolCache) { super(); }
|
constructor(
|
||||||
|
private symbolCache: StaticSymbolCache,
|
||||||
|
private summaryResolver: SummaryResolver<StaticSymbol>) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
deserialize(json: string):
|
deserialize(libraryFileName: string, json: string):
|
||||||
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
|
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
|
||||||
const data: {summaries: any[], symbols: any[]} = JSON.parse(json);
|
const data: {summaries: any[], symbols: any[]} = JSON.parse(json);
|
||||||
const importAs: {symbol: StaticSymbol, importAs: string}[] = [];
|
const importAs: {symbol: StaticSymbol, importAs: string}[] = [];
|
||||||
this.symbols = [];
|
this.symbols = [];
|
||||||
data.symbols.forEach((serializedSymbol) => {
|
data.symbols.forEach((serializedSymbol) => {
|
||||||
const symbol = this.symbolCache.get(serializedSymbol.filePath, serializedSymbol.name);
|
const symbol = this.symbolCache.get(
|
||||||
|
this.summaryResolver.fromSummaryFileName(serializedSymbol.filePath, libraryFileName),
|
||||||
|
serializedSymbol.name);
|
||||||
this.symbols.push(symbol);
|
this.symbols.push(symbol);
|
||||||
if (serializedSymbol.importAs) {
|
if (serializedSymbol.importAs) {
|
||||||
importAs.push({symbol: symbol, importAs: serializedSymbol.importAs});
|
importAs.push({symbol: symbol, importAs: serializedSymbol.importAs});
|
||||||
|
|
|
@ -17,7 +17,8 @@ export interface Summary<T> {
|
||||||
|
|
||||||
export abstract class SummaryResolver<T> {
|
export abstract class SummaryResolver<T> {
|
||||||
abstract isLibraryFile(fileName: string): boolean;
|
abstract isLibraryFile(fileName: string): boolean;
|
||||||
abstract getLibraryFileName(fileName: string): string|null;
|
abstract toSummaryFileName(fileName: string, referringSrcFileName: string): string;
|
||||||
|
abstract fromSummaryFileName(fileName: string, referringLibFileName: string): string;
|
||||||
abstract resolveSummary(reference: T): Summary<T>|null;
|
abstract resolveSummary(reference: T): Summary<T>|null;
|
||||||
abstract getSymbolsOf(filePath: string): T[];
|
abstract getSymbolsOf(filePath: string): T[];
|
||||||
abstract getImportAs(reference: T): T;
|
abstract getImportAs(reference: T): T;
|
||||||
|
@ -28,12 +29,13 @@ export abstract class SummaryResolver<T> {
|
||||||
export class JitSummaryResolver implements SummaryResolver<Type<any>> {
|
export class JitSummaryResolver implements SummaryResolver<Type<any>> {
|
||||||
private _summaries = new Map<Type<any>, Summary<Type<any>>>();
|
private _summaries = new Map<Type<any>, Summary<Type<any>>>();
|
||||||
|
|
||||||
isLibraryFile(fileName: string): boolean { return false; };
|
isLibraryFile(): boolean { return false; };
|
||||||
getLibraryFileName(fileName: string): string|null { return null; }
|
toSummaryFileName(fileName: string): string { return fileName; }
|
||||||
|
fromSummaryFileName(fileName: string): string { return fileName; }
|
||||||
resolveSummary(reference: Type<any>): Summary<Type<any>>|null {
|
resolveSummary(reference: Type<any>): Summary<Type<any>>|null {
|
||||||
return this._summaries.get(reference) || null;
|
return this._summaries.get(reference) || null;
|
||||||
};
|
};
|
||||||
getSymbolsOf(filePath: string): Type<any>[] { return []; }
|
getSymbolsOf(): Type<any>[] { return []; }
|
||||||
getImportAs(reference: Type<any>): Type<any> { return reference; }
|
getImportAs(reference: Type<any>): Type<any> { return reference; }
|
||||||
addSummary(summary: Summary<Type<any>>) { this._summaries.set(summary.symbol, summary); };
|
addSummary(summary: Summary<Type<any>>) { this._summaries.set(summary.symbol, summary); };
|
||||||
}
|
}
|
||||||
|
|
|
@ -386,7 +386,8 @@ export class MockSummaryResolver implements SummaryResolver<StaticSymbol> {
|
||||||
}
|
}
|
||||||
|
|
||||||
isLibraryFile(filePath: string): boolean { return filePath.endsWith('.d.ts'); }
|
isLibraryFile(filePath: string): boolean { return filePath.endsWith('.d.ts'); }
|
||||||
getLibraryFileName(filePath: string): string { return filePath.replace(/(\.d)?\.ts$/, '.d.ts'); }
|
toSummaryFileName(filePath: string): string { return filePath.replace(/(\.d)?\.ts$/, '.d.ts'); }
|
||||||
|
fromSummaryFileName(filePath: string): string { return filePath; }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
|
export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
|
||||||
|
|
|
@ -35,7 +35,8 @@ export function main() {
|
||||||
const symbolResolver = new StaticSymbolResolver(
|
const symbolResolver = new StaticSymbolResolver(
|
||||||
new MockStaticSymbolResolverHost({}), symbolCache, mockSummaryResolver);
|
new MockStaticSymbolResolverHost({}), symbolCache, mockSummaryResolver);
|
||||||
return serializeSummaries(
|
return serializeSummaries(
|
||||||
createMockOutputContext(), mockSummaryResolver, symbolResolver, symbols, [])
|
'someFile.ts', createMockOutputContext(), mockSummaryResolver, symbolResolver,
|
||||||
|
symbols, [])
|
||||||
.json;
|
.json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,10 +106,12 @@ export class MockAotSummaryResolverHost implements AotSummaryResolverHost {
|
||||||
return './' + path.basename(fileName).replace(EXT, '');
|
return './' + path.basename(fileName).replace(EXT, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputFileName(sourceFileName: string): string {
|
toSummaryFileName(sourceFileName: string): string {
|
||||||
return sourceFileName.replace(EXT, '') + '.d.ts';
|
return sourceFileName.replace(EXT, '') + '.d.ts';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fromSummaryFileName(filePath: string): string { return filePath; }
|
||||||
|
|
||||||
isSourceFile(filePath: string) { return !filePath.endsWith('.d.ts'); }
|
isSourceFile(filePath: string) { return !filePath.endsWith('.d.ts'); }
|
||||||
|
|
||||||
loadSummary(filePath: string): string { return this.summaries[filePath]; }
|
loadSummary(filePath: string): string { return this.summaries[filePath]; }
|
||||||
|
|
|
@ -43,7 +43,7 @@ export function main() {
|
||||||
it('should serialize various data correctly', () => {
|
it('should serialize various data correctly', () => {
|
||||||
init();
|
init();
|
||||||
const serializedData = serializeSummaries(
|
const serializedData = serializeSummaries(
|
||||||
createMockOutputContext(), summaryResolver, symbolResolver,
|
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
symbol: symbolCache.get('/tmp/some_values.ts', 'Values'),
|
symbol: symbolCache.get('/tmp/some_values.ts', 'Values'),
|
||||||
|
@ -77,7 +77,9 @@ export function main() {
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
||||||
const summaries = deserializeSummaries(symbolCache, serializedData.json).summaries;
|
const summaries =
|
||||||
|
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serializedData.json)
|
||||||
|
.summaries;
|
||||||
expect(summaries.length).toBe(2);
|
expect(summaries.length).toBe(2);
|
||||||
|
|
||||||
// Note: change from .ts to .d.ts is expected
|
// Note: change from .ts to .d.ts is expected
|
||||||
|
@ -105,8 +107,8 @@ export function main() {
|
||||||
it('should automatically add exported directives / pipes of NgModules that are not source files',
|
it('should automatically add exported directives / pipes of NgModules that are not source files',
|
||||||
() => {
|
() => {
|
||||||
init();
|
init();
|
||||||
const externalSerialized =
|
const externalSerialized = serializeSummaries(
|
||||||
serializeSummaries(createMockOutputContext(), summaryResolver, symbolResolver, [], [
|
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [], [
|
||||||
{
|
{
|
||||||
summary: {
|
summary: {
|
||||||
summaryKind: CompileSummaryKind.Pipe,
|
summaryKind: CompileSummaryKind.Pipe,
|
||||||
|
@ -133,7 +135,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const serialized = serializeSummaries(
|
const serialized = serializeSummaries(
|
||||||
createMockOutputContext(), summaryResolver, symbolResolver, [], [{
|
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [], [{
|
||||||
summary: <any>{
|
summary: <any>{
|
||||||
summaryKind: CompileSummaryKind.NgModule,
|
summaryKind: CompileSummaryKind.NgModule,
|
||||||
type: {reference: symbolCache.get('/tmp/some_module.ts', 'SomeModule')},
|
type: {reference: symbolCache.get('/tmp/some_module.ts', 'SomeModule')},
|
||||||
|
@ -151,7 +153,9 @@ export function main() {
|
||||||
metadata: null as any
|
metadata: null as any
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const summaries = deserializeSummaries(symbolCache, serialized.json).summaries;
|
const summaries =
|
||||||
|
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json)
|
||||||
|
.summaries;
|
||||||
expect(summaries.length).toBe(3);
|
expect(summaries.length).toBe(3);
|
||||||
expect(summaries[0].symbol).toBe(symbolCache.get('/tmp/some_module.d.ts', 'SomeModule'));
|
expect(summaries[0].symbol).toBe(symbolCache.get('/tmp/some_module.d.ts', 'SomeModule'));
|
||||||
expect(summaries[1].symbol).toBe(symbolCache.get('/tmp/external.d.ts', 'SomeExternalDir'));
|
expect(summaries[1].symbol).toBe(symbolCache.get('/tmp/external.d.ts', 'SomeExternalDir'));
|
||||||
|
@ -163,7 +167,7 @@ export function main() {
|
||||||
() => {
|
() => {
|
||||||
init();
|
init();
|
||||||
const externalSerialized = serializeSummaries(
|
const externalSerialized = serializeSummaries(
|
||||||
createMockOutputContext(), summaryResolver, symbolResolver,
|
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
symbol: symbolCache.get('/tmp/external.ts', 'PROVIDERS'),
|
symbol: symbolCache.get('/tmp/external.ts', 'PROVIDERS'),
|
||||||
|
@ -195,7 +199,7 @@ export function main() {
|
||||||
{__symbolic: 'module', version: 3, metadata: {'external': 'b'}}
|
{__symbolic: 'module', version: 3, metadata: {'external': 'b'}}
|
||||||
});
|
});
|
||||||
const serialized = serializeSummaries(
|
const serialized = serializeSummaries(
|
||||||
createMockOutputContext(), summaryResolver, symbolResolver, [{
|
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [{
|
||||||
symbol: symbolCache.get('/tmp/test.ts', 'main'),
|
symbol: symbolCache.get('/tmp/test.ts', 'main'),
|
||||||
metadata: {
|
metadata: {
|
||||||
local: symbolCache.get('/tmp/local.ts', 'local'),
|
local: symbolCache.get('/tmp/local.ts', 'local'),
|
||||||
|
@ -205,7 +209,9 @@ export function main() {
|
||||||
}],
|
}],
|
||||||
[]);
|
[]);
|
||||||
|
|
||||||
const summaries = deserializeSummaries(symbolCache, serialized.json).summaries;
|
const summaries =
|
||||||
|
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json)
|
||||||
|
.summaries;
|
||||||
// Note: local should not show up!
|
// Note: local should not show up!
|
||||||
expect(summaries.length).toBe(4);
|
expect(summaries.length).toBe(4);
|
||||||
expect(summaries[0].symbol).toBe(symbolCache.get('/tmp/test.d.ts', 'main'));
|
expect(summaries[0].symbol).toBe(symbolCache.get('/tmp/test.d.ts', 'main'));
|
||||||
|
@ -230,7 +236,7 @@ export function main() {
|
||||||
it('should create "importAs" names for non source symbols', () => {
|
it('should create "importAs" names for non source symbols', () => {
|
||||||
init();
|
init();
|
||||||
const serialized = serializeSummaries(
|
const serialized = serializeSummaries(
|
||||||
createMockOutputContext(), summaryResolver, symbolResolver, [{
|
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [{
|
||||||
symbol: symbolCache.get('/tmp/test.ts', 'main'),
|
symbol: symbolCache.get('/tmp/test.ts', 'main'),
|
||||||
metadata: [
|
metadata: [
|
||||||
symbolCache.get('/tmp/external.d.ts', 'lib'),
|
symbolCache.get('/tmp/external.d.ts', 'lib'),
|
||||||
|
@ -243,7 +249,8 @@ export function main() {
|
||||||
{symbol: symbolCache.get('/tmp/external.d.ts', 'lib'), exportAs: 'lib_1'}
|
{symbol: symbolCache.get('/tmp/external.d.ts', 'lib'), exportAs: 'lib_1'}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const deserialized = deserializeSummaries(symbolCache, serialized.json);
|
const deserialized =
|
||||||
|
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json);
|
||||||
// Note: no entry for the symbol with members!
|
// Note: no entry for the symbol with members!
|
||||||
expect(deserialized.importAs).toEqual([
|
expect(deserialized.importAs).toEqual([
|
||||||
{symbol: symbolCache.get('/tmp/external.d.ts', 'lib'), importAs: 'lib_1'}
|
{symbol: symbolCache.get('/tmp/external.d.ts', 'lib'), importAs: 'lib_1'}
|
||||||
|
|
|
@ -382,9 +382,9 @@ export class MockAotCompilerHost implements AotCompilerHost {
|
||||||
(this.dtsAreSource || !DTS.test(sourceFilePath));
|
(this.dtsAreSource || !DTS.test(sourceFilePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputFileName(sourceFilePath: string): string {
|
toSummaryFileName(filePath: string): string { return filePath.replace(EXT, '') + '.d.ts'; }
|
||||||
return sourceFilePath.replace(EXT, '') + '.d.ts';
|
|
||||||
}
|
fromSummaryFileName(filePath: string): string { return filePath; }
|
||||||
|
|
||||||
// AotCompilerHost
|
// AotCompilerHost
|
||||||
fileNameToModuleName(importedFile: string, containingFile: string): string|null {
|
fileNameToModuleName(importedFile: string, containingFile: string): string|null {
|
||||||
|
|
|
@ -405,7 +405,8 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
||||||
{
|
{
|
||||||
loadSummary(filePath: string) { return null; },
|
loadSummary(filePath: string) { return null; },
|
||||||
isSourceFile(sourceFilePath: string) { return true; },
|
isSourceFile(sourceFilePath: string) { return true; },
|
||||||
getOutputFileName(sourceFilePath: string) { return sourceFilePath; }
|
toSummaryFileName(sourceFilePath: string) { return sourceFilePath; },
|
||||||
|
fromSummaryFileName(filePath: string): string{return filePath;},
|
||||||
},
|
},
|
||||||
this._staticSymbolCache);
|
this._staticSymbolCache);
|
||||||
result = this._staticSymbolResolver = new StaticSymbolResolver(
|
result = this._staticSymbolResolver = new StaticSymbolResolver(
|
||||||
|
|
Loading…
Reference in New Issue