feat(compiler-cli): partial compilation of directives (#39518)

This commit implements partial code generation for directives, which
will be transformed by the linker plugin to fully AOT compiled code in
follow-up work.

PR Close #39518
This commit is contained in:
JoostK
2020-10-30 23:45:15 +01:00
committed by Joey Perrott
parent ded7beed32
commit 8c0a92bb45
13 changed files with 363 additions and 15 deletions
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {compileDirectiveFromMetadata, ConstantPool, Expression, Identifiers, makeBindingParser, ParsedHostBindings, ParseError, parseHostBindings, R3DependencyMetadata, R3DirectiveMetadata, R3FactoryTarget, R3QueryMetadata, Statement, verifyHostBindings, WrappedNodeExpr} from '@angular/compiler';
import {compileDeclareDirectiveFromMetadata, compileDirectiveFromMetadata, ConstantPool, Expression, Identifiers, makeBindingParser, ParsedHostBindings, ParseError, parseHostBindings, R3DependencyMetadata, R3DirectiveDef, R3DirectiveMetadata, R3FactoryTarget, R3QueryMetadata, Statement, verifyHostBindings, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
@@ -154,19 +154,34 @@ export class DirectiveDecoratorHandler implements
compileFull(
node: ClassDeclaration, analysis: Readonly<DirectiveHandlerData>,
resolution: Readonly<unknown>, pool: ConstantPool): CompileResult[] {
const meta = analysis.meta;
const res = compileDirectiveFromMetadata(meta, pool, makeBindingParser());
const factoryRes = compileNgFactoryDefField(
{...meta, injectFn: Identifiers.directiveInject, target: R3FactoryTarget.Directive});
const def = compileDirectiveFromMetadata(analysis.meta, pool, makeBindingParser());
return this.compileDirective(analysis, def);
}
compilePartial(
node: ClassDeclaration, analysis: Readonly<DirectiveHandlerData>,
resolution: Readonly<unknown>): CompileResult[] {
const def = compileDeclareDirectiveFromMetadata(analysis.meta);
return this.compileDirective(analysis, def);
}
private compileDirective(
analysis: Readonly<DirectiveHandlerData>,
{expression: initializer, type}: R3DirectiveDef): CompileResult[] {
const factoryRes = compileNgFactoryDefField({
...analysis.meta,
injectFn: Identifiers.directiveInject,
target: R3FactoryTarget.Directive,
});
if (analysis.metadataStmt !== null) {
factoryRes.statements.push(analysis.metadataStmt);
}
return [
factoryRes, {
name: 'ɵdir',
initializer: res.expression,
initializer,
statements: [],
type: res.type,
type,
}
];
}
@@ -249,7 +249,10 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
visitExternalExpr(ast: o.ExternalExpr, _context: Context): TExpression {
if (ast.value.name === null) {
throw new Error(`Import unknown module or symbol ${ast.value}`);
if (ast.value.moduleName === null) {
throw new Error('Invalid import without name nor moduleName');
}
return this.imports.generateNamespaceImport(ast.value.moduleName);
}
// If a moduleName is specified, this is a normal import. If there's no module name, it's a
// reference to a global/ambient symbol.