From 665cda4dbb91127bfa3fc35c97c78e8a3460400a Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sun, 28 Nov 2021 11:48:05 +0900 Subject: [PATCH 1/2] Fix else block location --- src/parser/converts/block.ts | 2 +- .../parser/ast/if-block0101-input.svelte | 1 + .../ast/if-block0101-no-undef-result.json | 14 + .../parser/ast/if-block0101-output.json | 530 ++++++++++++++++++ .../parser/ast/if-block0101-scope-output.json | 197 +++++++ 5 files changed, 743 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/parser/ast/if-block0101-input.svelte create mode 100644 tests/fixtures/parser/ast/if-block0101-no-undef-result.json create mode 100644 tests/fixtures/parser/ast/if-block0101-output.json create mode 100644 tests/fixtures/parser/ast/if-block0101-scope-output.json diff --git a/src/parser/converts/block.ts b/src/parser/converts/block.ts index a25b2686..368aa4b0 100644 --- a/src/parser/converts/block.ts +++ b/src/parser/converts/block.ts @@ -49,7 +49,7 @@ export function convertIfBlock( return ifBlock } - const elseStart = ctx.code.lastIndexOf("{", node.else.start) + const elseStart = ctx.code.lastIndexOf("{", node.else.start - 1) const elseBlock: SvelteElseBlock = { type: "SvelteElseBlock", diff --git a/tests/fixtures/parser/ast/if-block0101-input.svelte b/tests/fixtures/parser/ast/if-block0101-input.svelte new file mode 100644 index 00000000..0c10721d --- /dev/null +++ b/tests/fixtures/parser/ast/if-block0101-input.svelte @@ -0,0 +1 @@ +{#if expression}{:else if expression}{:else}{/if} diff --git a/tests/fixtures/parser/ast/if-block0101-no-undef-result.json b/tests/fixtures/parser/ast/if-block0101-no-undef-result.json new file mode 100644 index 00000000..0cc7e078 --- /dev/null +++ b/tests/fixtures/parser/ast/if-block0101-no-undef-result.json @@ -0,0 +1,14 @@ +[ + { + "ruleId": "no-undef", + "code": "expression", + "line": 1, + "column": 6 + }, + { + "ruleId": "no-undef", + "code": "expression", + "line": 1, + "column": 27 + } +] \ No newline at end of file diff --git a/tests/fixtures/parser/ast/if-block0101-output.json b/tests/fixtures/parser/ast/if-block0101-output.json new file mode 100644 index 00000000..ed6a0e39 --- /dev/null +++ b/tests/fixtures/parser/ast/if-block0101-output.json @@ -0,0 +1,530 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteIfBlock", + "elseif": false, + "expression": { + "type": "Identifier", + "name": "expression", + "range": [ + 5, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "children": [], + "else": { + "type": "SvelteElseBlock", + "children": [ + { + "type": "SvelteIfBlock", + "elseif": true, + "expression": { + "type": "Identifier", + "name": "expression", + "range": [ + 26, + 36 + ], + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 36 + } + } + }, + "children": [], + "else": { + "type": "SvelteElseBlock", + "children": [], + "range": [ + 37, + 44 + ], + "loc": { + "start": { + "line": 1, + "column": 37 + }, + "end": { + "line": 1, + "column": 44 + } + } + }, + "range": [ + 37, + 49 + ], + "loc": { + "start": { + "line": 1, + "column": 37 + }, + "end": { + "line": 1, + "column": 49 + } + } + } + ], + "range": [ + 16, + 49 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 49 + } + } + }, + "range": [ + 0, + 49 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 49 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "{", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MustacheKeyword", + "value": "#if", + "range": [ + 1, + 4 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 4 + } + } + }, + { + "type": "Identifier", + "value": "expression", + "range": [ + 5, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 15, + 16 + ], + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 16 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 16, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Identifier", + "value": "e", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "Identifier", + "value": "l", + "range": [ + 19, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 20 + } + } + }, + { + "type": "Identifier", + "value": "s", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "Identifier", + "value": "e", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 22 + } + } + }, + { + "type": "Identifier", + "value": "i", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 24 + } + } + }, + { + "type": "Identifier", + "value": "f", + "range": [ + 24, + 25 + ], + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 25 + } + } + }, + { + "type": "Identifier", + "value": "expression", + "range": [ + 26, + 36 + ], + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 36 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 1, + "column": 36 + }, + "end": { + "line": 1, + "column": 37 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 37, + 38 + ], + "loc": { + "start": { + "line": 1, + "column": 37 + }, + "end": { + "line": 1, + "column": 38 + } + } + }, + { + "type": "MustacheKeyword", + "value": ":else", + "range": [ + 38, + 43 + ], + "loc": { + "start": { + "line": 1, + "column": 38 + }, + "end": { + "line": 1, + "column": 43 + } + } + }, + { + "type": "MustacheKeyword", + "value": ":else", + "range": [ + 38, + 43 + ], + "loc": { + "start": { + "line": 1, + "column": 38 + }, + "end": { + "line": 1, + "column": 43 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 43, + 44 + ], + "loc": { + "start": { + "line": 1, + "column": 43 + }, + "end": { + "line": 1, + "column": 44 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 44, + 45 + ], + "loc": { + "start": { + "line": 1, + "column": 44 + }, + "end": { + "line": 1, + "column": 45 + } + } + }, + { + "type": "MustacheKeyword", + "value": "/if", + "range": [ + 45, + 48 + ], + "loc": { + "start": { + "line": 1, + "column": 45 + }, + "end": { + "line": 1, + "column": 48 + } + } + }, + { + "type": "MustacheKeyword", + "value": "if", + "range": [ + 46, + 48 + ], + "loc": { + "start": { + "line": 1, + "column": 46 + }, + "end": { + "line": 1, + "column": 48 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 48, + 49 + ], + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 49 + } + } + } + ], + "range": [ + 0, + 50 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/if-block0101-scope-output.json b/tests/fixtures/parser/ast/if-block0101-scope-output.json new file mode 100644 index 00000000..dc781fe1 --- /dev/null +++ b/tests/fixtures/parser/ast/if-block0101-scope-output.json @@ -0,0 +1,197 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "expression", + "range": [ + 5, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "expression", + "range": [ + 26, + 36 + ], + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 36 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ], + "childScopes": [ + { + "type": "block", + "variables": [], + "references": [], + "childScopes": [], + "through": [] + }, + { + "type": "block", + "variables": [], + "references": [], + "childScopes": [], + "through": [] + }, + { + "type": "block", + "variables": [], + "references": [], + "childScopes": [], + "through": [] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "expression", + "range": [ + 5, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "expression", + "range": [ + 26, + 36 + ], + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 36 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "expression", + "range": [ + 5, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "expression", + "range": [ + 26, + 36 + ], + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 36 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] +} \ No newline at end of file From f2fd1b2bb57f2dca0005d3bb5bf0bce21014eec9 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sun, 28 Nov 2021 12:18:13 +0900 Subject: [PATCH 2/2] fix --- src/parser/converts/block.ts | 30 +++- src/parser/converts/common.ts | 4 +- ...1-input.svelte => if-block01-input.svelte} | 0 ...t.json => if-block01-no-undef-result.json} | 0 ...101-output.json => if-block01-output.json} | 142 +----------------- ...tput.json => if-block01-scope-output.json} | 0 6 files changed, 37 insertions(+), 139 deletions(-) rename tests/fixtures/parser/ast/{if-block0101-input.svelte => if-block01-input.svelte} (100%) rename tests/fixtures/parser/ast/{if-block0101-no-undef-result.json => if-block01-no-undef-result.json} (100%) rename tests/fixtures/parser/ast/{if-block0101-output.json => if-block01-output.json} (77%) rename tests/fixtures/parser/ast/{if-block0101-scope-output.json => if-block01-scope-output.json} (100%) diff --git a/src/parser/converts/block.ts b/src/parser/converts/block.ts index 368aa4b0..59f8c274 100644 --- a/src/parser/converts/block.ts +++ b/src/parser/converts/block.ts @@ -13,6 +13,30 @@ import type { Context } from "../../context" import { convertChildren } from "./element" import { getWithLoc, indexOf, lastIndexOf } from "./common" +/** Get start index of block */ +function startBlockIndex(code: string, endIndex: number): number { + return lastIndexOf( + code, + (c, index) => { + if (c !== "{") { + return false + } + for (let next = index + 1; next < code.length; next++) { + const nextC = code[next] + if (!nextC.trim()) { + continue + } + return ( + code.startsWith("#if", next) || + code.startsWith(":else", next) + ) + } + return false + }, + endIndex, + ) +} + /** Convert for IfBlock */ export function convertIfBlock( node: SvAST.IfBlock, @@ -22,7 +46,7 @@ export function convertIfBlock( // {#if expr} {:else} {/if} // {:else if expr} {/if} const nodeStart = node.elseif - ? ctx.code.lastIndexOf("{", node.start) + ? startBlockIndex(ctx.code, node.start - 1) : node.start const ifBlock: SvelteIfBlock = { type: "SvelteIfBlock", @@ -49,7 +73,7 @@ export function convertIfBlock( return ifBlock } - const elseStart = ctx.code.lastIndexOf("{", node.else.start - 1) + const elseStart = startBlockIndex(ctx.code, node.else.start - 1) const elseBlock: SvelteElseBlock = { type: "SvelteElseBlock", @@ -149,7 +173,7 @@ export function convertEachBlock( return eachBlock } - const elseStart = ctx.code.lastIndexOf("{", node.else.start) + const elseStart = startBlockIndex(ctx.code, node.else.start - 1) const elseBlock: SvelteElseBlock = { type: "SvelteElseBlock", diff --git a/src/parser/converts/common.ts b/src/parser/converts/common.ts index 12980efb..57370bb7 100644 --- a/src/parser/converts/common.ts +++ b/src/parser/converts/common.ts @@ -17,12 +17,12 @@ export function indexOf( /** lastIndexOf */ export function lastIndexOf( str: string, - search: (c: string) => boolean, + search: (c: string, index: number) => boolean, end: number, ): number { for (let index = end; index >= 0; index--) { const c = str[index] - if (search(c)) { + if (search(c, index)) { return index } } diff --git a/tests/fixtures/parser/ast/if-block0101-input.svelte b/tests/fixtures/parser/ast/if-block01-input.svelte similarity index 100% rename from tests/fixtures/parser/ast/if-block0101-input.svelte rename to tests/fixtures/parser/ast/if-block01-input.svelte diff --git a/tests/fixtures/parser/ast/if-block0101-no-undef-result.json b/tests/fixtures/parser/ast/if-block01-no-undef-result.json similarity index 100% rename from tests/fixtures/parser/ast/if-block0101-no-undef-result.json rename to tests/fixtures/parser/ast/if-block01-no-undef-result.json diff --git a/tests/fixtures/parser/ast/if-block0101-output.json b/tests/fixtures/parser/ast/if-block01-output.json similarity index 77% rename from tests/fixtures/parser/ast/if-block0101-output.json rename to tests/fixtures/parser/ast/if-block01-output.json index ed6a0e39..359c6b8e 100644 --- a/tests/fixtures/parser/ast/if-block0101-output.json +++ b/tests/fixtures/parser/ast/if-block01-output.json @@ -67,13 +67,13 @@ } }, "range": [ - 37, + 16, 49 ], "loc": { "start": { "line": 1, - "column": 37 + "column": 16 }, "end": { "line": 1, @@ -207,88 +207,16 @@ } }, { - "type": "Punctuator", - "value": ":", + "type": "MustacheKeyword", + "value": ":else", "range": [ 17, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 17 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - { - "type": "Identifier", - "value": "e", - "range": [ - 18, - 19 - ], - "loc": { - "start": { - "line": 1, - "column": 18 - }, - "end": { - "line": 1, - "column": 19 - } - } - }, - { - "type": "Identifier", - "value": "l", - "range": [ - 19, - 20 - ], - "loc": { - "start": { - "line": 1, - "column": 19 - }, - "end": { - "line": 1, - "column": 20 - } - } - }, - { - "type": "Identifier", - "value": "s", - "range": [ - 20, - 21 - ], - "loc": { - "start": { - "line": 1, - "column": 20 - }, - "end": { - "line": 1, - "column": 21 - } - } - }, - { - "type": "Identifier", - "value": "e", - "range": [ - 21, 22 ], "loc": { "start": { "line": 1, - "column": 21 + "column": 17 }, "end": { "line": 1, @@ -297,34 +225,16 @@ } }, { - "type": "Identifier", - "value": "i", + "type": "MustacheKeyword", + "value": "if", "range": [ 23, - 24 - ], - "loc": { - "start": { - "line": 1, - "column": 23 - }, - "end": { - "line": 1, - "column": 24 - } - } - }, - { - "type": "Identifier", - "value": "f", - "range": [ - 24, 25 ], "loc": { "start": { "line": 1, - "column": 24 + "column": 23 }, "end": { "line": 1, @@ -404,24 +314,6 @@ } } }, - { - "type": "MustacheKeyword", - "value": ":else", - "range": [ - 38, - 43 - ], - "loc": { - "start": { - "line": 1, - "column": 38 - }, - "end": { - "line": 1, - "column": 43 - } - } - }, { "type": "Punctuator", "value": "}", @@ -476,24 +368,6 @@ } } }, - { - "type": "MustacheKeyword", - "value": "if", - "range": [ - 46, - 48 - ], - "loc": { - "start": { - "line": 1, - "column": 46 - }, - "end": { - "line": 1, - "column": 48 - } - } - }, { "type": "Punctuator", "value": "}", diff --git a/tests/fixtures/parser/ast/if-block0101-scope-output.json b/tests/fixtures/parser/ast/if-block01-scope-output.json similarity index 100% rename from tests/fixtures/parser/ast/if-block0101-scope-output.json rename to tests/fixtures/parser/ast/if-block01-scope-output.json