refactor(compiler): Add contextType to I18nContextOp (#53209)

Adding a context type makes code that depends on the kind of context
more explicit and easier to follow

PR Close #53209
This commit is contained in:
Miles Malerba
2023-11-11 10:09:17 -08:00
committed by Pawel Kozlowski
parent 2b3d3b0fe1
commit d121e4e91f
6 changed files with 28 additions and 39 deletions
@@ -553,3 +553,9 @@ export enum DerivedRepeaterVarIdentity {
Even,
Odd,
}
export enum I18nContextKind {
RootI18n,
ChildI18n,
Icu
}
@@ -10,7 +10,7 @@ import * as i18n from '../../../../../i18n/i18n_ast';
import * as o from '../../../../../output/output_ast';
import {ParseSourceSpan} from '../../../../../parse_util';
import {R3DeferBlockMetadata} from '../../../../../render3/view/api';
import {BindingKind, DeferTriggerKind, I18nParamValueFlags, Namespace, OpKind} from '../enums';
import {BindingKind, DeferTriggerKind, I18nContextKind, I18nParamValueFlags, Namespace, OpKind} from '../enums';
import {SlotHandle} from '../handle';
import {Op, OpList, XrefId} from '../operations';
import {ConsumesSlotOpTrait, TRAIT_CONSUMES_SLOT} from '../traits';
@@ -1088,6 +1088,8 @@ export function createIcuEndOp(xref: XrefId): IcuEndOp {
export interface I18nContextOp extends Op<CreateOp> {
kind: OpKind.I18nContext;
contextKind: I18nContextKind;
/**
* The id of this context.
*/
@@ -1120,10 +1122,11 @@ export interface I18nContextOp extends Op<CreateOp> {
}
export function createI18nContextOp(
xref: XrefId, i18nBlock: XrefId, message: i18n.Message,
contextKind: I18nContextKind, xref: XrefId, i18nBlock: XrefId, message: i18n.Message,
sourceSpan: ParseSourceSpan): I18nContextOp {
return {
kind: OpKind.I18nContext,
contextKind,
xref,
i18nBlock,
message,
@@ -28,7 +28,9 @@ export function createI18nContexts(job: CompilationJob) {
case ir.OpKind.I18nStart:
// Each i18n block gets its own context.
xref = job.allocateXrefId();
unit.create.push(ir.createI18nContextOp(xref, op.xref, op.message, null!));
const contextKind =
op.xref === op.root ? ir.I18nContextKind.RootI18n : ir.I18nContextKind.ChildI18n;
unit.create.push(ir.createI18nContextOp(contextKind, xref, op.xref, op.message, null!));
op.context = xref;
currentI18nOp = op;
break;
@@ -44,7 +46,8 @@ export function createI18nContexts(job: CompilationJob) {
if (op.message.id !== currentI18nOp.message.id) {
// There was an enclosing i18n block around this ICU somewhere.
xref = job.allocateXrefId();
unit.create.push(ir.createI18nContextOp(xref, currentI18nOp.xref, op.message, null!));
unit.create.push(ir.createI18nContextOp(
ir.I18nContextKind.Icu, xref, currentI18nOp.xref, op.message, null!));
op.context = xref;
} else {
// The i18n block was generated because of this ICU, OR it was explicit, but the ICU is
@@ -57,18 +57,12 @@ const LIST_DELIMITER = '|';
export function extractI18nMessages(job: CompilationJob): void {
// Save the i18n context ops for later use.
const i18nContexts = new Map<ir.XrefId, ir.I18nContextOp>();
// Record which contexts represent i18n blocks (any other contexts are assumed to have been
// created from ICUs).
const i18nBlockContexts = new Set<ir.XrefId>();
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case ir.OpKind.I18nContext:
i18nContexts.set(op.xref, op);
break;
case ir.OpKind.I18nStart:
i18nBlockContexts.add(op.context!);
break;
}
}
}
@@ -96,8 +90,8 @@ export function extractI18nMessages(job: CompilationJob): void {
if (!op.context) {
throw Error('ICU op should have its context set.');
}
if (!i18nBlockContexts.has(op.context)) {
const i18nContext = i18nContexts.get(op.context)!;
const i18nContext = i18nContexts.get(op.context)!;
if (i18nContext.contextKind === ir.I18nContextKind.Icu) {
const subMessage = createI18nMessage(job, i18nContext, op.messagePlaceholder);
unit.create.push(subMessage);
const parentMessage = i18nBlockMessages.get(i18nContext.i18nBlock);
@@ -33,13 +33,13 @@ export function mergeI18nContexts(job: ComponentCompilationJob) {
}
// For each non-root i18n op, merge its context into the root i18n op's context.
for (const childI18nOp of i18nOps.values()) {
if (childI18nOp.xref !== childI18nOp.root) {
const childContext = i18nContexts.get(childI18nOp.context!)!;
const rootI18nOp = i18nOps.get(childI18nOp.root)!;
for (const context of i18nContexts.values()) {
if (context.contextKind === ir.I18nContextKind.ChildI18n) {
const childI18n = i18nOps.get(context.i18nBlock)!;
const rootI18nOp = i18nOps.get(childI18n.root)!;
const rootContext = i18nContexts.get(rootI18nOp.context!)!;
mergeParams(rootContext.params, childContext.params);
mergeParams(rootContext.postprocessingParams, childContext.postprocessingParams);
mergeParams(rootContext.params, context.params);
mergeParams(rootContext.postprocessingParams, context.postprocessingParams);
}
}
}
@@ -14,29 +14,12 @@ import {CompilationJob} from '../compilation';
* Resolves placeholders for element tags inside of an ICU.
*/
export function resolveI18nIcuPlaceholders(job: CompilationJob) {
const contextOps = new Map<ir.XrefId, ir.I18nContextOp>();
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case ir.OpKind.I18nContext:
contextOps.set(op.xref, op);
break;
}
}
}
for (const unit of job.units) {
for (const op of unit.create) {
switch (op.kind) {
case ir.OpKind.IcuStart:
if (op.context === null) {
throw Error('Icu should have its i18n context set.');
}
const i18nContext = contextOps.get(op.context)!;
for (const node of op.message.nodes) {
node.visit(new ResolveIcuPlaceholdersVisitor(i18nContext.postprocessingParams));
}
break;
if (op.kind === ir.OpKind.I18nContext && op.contextKind === ir.I18nContextKind.Icu) {
for (const node of op.message.nodes) {
node.visit(new ResolveIcuPlaceholdersVisitor(op.postprocessingParams));
}
}
}
}