refactor(ivy): compute ignoreFiles for compilation on initialization (#34792)

This commit moves the calculation of `ignoreFiles` - the set of files to be
ignored by a consumer of the `NgCompiler` API - from its `prepareEmit`
operation to its initialization. It's now available as a field on
`NgCompiler`.

This will allow a consumer to skip gathering diagnostics for `ignoreFiles`
as well as skip emit.

PR Close #34792
This commit is contained in:
Alex Rickabaugh 2020-02-03 10:48:05 -08:00 committed by Misko Hevery
parent 49dd7b6a0a
commit 14aa6d090e
5 changed files with 70 additions and 20 deletions

View File

@ -97,6 +97,8 @@ export class NgCompiler {
private resourceManager: HostResourceLoader; private resourceManager: HostResourceLoader;
private cycleAnalyzer: CycleAnalyzer; private cycleAnalyzer: CycleAnalyzer;
readonly incrementalDriver: IncrementalDriver; readonly incrementalDriver: IncrementalDriver;
readonly ignoreForDiagnostics: Set<ts.SourceFile>;
readonly ignoreForEmit: Set<ts.SourceFile>;
constructor( constructor(
private host: NgCompilerHost, private options: NgCompilerOptions, private host: NgCompilerHost, private options: NgCompilerOptions,
@ -142,6 +144,14 @@ export class NgCompiler {
} }
} }
setIncrementalDriver(tsProgram, this.incrementalDriver); setIncrementalDriver(tsProgram, this.incrementalDriver);
this.ignoreForDiagnostics = new Set([
this.typeCheckFile,
...host.factoryFiles.map(fileName => getSourceFileOrError(tsProgram, fileName)),
...host.summaryFiles.map(fileName => getSourceFileOrError(tsProgram, fileName)),
]);
this.ignoreForEmit = new Set([this.typeCheckFile]);
} }
/** /**
@ -285,7 +295,6 @@ export class NgCompiler {
*/ */
prepareEmit(): { prepareEmit(): {
transformers: ts.CustomTransformers, transformers: ts.CustomTransformers,
ignoreFiles: Set<ts.SourceFile>,
} { } {
const compilation = this.ensureAnalyzed(); const compilation = this.ensureAnalyzed();
@ -321,9 +330,7 @@ export class NgCompiler {
} }
before.push(ivySwitchTransform); before.push(ivySwitchTransform);
const ignoreFiles = new Set<ts.SourceFile>([this.typeCheckFile]); return {transformers: {before, afterDeclarations} as ts.CustomTransformers};
return {transformers: {before, afterDeclarations} as ts.CustomTransformers, ignoreFiles};
} }
/** /**

View File

@ -97,17 +97,22 @@ export class NgCompilerHost extends DelegatingCompilerHost implements
readonly inputFiles: ReadonlyArray<string>; readonly inputFiles: ReadonlyArray<string>;
readonly rootDirs: ReadonlyArray<AbsoluteFsPath>; readonly rootDirs: ReadonlyArray<AbsoluteFsPath>;
readonly typeCheckFile: AbsoluteFsPath; readonly typeCheckFile: AbsoluteFsPath;
readonly factoryFiles: AbsoluteFsPath[];
readonly summaryFiles: AbsoluteFsPath[];
constructor( constructor(
delegate: ExtendedTsCompilerHost, inputFiles: ReadonlyArray<string>, delegate: ExtendedTsCompilerHost, inputFiles: ReadonlyArray<string>,
rootDirs: ReadonlyArray<AbsoluteFsPath>, private shims: ShimGenerator[], rootDirs: ReadonlyArray<AbsoluteFsPath>, private shims: ShimGenerator[],
entryPoint: AbsoluteFsPath|null, typeCheckFile: AbsoluteFsPath, entryPoint: AbsoluteFsPath|null, typeCheckFile: AbsoluteFsPath,
factoryFiles: AbsoluteFsPath[], summaryFiles: AbsoluteFsPath[],
factoryTracker: FactoryTracker|null, diagnostics: ts.Diagnostic[]) { factoryTracker: FactoryTracker|null, diagnostics: ts.Diagnostic[]) {
super(delegate); super(delegate);
this.factoryTracker = factoryTracker; this.factoryTracker = factoryTracker;
this.entryPoint = entryPoint; this.entryPoint = entryPoint;
this.typeCheckFile = typeCheckFile; this.typeCheckFile = typeCheckFile;
this.factoryFiles = factoryFiles;
this.summaryFiles = summaryFiles;
this.diagnostics = diagnostics; this.diagnostics = diagnostics;
this.inputFiles = inputFiles; this.inputFiles = inputFiles;
this.rootDirs = rootDirs; this.rootDirs = rootDirs;
@ -136,31 +141,36 @@ export class NgCompilerHost extends DelegatingCompilerHost implements
const generators: ShimGenerator[] = []; const generators: ShimGenerator[] = [];
let summaryGenerator: SummaryGenerator|null = null; let summaryGenerator: SummaryGenerator|null = null;
let summaryFiles: AbsoluteFsPath[];
if (shouldGenerateSummaryShims) { if (shouldGenerateSummaryShims) {
// Summary generation. // Summary generation.
summaryGenerator = SummaryGenerator.forRootFiles(normalizedInputFiles); summaryGenerator = SummaryGenerator.forRootFiles(normalizedInputFiles);
generators.push(summaryGenerator); generators.push(summaryGenerator);
summaryFiles = summaryGenerator.getSummaryFileNames();
} else {
summaryFiles = [];
} }
let factoryTracker: FactoryTracker|null = null; let factoryTracker: FactoryTracker|null = null;
let factoryFiles: AbsoluteFsPath[];
if (shouldGenerateFactoryShims) { if (shouldGenerateFactoryShims) {
// Factory generation. // Factory generation.
const factoryGenerator = FactoryGenerator.forRootFiles(normalizedInputFiles); const factoryGenerator = FactoryGenerator.forRootFiles(normalizedInputFiles);
const factoryFileMap = factoryGenerator.factoryFileMap; const factoryFileMap = factoryGenerator.factoryFileMap;
const factoryFileNames = Array.from(factoryFileMap.keys()); factoryFiles = Array.from(factoryFileMap.keys());
rootFiles.push(...factoryFileNames); rootFiles.push(...factoryFiles);
generators.push(factoryGenerator); generators.push(factoryGenerator);
factoryTracker = new FactoryTracker(factoryGenerator); factoryTracker = new FactoryTracker(factoryGenerator);
} else {
factoryFiles = [];
} }
// Done separately to preserve the order of factory files before summary files in rootFiles. // Done separately to preserve the order of factory files before summary files in rootFiles.
// TODO(alxhub): validate that this is necessary. // TODO(alxhub): validate that this is necessary.
if (summaryGenerator !== null) { rootFiles.push(...summaryFiles);
rootFiles.push(...summaryGenerator.getSummaryFileNames());
}
const rootDirs = getRootDirs(delegate, options as ts.CompilerOptions); const rootDirs = getRootDirs(delegate, options as ts.CompilerOptions);
@ -203,8 +213,8 @@ export class NgCompilerHost extends DelegatingCompilerHost implements
} }
return new NgCompilerHost( return new NgCompilerHost(
delegate, rootFiles, rootDirs, generators, entryPoint, typeCheckFile, factoryTracker, delegate, rootFiles, rootDirs, generators, entryPoint, typeCheckFile, factoryFiles,
diagnostics); summaryFiles, factoryTracker, diagnostics);
} }
getSourceFile( getSourceFile(

View File

@ -88,13 +88,43 @@ export class NgtscProgram implements api.Program {
getTsSyntacticDiagnostics( getTsSyntacticDiagnostics(
sourceFile?: ts.SourceFile|undefined, sourceFile?: ts.SourceFile|undefined,
cancellationToken?: ts.CancellationToken|undefined): readonly ts.Diagnostic[] { cancellationToken?: ts.CancellationToken|undefined): readonly ts.Diagnostic[] {
return this.tsProgram.getSyntacticDiagnostics(sourceFile, cancellationToken); const ignoredFiles = this.compiler.ignoreForDiagnostics;
if (sourceFile !== undefined) {
if (ignoredFiles.has(sourceFile)) {
return [];
}
return this.tsProgram.getSyntacticDiagnostics(sourceFile, cancellationToken);
} else {
const diagnostics: ts.Diagnostic[] = [];
for (const sf of this.tsProgram.getSourceFiles()) {
if (!ignoredFiles.has(sf)) {
diagnostics.push(...this.tsProgram.getSyntacticDiagnostics(sf, cancellationToken));
}
}
return diagnostics;
}
} }
getTsSemanticDiagnostics( getTsSemanticDiagnostics(
sourceFile?: ts.SourceFile|undefined, sourceFile?: ts.SourceFile|undefined,
cancellationToken?: ts.CancellationToken|undefined): readonly ts.Diagnostic[] { cancellationToken?: ts.CancellationToken|undefined): readonly ts.Diagnostic[] {
return this.tsProgram.getSemanticDiagnostics(sourceFile, cancellationToken); const ignoredFiles = this.compiler.ignoreForDiagnostics;
if (sourceFile !== undefined) {
if (ignoredFiles.has(sourceFile)) {
return [];
}
return this.tsProgram.getSemanticDiagnostics(sourceFile, cancellationToken);
} else {
const diagnostics: ts.Diagnostic[] = [];
for (const sf of this.tsProgram.getSourceFiles()) {
if (!ignoredFiles.has(sf)) {
diagnostics.push(...this.tsProgram.getSemanticDiagnostics(sf, cancellationToken));
}
}
return diagnostics;
}
} }
getNgOptionDiagnostics(cancellationToken?: ts.CancellationToken| getNgOptionDiagnostics(cancellationToken?: ts.CancellationToken|
@ -144,7 +174,8 @@ export class NgtscProgram implements api.Program {
emitCallback?: api.TsEmitCallback | undefined; emitCallback?: api.TsEmitCallback | undefined;
mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback | undefined; mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback | undefined;
}|undefined): ts.EmitResult { }|undefined): ts.EmitResult {
const {transformers, ignoreFiles} = this.compiler.prepareEmit(); const {transformers} = this.compiler.prepareEmit();
const ignoreFiles = this.compiler.ignoreForEmit;
const emitCallback = opts && opts.emitCallback || defaultEmitCallback; const emitCallback = opts && opts.emitCallback || defaultEmitCallback;
const writeFile: ts.WriteFileCallback = const writeFile: ts.WriteFileCallback =

View File

@ -22,9 +22,11 @@ const STRIP_NG_FACTORY = /(.*)NgFactory$/;
* class of an input ts.SourceFile. * class of an input ts.SourceFile.
*/ */
export class FactoryGenerator implements ShimGenerator { export class FactoryGenerator implements ShimGenerator {
private constructor(private map: Map<string, string>) {} private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
get factoryFileMap(): Map<string, string> { return this.map; } get factoryFileMap(): Map<AbsoluteFsPath, AbsoluteFsPath> { return this.map; }
get factoryFileNames(): AbsoluteFsPath[] { return Array.from(this.map.keys()); }
recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); } recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); }
@ -101,7 +103,7 @@ export class FactoryGenerator implements ShimGenerator {
} }
static forRootFiles(files: ReadonlyArray<AbsoluteFsPath>): FactoryGenerator { static forRootFiles(files: ReadonlyArray<AbsoluteFsPath>): FactoryGenerator {
const map = new Map<AbsoluteFsPath, string>(); const map = new Map<AbsoluteFsPath, AbsoluteFsPath>();
files.filter(sourceFile => isNonDeclarationTsPath(sourceFile)) files.filter(sourceFile => isNonDeclarationTsPath(sourceFile))
.forEach( .forEach(
sourceFile => sourceFile =>

View File

@ -15,9 +15,9 @@ import {ShimGenerator} from './api';
import {generatedModuleName} from './util'; import {generatedModuleName} from './util';
export class SummaryGenerator implements ShimGenerator { export class SummaryGenerator implements ShimGenerator {
private constructor(private map: Map<AbsoluteFsPath, string>) {} private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
getSummaryFileNames(): string[] { return Array.from(this.map.keys()); } getSummaryFileNames(): AbsoluteFsPath[] { return Array.from(this.map.keys()); }
recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); } recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); }
@ -78,7 +78,7 @@ export class SummaryGenerator implements ShimGenerator {
} }
static forRootFiles(files: ReadonlyArray<AbsoluteFsPath>): SummaryGenerator { static forRootFiles(files: ReadonlyArray<AbsoluteFsPath>): SummaryGenerator {
const map = new Map<AbsoluteFsPath, string>(); const map = new Map<AbsoluteFsPath, AbsoluteFsPath>();
files.filter(sourceFile => isNonDeclarationTsPath(sourceFile)) files.filter(sourceFile => isNonDeclarationTsPath(sourceFile))
.forEach( .forEach(
sourceFile => sourceFile =>