Skip to content

Commit a07d895

Browse files
committed
refactor(parser): replace nextNode logic with explicit expect method
- Replace parser.nextNode property with private expectedTagName and expect method - Change verifyNextNode method to expectMatch for node validation - Update methods start, between, end to use expect and expectMatch - Rename and update checkStartNode to startMatch and startOptionalMatch - Rename and update checkAncestorStartNode to startRecursiveMatch - Modify tag handlers to use new startMatch and startRecursiveMatch methods - Adjust error messages to remove redundant incorrect parent references - Update tests to reflect new method names and error message formats
1 parent 6d2a50e commit a07d895

20 files changed

Lines changed: 88 additions & 77 deletions

packages/template/src/compiler.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ it('translate', async () => {
7070
it('invalid', async () => {
7171
expect(await compile(`{{ /if }}`, { debug: true })).toMatchInlineSnapshot(
7272
`
73-
" JianJia "end_if" must follow "if", not "root".
73+
" JianJia "end_if" must follow "if".
7474
7575
1: {{ /if }}
7676
^^^^^^^^^

packages/template/src/engine.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,9 @@ it('destructing', async () => {
119119
it('compile error', async () => {
120120
expect(await compile(`{{ #for name in names }}{{ /if }}`, { debug: true }))
121121
.toMatchInlineSnapshot(`
122-
" JianJia "end_if" must follow "if", not "for".
122+
" JianJia "end_if" must follow "if".
123123
124124
1: {{ #for name in names }}{{ /if }}
125-
^^^^^^^^^^^^^^^^^^^^^^^^
126125
^^^^^^^^^
127126
"
128127
`)

packages/template/src/parser.test.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ describe('validation', () => {
162162
startIndex: 0,
163163
endIndex: 1,
164164
})
165-
parser.nextNode = 'end_raw'
165+
parser.expect('end_raw')
166166
parser.end({
167167
name: 'for',
168168
startIndex: 2,
@@ -194,7 +194,7 @@ describe('validation', () => {
194194
startIndex: 0,
195195
endIndex: 1,
196196
})
197-
parser.nextNode = 'end_raw'
197+
parser.expect('end_raw')
198198
parser.between({
199199
name: 'for',
200200
startIndex: 2,
@@ -259,7 +259,7 @@ describe('validation w/ debug', () => {
259259
startIndex: 0,
260260
endIndex: 1,
261261
})
262-
ast.nextNode = 'end_raw'
262+
ast.expect('end_raw')
263263
ast.end({
264264
name: 'for',
265265
startIndex: 2,
@@ -282,7 +282,7 @@ describe('validation w/ debug', () => {
282282
startIndex: 0,
283283
endIndex: 1,
284284
})
285-
ast.nextNode = 'end_raw'
285+
ast.expect('end_raw')
286286
ast.between({
287287
name: 'for',
288288
startIndex: 2,
@@ -298,7 +298,7 @@ describe('validation w/ debug', () => {
298298
})
299299

300300
describe('verify', () => {
301-
it('checkStartNode', () => {
301+
it('startMatch', () => {
302302
const parser = new Parser({} as Required<EngineOptions>)
303303
const nodes = [
304304
{ name: 'for', startIndex: 0, endIndex: 1 },
@@ -307,11 +307,11 @@ describe('verify', () => {
307307
]
308308
parser.start(nodes[0])
309309

310-
expect(parser.checkStartNode('if', nodes[1], false)).toBe(false)
311-
expect(parser.checkStartNode('for', nodes[2], false)).toBe(true)
310+
expect(parser.startOptionalMatch('if', nodes[1])).toBe(false)
311+
expect(parser.startOptionalMatch('for', nodes[2])).toBe(true)
312312
})
313313

314-
it('checkStartNode /w debug', () => {
314+
it('startMatch /w debug', () => {
315315
const parser = new Parser({ debug: true } as Required<EngineOptions>)
316316
const nodes = [
317317
{ name: 'for', startIndex: 0, endIndex: 1 },
@@ -320,13 +320,13 @@ describe('verify', () => {
320320
parser.start(nodes[0])
321321

322322
expect(() =>
323-
parser.checkStartNode('if', nodes[1]),
323+
parser.startMatch('if', nodes[1]),
324324
).toThrowErrorMatchingInlineSnapshot(
325-
`[ASTError: "end_if" must follow "if", not "for".]`,
325+
`[ASTError: "end_if" must follow "if".]`,
326326
)
327327
})
328328

329-
it('checkAncestorStartNode', () => {
329+
it('startRecursiveMatch', () => {
330330
const ast = new Parser({} as Required<EngineOptions>)
331331
const nodes = [
332332
{ name: 'root', startIndex: 0, endIndex: 0 },
@@ -336,17 +336,17 @@ describe('verify', () => {
336336
]
337337

338338
ast.start(nodes[0])
339-
ast.nextNode = 'end_raw'
340-
expect(ast.checkAncestorStartNode('for', nodes[3])).toBe(true)
339+
ast.expect('end_raw')
340+
expect(ast.startRecursiveMatch('for', nodes[3])).toBe(true)
341341

342-
ast.nextNode = null
343-
expect(ast.checkAncestorStartNode('for', nodes[3])).toBe(false)
342+
ast.expect(null)
343+
expect(ast.startRecursiveMatch('for', nodes[3])).toBe(false)
344344

345345
ast.start(nodes[1])
346-
expect(ast.checkAncestorStartNode('for', nodes[3])).toBe(true)
346+
expect(ast.startRecursiveMatch('for', nodes[3])).toBe(true)
347347

348348
ast.start(nodes[2])
349-
expect(ast.checkAncestorStartNode('for', nodes[3])).toBe(true)
349+
expect(ast.startRecursiveMatch('for', nodes[3])).toBe(true)
350350
})
351351
})
352352

packages/template/src/parser.ts

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ export class Parser implements ASTTag {
4343
/**
4444
* Next node that is expected to be parsed.
4545
*/
46-
nextNode: string | null = null
46+
private expectedTagName: string | null = null
4747

4848
body: ASTNode[]
49-
parent: null
49+
parent: ASTTag | null
5050
previousSibling: null
5151
nextSibling: null
5252
level: number
@@ -167,11 +167,11 @@ export class Parser implements ASTTag {
167167
* 2. has body, add a new ast with the node to the tags of the last node.
168168
*/
169169
start(baseNode: Partial<ASTNode> & Location) {
170-
if (!this.verifyNextNode(baseNode)) {
170+
if (!this.expectMatch(baseNode)) {
171171
return
172172
}
173173

174-
this.nextNode = null
174+
this.expect(null)
175175

176176
const { body } = this.current
177177

@@ -212,11 +212,11 @@ export class Parser implements ASTTag {
212212
}
213213

214214
between(baseNode: Partial<ASTNode> & Location) {
215-
if (!this.verifyNextNode(baseNode)) {
215+
if (!this.expectMatch(baseNode)) {
216216
return
217217
}
218218

219-
this.nextNode = null
219+
this.expect(null)
220220

221221
const { body } = this.current
222222

@@ -243,11 +243,11 @@ export class Parser implements ASTTag {
243243
}
244244

245245
end(baseNode: Partial<ASTNode> & Location) {
246-
if (!this.verifyNextNode(baseNode)) {
246+
if (!this.expectMatch(baseNode)) {
247247
return
248248
}
249249

250-
this.nextNode = null
250+
this.expect(null)
251251

252252
const { body } = this.current
253253

@@ -274,43 +274,60 @@ export class Parser implements ASTTag {
274274
return this.goto(node)
275275
}
276276

277-
private verifyNextNode(node: Partial<ASTNode> & Location) {
278-
if (!this.nextNode || node.name === this.nextNode) {
277+
/**
278+
* Expect the next node to be the given name.
279+
* If
280+
*/
281+
expect(name: string | null) {
282+
this.expectedTagName = name
283+
}
284+
285+
/**
286+
* Check if the given node matches the expected name.
287+
*/
288+
private expectMatch(node: Partial<ASTNode> & Location) {
289+
if (!this.expectedTagName || node.name === this.expectedTagName) {
279290
return true
280291
}
281-
this.throwError(`expect "${this.nextNode}", "${node.name}" found.`, [node])
292+
this.throwError(`expect "${this.expectedTagName}", "${node.name}" found.`, [node])
282293
return false
283294
}
284295

285296
/**
286-
* Check if the start node in current ast matches the given name.
297+
* Check if the given name matches the start node in current body.
287298
*/
288-
checkStartNode(
299+
startMatch(
289300
name: string,
290301
node: Partial<ASTNode> & Location,
291-
required = true,
292302
) {
293-
if (!this.verifyNextNode(node)) {
303+
if (this.startOptionalMatch(name, node)) {
294304
return true
295305
}
296-
const startNode = this.current.body.at(0)!
297-
if (startNode.name === name) {
306+
this.throwError(`"${node.name}" must follow "${name}".`, [node])
307+
return false
308+
}
309+
310+
/**
311+
* Check if the given name matches the start node in current body.
312+
*/
313+
startOptionalMatch(
314+
name: string,
315+
node: Partial<ASTNode> & Location,
316+
) {
317+
if (!this.expectMatch(node)) {
298318
return true
299319
}
300-
if (required) {
301-
this.throwError(`"${node.name}" must follow "${name}", not "${startNode.name}".`, [startNode, node])
302-
}
303-
return false
320+
return this.current.body.at(0)!.name === name
304321
}
305322

306323
/**
307-
* Check if the start nide in current ast or its ancestor matches the given name.
324+
* Check if the given name matches the start node in current body or its parents.
308325
*/
309-
checkAncestorStartNode(
326+
startRecursiveMatch(
310327
name: string,
311328
node: Partial<ASTNode> & Location,
312329
) {
313-
if (!this.verifyNextNode(node)) {
330+
if (!this.expectMatch(node)) {
314331
return true
315332
}
316333
let ast = this.current

packages/template/src/tags/assign.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const tag: Tag = {
2222
name: END_ASSIGN,
2323
}
2424

25-
if (parser.checkStartNode(ASSIGN, node)) {
25+
if (parser.startMatch(ASSIGN, node)) {
2626
parser.end(node)
2727
}
2828

packages/template/src/tags/block.test.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ it('invalid', async () => {
2323
debug: true,
2424
}),
2525
).toMatchInlineSnapshot(`
26-
" JianJia "end_block" must follow "block", not "root".
26+
" JianJia "end_block" must follow "block".
2727
2828
1: {{ #block }}{{ /block }}
2929
^^^^^^^^^^^^
@@ -41,10 +41,9 @@ it('invalid', async () => {
4141
debug: true,
4242
}),
4343
).toMatchInlineSnapshot(`
44-
" JianJia "block" must follow "root", not "if".
44+
" JianJia "block" must follow "root".
4545
4646
1: {{ #if x }}{{ #block title }}{{ /block }}{{ /if }}
47-
^^^^^^^^^^^
4847
^^^^^^^^^^^^^^^^^^
4948
"
5049
`)
@@ -59,10 +58,9 @@ it('invalid', async () => {
5958
await compile(`{{ #if x }}{{ super }}{{ /if }}`, { debug: true }),
6059
).toMatchInlineSnapshot(
6160
`
62-
" JianJia "super" must follow "block", not "if".
61+
" JianJia "super" must follow "block".
6362
6463
1: {{ #if x }}{{ super }}{{ /if }}
65-
^^^^^^^^^^^
6664
^^^^^^^^^^^
6765
"
6866
`,

packages/template/src/tags/block.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const tag: Tag = {
2121
name: END_BLOCK,
2222
}
2323

24-
if (parser.checkStartNode(BLOCK, node)) {
24+
if (parser.startMatch(BLOCK, node)) {
2525
parser.end(node)
2626
}
2727

@@ -34,7 +34,7 @@ export const tag: Tag = {
3434
name: SUPER,
3535
}
3636

37-
if (parser.checkStartNode(BLOCK, node)) {
37+
if (parser.startMatch(BLOCK, node)) {
3838
parser.start(node)
3939

4040
// Self closing
@@ -54,7 +54,7 @@ export const tag: Tag = {
5454
name: BLOCK,
5555
}
5656

57-
if (parser.checkStartNode(ROOT, node)) {
57+
if (parser.startMatch(ROOT, node)) {
5858
const startNode = parser.start(node)
5959

6060
if (startNode) {

packages/template/src/tags/break.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const tag: Tag = {
1616
name: BREAK,
1717
}
1818

19-
if (parser.checkAncestorStartNode(FOR, node)) {
19+
if (parser.startRecursiveMatch(FOR, node)) {
2020
parser.start(node)
2121

2222
// Self closing

packages/template/src/tags/call.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ it('invalid', async () => {
2727

2828
expect(await compile(`{{ #call }}3{{ /call }}`, { debug: true })).toMatchInlineSnapshot(
2929
`
30-
" JianJia "end_call" must follow "call", not "root".
30+
" JianJia "end_call" must follow "call".
3131
3232
1: {{ #call }}3{{ /call }}
3333
^^^^^^^^^^^

packages/template/src/tags/call.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const tag: Tag = {
1717
name: END_CALL,
1818
}
1919

20-
if (parser.checkStartNode(CALL, node)) {
20+
if (parser.startMatch(CALL, node)) {
2121
parser.end(node)
2222
}
2323

0 commit comments

Comments
 (0)