feat(ivy): track compilation scope dependencies for components (#30238)

To support skipping analysis of a file containing a component
we need to know that none of the declarations that might affect
its ngtsc compilation have not changed. The files that we need to
check are those that contain classes from the `CompilationScope`
of the component. These classes are already tracked in the
`LocalModuleScopeRegistry`.

This commit modifies the `IvyCompilation` class to record the
files that are in each declared class's `CompilationScope` via
a new method, `recordNgModuleScopeDependencies()`, that is called
after all the handlers have been "resolved".

Further, if analysis is skipped for a declared class, then we need
to recover the analysis from the previous compilation run. To
support this, the `IncrementalState` class has been updated to
expose the `MetadataReader` and `MetadataRegistry` interfaces.
This is included in the `metaRegistry` object to capture these analyses,
and also in the `localMetaReader` as a fallback to use if the
current compilation analysis was skipped.

PR Close #30238
This commit is contained in:
Pete Bacon Darwin
2019-05-08 15:10:50 +01:00
committed by Alex Rickabaugh
parent 0a0b4c1d8f
commit 411524d341
6 changed files with 111 additions and 22 deletions

View File

@ -14,6 +14,7 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/incremental",
"//packages/compiler-cli/src/ngtsc/perf",
"//packages/compiler-cli/src/ngtsc/reflection",
"//packages/compiler-cli/src/ngtsc/scope",
"//packages/compiler-cli/src/ngtsc/translator",
"//packages/compiler-cli/src/ngtsc/typecheck",
"//packages/compiler-cli/src/ngtsc/util",

View File

@ -14,6 +14,7 @@ import {ImportRewriter} from '../../imports';
import {IncrementalState} from '../../incremental';
import {PerfRecorder} from '../../perf';
import {ClassDeclaration, ReflectionHost, isNamedClassDeclaration, reflectNameOfDeclaration} from '../../reflection';
import {LocalModuleScopeRegistry} from '../../scope';
import {TypeCheckContext} from '../../typecheck';
import {getSourceFile} from '../../util/src/typescript';
@ -75,10 +76,10 @@ export class IvyCompilation {
* `null` in most cases.
*/
constructor(
private handlers: DecoratorHandler<any, any>[], private checker: ts.TypeChecker,
private reflector: ReflectionHost, private importRewriter: ImportRewriter,
private incrementalState: IncrementalState, private perf: PerfRecorder,
private sourceToFactorySymbols: Map<string, Set<string>>|null) {}
private handlers: DecoratorHandler<any, any>[], private reflector: ReflectionHost,
private importRewriter: ImportRewriter, private incrementalState: IncrementalState,
private perf: PerfRecorder, private sourceToFactorySymbols: Map<string, Set<string>>|null,
private scopeRegistry: LocalModuleScopeRegistry) {}
get exportStatements(): Map<string, Map<string, [string, string]>> { return this.reexportMap; }
@ -302,6 +303,22 @@ export class IvyCompilation {
}
});
this.perf.stop(resolveSpan);
this.recordNgModuleScopeDependencies();
}
private recordNgModuleScopeDependencies() {
const recordSpan = this.perf.start('recordDependencies');
this.scopeRegistry !.getCompilationScopes().forEach(scope => {
const file = scope.declaration.getSourceFile();
// Register the file containing the NgModule where the declaration is declared.
this.incrementalState.trackFileDependency(scope.ngModule.getSourceFile(), file);
scope.directives.forEach(
directive =>
this.incrementalState.trackFileDependency(directive.ref.node.getSourceFile(), file));
scope.pipes.forEach(
pipe => this.incrementalState.trackFileDependency(pipe.ref.node.getSourceFile(), file));
});
this.perf.stop(recordSpan);
}
typeCheck(context: TypeCheckContext): void {