Skip to content

Commit

Permalink
refactor(compiler): Add a kind field to the parsed AST
Browse files Browse the repository at this point in the history
The Aspirin team wants to use the output of `parseTemplate` in order to build some g3-internal tooling. However, our AST is very serialization-unfriendly.

With this change, all AST nodes now have a `kind`, and can be reasonably navigated after serialization (although the inner fields are still pretty messy).

Additionally, create a separate entrypoint that only reexports the AST nodes, so that we can control visibility on a more granular level to the AST alone.
  • Loading branch information
dylhunn committed Sep 16, 2024
1 parent 59fe9bc commit 3f68cea
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 41 deletions.
40 changes: 1 addition & 39 deletions packages/compiler/src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,45 +121,7 @@ export {SourceMap} from './output/source_map';
export * from './injectable_compiler_2';
export * from './render3/partial/api';
export * from './render3/view/api';
export {
visitAll as tmplAstVisitAll,
BlockNode as TmplAstBlockNode,
BoundAttribute as TmplAstBoundAttribute,
BoundEvent as TmplAstBoundEvent,
BoundText as TmplAstBoundText,
Content as TmplAstContent,
Element as TmplAstElement,
Icu as TmplAstIcu,
Node as TmplAstNode,
Visitor as TmplAstVisitor,
RecursiveVisitor as TmplAstRecursiveVisitor,
Reference as TmplAstReference,
Template as TmplAstTemplate,
Text as TmplAstText,
TextAttribute as TmplAstTextAttribute,
Variable as TmplAstVariable,
DeferredBlock as TmplAstDeferredBlock,
DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder,
DeferredBlockLoading as TmplAstDeferredBlockLoading,
DeferredBlockError as TmplAstDeferredBlockError,
DeferredTrigger as TmplAstDeferredTrigger,
BoundDeferredTrigger as TmplAstBoundDeferredTrigger,
IdleDeferredTrigger as TmplAstIdleDeferredTrigger,
ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger,
HoverDeferredTrigger as TmplAstHoverDeferredTrigger,
TimerDeferredTrigger as TmplAstTimerDeferredTrigger,
InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger,
ViewportDeferredTrigger as TmplAstViewportDeferredTrigger,
SwitchBlock as TmplAstSwitchBlock,
SwitchBlockCase as TmplAstSwitchBlockCase,
ForLoopBlock as TmplAstForLoopBlock,
ForLoopBlockEmpty as TmplAstForLoopBlockEmpty,
IfBlock as TmplAstIfBlock,
IfBlockBranch as TmplAstIfBlockBranch,
DeferredBlockTriggers as TmplAstDeferredBlockTriggers,
UnknownBlock as TmplAstUnknownBlock,
LetDeclaration as TmplAstLetDeclaration,
} from './render3/r3_ast';
export * from './compiler_ast_exports';
export * from './render3/view/t2_api';
export * from './render3/view/t2_binder';
export {createCssSelectorFromNode} from './render3/view/util';
Expand Down
40 changes: 40 additions & 0 deletions packages/compiler/src/compiler_ast_exports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export {
BlockNode as TmplAstBlockNode,
BoundAttribute as TmplAstBoundAttribute,
BoundDeferredTrigger as TmplAstBoundDeferredTrigger,
BoundEvent as TmplAstBoundEvent,
BoundText as TmplAstBoundText,
Content as TmplAstContent,
Comment as TmplAstComment,
DeferredBlock as TmplAstDeferredBlock,
DeferredBlockError as TmplAstDeferredBlockError,
DeferredBlockLoading as TmplAstDeferredBlockLoading,
DeferredBlockPlaceholder as TmplAstDeferredBlockPlaceholder,
DeferredBlockTriggers as TmplAstDeferredBlockTriggers,
DeferredTrigger as TmplAstDeferredTrigger,
Element as TmplAstElement,
ForLoopBlock as TmplAstForLoopBlock,
ForLoopBlockEmpty as TmplAstForLoopBlockEmpty,
HoverDeferredTrigger as TmplAstHoverDeferredTrigger,
Icu as TmplAstIcu,
IdleDeferredTrigger as TmplAstIdleDeferredTrigger,
IfBlock as TmplAstIfBlock,
IfBlockBranch as TmplAstIfBlockBranch,
ImmediateDeferredTrigger as TmplAstImmediateDeferredTrigger,
InteractionDeferredTrigger as TmplAstInteractionDeferredTrigger,
LetDeclaration as TmplAstLetDeclaration,
Node as TmplAstNode,
RecursiveVisitor as TmplAstRecursiveVisitor,
Reference as TmplAstReference,
SwitchBlock as TmplAstSwitchBlock,
SwitchBlockCase as TmplAstSwitchBlockCase,
Template as TmplAstTemplate,
Text as TmplAstText,
TextAttribute as TmplAstTextAttribute,
TimerDeferredTrigger as TmplAstTimerDeferredTrigger,
UnknownBlock as TmplAstUnknownBlock,
Variable as TmplAstVariable,
ViewportDeferredTrigger as TmplAstViewportDeferredTrigger,
Visitor as TmplAstVisitor,
visitAll as tmplAstVisitAll,
} from './render3/r3_ast';
81 changes: 79 additions & 2 deletions packages/compiler/src/render3/r3_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {I18nMeta} from '../i18n/i18n_ast';
import {ParseSourceSpan} from '../parse_util';

