Skip to content

Commit 422e05d

Browse files
committed
Add v1 AST PathHead.original
This makes printing-esq tasks easier when working with `path.head` and restores feature parity with `path.original` which is a very common way to work with PathExpression nodes
1 parent 39dc632 commit 422e05d

File tree

4 files changed

+79
-49
lines changed

4 files changed

+79
-49
lines changed

packages/@glimmer/syntax/lib/v1/legacy-interop.ts

+5-19
Original file line numberDiff line numberDiff line change
@@ -70,35 +70,21 @@ export function buildLegacyMustache({
7070

7171
export type PathExpressionParams = Omit<ASTv1.MinimalPathExpression, 'type'>;
7272

73-
function original(head: ASTv1.PathHead, tail: readonly string[]): string {
74-
switch (head.type) {
75-
case 'ThisHead':
76-
return ['this', ...tail].join('.');
77-
case 'AtHead':
78-
case 'VarHead':
79-
return [head.name, ...tail].join('.');
80-
}
81-
}
82-
8373
export function buildLegacyPath({ head, tail, loc }: PathExpressionParams): ASTv1.PathExpression {
8474
const node = {
8575
type: 'PathExpression',
8676
head,
8777
tail,
88-
loc,
89-
};
90-
91-
Object.defineProperty(node, 'original', {
92-
enumerable: true,
93-
get(this: typeof node): string {
94-
return original(this.head, this.tail);
78+
get original() {
79+
return [this.head.original, ...this.tail].join('.');
9580
},
96-
set(this: typeof node, value: string) {
81+
set original(value: string) {
9782
let [head, ...tail] = asPresentArray(value.split('.'));
9883
this.head = b.head(head, this.head.loc);
9984
this.tail = tail;
10085
},
101-
});
86+
loc,
87+
};
10288

10389
Object.defineProperty(node, 'parts', {
10490
enumerable: false,

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

+11
Original file line numberDiff line numberDiff line change
@@ -146,19 +146,30 @@ export interface SubExpression extends BaseNode {
146146

147147
export interface ThisHead {
148148
type: 'ThisHead';
149+
original: 'this';
149150
loc: SourceSpan;
150151
}
151152

152153
export interface AtHead {
153154
type: 'AtHead';
154155
name: string;
155156
loc: SourceSpan;
157+
158+
/**
159+
* alias for name
160+
*/
161+
original: string;
156162
}
157163

158164
export interface VarHead {
159165
type: 'VarHead';
160166
name: string;
161167
loc: SourceSpan;
168+
169+
/**
170+
* alias for name
171+
*/
172+
original: string;
162173
}
163174

164175
export type PathHead = ThisHead | AtHead | VarHead;

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

+62-23
Original file line numberDiff line numberDiff line change
@@ -286,41 +286,80 @@ class Builders {
286286
this({ loc }: { loc: SourceSpan }): ASTv1.ThisHead {
287287
return {
288288
type: 'ThisHead',
289+
get original() {
290+
return 'this' as const;
291+
},
289292
loc,
290293
};
291294
}
292295

293296
atName({ name, loc }: { name: string; loc: SourceSpan }): ASTv1.PathHead {
294-
// the `@` should be included so we have a complete source range
295-
assert(name[0] === '@', `call builders.at() with a string that starts with '@'`);
296-
assert(
297-
name.indexOf('.') === -1,
298-
`builder.at() should not be called with a name with dots in it`
299-
);
300-
301-
return {
302-
type: 'AtHead',
303-
name,
297+
let _name = '';
298+
299+
const node = {
300+
type: 'AtHead' as const,
301+
get name() {
302+
return _name;
303+
},
304+
set name(value) {
305+
assert(value[0] === '@', `call builders.at() with a string that starts with '@'`);
306+
assert(
307+
value.indexOf('.') === -1,
308+
`builder.at() should not be called with a name with dots in it`
309+
);
310+
_name = value;
311+
},
312+
get original() {
313+
return this.name;
314+
},
315+
set original(value) {
316+
this.name = value;
317+
},
304318
loc,
305319
};
320+
321+
// trigger the assertions
322+
node.name = name;
323+
324+
return node;
306325
}
307326

308327
var({ name, loc }: { name: string; loc: SourceSpan }): ASTv1.PathHead {
309-
assert(name !== 'this', `You called builders.var() with 'this'. Call builders.this instead`);
310-
assert(
311-
name[0] !== '@',
312-
`You called builders.var() with '${name}'. Call builders.at('${name}') instead`
313-
);
314-
assert(
315-
name.indexOf('.') === -1,
316-
`builder.var() should not be called with a name with dots in it`
317-
);
318-
319-
return {
320-
type: 'VarHead',
321-
name,
328+
let _name = '';
329+
330+
const node = {
331+
type: 'VarHead' as const,
332+
get name() {
333+
return _name;
334+
},
335+
set name(value) {
336+
assert(
337+
value !== 'this',
338+
`You called builders.var() with 'this'. Call builders.this instead`
339+
);
340+
assert(
341+
value[0] !== '@',
342+
`You called builders.var() with '${name}'. Call builders.at('${name}') instead`
343+
);
344+
assert(
345+
value.indexOf('.') === -1,
346+
`builder.var() should not be called with a name with dots in it`
347+
);
348+
_name = value;
349+
},
350+
get original() {
351+
return this.name;
352+
},
353+
set original(value) {
354+
this.name = value;
355+
},
322356
loc,
323357
};
358+
359+
// trigger the assertions
360+
node.name = name;
361+
362+
return node;
324363
}
325364

326365
hash({ pairs, loc }: { pairs: ASTv1.HashPair[]; loc: SourceSpan }): ASTv1.Hash {

packages/@glimmer/syntax/lib/v2/normalize.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -1010,13 +1010,7 @@ function printPath(node: ASTv1.PathExpression | ASTv1.CallNode): string {
10101010

10111011
function printHead(node: ASTv1.PathExpression | ASTv1.CallNode): string {
10121012
if (node.type === 'PathExpression') {
1013-
switch (node.head.type) {
1014-
case 'AtHead':
1015-
case 'VarHead':
1016-
return node.head.name;
1017-
case 'ThisHead':
1018-
return 'this';
1019-
}
1013+
return node.head.original;
10201014
} else if (node.path.type === 'PathExpression') {
10211015
return printHead(node.path);
10221016
} else {

0 commit comments

Comments
 (0)