refactor(ivy): formalize the compilation process for matched handlers (#34288)

Prior to this commit, the `IvyCompilation` tracked the state of each matched
`DecoratorHandler` on each class in the `ts.Program`, and how they
progressed through the compilation process. This tracking was originally
simple, but had grown more complicated as the compiler evolved. The state of
each specific "target" of compilation was determined by the nullability of
a number of fields on the object which tracked it.

This commit formalizes the process of compilation of each matched handler
into a new "trait" concept. A trait is some aspect of a class which gets
created when a `DecoratorHandler` matches the class. It represents an Ivy
aspect that needs to go through the compilation process.

Traits begin in a "pending" state and undergo transitions as various steps
of compilation take place. The `IvyCompilation` class is renamed to the
`TraitCompiler`, which manages the state of all of the traits in the active
program.

Making the trait concept explicit will support future work to incrementalize
the expensive analysis process of compilation.

PR Close #34288
This commit is contained in:
Alex Rickabaugh
2019-12-09 15:22:59 -08:00
committed by Kara Erickson
parent 25b210a269
commit 631e70b6ae
18 changed files with 825 additions and 428 deletions

View File

@ -21,8 +21,8 @@ import {Migration, MigrationHost} from '../../src/migrations/migration';
import {MockLogger} from '../helpers/mock_logger';
import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils';
type DecoratorHandlerWithResolve = DecoratorHandler<any, any>& {
resolve: NonNullable<DecoratorHandler<any, any>['resolve']>;
type DecoratorHandlerWithResolve = DecoratorHandler<unknown, unknown, unknown>& {
resolve: NonNullable<DecoratorHandler<unknown, unknown, unknown>['resolve']>;
};
runInEachFileSystem(() => {
@ -49,7 +49,7 @@ runInEachFileSystem(() => {
]);
// Only detect the Component and Directive decorators
handler.detect.and.callFake(
(node: ts.Declaration, decorators: Decorator[] | null): DetectResult<any>|
(node: ts.Declaration, decorators: Decorator[] | null): DetectResult<unknown>|
undefined => {
const className = (node as any).name.text;
if (decorators === null) {

View File

@ -297,15 +297,15 @@ runInEachFileSystem(() => {
});
});
class TestHandler implements DecoratorHandler<any, any> {
class TestHandler implements DecoratorHandler<unknown, unknown, unknown> {
constructor(protected name: string, protected log: string[]) {}
precedence = HandlerPrecedence.PRIMARY;
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<any>|undefined {
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<unknown>|undefined {
this.log.push(`${this.name}:detect:${node.name.text}:${decorators !.map(d => d.name)}`);
return undefined;
}
analyze(node: ClassDeclaration): AnalysisOutput<any> {
analyze(node: ClassDeclaration): AnalysisOutput<unknown> {
this.log.push(this.name + ':analyze:' + node.name.text);
return {};
}
@ -316,7 +316,7 @@ class TestHandler implements DecoratorHandler<any, any> {
}
class AlwaysDetectHandler extends TestHandler {
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<any>|undefined {
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<unknown>|undefined {
super.detect(node, decorators);
return {trigger: node, metadata: {}};
}