export interface Node {
readonly kind: string;
sourceSpan: ParseSourceSpan;
visit<Result>(visitor: Visitor<Result>): Result;
}
Expand All @@ -34,6 +35,9 @@ export class Comment implements Node {
public value: string,
public sourceSpan: ParseSourceSpan,
) {}

readonly kind = 'Comment';

visit<Result>(_visitor: Visitor<Result>): Result {
throw new Error('visit() not implemented for Comment');
}
Expand All @@ -44,6 +48,9 @@ export class Text implements Node {
public value: string,
public sourceSpan: ParseSourceSpan,
) {}

readonly kind = 'Text';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitText(this);
}
Expand All @@ -55,6 +62,9 @@ export class BoundText implements Node {
public sourceSpan: ParseSourceSpan,
public i18n?: I18nMeta,
) {}

readonly kind = 'BoundText';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitBoundText(this);
}
Expand All @@ -75,6 +85,9 @@ export class TextAttribute implements Node {
public valueSpan?: ParseSourceSpan,
public i18n?: I18nMeta,
) {}

readonly kind = 'TextAttribute';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitTextAttribute(this);
}
Expand All @@ -93,6 +106,8 @@ export class BoundAttribute implements Node {
public i18n: I18nMeta | undefined,
) {}

readonly kind = 'BoundAttribute';

static fromBoundElementProperty(prop: BoundElementProperty, i18n?: I18nMeta): BoundAttribute {
if (prop.keySpan === undefined) {
throw new Error(
Expand Down Expand Up @@ -129,6 +144,8 @@ export class BoundEvent implements Node {
readonly keySpan: ParseSourceSpan,
) {}

readonly kind = 'BoundEvent';

static fromParsedEvent(event: ParsedEvent) {
const target: string | null =
event.type === ParsedEventType.Regular ? event.targetOrPhase : null;
Expand Down Expand Up @@ -169,6 +186,9 @@ export class Element implements Node {
public endSourceSpan: ParseSourceSpan | null,
public i18n?: I18nMeta,
) {}

readonly kind = 'Element';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitElement(this);
}
Expand All @@ -182,6 +202,8 @@ export abstract class DeferredTrigger implements Node {
public whenOrOnSourceSpan: ParseSourceSpan | null,
) {}

abstract readonly kind: string;

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitDeferredTrigger(this);
}
Expand All @@ -198,11 +220,17 @@ export class BoundDeferredTrigger extends DeferredTrigger {
// nameSpan. Trigger names are the built in event triggers like hover, interaction, etc.
super(/** nameSpan */ null, sourceSpan, prefetchSpan, whenSourceSpan);
}

readonly kind = 'BoundDeferredTrigger';
}

export class IdleDeferredTrigger extends DeferredTrigger {}
export class IdleDeferredTrigger extends DeferredTrigger {
readonly kind = 'IdleDeferredTrigger';
}

export class ImmediateDeferredTrigger extends DeferredTrigger {}
export class ImmediateDeferredTrigger extends DeferredTrigger {
readonly kind = 'ImmediateDeferredTrigger';
}

export class HoverDeferredTrigger extends DeferredTrigger {
constructor(
Expand All @@ -214,6 +242,8 @@ export class HoverDeferredTrigger extends DeferredTrigger {
) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);
}

readonly kind = 'HoverDeferredTrigger';
}

export class TimerDeferredTrigger extends DeferredTrigger {
Expand All @@ -226,6 +256,8 @@ export class TimerDeferredTrigger extends DeferredTrigger {
) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);
}

readonly kind = 'TimerDeferredTrigger';
}

export class InteractionDeferredTrigger extends DeferredTrigger {
Expand All @@ -238,6 +270,8 @@ export class InteractionDeferredTrigger extends DeferredTrigger {
) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);
}

readonly kind = 'InteractionDeferredTrigger';
}

