fix(ivy): reuse compilation scope for incremental template changes. (#31932)

Previously if only a component template changed then we would know to
rebuild its component source file. But the compilation was incorrect if the
component was part of an NgModule, since we were not capturing the
compilation scope information that had a been acquired from the NgModule
and was not being regenerated since we were not needing to recompile
the NgModule.

Now we register compilation scope information for each component, via the
`ComponentScopeRegistry` interface, so that it is available for incremental
compilation.

The `ComponentDecoratorHandler` now reads the compilation scope from a
`ComponentScopeReader` interface which is implemented as a compound
reader composed of the original `LocalModuleScopeRegistry` and the
`IncrementalState`.

Fixes #31654

PR Close #31932
This commit is contained in:
Pete Bacon Darwin
2019-07-31 17:11:33 +01:00
committed by Kara Erickson
parent 7533338362
commit eb5412d76f
10 changed files with 188 additions and 30 deletions

View File

@ -18,7 +18,7 @@ import {DirectiveMeta, MetadataReader, MetadataRegistry, extractDirectiveGuards}
import {flattenInheritedDirectiveMetadata} from '../../metadata/src/inheritance';
import {EnumValue, PartialEvaluator} from '../../partial_evaluator';
import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
import {LocalModuleScopeRegistry} from '../../scope';
import {ComponentScopeReader, LocalModuleScopeRegistry} from '../../scope';
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence, ResolveResult} from '../../transform';
import {TypeCheckContext} from '../../typecheck';
import {NoopResourceDependencyRecorder, ResourceDependencyRecorder} from '../../util/src/resource_recorder';
@ -47,8 +47,8 @@ export class ComponentDecoratorHandler implements
constructor(
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
private metaRegistry: MetadataRegistry, private metaReader: MetadataReader,
private scopeRegistry: LocalModuleScopeRegistry, private isCore: boolean,
private resourceLoader: ResourceLoader, private rootDirs: string[],
private scopeReader: ComponentScopeReader, private scopeRegistry: LocalModuleScopeRegistry,
private isCore: boolean, private resourceLoader: ResourceLoader, private rootDirs: string[],
private defaultPreserveWhitespaces: boolean, private i18nUseExternalIds: boolean,
private moduleResolver: ModuleResolver, private cycleAnalyzer: CycleAnalyzer,
private refEmitter: ReferenceEmitter, private defaultImportRecorder: DefaultImportRecorder,
@ -327,7 +327,7 @@ export class ComponentDecoratorHandler implements
preserveWhitespaces: true,
leadingTriviaChars: [],
});
const scope = this.scopeRegistry.getScopeForComponent(node);
const scope = this.scopeReader.getScopeForComponent(node);
const selector = analysis.meta.selector;
const matcher = new SelectorMatcher<DirectiveMeta>();
if (scope !== null) {
@ -353,7 +353,7 @@ export class ComponentDecoratorHandler implements
if (!ts.isClassDeclaration(node)) {
return;
}
const scope = this.scopeRegistry.getScopeForComponent(node);
const scope = this.scopeReader.getScopeForComponent(node);
const matcher = new SelectorMatcher<DirectiveMeta>();
if (scope !== null) {
for (const meta of scope.compilation.directives) {
@ -377,7 +377,7 @@ export class ComponentDecoratorHandler implements
const context = node.getSourceFile();
// Check whether this component was registered with an NgModule. If so, it should be compiled
// under that module's compilation scope.
const scope = this.scopeRegistry.getScopeForComponent(node);
const scope = this.scopeReader.getScopeForComponent(node);
let metadata = analysis.meta;
if (scope !== null) {
// Replace the empty components and directives from the analyze() step with a fully expanded

View File

@ -60,7 +60,7 @@ runInEachFileSystem(() => {
const refEmitter = new ReferenceEmitter([]);
const handler = new ComponentDecoratorHandler(
reflectionHost, evaluator, metaRegistry, metaReader, scopeRegistry, false,
reflectionHost, evaluator, metaRegistry, metaReader, scopeRegistry, scopeRegistry, false,
new NoopResourceLoader(), [''], false, true, moduleResolver, cycleAnalyzer, refEmitter,
NOOP_DEFAULT_IMPORT_RECORDER);
const TestCmp = getDeclaration(program, _('/entry.ts'), 'TestCmp', isNamedClassDeclaration);