Skip to content

Commit 0ef067b

Browse files
authored
fix: incorrect location when there is whitespace at the beginning of block (#434)
1 parent c023160 commit 0ef067b

8 files changed

+3515
-17
lines changed

.changeset/honest-mangos-wave.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte-eslint-parser": patch
3+
---
4+
5+
fix: incorrect location when there is whitespace at the beginning of block

src/parser/converts/block.ts

+29-11
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import { getWithLoc, indexOf, lastIndexOf } from "./common";
2222
import type * as ESTree from "estree";
2323

2424
/** Get start index of block */
25-
function startBlockIndex(code: string, endIndex: number): number {
25+
function startBlockIndex(
26+
code: string,
27+
endIndex: number,
28+
block: string,
29+
): number {
2630
return lastIndexOf(
2731
code,
2832
(c, index) => {
@@ -34,7 +38,7 @@ function startBlockIndex(code: string, endIndex: number): number {
3438
if (!nextC.trim()) {
3539
continue;
3640
}
37-
return code.startsWith("#if", next) || code.startsWith(":else", next);
41+
return code.startsWith(block, next);
3842
}
3943
return false;
4044
},
@@ -62,9 +66,11 @@ export function convertIfBlock(
6266
): SvelteIfBlock {
6367
// {#if expr} {:else} {/if}
6468
// {:else if expr} {/if}
65-
const nodeStart = elseif
66-
? startBlockIndex(ctx.code, node.start - 1)
67-
: node.start;
69+
const nodeStart = startBlockIndex(
70+
ctx.code,
71+
elseif ? node.start - 1 : node.start,
72+
elseif ? ":else" : "#if",
73+
);
6874
const ifBlock: SvelteIfBlock = {
6975
type: "SvelteIfBlock",
7076
elseif: Boolean(elseif),
@@ -90,7 +96,15 @@ export function convertIfBlock(
9096
return ifBlock;
9197
}
9298

93-
const elseStart = startBlockIndex(ctx.code, node.else.start - 1);
99+
let baseStart = node.else.start;
100+
if (node.else.children.length === 1) {
101+
const c = node.else.children[0];
102+
if (c.type === "IfBlock" && c.elseif) {
103+
baseStart = Math.min(baseStart, c.start, getWithLoc(c.expression).start);
104+
}
105+
}
106+
107+
const elseStart = startBlockIndex(ctx.code, baseStart - 1, ":else");
94108

95109
if (node.else.children.length === 1) {
96110
const c = node.else.children[0];
@@ -145,6 +159,7 @@ export function convertEachBlock(
145159
ctx: Context,
146160
): SvelteEachBlock {
147161
// {#each expr as item, index (key)} {/each}
162+
const nodeStart = startBlockIndex(ctx.code, node.start, "#each");
148163
const eachBlock: SvelteEachBlock = {
149164
type: "SvelteEachBlock",
150165
expression: null as any,
@@ -154,7 +169,7 @@ export function convertEachBlock(
154169
children: [],
155170
else: null,
156171
parent,
157-
...ctx.getConvertLocation(node),
172+
...ctx.getConvertLocation({ start: nodeStart, end: node.end }),
158173
};
159174

160175
let indexRange: null | { start: number; end: number } = null;
@@ -199,7 +214,7 @@ export function convertEachBlock(
199214
return eachBlock;
200215
}
201216

202-
const elseStart = startBlockIndex(ctx.code, node.else.start - 1);
217+
const elseStart = startBlockIndex(ctx.code, node.else.start - 1, ":else");
203218

204219
const elseBlock: SvelteElseBlockAlone = {
205220
type: "SvelteElseBlock",
@@ -227,6 +242,7 @@ export function convertAwaitBlock(
227242
parent: SvelteAwaitBlock["parent"],
228243
ctx: Context,
229244
): SvelteAwaitBlock {
245+
const nodeStart = startBlockIndex(ctx.code, node.start, "#await");
230246
const awaitBlock = {
231247
type: "SvelteAwaitBlock",
232248
expression: null as any,
@@ -235,7 +251,7 @@ export function convertAwaitBlock(
235251
then: null as any,
236252
catch: null as any,
237253
parent,
238-
...ctx.getConvertLocation(node),
254+
...ctx.getConvertLocation({ start: nodeStart, end: node.end }),
239255
} as SvelteAwaitBlock;
240256

241257
ctx.scriptLet.addExpression(
@@ -413,12 +429,13 @@ export function convertKeyBlock(
413429
parent: SvelteKeyBlock["parent"],
414430
ctx: Context,
415431
): SvelteKeyBlock {
432+
const nodeStart = startBlockIndex(ctx.code, node.start, "#key");
416433
const keyBlock: SvelteKeyBlock = {
417434
type: "SvelteKeyBlock",
418435
expression: null as any,
419436
children: [],
420437
parent,
421-
...ctx.getConvertLocation(node),
438+
...ctx.getConvertLocation({ start: nodeStart, end: node.end }),
422439
};
423440

424441
ctx.scriptLet.addExpression(node.expression, keyBlock, null, (expression) => {
@@ -441,13 +458,14 @@ export function convertSnippetBlock(
441458
ctx: Context,
442459
): SvelteSnippetBlock {
443460
// {#snippet x(args)}...{/snippet}
461+
const nodeStart = startBlockIndex(ctx.code, node.start, "#snippet");
444462
const snippetBlock: SvelteSnippetBlock = {
445463
type: "SvelteSnippetBlock",
446464
id: null as any,
447465
context: null as any,
448466
children: [],
449467
parent,
450-
...ctx.getConvertLocation(node),
468+
...ctx.getConvertLocation({ start: nodeStart, end: node.end }),
451469
};
452470

453471
const closeParenIndex = ctx.code.indexOf(

tests/fixtures/parser/ast/if-block01-requirements.json

-6
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!--await-->
2+
{
3+
#await
4+
expression
5+
}
6+
...
7+
{
8+
:then
9+
name
10+
}
11+
...
12+
{
13+
:catch
14+
name
15+
}
16+
...
17+
{
18+
/await
19+
}
20+
<!--each-->
21+
{
22+
#each
23+
cats
24+
as
25+
{
26+
id,
27+
name
28+
}
29+
,
30+
i
31+
}
32+
...
33+
{
34+
/each
35+
}
36+
<!--if-->
37+
{
38+
#if
39+
a
40+
}
41+
...
42+
{
43+
/if
44+
}
45+
<!--key-->
46+
{
47+
#key
48+
value
49+
}
50+
...
51+
{
52+
/key
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
{
3+
"ruleId": "no-undef",
4+
"code": "expression",
5+
"line": 4,
6+
"column": 1
7+
},
8+
{
9+
"ruleId": "no-undef",
10+
"code": "cats",
11+
"line": 23,
12+
"column": 1
13+
},
14+
{
15+
"ruleId": "no-undef",
16+
"code": "a",
17+
"line": 39,
18+
"column": 1
19+
},
20+
{
21+
"ruleId": "no-undef",
22+
"code": "value",
23+
"line": 48,
24+
"column": 1
25+
}
26+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[
2+
{
3+
"ruleId": "no-unused-vars",
4+
"code": "name",
5+
"line": 9,
6+
"column": 1
7+
},
8+
{
9+
"ruleId": "no-unused-vars",
10+
"code": "name",
11+
"line": 14,
12+
"column": 1
13+
},
14+
{
15+
"ruleId": "no-unused-vars",
16+
"code": "id",
17+
"line": 26,
18+
"column": 1
19+
},
20+
{
21+
"ruleId": "no-unused-vars",
22+
"code": "name",
23+
"line": 27,
24+
"column": 1
25+
},
26+
{
27+
"ruleId": "no-unused-vars",
28+
"code": "i",
29+
"line": 30,
30+
"column": 1
31+
}
32+
]

0 commit comments

Comments
 (0)