export class ViewportDeferredTrigger extends DeferredTrigger {
Expand All @@ -250,6 +284,8 @@ export class ViewportDeferredTrigger extends DeferredTrigger {
) {
super(nameSpan, sourceSpan, prefetchSpan, onSourceSpan);
}

readonly kind = 'ViewportDeferredTrigger';
}

export class BlockNode {
Expand All @@ -259,6 +295,8 @@ export class BlockNode {
public startSourceSpan: ParseSourceSpan,
public endSourceSpan: ParseSourceSpan | null,
) {}

readonly kind: string = 'BlockNode';
}

export class DeferredBlockPlaceholder extends BlockNode implements Node {
Expand All @@ -277,6 +315,8 @@ export class DeferredBlockPlaceholder extends BlockNode implements Node {
visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitDeferredBlockPlaceholder(this);
}

override readonly kind = 'DeferredBlockPlaceholder';
}

export class DeferredBlockLoading extends BlockNode implements Node {
Expand All @@ -296,6 +336,8 @@ export class DeferredBlockLoading extends BlockNode implements Node {
visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitDeferredBlockLoading(this);
}

override readonly kind = 'DeferredBlockLoading';
}

export class DeferredBlockError extends BlockNode implements Node {
Expand All @@ -310,6 +352,8 @@ export class DeferredBlockError extends BlockNode implements Node {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
}

override readonly kind = 'DeferredBlockError';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitDeferredBlockError(this);
}
Expand Down Expand Up @@ -354,6 +398,8 @@ export class DeferredBlock extends BlockNode implements Node {
this.definedPrefetchTriggers = Object.keys(prefetchTriggers) as (keyof DeferredBlockTriggers)[];
}

override readonly kind = 'DeferredBlock';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitDeferredBlock(this);
}
Expand Down Expand Up @@ -397,6 +443,8 @@ export class SwitchBlock extends BlockNode implements Node {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
}

override readonly kind = 'SwitchBlock';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitSwitchBlock(this);
}
Expand All @@ -415,6 +463,8 @@ export class SwitchBlockCase extends BlockNode implements Node {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
}

override readonly kind = 'SwitchBlockCase';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitSwitchBlockCase(this);
}
Expand All @@ -439,6 +489,8 @@ export class ForLoopBlock extends BlockNode implements Node {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
}

override readonly kind = 'ForLoopBlock';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitForLoopBlock(this);
}
Expand All @@ -456,6 +508,8 @@ export class ForLoopBlockEmpty extends BlockNode implements Node {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
}

override readonly kind = 'ForLoopBlockEmpty';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitForLoopBlockEmpty(this);
}
Expand All @@ -472,6 +526,8 @@ export class IfBlock extends BlockNode implements Node {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
}

override readonly kind = 'IfBlock';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitIfBlock(this);
}
Expand All @@ -491,6 +547,8 @@ export class IfBlockBranch extends BlockNode implements Node {
super(nameSpan, sourceSpan, startSourceSpan, endSourceSpan);
}

override readonly kind = 'IfBlockBranch';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitIfBlockBranch(this);
}
Expand All @@ -503,6 +561,8 @@ export class UnknownBlock implements Node {
public nameSpan: ParseSourceSpan,
) {}

readonly kind = 'UnknownBlock';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitUnknownBlock(this);
}
Expand All @@ -517,6 +577,8 @@ export class LetDeclaration implements Node {
public valueSpan: ParseSourceSpan,
) {}

readonly kind = 'LetDeclaration';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitLetDeclaration(this);
}
Expand All @@ -541,6 +603,9 @@ export class Template implements Node {
public endSourceSpan: ParseSourceSpan | null,
public i18n?: I18nMeta,
) {}

readonly kind = 'Template';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitTemplate(this);
}
Expand All @@ -556,6 +621,9 @@ export class Content implements Node {
public sourceSpan: ParseSourceSpan,
public i18n?: I18nMeta,
) {}

readonly kind = 'Content';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitContent(this);
}
Expand All @@ -569,6 +637,9 @@ export class Variable implements Node {
readonly keySpan: ParseSourceSpan,
public valueSpan?: ParseSourceSpan,
) {}

readonly kind = 'Variable';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitVariable(this);
}
Expand All @@ -582,6 +653,9 @@ export class Reference implements Node {
readonly keySpan: ParseSourceSpan,
public valueSpan?: ParseSourceSpan,
) {}

readonly kind = 'Reference';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitReference(this);
}
Expand All @@ -594,6 +668,9 @@ export class Icu implements Node {
public sourceSpan: ParseSourceSpan,
public i18n?: I18nMeta,
) {}

readonly kind = 'Icu';

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitIcu(this);
}
Expand Down

0 comments on commit 3f68cea

Please sign in to comment.