fix(compiler-cli): use CompilerHost to ensure canonical file paths (#36859)

The type checking infrastrure uses file-paths that may come from the
TS compiler. Such paths will have been canonicalized, and so the type
checking classes must also canonicalize paths when matching.

PR Close #36859
This commit is contained in:
Pete Bacon Darwin 2020-05-06 22:18:47 +01:00 committed by Alex Rickabaugh
parent b682bd1916
commit a10c126692
6 changed files with 22 additions and 17 deletions

View File

@ -731,7 +731,7 @@ export class NgCompiler {
const templateTypeChecker = new TemplateTypeChecker( const templateTypeChecker = new TemplateTypeChecker(
this.tsProgram, this.typeCheckingProgramStrategy, traitCompiler, this.tsProgram, this.typeCheckingProgramStrategy, traitCompiler,
this.getTypeCheckingConfig(), refEmitter, reflector, this.incrementalDriver); this.getTypeCheckingConfig(), refEmitter, reflector, this.host, this.incrementalDriver);
return { return {
isCore, isCore,

View File

@ -39,6 +39,7 @@ export class TemplateTypeChecker {
private typeCheckingStrategy: TypeCheckingProgramStrategy, private typeCheckingStrategy: TypeCheckingProgramStrategy,
private typeCheckAdapter: ProgramTypeCheckAdapter, private config: TypeCheckingConfig, private typeCheckAdapter: ProgramTypeCheckAdapter, private config: TypeCheckingConfig,
private refEmitter: ReferenceEmitter, private reflector: ReflectionHost, private refEmitter: ReferenceEmitter, private reflector: ReflectionHost,
private compilerHost: ts.CompilerHost,
private priorBuild: IncrementalBuild<unknown, FileTypeCheckingData>) {} private priorBuild: IncrementalBuild<unknown, FileTypeCheckingData>) {}
/** /**
@ -49,7 +50,7 @@ export class TemplateTypeChecker {
this.files.clear(); this.files.clear();
const ctx = const ctx =
new TypeCheckContext(this.config, this.originalProgram, this.refEmitter, this.reflector); new TypeCheckContext(this.config, this.compilerHost, this.refEmitter, this.reflector);
// Typecheck all the files. // Typecheck all the files.
for (const sf of this.originalProgram.getSourceFiles()) { for (const sf of this.originalProgram.getSourceFiles()) {

View File

@ -113,7 +113,7 @@ export class TypeCheckContext {
private fileMap = new Map<AbsoluteFsPath, PendingFileTypeCheckingData>(); private fileMap = new Map<AbsoluteFsPath, PendingFileTypeCheckingData>();
constructor( constructor(
private config: TypeCheckingConfig, private program: ts.Program, private config: TypeCheckingConfig, private compilerHost: ts.CompilerHost,
private refEmitter: ReferenceEmitter, private reflector: ReflectionHost) {} private refEmitter: ReferenceEmitter, private reflector: ReflectionHost) {}
/** /**
@ -320,7 +320,8 @@ export class TypeCheckContext {
domSchemaChecker: new RegistryDomSchemaChecker(sourceManager), domSchemaChecker: new RegistryDomSchemaChecker(sourceManager),
oobRecorder: new OutOfBandDiagnosticRecorderImpl(sourceManager), oobRecorder: new OutOfBandDiagnosticRecorderImpl(sourceManager),
typeCheckFile: new TypeCheckFile( typeCheckFile: new TypeCheckFile(
TypeCheckShimGenerator.shimFor(sfPath), this.config, this.refEmitter, this.reflector), TypeCheckShimGenerator.shimFor(sfPath), this.config, this.refEmitter, this.reflector,
this.compilerHost),
hasInlines: false, hasInlines: false,
sourceManager, sourceManager,
}; };

View File

@ -34,10 +34,11 @@ export class TypeCheckFile extends Environment {
constructor( constructor(
readonly fileName: AbsoluteFsPath, config: TypeCheckingConfig, refEmitter: ReferenceEmitter, readonly fileName: AbsoluteFsPath, config: TypeCheckingConfig, refEmitter: ReferenceEmitter,
reflector: ReflectionHost) { reflector: ReflectionHost, compilerHost: ts.CompilerHost) {
super( super(
config, new ImportManager(new NoopImportRewriter(), 'i'), refEmitter, reflector, config, new ImportManager(new NoopImportRewriter(), 'i'), refEmitter, reflector,
ts.createSourceFile(fileName, '', ts.ScriptTarget.Latest, true)); ts.createSourceFile(
compilerHost.getCanonicalFileName(fileName), '', ts.ScriptTarget.Latest, true));
} }
addTypeCheckBlock( addTypeCheckBlock(
@ -49,7 +50,7 @@ export class TypeCheckFile extends Environment {
} }
render(): string { render(): string {
let source: string = this.importManager.getAllImports(this.fileName) let source: string = this.importManager.getAllImports(this.contextFile.fileName)
.map(i => `import * as ${i.qualifier} from '${i.specifier}';`) .map(i => `import * as ${i.qualifier} from '${i.specifier}';`)
.join('\n') + .join('\n') +
'\n\n'; '\n\n';

View File

@ -302,7 +302,7 @@ export function typecheck(
const programStrategy = new ReusedProgramStrategy(program, host, options, []); const programStrategy = new ReusedProgramStrategy(program, host, options, []);
const templateTypeChecker = new TemplateTypeChecker( const templateTypeChecker = new TemplateTypeChecker(
program, programStrategy, checkAdapter, fullConfig, emitter, reflectionHost, program, programStrategy, checkAdapter, fullConfig, emitter, reflectionHost, host,
NOOP_INCREMENTAL_BUILD); NOOP_INCREMENTAL_BUILD);
templateTypeChecker.refresh(); templateTypeChecker.refresh();
return templateTypeChecker.getDiagnosticsForFile(sf); return templateTypeChecker.getDiagnosticsForFile(sf);

View File

@ -43,7 +43,7 @@ runInEachFileSystem(() => {
const host = new NgtscCompilerHost(getFileSystem()); const host = new NgtscCompilerHost(getFileSystem());
const file = new TypeCheckFile( const file = new TypeCheckFile(
_('/_typecheck_.ts'), ALL_ENABLED_CONFIG, new ReferenceEmitter([]), _('/_typecheck_.ts'), ALL_ENABLED_CONFIG, new ReferenceEmitter([]),
/* reflector */ null!); /* reflector */ null!, host);
const sf = file.render(); const sf = file.render();
expect(sf).toContain('export const IS_A_MODULE = true;'); expect(sf).toContain('export const IS_A_MODULE = true;');
}); });
@ -73,10 +73,10 @@ TestClass.ngTypeCtor({value: 'test'});
new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost), new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost),
new LogicalProjectStrategy(reflectionHost, logicalFs), new LogicalProjectStrategy(reflectionHost, logicalFs),
]); ]);
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, program, emitter, reflectionHost); const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, host, emitter, reflectionHost);
const TestClass = const TestClass =
getDeclaration(program, _('/main.ts'), 'TestClass', isNamedClassDeclaration); getDeclaration(program, _('/main.ts'), 'TestClass', isNamedClassDeclaration);
const pendingFile = makePendingFile(reflectionHost); const pendingFile = makePendingFile(reflectionHost, host);
ctx.addInlineTypeCtor( ctx.addInlineTypeCtor(
pendingFile, getSourceFileOrError(program, _('/main.ts')), new Reference(TestClass), { pendingFile, getSourceFileOrError(program, _('/main.ts')), new Reference(TestClass), {
fnName: 'ngTypeCtor', fnName: 'ngTypeCtor',
@ -109,8 +109,8 @@ TestClass.ngTypeCtor({value: 'test'});
new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost), new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost),
new LogicalProjectStrategy(reflectionHost, logicalFs), new LogicalProjectStrategy(reflectionHost, logicalFs),
]); ]);
const pendingFile = makePendingFile(reflectionHost); const pendingFile = makePendingFile(reflectionHost, host);
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, program, emitter, reflectionHost); const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, host, emitter, reflectionHost);
const TestClass = const TestClass =
getDeclaration(program, _('/main.ts'), 'TestClass', isNamedClassDeclaration); getDeclaration(program, _('/main.ts'), 'TestClass', isNamedClassDeclaration);
ctx.addInlineTypeCtor( ctx.addInlineTypeCtor(
@ -152,8 +152,8 @@ TestClass.ngTypeCtor({value: 'test'});
new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost), new AbsoluteModuleStrategy(program, checker, moduleResolver, reflectionHost),
new LogicalProjectStrategy(reflectionHost, logicalFs), new LogicalProjectStrategy(reflectionHost, logicalFs),
]); ]);
const pendingFile = makePendingFile(reflectionHost); const pendingFile = makePendingFile(reflectionHost, host);
const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, program, emitter, reflectionHost); const ctx = new TypeCheckContext(ALL_ENABLED_CONFIG, host, emitter, reflectionHost);
const TestClass = const TestClass =
getDeclaration(program, _('/main.ts'), 'TestClass', isNamedClassDeclaration); getDeclaration(program, _('/main.ts'), 'TestClass', isNamedClassDeclaration);
ctx.addInlineTypeCtor( ctx.addInlineTypeCtor(
@ -184,7 +184,8 @@ TestClass.ngTypeCtor({value: 'test'});
} }
}); });
function makePendingFile(reflector: ReflectionHost): PendingFileTypeCheckingData { function makePendingFile(
reflector: ReflectionHost, compilerHost: ts.CompilerHost): PendingFileTypeCheckingData {
const manager = new TemplateSourceManager(); const manager = new TemplateSourceManager();
return { return {
domSchemaChecker: new RegistryDomSchemaChecker(manager), domSchemaChecker: new RegistryDomSchemaChecker(manager),
@ -192,6 +193,7 @@ function makePendingFile(reflector: ReflectionHost): PendingFileTypeCheckingData
oobRecorder: new NoopOobRecorder(), oobRecorder: new NoopOobRecorder(),
sourceManager: manager, sourceManager: manager,
typeCheckFile: new TypeCheckFile( typeCheckFile: new TypeCheckFile(
absoluteFrom('/typecheck.ts'), ALL_ENABLED_CONFIG, new ReferenceEmitter([]), reflector) absoluteFrom('/typecheck.ts'), ALL_ENABLED_CONFIG, new ReferenceEmitter([]), reflector,
compilerHost)
}; };
} }