Skip to content

Commit 39fcb76

Browse files
committed
Deprecate Program in v1 AST
1 parent 1cb493b commit 39fcb76

11 files changed

+153
-96
lines changed

packages/@glimmer/syntax/lib/generation/printer.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ export default class Printer {
113113
case 'PathExpression':
114114
case 'SubExpression':
115115
return this.Expression(node);
116-
case 'Program':
117-
return this.Block(node);
118116
case 'ConcatStatement':
119117
// should have an AttrNode parent
120118
return this.ConcatStatement(node);
@@ -174,15 +172,20 @@ export default class Printer {
174172
case 'ElementNode':
175173
return this.ElementNode(statement);
176174
case 'Block':
177-
case 'Template':
178175
return this.Block(statement);
176+
case 'Template':
177+
return this.Template(statement);
179178
case 'AttrNode':
180179
// should have element
181180
return this.AttrNode(statement);
182181
}
183182
}
184183

185-
Block(block: ASTv1.Block | ASTv1.Program | ASTv1.Template): void {
184+
Template(template: ASTv1.Template): void {
185+
this.TopLevelStatements(template.body);
186+
}
187+
188+
Block(block: ASTv1.Block): void {
186189
/*
187190
When processing a template like:
188191

packages/@glimmer/syntax/lib/parser/handlebars-node-visitors.ts

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export abstract class HandlebarsNodeVisitors extends Parser {
3535
if (this.isTopLevel) {
3636
node = b.template({
3737
body,
38-
blockParams: program.blockParams,
3938
loc: this.source.spanFor(program.loc),
4039
});
4140
} else {

packages/@glimmer/syntax/lib/parser/tokenizer-event-handlers.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -461,21 +461,17 @@ export function preprocess(
461461
end: offsets.endPosition,
462462
};
463463

464-
let program = new TokenizerEventHandlers(source, entityParser, mode).acceptTemplate(ast);
465-
466-
if (options.strictMode) {
467-
program.blockParams = options.locals ?? [];
468-
}
464+
let template = new TokenizerEventHandlers(source, entityParser, mode).acceptTemplate(ast);
469465

470466
if (options && options.plugins && options.plugins.ast) {
471467
for (const transform of options.plugins.ast) {
472468
let env: ASTPluginEnvironment = assign({}, options, { syntax }, { plugins: undefined });
473469

474470
let pluginResult = transform(env);
475471

476-
traverse(program, pluginResult.visitor);
472+
traverse(template, pluginResult.visitor);
477473
}
478474
}
479475

480-
return program;
476+
return template;
481477
}

packages/@glimmer/syntax/lib/traversal/traverse.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@ function getNodeHandler<N extends ASTv1.Node>(
6767
visitor: NodeVisitor,
6868
nodeType: N['type']
6969
): NodeTraversal<ASTv1.Node> | undefined {
70-
if (nodeType === 'Template' || nodeType === 'Block') {
71-
if (visitor.Program) {
70+
if (visitor.Program) {
71+
if (
72+
(nodeType === 'Template' && !visitor.Template) ||
73+
(nodeType === 'Block' && !visitor.Block)
74+
) {
7275
deprecate(
7376
`The 'Program' visitor node is deprecated. Use 'Template' or 'Block' instead (node was '${nodeType}') `
7477
);

packages/@glimmer/syntax/lib/traversal/visitor.ts

+10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export type NodeTraversal<N extends ASTv1.Node> = FullNodeTraversal<N> | NodeHan
1313

1414
export type NodeVisitor = { [P in keyof ASTv1.Nodes]?: NodeTraversal<ASTv1.Nodes[P]> } & {
1515
All?: NodeTraversal<ASTv1.Node>;
16+
17+
/**
18+
* @deprecated use Template or Block instead
19+
*/
20+
Program?: NodeTraversal<ASTv1.Template | ASTv1.Block>;
1621
};
1722

1823
export interface FullKeyTraversal<N extends ASTv1.Node, K extends string> {
@@ -27,4 +32,9 @@ export type KeyTraversal<N extends ASTv1.Node, K extends VisitorKey<N>> =
2732

2833
export type KeysVisitor<N extends ASTv1.Node> = { [P in VisitorKey<N>]?: KeyTraversal<N, P> } & {
2934
All?: KeyTraversal<N, VisitorKey<N>>;
35+
36+
/**
37+
* @deprecated use Template or Block instead
38+
*/
39+
Program?: KeyTraversal<ASTv1.Template | ASTv1.Block, 'body'>;
3040
};

packages/@glimmer/syntax/lib/traversal/walker.ts

+7-26
Original file line numberDiff line numberDiff line change
@@ -33,40 +33,21 @@ export default class Walker {
3333
switch (node.type) {
3434
case 'Block':
3535
case 'Template':
36-
return visitors.Program(this, node as unknown as ASTv1.Program, callback);
36+
walkBody(this, node.body, callback);
37+
return;
3738
case 'ElementNode':
38-
return visitors.ElementNode(this, node, callback);
39+
walkBody(this, node.children, callback);
40+
return;
3941
case 'BlockStatement':
40-
return visitors.BlockStatement(this, node, callback);
42+
this.visit(node.program, callback);
43+
this.visit(node.inverse || null, callback);
44+
return;
4145
default:
4246
return;
4347
}
4448
}
4549
}
4650

47-
const visitors = {
48-
Program(walker: Walker, node: ASTv1.Program, callback: NodeCallback<ASTv1.Statement>) {
49-
walkBody(walker, node.body, callback);
50-
},
51-
52-
Template(walker: Walker, node: ASTv1.Template, callback: NodeCallback<ASTv1.Node>) {
53-
walkBody(walker, node.body, callback);
54-
},
55-
56-
Block(walker: Walker, node: ASTv1.Block, callback: NodeCallback<ASTv1.Node>) {
57-
walkBody(walker, node.body, callback);
58-
},
59-
60-
ElementNode(walker: Walker, node: ASTv1.ElementNode, callback: NodeCallback<ASTv1.Node>) {
61-
walkBody(walker, node.children, callback);
62-
},
63-
64-
BlockStatement(walker: Walker, node: ASTv1.BlockStatement, callback: NodeCallback<ASTv1.Block>) {
65-
walker.visit(node.program, callback);
66-
walker.visit(node.inverse || null, callback);
67-
},
68-
} as const;
69-
7051
function walkBody(
7152
walker: Walker,
7253
body: ASTv1.Statement[],

packages/@glimmer/syntax/lib/v1/nodes-v1.ts

+11-8
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,30 @@ export interface BaseNode {
1212

1313
export interface CommonProgram extends BaseNode {
1414
body: Statement[];
15-
blockParams: string[];
16-
chained?: boolean;
17-
}
18-
19-
export interface Program extends CommonProgram {
20-
type: 'Program';
2115
}
2216

2317
export interface Block extends CommonProgram {
2418
type: 'Block';
19+
blockParams: string[];
2520
blockParamNodes: BlockParam[];
21+
chained?: boolean;
2622
}
2723

2824
export type EntityEncodingState = 'transformed' | 'raw';
2925

3026
export interface Template extends CommonProgram {
3127
type: 'Template';
28+
29+
/**
30+
* @deprecated Template can never have block params
31+
*/
32+
blockParams: never[];
3233
}
3334

34-
export type PossiblyDeprecatedBlock = Block | Template;
35+
/**
36+
* @deprecated use Template or Block instead
37+
*/
38+
export type Program = Template | Block;
3539

3640
export interface CallParts {
3741
path: Expression;
@@ -320,7 +324,6 @@ export type Nodes = SharedNodes & {
320324
ElementStartNode: ElementStartNode;
321325
ElementPartNode: ElementPartNode;
322326
ElementNameNode: ElementNameNode;
323-
Program: Program;
324327
Template: Template;
325328
Block: Block;
326329
BlockStatement: BlockStatement;

packages/@glimmer/syntax/lib/v1/parser-builders.ts

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Dict, Nullable, PresentArray } from '@glimmer/interfaces';
2-
import { assert } from '@glimmer/util';
2+
import { assert, deprecate } from '@glimmer/util';
33

44
import type { ParserNodeBuilder } from '../parser';
55
import type { SourceLocation } from '../source/location';
@@ -50,19 +50,16 @@ class Builders {
5050
};
5151
}
5252

53-
template({
54-
body,
55-
blockParams,
56-
loc,
57-
}: {
58-
body?: ASTv1.Statement[];
59-
blockParams?: string[];
60-
loc: SourceSpan;
61-
}): ASTv1.Template {
53+
template({ body, loc }: { body?: ASTv1.Statement[]; loc: SourceSpan }): ASTv1.Template {
6254
return {
6355
type: 'Template',
6456
body: body || [],
65-
blockParams: blockParams || [],
57+
get blockParams() {
58+
deprecate(
59+
`Template nodes can never have block params. This array is always empty and will be removed in the future.`
60+
);
61+
return [];
62+
},
6663
loc,
6764
};
6865
}

packages/@glimmer/syntax/lib/v1/public-builders.ts

+57-11
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@ function buildMustache(
5050
};
5151
}
5252

53+
type PossiblyDeprecatedBlock = ASTv1.Block | ASTv1.Template;
54+
5355
function buildBlock(
5456
path: BuilderHead,
5557
params: Nullable<ASTv1.Expression[]>,
5658
hash: Nullable<ASTv1.Hash>,
57-
_defaultBlock: ASTv1.PossiblyDeprecatedBlock,
58-
_elseBlock?: Nullable<ASTv1.PossiblyDeprecatedBlock>,
59+
_defaultBlock: PossiblyDeprecatedBlock,
60+
_elseBlock?: Nullable<PossiblyDeprecatedBlock>,
5961
loc?: SourceLocation,
6062
openStrip?: ASTv1.StripFlags,
6163
inverseStrip?: ASTv1.StripFlags,
@@ -454,13 +456,14 @@ function buildProgram(
454456
body?: ASTv1.Statement[],
455457
blockParams?: string[],
456458
loc?: SourceLocation
457-
): ASTv1.Template {
458-
return {
459-
type: 'Template',
460-
body: body || [],
461-
blockParams: blockParams || [],
462-
loc: buildLoc(loc || null),
463-
};
459+
): ASTv1.Template | ASTv1.Block {
460+
deprecate(`b.program is deprecated. Use b.template or b.blockItself instead.`);
461+
462+
if (blockParams && blockParams.length) {
463+
return buildBlockItself(body, blockParams, false, loc);
464+
} else {
465+
return buildTemplate(body, loc);
466+
}
464467
}
465468

466469
function buildBlockItself(
@@ -480,15 +483,58 @@ function buildBlockItself(
480483
};
481484
}
482485

486+
type BuildTemplateRestArgs =
487+
| [loc?: SourceLocation | undefined]
488+
| [blockParams?: string[] | never[] | undefined, loc?: SourceLocation | undefined];
489+
490+
function buildTemplate(body?: ASTv1.Statement[], loc?: SourceLocation): ASTv1.Template;
491+
function buildTemplate(
492+
body?: ASTv1.Statement[],
493+
blockParams?: never[],
494+
loc?: SourceLocation
495+
): ASTv1.Template;
483496
function buildTemplate(
484497
body?: ASTv1.Statement[],
485498
blockParams?: string[],
486499
loc?: SourceLocation
487-
): ASTv1.Template {
500+
): never;
501+
function buildTemplate(body?: ASTv1.Statement[], ...args: BuildTemplateRestArgs): ASTv1.Template {
502+
let blockParams: string[] | undefined;
503+
let loc: SourceLocation | undefined;
504+
505+
if (args.length === 1) {
506+
let [arg] = args;
507+
508+
if (Array.isArray(arg)) {
509+
blockParams = arg;
510+
} else {
511+
loc = arg;
512+
}
513+
} else if (args.length > 1) {
514+
// force this to be an empty array to trigger the deprecation message
515+
blockParams = (args[0] || []) as string[];
516+
loc = args[1];
517+
}
518+
519+
if (blockParams) {
520+
if (blockParams.length === 0) {
521+
deprecate(
522+
`Template nodes can never have block params, you may omit the second argument to b.template`
523+
);
524+
} else {
525+
throw new Error('Template nodes can never have block params');
526+
}
527+
}
528+
488529
return {
489530
type: 'Template',
490531
body: body || [],
491-
blockParams: blockParams || [],
532+
get blockParams() {
533+
deprecate(
534+
`Template nodes can never have block params. This array is always empty and will be removed in the future.`
535+
);
536+
return [];
537+
},
492538
loc: buildLoc(loc || null),
493539
};
494540
}

packages/@glimmer/syntax/lib/v1/visitor-keys.ts

-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import type * as ASTv1 from './api';
33
// ensure stays in sync with typing
44
// ParentNode and ChildKey types are derived from VisitorKeysMap
55
const visitorKeys = {
6-
Program: ['body'],
76
Template: ['body'],
87
Block: ['body'],
98

@@ -35,11 +34,6 @@ const visitorKeys = {
3534
Hash: ['pairs'],
3635
HashPair: ['value'],
3736
BlockParam: [],
38-
39-
// v2 new nodes
40-
NamedBlock: ['attributes', 'modifiers', 'children', 'comments'],
41-
SimpleElement: ['attributes', 'modifiers', 'children', 'comments'],
42-
Component: ['head', 'attributes', 'modifiers', 'children', 'comments'],
4337
} as const;
4438

4539
type VisitorKeysMap = typeof visitorKeys;

0 commit comments

Comments
 (0)