angular/packages/compiler/src/view_compiler/provider_compiler.ts
Alex Rickabaugh 83a9159063 style(compiler): reformat of codebase with new clang-format version (#36520)
This commit reformats the packages/compiler tree using the new version of
clang-format.

PR Close #36520
2020-04-08 14:51:08 -07:00

210 lines
7.8 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {CompileDiDependencyMetadata, CompileEntryComponentMetadata, CompileProviderMetadata, CompileTokenMetadata} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector';
import {DepFlags, NodeFlags} from '../core';
import {createTokenForExternalReference, Identifiers} from '../identifiers';
import {LifecycleHooks} from '../lifecycle_reflector';
import * as o from '../output/output_ast';
import {convertValueToOutputAst} from '../output/value_util';
import {ProviderAst, ProviderAstType} from '../template_parser/template_ast';
import {OutputContext} from '../util';
export function providerDef(ctx: OutputContext, providerAst: ProviderAst): {
providerExpr: o.Expression,
flags: NodeFlags,
depsExpr: o.Expression,
tokenExpr: o.Expression
} {
let flags = NodeFlags.None;
if (!providerAst.eager) {
flags |= NodeFlags.LazyProvider;
}
if (providerAst.providerType === ProviderAstType.PrivateService) {
flags |= NodeFlags.PrivateProvider;
}
if (providerAst.isModule) {
flags |= NodeFlags.TypeModuleProvider;
}
providerAst.lifecycleHooks.forEach((lifecycleHook) => {
// for regular providers, we only support ngOnDestroy
if (lifecycleHook === LifecycleHooks.OnDestroy ||
providerAst.providerType === ProviderAstType.Directive ||
providerAst.providerType === ProviderAstType.Component) {
flags |= lifecycleHookToNodeFlag(lifecycleHook);
}
});
const {providerExpr, flags: providerFlags, depsExpr} = providerAst.multiProvider ?
multiProviderDef(ctx, flags, providerAst.providers) :
singleProviderDef(ctx, flags, providerAst.providerType, providerAst.providers[0]);
return {
providerExpr,
flags: providerFlags,
depsExpr,
tokenExpr: tokenExpr(ctx, providerAst.token),
};
}
function multiProviderDef(
ctx: OutputContext, flags: NodeFlags, providers: CompileProviderMetadata[]):
{providerExpr: o.Expression, flags: NodeFlags, depsExpr: o.Expression} {
const allDepDefs: o.Expression[] = [];
const allParams: o.FnParam[] = [];
const exprs = providers.map((provider, providerIndex) => {
let expr: o.Expression;
if (provider.useClass) {
const depExprs = convertDeps(providerIndex, provider.deps || provider.useClass.diDeps);
expr = ctx.importExpr(provider.useClass.reference).instantiate(depExprs);
} else if (provider.useFactory) {
const depExprs = convertDeps(providerIndex, provider.deps || provider.useFactory.diDeps);
expr = ctx.importExpr(provider.useFactory.reference).callFn(depExprs);
} else if (provider.useExisting) {
const depExprs = convertDeps(providerIndex, [{token: provider.useExisting}]);
expr = depExprs[0];
} else {
expr = convertValueToOutputAst(ctx, provider.useValue);
}
return expr;
});
const providerExpr =
o.fn(allParams, [new o.ReturnStatement(o.literalArr(exprs))], o.INFERRED_TYPE);
return {
providerExpr,
flags: flags | NodeFlags.TypeFactoryProvider,
depsExpr: o.literalArr(allDepDefs)
};
function convertDeps(providerIndex: number, deps: CompileDiDependencyMetadata[]) {
return deps.map((dep, depIndex) => {
const paramName = `p${providerIndex}_${depIndex}`;
allParams.push(new o.FnParam(paramName, o.DYNAMIC_TYPE));
allDepDefs.push(depDef(ctx, dep));
return o.variable(paramName);
});
}
}
function singleProviderDef(
ctx: OutputContext, flags: NodeFlags, providerType: ProviderAstType,
providerMeta: CompileProviderMetadata):
{providerExpr: o.Expression, flags: NodeFlags, depsExpr: o.Expression} {
let providerExpr: o.Expression;
let deps: CompileDiDependencyMetadata[];
if (providerType === ProviderAstType.Directive || providerType === ProviderAstType.Component) {
providerExpr = ctx.importExpr(providerMeta.useClass!.reference);
flags |= NodeFlags.TypeDirective;
deps = providerMeta.deps || providerMeta.useClass!.diDeps;
} else {
if (providerMeta.useClass) {
providerExpr = ctx.importExpr(providerMeta.useClass.reference);
flags |= NodeFlags.TypeClassProvider;
deps = providerMeta.deps || providerMeta.useClass.diDeps;
} else if (providerMeta.useFactory) {
providerExpr = ctx.importExpr(providerMeta.useFactory.reference);
flags |= NodeFlags.TypeFactoryProvider;
deps = providerMeta.deps || providerMeta.useFactory.diDeps;
} else if (providerMeta.useExisting) {
providerExpr = o.NULL_EXPR;
flags |= NodeFlags.TypeUseExistingProvider;
deps = [{token: providerMeta.useExisting}];
} else {
providerExpr = convertValueToOutputAst(ctx, providerMeta.useValue);
flags |= NodeFlags.TypeValueProvider;
deps = [];
}
}
const depsExpr = o.literalArr(deps.map(dep => depDef(ctx, dep)));
return {providerExpr, flags, depsExpr};
}
function tokenExpr(ctx: OutputContext, tokenMeta: CompileTokenMetadata): o.Expression {
return tokenMeta.identifier ? ctx.importExpr(tokenMeta.identifier.reference) :
o.literal(tokenMeta.value);
}
export function depDef(ctx: OutputContext, dep: CompileDiDependencyMetadata): o.Expression {
// Note: the following fields have already been normalized out by provider_analyzer:
// - isAttribute, isHost
const expr = dep.isValue ? convertValueToOutputAst(ctx, dep.value) : tokenExpr(ctx, dep.token!);
let flags = DepFlags.None;
if (dep.isSkipSelf) {
flags |= DepFlags.SkipSelf;
}
if (dep.isOptional) {
flags |= DepFlags.Optional;
}
if (dep.isSelf) {
flags |= DepFlags.Self;
}
if (dep.isValue) {
flags |= DepFlags.Value;
}
return flags === DepFlags.None ? expr : o.literalArr([o.literal(flags), expr]);
}
export function lifecycleHookToNodeFlag(lifecycleHook: LifecycleHooks): NodeFlags {
let nodeFlag = NodeFlags.None;
switch (lifecycleHook) {
case LifecycleHooks.AfterContentChecked:
nodeFlag = NodeFlags.AfterContentChecked;
break;
case LifecycleHooks.AfterContentInit:
nodeFlag = NodeFlags.AfterContentInit;
break;
case LifecycleHooks.AfterViewChecked:
nodeFlag = NodeFlags.AfterViewChecked;
break;
case LifecycleHooks.AfterViewInit:
nodeFlag = NodeFlags.AfterViewInit;
break;
case LifecycleHooks.DoCheck:
nodeFlag = NodeFlags.DoCheck;
break;
case LifecycleHooks.OnChanges:
nodeFlag = NodeFlags.OnChanges;
break;
case LifecycleHooks.OnDestroy:
nodeFlag = NodeFlags.OnDestroy;
break;
case LifecycleHooks.OnInit:
nodeFlag = NodeFlags.OnInit;
break;
}
return nodeFlag;
}
export function componentFactoryResolverProviderDef(
reflector: CompileReflector, ctx: OutputContext, flags: NodeFlags,
entryComponents: CompileEntryComponentMetadata[]): {
providerExpr: o.Expression,
flags: NodeFlags,
depsExpr: o.Expression,
tokenExpr: o.Expression
} {
const entryComponentFactories =
entryComponents.map((entryComponent) => ctx.importExpr(entryComponent.componentFactory));
const token = createTokenForExternalReference(reflector, Identifiers.ComponentFactoryResolver);
const classMeta = {
diDeps: [
{isValue: true, value: o.literalArr(entryComponentFactories)},
{token: token, isSkipSelf: true, isOptional: true},
{token: createTokenForExternalReference(reflector, Identifiers.NgModuleRef)},
],
lifecycleHooks: [],
reference: reflector.resolveExternalReference(Identifiers.CodegenComponentFactoryResolver)
};
const {providerExpr, flags: providerFlags, depsExpr} =
singleProviderDef(ctx, flags, ProviderAstType.PrivateService, {
token,
multi: false,
useClass: classMeta,
});
return {providerExpr, flags: providerFlags, depsExpr, tokenExpr: tokenExpr(ctx, token)};
}