perf(ivy): use module resolution cache (#34332)
During TypeScript module resolution, a lot of filesystem requests are done. This is quite an expensive operation, so a module resolution cache can be used to speed up the process significantly. This commit lets the Ivy compiler perform all module resolution with a module resolution cache. Note that the module resolution behavior can be changed with a custom compiler host, in which case that custom host implementation is responsible for caching. In the case of the Angular CLI a custom compiler host with proper module resolution caching is already in place, so the CLI already has this optimization. PR Close #34332
This commit is contained in:
parent
2f5ddd9c96
commit
8c2cbdd385
|
@ -59,6 +59,8 @@ export class DecorationAnalyzer {
|
||||||
* Map of NgModule declarations to the re-exports for that NgModule.
|
* Map of NgModule declarations to the re-exports for that NgModule.
|
||||||
*/
|
*/
|
||||||
private reexportMap = new Map<ts.Declaration, Map<string, [string, string]>>();
|
private reexportMap = new Map<ts.Declaration, Map<string, [string, string]>>();
|
||||||
|
moduleResolver =
|
||||||
|
new ModuleResolver(this.program, this.options, this.host, /* moduleResolutionCache */ null);
|
||||||
resourceManager = new NgccResourceLoader(this.fs);
|
resourceManager = new NgccResourceLoader(this.fs);
|
||||||
metaRegistry = new LocalMetadataRegistry();
|
metaRegistry = new LocalMetadataRegistry();
|
||||||
dtsMetaReader = new DtsMetadataReader(this.typeChecker, this.reflectionHost);
|
dtsMetaReader = new DtsMetadataReader(this.typeChecker, this.reflectionHost);
|
||||||
|
@ -66,7 +68,7 @@ export class DecorationAnalyzer {
|
||||||
refEmitter = new ReferenceEmitter([
|
refEmitter = new ReferenceEmitter([
|
||||||
new LocalIdentifierStrategy(),
|
new LocalIdentifierStrategy(),
|
||||||
new AbsoluteModuleStrategy(
|
new AbsoluteModuleStrategy(
|
||||||
this.program, this.typeChecker, this.options, this.host, this.reflectionHost),
|
this.program, this.typeChecker, this.moduleResolver, this.reflectionHost),
|
||||||
// TODO(alxhub): there's no reason why ngcc needs the "logical file system" logic here, as ngcc
|
// TODO(alxhub): there's no reason why ngcc needs the "logical file system" logic here, as ngcc
|
||||||
// projects only ever have one rootDir. Instead, ngcc should just switch its emitted import
|
// projects only ever have one rootDir. Instead, ngcc should just switch its emitted import
|
||||||
// based on whether a bestGuessOwningModule is present in the Reference.
|
// based on whether a bestGuessOwningModule is present in the Reference.
|
||||||
|
@ -81,7 +83,6 @@ export class DecorationAnalyzer {
|
||||||
fullRegistry = new CompoundMetadataRegistry([this.metaRegistry, this.scopeRegistry]);
|
fullRegistry = new CompoundMetadataRegistry([this.metaRegistry, this.scopeRegistry]);
|
||||||
evaluator =
|
evaluator =
|
||||||
new PartialEvaluator(this.reflectionHost, this.typeChecker, /* dependencyTracker */ null);
|
new PartialEvaluator(this.reflectionHost, this.typeChecker, /* dependencyTracker */ null);
|
||||||
moduleResolver = new ModuleResolver(this.program, this.options, this.host);
|
|
||||||
importGraph = new ImportGraph(this.moduleResolver);
|
importGraph = new ImportGraph(this.moduleResolver);
|
||||||
cycleAnalyzer = new CycleAnalyzer(this.importGraph);
|
cycleAnalyzer = new CycleAnalyzer(this.importGraph);
|
||||||
handlers: DecoratorHandler<unknown, unknown, unknown>[] = [
|
handlers: DecoratorHandler<unknown, unknown, unknown>[] = [
|
||||||
|
|
|
@ -757,7 +757,7 @@ export class ComponentDecoratorHandler implements
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out what file is being imported.
|
// Figure out what file is being imported.
|
||||||
return this.moduleResolver.resolveModuleName(expr.value.moduleName !, origin);
|
return this.moduleResolver.resolveModule(expr.value.moduleName !, origin.fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _isCyclicImport(expr: Expression, origin: ts.SourceFile): boolean {
|
private _isCyclicImport(expr: Expression, origin: ts.SourceFile): boolean {
|
||||||
|
|
|
@ -48,7 +48,8 @@ runInEachFileSystem(() => {
|
||||||
const checker = program.getTypeChecker();
|
const checker = program.getTypeChecker();
|
||||||
const reflectionHost = new TypeScriptReflectionHost(checker);
|
const reflectionHost = new TypeScriptReflectionHost(checker);
|
||||||
const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null);
|
const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null);
|
||||||
const moduleResolver = new ModuleResolver(program, options, host);
|
const moduleResolver =
|
||||||
|
new ModuleResolver(program, options, host, /* moduleResolutionCache */ null);
|
||||||
const importGraph = new ImportGraph(moduleResolver);
|
const importGraph = new ImportGraph(moduleResolver);
|
||||||
const cycleAnalyzer = new CycleAnalyzer(importGraph);
|
const cycleAnalyzer = new CycleAnalyzer(importGraph);
|
||||||
const metaRegistry = new LocalMetadataRegistry();
|
const metaRegistry = new LocalMetadataRegistry();
|
||||||
|
|
|
@ -68,7 +68,7 @@ export class ImportGraph {
|
||||||
stmt.moduleSpecifier !== undefined && ts.isStringLiteral(stmt.moduleSpecifier)) {
|
stmt.moduleSpecifier !== undefined && ts.isStringLiteral(stmt.moduleSpecifier)) {
|
||||||
// Resolve the module to a file, and check whether that file is in the ts.Program.
|
// Resolve the module to a file, and check whether that file is in the ts.Program.
|
||||||
const moduleName = stmt.moduleSpecifier.text;
|
const moduleName = stmt.moduleSpecifier.text;
|
||||||
const moduleFile = this.resolver.resolveModuleName(moduleName, sf);
|
const moduleFile = this.resolver.resolveModule(moduleName, sf.fileName);
|
||||||
if (moduleFile !== null && isLocalFile(moduleFile)) {
|
if (moduleFile !== null && isLocalFile(moduleFile)) {
|
||||||
// Record this local import.
|
// Record this local import.
|
||||||
imports.add(moduleFile);
|
imports.add(moduleFile);
|
||||||
|
|
|
@ -62,9 +62,11 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
function makeAnalyzer(graph: string): {program: ts.Program, analyzer: CycleAnalyzer} {
|
function makeAnalyzer(graph: string): {program: ts.Program, analyzer: CycleAnalyzer} {
|
||||||
const {program, options, host} = makeProgramFromGraph(getFileSystem(), graph);
|
const {program, options, host} = makeProgramFromGraph(getFileSystem(), graph);
|
||||||
|
const moduleResolver =
|
||||||
|
new ModuleResolver(program, options, host, /* moduleResolutionCache */ null);
|
||||||
return {
|
return {
|
||||||
program,
|
program,
|
||||||
analyzer: new CycleAnalyzer(new ImportGraph(new ModuleResolver(program, options, host))),
|
analyzer: new CycleAnalyzer(new ImportGraph(moduleResolver)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -55,9 +55,11 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
function makeImportGraph(graph: string): {program: ts.Program, graph: ImportGraph} {
|
function makeImportGraph(graph: string): {program: ts.Program, graph: ImportGraph} {
|
||||||
const {program, options, host} = makeProgramFromGraph(getFileSystem(), graph);
|
const {program, options, host} = makeProgramFromGraph(getFileSystem(), graph);
|
||||||
|
const moduleResolver =
|
||||||
|
new ModuleResolver(program, options, host, /* moduleResolutionCache */ null);
|
||||||
return {
|
return {
|
||||||
program,
|
program,
|
||||||
graph: new ImportGraph(new ModuleResolver(program, options, host)),
|
graph: new ImportGraph(moduleResolver),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,14 @@
|
||||||
import {Expression, ExternalExpr, ExternalReference, WrappedNodeExpr} from '@angular/compiler';
|
import {Expression, ExternalExpr, ExternalReference, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {LogicalFileSystem, LogicalProjectPath, PathSegment, absoluteFrom, absoluteFromSourceFile, basename, dirname, relative, resolve} from '../../file_system';
|
import {LogicalFileSystem, LogicalProjectPath, PathSegment, absoluteFromSourceFile, dirname, relative} from '../../file_system';
|
||||||
import {stripExtension} from '../../file_system/src/util';
|
import {stripExtension} from '../../file_system/src/util';
|
||||||
import {ReflectionHost} from '../../reflection';
|
import {ReflectionHost} from '../../reflection';
|
||||||
import {getSourceFile, getSourceFileOrNull, isDeclaration, nodeNameForError, resolveModuleName} from '../../util/src/typescript';
|
import {getSourceFile, isDeclaration, nodeNameForError} from '../../util/src/typescript';
|
||||||
|
|
||||||
import {findExportedNameOfNode} from './find_export';
|
import {findExportedNameOfNode} from './find_export';
|
||||||
import {ImportMode, Reference} from './references';
|
import {ImportMode, Reference} from './references';
|
||||||
|
import {ModuleResolver} from './resolver';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,8 +119,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected program: ts.Program, protected checker: ts.TypeChecker,
|
protected program: ts.Program, protected checker: ts.TypeChecker,
|
||||||
protected options: ts.CompilerOptions, protected host: ts.CompilerHost,
|
protected moduleResolver: ModuleResolver, private reflectionHost: ReflectionHost) {}
|
||||||
private reflectionHost: ReflectionHost) {}
|
|
||||||
|
|
||||||
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importMode: ImportMode): Expression|null {
|
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importMode: ImportMode): Expression|null {
|
||||||
if (ref.bestGuessOwningModule === null) {
|
if (ref.bestGuessOwningModule === null) {
|
||||||
|
@ -165,13 +165,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
|
||||||
protected enumerateExportsOfModule(specifier: string, fromFile: string):
|
protected enumerateExportsOfModule(specifier: string, fromFile: string):
|
||||||
Map<ts.Declaration, string>|null {
|
Map<ts.Declaration, string>|null {
|
||||||
// First, resolve the module specifier to its entry point, and get the ts.Symbol for it.
|
// First, resolve the module specifier to its entry point, and get the ts.Symbol for it.
|
||||||
const resolvedModule = resolveModuleName(specifier, fromFile, this.options, this.host);
|
const entryPointFile = this.moduleResolver.resolveModule(specifier, fromFile);
|
||||||
if (resolvedModule === undefined) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const entryPointFile =
|
|
||||||
getSourceFileOrNull(this.program, absoluteFrom(resolvedModule.resolvedFileName));
|
|
||||||
if (entryPointFile === null) {
|
if (entryPointFile === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,6 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {absoluteFrom} from '../../file_system';
|
import {absoluteFrom} from '../../file_system';
|
||||||
import {getSourceFileOrNull, resolveModuleName} from '../../util/src/typescript';
|
import {getSourceFileOrNull, resolveModuleName} from '../../util/src/typescript';
|
||||||
import {Reference} from './references';
|
|
||||||
|
|
||||||
export interface ReferenceResolver {
|
|
||||||
resolve(decl: ts.Declaration, importFromHint: string|null, fromFile: string):
|
|
||||||
Reference<ts.Declaration>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by `RouterEntryPointManager` and `NgModuleRouteAnalyzer` (which is in turn is used by
|
* Used by `RouterEntryPointManager` and `NgModuleRouteAnalyzer` (which is in turn is used by
|
||||||
|
@ -24,11 +18,12 @@ export interface ReferenceResolver {
|
||||||
export class ModuleResolver {
|
export class ModuleResolver {
|
||||||
constructor(
|
constructor(
|
||||||
private program: ts.Program, private compilerOptions: ts.CompilerOptions,
|
private program: ts.Program, private compilerOptions: ts.CompilerOptions,
|
||||||
private host: ts.CompilerHost) {}
|
private host: ts.CompilerHost, private moduleResolutionCache: ts.ModuleResolutionCache|null) {
|
||||||
|
}
|
||||||
|
|
||||||
resolveModuleName(module: string, containingFile: ts.SourceFile): ts.SourceFile|null {
|
resolveModule(moduleName: string, containingFile: string): ts.SourceFile|null {
|
||||||
const resolved =
|
const resolved = resolveModuleName(
|
||||||
resolveModuleName(module, containingFile.fileName, this.compilerOptions, this.host);
|
moduleName, containingFile, this.compilerOptions, this.host, this.moduleResolutionCache);
|
||||||
if (resolved === undefined) {
|
if (resolved === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,10 @@ export class NgtscProgram implements api.Program {
|
||||||
this.reuseTsProgram = this.tsProgram;
|
this.reuseTsProgram = this.tsProgram;
|
||||||
|
|
||||||
this.entryPoint = entryPoint !== null ? getSourceFileOrNull(this.tsProgram, entryPoint) : null;
|
this.entryPoint = entryPoint !== null ? getSourceFileOrNull(this.tsProgram, entryPoint) : null;
|
||||||
this.moduleResolver = new ModuleResolver(this.tsProgram, options, this.host);
|
const moduleResolutionCache = ts.createModuleResolutionCache(
|
||||||
|
this.host.getCurrentDirectory(), fileName => this.host.getCanonicalFileName(fileName));
|
||||||
|
this.moduleResolver =
|
||||||
|
new ModuleResolver(this.tsProgram, options, this.host, moduleResolutionCache);
|
||||||
this.cycleAnalyzer = new CycleAnalyzer(new ImportGraph(this.moduleResolver));
|
this.cycleAnalyzer = new CycleAnalyzer(new ImportGraph(this.moduleResolver));
|
||||||
this.defaultImportTracker = new DefaultImportTracker();
|
this.defaultImportTracker = new DefaultImportTracker();
|
||||||
if (oldProgram === undefined) {
|
if (oldProgram === undefined) {
|
||||||
|
@ -287,7 +290,8 @@ export class NgtscProgram implements api.Program {
|
||||||
// of the root files.
|
// of the root files.
|
||||||
const containingFile = this.tsProgram.getRootFileNames()[0];
|
const containingFile = this.tsProgram.getRootFileNames()[0];
|
||||||
const [entryPath, moduleName] = entryRoute.split('#');
|
const [entryPath, moduleName] = entryRoute.split('#');
|
||||||
const resolvedModule = resolveModuleName(entryPath, containingFile, this.options, this.host);
|
const resolvedModule =
|
||||||
|
resolveModuleName(entryPath, containingFile, this.options, this.host, null);
|
||||||
|
|
||||||
if (resolvedModule) {
|
if (resolvedModule) {
|
||||||
entryRoute = entryPointKeyFor(resolvedModule.resolvedFileName, moduleName);
|
entryRoute = entryPointKeyFor(resolvedModule.resolvedFileName, moduleName);
|
||||||
|
@ -587,8 +591,7 @@ export class NgtscProgram implements api.Program {
|
||||||
// First, try to use local identifiers if available.
|
// First, try to use local identifiers if available.
|
||||||
new LocalIdentifierStrategy(),
|
new LocalIdentifierStrategy(),
|
||||||
// Next, attempt to use an absolute import.
|
// Next, attempt to use an absolute import.
|
||||||
new AbsoluteModuleStrategy(
|
new AbsoluteModuleStrategy(this.tsProgram, checker, this.moduleResolver, this.reflector),
|
||||||
this.tsProgram, checker, this.options, this.host, this.reflector),
|
|
||||||
// Finally, check if the reference is being written into a file within the project's .ts
|
// Finally, check if the reference is being written into a file within the project's .ts
|
||||||
// sources, and use a relative import if so. If this fails, ReferenceEmitter will throw
|
// sources, and use a relative import if so. If this fails, ReferenceEmitter will throw
|
||||||
// an error.
|
// an error.
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class RouterEntryPointManager {
|
||||||
if (moduleName === undefined) {
|
if (moduleName === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const resolvedSf = this.moduleResolver.resolveModuleName(relativeFile, context);
|
const resolvedSf = this.moduleResolver.resolveModule(relativeFile, context.fileName);
|
||||||
if (resolvedSf === null) {
|
if (resolvedSf === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, LogicalFileSystem, absoluteFrom} from '../../file_system';
|
import {AbsoluteFsPath, LogicalFileSystem, absoluteFrom} from '../../file_system';
|
||||||
import {TestFile} from '../../file_system/testing';
|
import {TestFile} from '../../file_system/testing';
|
||||||
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, Reference, ReferenceEmitter} from '../../imports';
|
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {ClassDeclaration, TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {ClassDeclaration, TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||||
import {makeProgram} from '../../testing';
|
import {makeProgram} from '../../testing';
|
||||||
import {getRootDirs} from '../../util/src/typescript';
|
import {getRootDirs} from '../../util/src/typescript';
|
||||||
|
@ -29,7 +29,7 @@ export function typescriptLibDts(): TestFile {
|
||||||
type Partial<T> = { [P in keyof T]?: T[P]; };
|
type Partial<T> = { [P in keyof T]?: T[P]; };
|
||||||
type Pick<T, K extends keyof T> = { [P in K]: T[P]; };
|
type Pick<T, K extends keyof T> = { [P in K]: T[P]; };
|
||||||
type NonNullable<T> = T extends null | undefined ? never : T;
|
type NonNullable<T> = T extends null | undefined ? never : T;
|
||||||
|
|
||||||
// The following native type declarations are required for proper type inference
|
// The following native type declarations are required for proper type inference
|
||||||
declare interface Function {
|
declare interface Function {
|
||||||
call(...args: any[]): any;
|
call(...args: any[]): any;
|
||||||
|
@ -40,7 +40,7 @@ export function typescriptLibDts(): TestFile {
|
||||||
declare interface String {
|
declare interface String {
|
||||||
length: number;
|
length: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface Event {
|
declare interface Event {
|
||||||
preventDefault(): void;
|
preventDefault(): void;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ export function typescriptLibDts(): TestFile {
|
||||||
readonly x: number;
|
readonly x: number;
|
||||||
readonly y: number;
|
readonly y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface HTMLElementEventMap {
|
declare interface HTMLElementEventMap {
|
||||||
"click": MouseEvent;
|
"click": MouseEvent;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ export function angularCoreDts(): TestFile {
|
||||||
abstract readonly elementRef: unknown;
|
abstract readonly elementRef: unknown;
|
||||||
abstract createEmbeddedView(context: C): unknown;
|
abstract createEmbeddedView(context: C): unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare class EventEmitter<T> {
|
export declare class EventEmitter<T> {
|
||||||
subscribe(generatorOrNext?: any, error?: any, complete?: any): unknown;
|
subscribe(generatorOrNext?: any, error?: any, complete?: any): unknown;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ export function ngForDts(): TestFile {
|
||||||
export interface TrackByFunction<T> {
|
export interface TrackByFunction<T> {
|
||||||
(index: number, item: T): any;
|
(index: number, item: T): any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare class NgForOfContext<T> {
|
export declare class NgForOfContext<T> {
|
||||||
$implicit: T;
|
$implicit: T;
|
||||||
index: number;
|
index: number;
|
||||||
|
@ -249,10 +249,12 @@ export function typecheck(
|
||||||
const checker = program.getTypeChecker();
|
const checker = program.getTypeChecker();
|
||||||
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
||||||
const reflectionHost = new TypeScriptReflectionHost(checker);
|
const reflectionHost = new TypeScriptReflectionHost(checker);
|
||||||
|
const moduleResolver =
|
||||||
|
new ModuleResolver(program, options, host, /* moduleResolutionCache */ null);
|
||||||
const emitter = new ReferenceEmitter([
|
const emitter = new ReferenceEmitter([
|
||||||
new LocalIdentifierStrategy(),
|
new LocalIdentifierStrategy(),
|
||||||
new AbsoluteModuleStrategy(
|
new AbsoluteModuleStrategy(
|
||||||
program, checker, options, host, new TypeScriptReflectionHost(checker)),
|
program, checker, moduleResolver, new TypeScriptReflectionHost(checker)),
|
||||||
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
||||||
]);
|
]);
|
||||||
const ctx = new TypeCheckContext({...ALL_ENABLED_CONFIG, ...config}, emitter, typeCheckFilePath);
|
const ctx = new TypeCheckContext({...ALL_ENABLED_CONFIG, ...config}, emitter, typeCheckFilePath);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {LogicalFileSystem, absoluteFrom, getSourceFileOrError} from '../../file_system';
|
import {LogicalFileSystem, absoluteFrom, getSourceFileOrError} from '../../file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../file_system/testing';
|
import {TestFile, runInEachFileSystem} from '../../file_system/testing';
|
||||||
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, Reference, ReferenceEmitter} from '../../imports';
|
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
import {getRootDirs} from '../../util/src/typescript';
|
import {getRootDirs} from '../../util/src/typescript';
|
||||||
|
@ -64,9 +64,11 @@ TestClass.ngTypeCtor({value: 'test'});
|
||||||
const checker = program.getTypeChecker();
|
const checker = program.getTypeChecker();
|
||||||
const reflectionHost = new TypeScriptReflectionHost(checker);
|
const reflectionHost = new TypeScriptReflectionHost(checker);
|
||||||
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
||||||
|
const moduleResolver =
|
||||||
|
new ModuleResolver(program, options, host, /* moduleResolutionCache */ null);
|
||||||
const emitter = new ReferenceEmitter([
|
const emitter = new ReferenceEmitter([
|
||||||
new LocalIdentifierStrategy(),
|
new LocalIdentifierStrategy(),
|
||||||
new AbsoluteModuleStrategy(program, checker, options, host, reflectionHost),
|
new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost),
|
||||||
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
||||||
]);
|
]);
|
||||||
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, emitter, _('/_typecheck_.ts'));
|
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, emitter, _('/_typecheck_.ts'));
|
||||||
|
@ -97,9 +99,11 @@ TestClass.ngTypeCtor({value: 'test'});
|
||||||
const checker = program.getTypeChecker();
|
const checker = program.getTypeChecker();
|
||||||
const reflectionHost = new TypeScriptReflectionHost(checker);
|
const reflectionHost = new TypeScriptReflectionHost(checker);
|
||||||
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
||||||
|
const moduleResolver =
|
||||||
|
new ModuleResolver(program, options, host, /* moduleResolutionCache */ null);
|
||||||
const emitter = new ReferenceEmitter([
|
const emitter = new ReferenceEmitter([
|
||||||
new LocalIdentifierStrategy(),
|
new LocalIdentifierStrategy(),
|
||||||
new AbsoluteModuleStrategy(program, checker, options, host, reflectionHost),
|
new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost),
|
||||||
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
||||||
]);
|
]);
|
||||||
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, emitter, _('/_typecheck_.ts'));
|
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, emitter, _('/_typecheck_.ts'));
|
||||||
|
@ -136,9 +140,11 @@ TestClass.ngTypeCtor({value: 'test'});
|
||||||
const checker = program.getTypeChecker();
|
const checker = program.getTypeChecker();
|
||||||
const reflectionHost = new TypeScriptReflectionHost(checker);
|
const reflectionHost = new TypeScriptReflectionHost(checker);
|
||||||
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
const logicalFs = new LogicalFileSystem(getRootDirs(host, options));
|
||||||
|
const moduleResolver =
|
||||||
|
new ModuleResolver(program, options, host, /* moduleResolutionCache */ null);
|
||||||
const emitter = new ReferenceEmitter([
|
const emitter = new ReferenceEmitter([
|
||||||
new LocalIdentifierStrategy(),
|
new LocalIdentifierStrategy(),
|
||||||
new AbsoluteModuleStrategy(program, checker, options, host, reflectionHost),
|
new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost),
|
||||||
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
new LogicalProjectStrategy(reflectionHost, logicalFs),
|
||||||
]);
|
]);
|
||||||
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, emitter, _('/_typecheck_.ts'));
|
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, emitter, _('/_typecheck_.ts'));
|
||||||
|
|
|
@ -111,14 +111,18 @@ export function nodeDebugInfo(node: ts.Node): string {
|
||||||
*/
|
*/
|
||||||
export function resolveModuleName(
|
export function resolveModuleName(
|
||||||
moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions,
|
moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions,
|
||||||
compilerHost: ts.CompilerHost): ts.ResolvedModule|undefined {
|
compilerHost: ts.CompilerHost,
|
||||||
|
moduleResolutionCache: ts.ModuleResolutionCache | null): ts.ResolvedModule|undefined {
|
||||||
if (compilerHost.resolveModuleNames) {
|
if (compilerHost.resolveModuleNames) {
|
||||||
// FIXME: Additional parameters are required in TS3.6, but ignored in 3.5.
|
// FIXME: Additional parameters are required in TS3.6, but ignored in 3.5.
|
||||||
// Remove the any cast once google3 is fully on TS3.6.
|
// Remove the any cast once google3 is fully on TS3.6.
|
||||||
return (compilerHost as any)
|
return (compilerHost as any)
|
||||||
.resolveModuleNames([moduleName], containingFile, undefined, undefined, compilerOptions)[0];
|
.resolveModuleNames([moduleName], containingFile, undefined, undefined, compilerOptions)[0];
|
||||||
} else {
|
} else {
|
||||||
return ts.resolveModuleName(moduleName, containingFile, compilerOptions, compilerHost)
|
return ts
|
||||||
|
.resolveModuleName(
|
||||||
|
moduleName, containingFile, compilerOptions, compilerHost,
|
||||||
|
moduleResolutionCache !== null ? moduleResolutionCache : undefined)
|
||||||
.resolvedModule;
|
.resolvedModule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue