diff --git a/.changeset/friendly-hats-flow.md b/.changeset/friendly-hats-flow.md new file mode 100644 index 00000000..bc0d0478 --- /dev/null +++ b/.changeset/friendly-hats-flow.md @@ -0,0 +1,5 @@ +--- +"svelte-eslint-parser": minor +--- + +feat: (experimental) partial support for Svelte v5 parser diff --git a/.github/workflows/NodeCI.yml b/.github/workflows/NodeCI.yml index c147a662..2c07f1ca 100644 --- a/.github/workflows/NodeCI.yml +++ b/.github/workflows/NodeCI.yml @@ -35,6 +35,21 @@ jobs: run: pnpm install - name: Test run: pnpm run test + test-for-svelte-v4: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v2 + - name: Use Node.js + uses: actions/setup-node@v4 + - name: Install Svelte v4 + run: |+ + pnpm install -D svelte@4 + rm -rf node_modules + - name: Install Packages + run: pnpm install + - name: Test + run: pnpm run test test-for-svelte-v3: runs-on: ubuntu-latest strategy: diff --git a/package.json b/package.json index 2e10b760..2340b8c2 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "version:ci": "env-cmd -e version-ci pnpm run build:meta && changeset version" }, "peerDependencies": { - "svelte": "^3.37.0 || ^4.0.0" + "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0-next.2" }, "peerDependenciesMeta": { "svelte": { @@ -103,8 +103,8 @@ "prettier-plugin-svelte": "^3.0.0", "rimraf": "^5.0.1", "semver": "^7.5.1", - "svelte": "^4.2.0", - "svelte2tsx": "^0.6.20", + "svelte": "^5.0.0-next.2", + "svelte2tsx": "^0.6.25", "typescript": "~5.1.3", "typescript-eslint-parser-for-extra-files": "^0.5.0" }, diff --git a/src/parser/converts/element.ts b/src/parser/converts/element.ts index cb4ddaa6..2c44cbef 100644 --- a/src/parser/converts/element.ts +++ b/src/parser/converts/element.ts @@ -52,7 +52,7 @@ import { ParseError } from "../.."; /** Convert for Fragment or Element or ... */ export function* convertChildren( /* eslint-enable complexity -- X */ - fragment: { children: SvAST.TemplateNode[] }, + fragment: { children?: SvAST.TemplateNode[] }, parent: | SvelteProgram | SvelteElement @@ -76,6 +76,7 @@ export function* convertChildren( | SvelteKeyBlock | SvelteHTMLComment > { + if (!fragment.children) return; for (const child of fragment.children) { if (child.type === "Comment") { yield convertComment(child, parent, ctx); @@ -199,8 +200,9 @@ function extractLetDirectives(fragment: { /** Check if children needs a scope. */ function needScopeByChildren(fragment: { - children: SvAST.TemplateNode[]; + children?: SvAST.TemplateNode[]; }): boolean { + if (!fragment.children) return false; for (const child of fragment.children) { if (child.type === "ConstTag") { return true; @@ -437,66 +439,92 @@ function processThisAttribute( (c) => Boolean(c.trim()), eqIndex + 1, ); - const quote = ctx.code.startsWith(thisValue, valueStartIndex) - ? null - : ctx.code[valueStartIndex]; - const literalStartIndex = quote - ? valueStartIndex + quote.length - : valueStartIndex; - const literalEndIndex = literalStartIndex + thisValue.length; - const endIndex = quote ? literalEndIndex + quote.length : literalEndIndex; - const thisAttr: SvelteAttribute = { - type: "SvelteAttribute", - key: null as any, - boolean: false, - value: [], - parent: element.startTag, - ...ctx.getConvertLocation({ start: startIndex, end: endIndex }), - }; - thisAttr.key = { - type: "SvelteName", - name: "this", - parent: thisAttr, - ...ctx.getConvertLocation({ start: startIndex, end: eqIndex }), - }; - thisAttr.value.push({ - type: "SvelteLiteral", - value: thisValue, - parent: thisAttr, - ...ctx.getConvertLocation({ - start: literalStartIndex, - end: literalEndIndex, - }), - }); - // this - ctx.addToken("HTMLIdentifier", { - start: startIndex, - end: startIndex + 4, - }); - // = - ctx.addToken("Punctuator", { - start: eqIndex, - end: eqIndex + 1, - }); - if (quote) { - // " - ctx.addToken("Punctuator", { - start: valueStartIndex, - end: literalStartIndex, + if (ctx.code[valueStartIndex] === "{") { + // Svelte v5 `this={"..."}` + const openingQuoteIndex = indexOf( + ctx.code, + (c) => c === '"' || c === "'", + valueStartIndex + 1, + ); + const quote = ctx.code[openingQuoteIndex]; + const closingQuoteIndex = indexOf( + ctx.code, + (c) => c === quote, + openingQuoteIndex + thisValue.length, + ); + const closeIndex = ctx.code.indexOf("}", closingQuoteIndex + 1); + const endIndex = indexOf( + ctx.code, + (c) => c === ">" || !c.trim(), + closeIndex, + ); + thisNode = createSvelteSpecialDirective(startIndex, endIndex, eqIndex, { + type: "Literal", + value: thisValue, + range: [openingQuoteIndex, closingQuoteIndex + 1], }); - } - ctx.addToken("HTMLText", { - start: literalStartIndex, - end: literalEndIndex, - }); - if (quote) { - // " + } else { + const quote = ctx.code.startsWith(thisValue, valueStartIndex) + ? null + : ctx.code[valueStartIndex]; + const literalStartIndex = quote + ? valueStartIndex + quote.length + : valueStartIndex; + const literalEndIndex = literalStartIndex + thisValue.length; + const endIndex = quote ? literalEndIndex + quote.length : literalEndIndex; + const thisAttr: SvelteAttribute = { + type: "SvelteAttribute", + key: null as any, + boolean: false, + value: [], + parent: element.startTag, + ...ctx.getConvertLocation({ start: startIndex, end: endIndex }), + }; + thisAttr.key = { + type: "SvelteName", + name: "this", + parent: thisAttr, + ...ctx.getConvertLocation({ start: startIndex, end: eqIndex }), + }; + thisAttr.value.push({ + type: "SvelteLiteral", + value: thisValue, + parent: thisAttr, + ...ctx.getConvertLocation({ + start: literalStartIndex, + end: literalEndIndex, + }), + }); + // this + ctx.addToken("HTMLIdentifier", { + start: startIndex, + end: startIndex + 4, + }); + // = ctx.addToken("Punctuator", { - start: literalEndIndex, - end: endIndex, + start: eqIndex, + end: eqIndex + 1, + }); + if (quote) { + // " + ctx.addToken("Punctuator", { + start: valueStartIndex, + end: literalStartIndex, + }); + } + ctx.addToken("HTMLText", { + start: literalStartIndex, + end: literalEndIndex, }); + if (quote) { + // " + ctx.addToken("Punctuator", { + start: literalEndIndex, + end: endIndex, + }); + } + thisNode = thisAttr; } - thisNode = thisAttr; } else { // this={...} const eqIndex = ctx.code.lastIndexOf("=", getWithLoc(thisValue).start); @@ -507,6 +535,30 @@ function processThisAttribute( (c) => c === ">" || !c.trim(), closeIndex, ); + thisNode = createSvelteSpecialDirective( + startIndex, + endIndex, + eqIndex, + thisValue, + ); + } + + const targetIndex = element.startTag.attributes.findIndex( + (attr) => thisNode.range[1] <= attr.range[0], + ); + if (targetIndex === -1) { + element.startTag.attributes.push(thisNode); + } else { + element.startTag.attributes.splice(targetIndex, 0, thisNode); + } + + /** Create SvelteSpecialDirective */ + function createSvelteSpecialDirective( + startIndex: number, + endIndex: number, + eqIndex: number, + expression: ESTree.Expression, + ): SvelteSpecialDirective { const thisDir: SvelteSpecialDirective = { type: "SvelteSpecialDirective", kind: "this", @@ -530,19 +582,11 @@ function processThisAttribute( start: eqIndex, end: eqIndex + 1, }); - ctx.scriptLet.addExpression(thisValue, thisDir, null, (es) => { + ctx.scriptLet.addExpression(expression, thisDir, null, (es) => { thisDir.expression = es; }); - thisNode = thisDir; - } - const targetIndex = element.startTag.attributes.findIndex( - (attr) => thisNode.range[1] <= attr.range[0], - ); - if (targetIndex === -1) { - element.startTag.attributes.push(thisNode); - } else { - element.startTag.attributes.splice(targetIndex, 0, thisNode); + return thisDir; } } diff --git a/src/parser/svelte-ast-types.ts b/src/parser/svelte-ast-types.ts index 3125c887..77bb0d79 100644 --- a/src/parser/svelte-ast-types.ts +++ b/src/parser/svelte-ast-types.ts @@ -162,7 +162,7 @@ export interface Title extends BaseNode { export interface Options extends BaseNode { type: "Options"; name: "svelte:options"; - children: TemplateNode[]; + children?: TemplateNode[]; // This property does not exist in Svelte v5. attributes: AttributeOrDirective[]; } export interface SlotTemplate extends BaseNode { diff --git a/src/parser/template.ts b/src/parser/template.ts index d5b4b63a..a9fa954a 100644 --- a/src/parser/template.ts +++ b/src/parser/template.ts @@ -21,7 +21,7 @@ export function parseTemplate( try { const svelteAst = parse(code, { filename: parserOptions.filePath, - }) as SvAST.Ast; + }) as never as SvAST.Ast; const ast = convertSvelteRoot(svelteAst, ctx); sortNodes(ast.body); diff --git a/tests/fixtures/parser/ast/await03-requirements.json b/tests/fixtures/parser/ast/await03-requirements.json new file mode 100644 index 00000000..acfee03d --- /dev/null +++ b/tests/fixtures/parser/ast/await03-requirements.json @@ -0,0 +1,6 @@ +{ + "FIXME": "As of now, Svelte v5 gives an error with single-line await blocks.", + "parse": { + "svelte": "^4 || ^3" + } +} diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/01-requirements.json b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/01-requirements.json new file mode 100644 index 00000000..7d726dc9 --- /dev/null +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/01-requirements.json @@ -0,0 +1,5 @@ +{ + "parse": { + "svelte": "^4 || ^3" + } +} diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-input.svelte b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-input.svelte index 69b43a26..9710e27e 100644 --- a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-input.svelte +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-input.svelte @@ -1 +1 @@ - + diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-input.svelte b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-input.svelte new file mode 100644 index 00000000..69b43a26 --- /dev/null +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-input.svelte @@ -0,0 +1 @@ + diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-output.json b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-output.json new file mode 100644 index 00000000..cc395321 --- /dev/null +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-output.json @@ -0,0 +1,299 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "special", + "name": { + "type": "SvelteName", + "name": "svelte:options", + "range": [ + 1, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "tag", + "range": [ + 16, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "my-custom-element", + "range": [ + 21, + 38 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 38 + } + } + } + ], + "range": [ + 16, + 39 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 39 + } + } + } + ], + "selfClosing": true, + "range": [ + 0, + 41 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 41 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 0, + 41 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 41 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "svelte:options", + "range": [ + 1, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "tag", + "range": [ + 16, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 19, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 20 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "HTMLText", + "value": "my-custom-element", + "range": [ + 21, + 38 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 38 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 38, + 39 + ], + "loc": { + "start": { + "line": 1, + "column": 38 + }, + "end": { + "line": 1, + "column": 39 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 1, + "column": 39 + }, + "end": { + "line": 1, + "column": 40 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 40, + 41 + ], + "loc": { + "start": { + "line": 1, + "column": 40 + }, + "end": { + "line": 1, + "column": 41 + } + } + } + ], + "range": [ + 0, + 42 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-requirements.json b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-requirements.json new file mode 100644 index 00000000..7d726dc9 --- /dev/null +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-requirements.json @@ -0,0 +1,5 @@ +{ + "parse": { + "svelte": "^4 || ^3" + } +} diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-scope-output.json b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-scope-output.json new file mode 100644 index 00000000..d392ca4b --- /dev/null +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-old-scope-output.json @@ -0,0 +1,34 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [], + "childScopes": [], + "through": [] + } + ], + "through": [] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-output.json b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-output.json index cc395321..914a2fb7 100644 --- a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-output.json +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-output.json @@ -29,10 +29,10 @@ "type": "SvelteAttribute", "key": { "type": "SvelteName", - "name": "tag", + "name": "customElement", "range": [ 16, - 19 + 29 ], "loc": { "start": { @@ -41,7 +41,7 @@ }, "end": { "line": 1, - "column": 19 + "column": 29 } } }, @@ -51,24 +51,24 @@ "type": "SvelteLiteral", "value": "my-custom-element", "range": [ - 21, - 38 + 31, + 48 ], "loc": { "start": { "line": 1, - "column": 21 + "column": 31 }, "end": { "line": 1, - "column": 38 + "column": 48 } } } ], "range": [ 16, - 39 + 49 ], "loc": { "start": { @@ -77,7 +77,7 @@ }, "end": { "line": 1, - "column": 39 + "column": 49 } } } @@ -85,7 +85,7 @@ "selfClosing": true, "range": [ 0, - 41 + 51 ], "loc": { "start": { @@ -94,7 +94,7 @@ }, "end": { "line": 1, - "column": 41 + "column": 51 } } }, @@ -102,7 +102,7 @@ "endTag": null, "range": [ 0, - 41 + 51 ], "loc": { "start": { @@ -111,7 +111,7 @@ }, "end": { "line": 1, - "column": 41 + "column": 51 } } } @@ -157,10 +157,10 @@ }, { "type": "HTMLIdentifier", - "value": "tag", + "value": "customElement", "range": [ 16, - 19 + 29 ], "loc": { "start": { @@ -169,7 +169,7 @@ }, "end": { "line": 1, - "column": 19 + "column": 29 } } }, @@ -177,17 +177,17 @@ "type": "Punctuator", "value": "=", "range": [ - 19, - 20 + 29, + 30 ], "loc": { "start": { "line": 1, - "column": 19 + "column": 29 }, "end": { "line": 1, - "column": 20 + "column": 30 } } }, @@ -195,17 +195,17 @@ "type": "Punctuator", "value": "\"", "range": [ - 20, - 21 + 30, + 31 ], "loc": { "start": { "line": 1, - "column": 20 + "column": 30 }, "end": { "line": 1, - "column": 21 + "column": 31 } } }, @@ -213,17 +213,17 @@ "type": "HTMLText", "value": "my-custom-element", "range": [ - 21, - 38 + 31, + 48 ], "loc": { "start": { "line": 1, - "column": 21 + "column": 31 }, "end": { "line": 1, - "column": 38 + "column": 48 } } }, @@ -231,17 +231,17 @@ "type": "Punctuator", "value": "\"", "range": [ - 38, - 39 + 48, + 49 ], "loc": { "start": { "line": 1, - "column": 38 + "column": 48 }, "end": { "line": 1, - "column": 39 + "column": 49 } } }, @@ -249,17 +249,17 @@ "type": "Punctuator", "value": "/", "range": [ - 39, - 40 + 49, + 50 ], "loc": { "start": { "line": 1, - "column": 39 + "column": 49 }, "end": { "line": 1, - "column": 40 + "column": 50 } } }, @@ -267,24 +267,24 @@ "type": "Punctuator", "value": ">", "range": [ - 40, - 41 + 50, + 51 ], "loc": { "start": { "line": 1, - "column": 40 + "column": 50 }, "end": { "line": 1, - "column": 41 + "column": 51 } } } ], "range": [ 0, - 42 + 52 ], "loc": { "start": { diff --git a/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-requirements.json b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-requirements.json new file mode 100644 index 00000000..87f1143e --- /dev/null +++ b/tests/fixtures/parser/ast/docs/template-syntax/19-svelte-options/02-requirements.json @@ -0,0 +1,5 @@ +{ + "test": { + "svelte": "^5.0.0-0" + } +} diff --git a/tests/fixtures/parser/ast/if-block01-requirements.json b/tests/fixtures/parser/ast/if-block01-requirements.json new file mode 100644 index 00000000..62679df4 --- /dev/null +++ b/tests/fixtures/parser/ast/if-block01-requirements.json @@ -0,0 +1,6 @@ +{ + "FIXME": "Probably a bug in the current Svelte v5. The position information in the else block is incorrect.", + "parse": { + "svelte": "^4 || ^3" + } +} diff --git a/tests/fixtures/parser/ast/this-attr05-input.svelte b/tests/fixtures/parser/ast/this-attr05-input.svelte new file mode 100644 index 00000000..c7ce494a --- /dev/null +++ b/tests/fixtures/parser/ast/this-attr05-input.svelte @@ -0,0 +1,2 @@ + + diff --git a/tests/fixtures/parser/ast/this-attr05-output.json b/tests/fixtures/parser/ast/this-attr05-output.json new file mode 100644 index 00000000..308f0730 --- /dev/null +++ b/tests/fixtures/parser/ast/this-attr05-output.json @@ -0,0 +1,1214 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "special", + "name": { + "type": "SvelteName", + "name": "svelte:element", + "range": [ + 1, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "class", + "range": [ + 16, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "foo", + "range": [ + 23, + 26 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 26 + } + } + } + ], + "range": [ + 16, + 27 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 27 + } + } + }, + { + "type": "SvelteSpecialDirective", + "kind": "this", + "key": { + "type": "SvelteSpecialDirectiveKey", + "range": [ + 28, + 32 + ], + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 32 + } + } + }, + "expression": { + "type": "Literal", + "raw": "'input'", + "value": "input", + "range": [ + 34, + 41 + ], + "loc": { + "start": { + "line": 1, + "column": 34 + }, + "end": { + "line": 1, + "column": 41 + } + } + }, + "range": [ + 28, + 42 + ], + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 42 + } + } + }, + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "type", + "range": [ + 43, + 47 + ], + "loc": { + "start": { + "line": 1, + "column": 43 + }, + "end": { + "line": 1, + "column": 47 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "number", + "range": [ + 49, + 55 + ], + "loc": { + "start": { + "line": 1, + "column": 49 + }, + "end": { + "line": 1, + "column": 55 + } + } + } + ], + "range": [ + 43, + 56 + ], + "loc": { + "start": { + "line": 1, + "column": 43 + }, + "end": { + "line": 1, + "column": 56 + } + } + } + ], + "selfClosing": true, + "range": [ + 0, + 58 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 58 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 0, + 58 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 58 + } + } + }, + { + "type": "SvelteText", + "value": "\n", + "range": [ + 58, + 59 + ], + "loc": { + "start": { + "line": 1, + "column": 58 + }, + "end": { + "line": 2, + "column": 0 + } + } + }, + { + "type": "SvelteElement", + "kind": "special", + "name": { + "type": "SvelteName", + "name": "svelte:element", + "range": [ + 60, + 74 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 15 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "class", + "range": [ + 75, + 80 + ], + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 2, + "column": 21 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "foo", + "range": [ + 82, + 85 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 2, + "column": 26 + } + } + } + ], + "range": [ + 75, + 86 + ], + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 2, + "column": 27 + } + } + }, + { + "type": "SvelteSpecialDirective", + "kind": "this", + "key": { + "type": "SvelteSpecialDirectiveKey", + "range": [ + 87, + 91 + ], + "loc": { + "start": { + "line": 2, + "column": 28 + }, + "end": { + "line": 2, + "column": 32 + } + } + }, + "expression": { + "type": "TemplateLiteral", + "expressions": [], + "quasis": [ + { + "type": "TemplateElement", + "tail": true, + "value": { + "cooked": "input", + "raw": "input" + }, + "range": [ + 93, + 100 + ], + "loc": { + "start": { + "line": 2, + "column": 34 + }, + "end": { + "line": 2, + "column": 41 + } + } + } + ], + "range": [ + 93, + 100 + ], + "loc": { + "start": { + "line": 2, + "column": 34 + }, + "end": { + "line": 2, + "column": 41 + } + } + }, + "range": [ + 87, + 101 + ], + "loc": { + "start": { + "line": 2, + "column": 28 + }, + "end": { + "line": 2, + "column": 42 + } + } + }, + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "type", + "range": [ + 102, + 106 + ], + "loc": { + "start": { + "line": 2, + "column": 43 + }, + "end": { + "line": 2, + "column": 47 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "number", + "range": [ + 108, + 114 + ], + "loc": { + "start": { + "line": 2, + "column": 49 + }, + "end": { + "line": 2, + "column": 55 + } + } + } + ], + "range": [ + 102, + 115 + ], + "loc": { + "start": { + "line": 2, + "column": 43 + }, + "end": { + "line": 2, + "column": 56 + } + } + } + ], + "selfClosing": true, + "range": [ + 59, + 117 + ], + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 58 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 59, + 117 + ], + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 58 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "svelte:element", + "range": [ + 1, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "class", + "range": [ + 16, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 22 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 23 + } + } + }, + { + "type": "HTMLText", + "value": "foo", + "range": [ + 23, + 26 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 26 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 26, + 27 + ], + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 27 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "this", + "range": [ + 28, + 32 + ], + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 32 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 32, + 33 + ], + "loc": { + "start": { + "line": 1, + "column": 32 + }, + "end": { + "line": 1, + "column": 33 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 33, + 34 + ], + "loc": { + "start": { + "line": 1, + "column": 33 + }, + "end": { + "line": 1, + "column": 34 + } + } + }, + { + "type": "String", + "value": "'input'", + "range": [ + 34, + 41 + ], + "loc": { + "start": { + "line": 1, + "column": 34 + }, + "end": { + "line": 1, + "column": 41 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 41, + 42 + ], + "loc": { + "start": { + "line": 1, + "column": 41 + }, + "end": { + "line": 1, + "column": 42 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "type", + "range": [ + 43, + 47 + ], + "loc": { + "start": { + "line": 1, + "column": 43 + }, + "end": { + "line": 1, + "column": 47 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 47, + 48 + ], + "loc": { + "start": { + "line": 1, + "column": 47 + }, + "end": { + "line": 1, + "column": 48 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 48, + 49 + ], + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 49 + } + } + }, + { + "type": "HTMLText", + "value": "number", + "range": [ + 49, + 55 + ], + "loc": { + "start": { + "line": 1, + "column": 49 + }, + "end": { + "line": 1, + "column": 55 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 55, + 56 + ], + "loc": { + "start": { + "line": 1, + "column": 55 + }, + "end": { + "line": 1, + "column": 56 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 56, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 56 + }, + "end": { + "line": 1, + "column": 57 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 57, + 58 + ], + "loc": { + "start": { + "line": 1, + "column": 57 + }, + "end": { + "line": 1, + "column": 58 + } + } + }, + { + "type": "HTMLText", + "value": "\n", + "range": [ + 58, + 59 + ], + "loc": { + "start": { + "line": 1, + "column": 58 + }, + "end": { + "line": 2, + "column": 0 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 59, + 60 + ], + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "svelte:element", + "range": [ + 60, + 74 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 15 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "class", + "range": [ + 75, + 80 + ], + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 2, + "column": 21 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 80, + 81 + ], + "loc": { + "start": { + "line": 2, + "column": 21 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 81, + 82 + ], + "loc": { + "start": { + "line": 2, + "column": 22 + }, + "end": { + "line": 2, + "column": 23 + } + } + }, + { + "type": "HTMLText", + "value": "foo", + "range": [ + 82, + 85 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 2, + "column": 26 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 85, + 86 + ], + "loc": { + "start": { + "line": 2, + "column": 26 + }, + "end": { + "line": 2, + "column": 27 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "this", + "range": [ + 87, + 91 + ], + "loc": { + "start": { + "line": 2, + "column": 28 + }, + "end": { + "line": 2, + "column": 32 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 91, + 92 + ], + "loc": { + "start": { + "line": 2, + "column": 32 + }, + "end": { + "line": 2, + "column": 33 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 92, + 93 + ], + "loc": { + "start": { + "line": 2, + "column": 33 + }, + "end": { + "line": 2, + "column": 34 + } + } + }, + { + "type": "Template", + "value": "`input`", + "range": [ + 93, + 100 + ], + "loc": { + "start": { + "line": 2, + "column": 34 + }, + "end": { + "line": 2, + "column": 41 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 100, + 101 + ], + "loc": { + "start": { + "line": 2, + "column": 41 + }, + "end": { + "line": 2, + "column": 42 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "type", + "range": [ + 102, + 106 + ], + "loc": { + "start": { + "line": 2, + "column": 43 + }, + "end": { + "line": 2, + "column": 47 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 106, + 107 + ], + "loc": { + "start": { + "line": 2, + "column": 47 + }, + "end": { + "line": 2, + "column": 48 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 107, + 108 + ], + "loc": { + "start": { + "line": 2, + "column": 48 + }, + "end": { + "line": 2, + "column": 49 + } + } + }, + { + "type": "HTMLText", + "value": "number", + "range": [ + 108, + 114 + ], + "loc": { + "start": { + "line": 2, + "column": 49 + }, + "end": { + "line": 2, + "column": 55 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 114, + 115 + ], + "loc": { + "start": { + "line": 2, + "column": 55 + }, + "end": { + "line": 2, + "column": 56 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 115, + 116 + ], + "loc": { + "start": { + "line": 2, + "column": 56 + }, + "end": { + "line": 2, + "column": 57 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 116, + 117 + ], + "loc": { + "start": { + "line": 2, + "column": 57 + }, + "end": { + "line": 2, + "column": 58 + } + } + } + ], + "range": [ + 0, + 118 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/this-attr05-scope-output.json b/tests/fixtures/parser/ast/this-attr05-scope-output.json new file mode 100644 index 00000000..d392ca4b --- /dev/null +++ b/tests/fixtures/parser/ast/this-attr05-scope-output.json @@ -0,0 +1,34 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [], + "childScopes": [], + "through": [] + } + ], + "through": [] +} \ No newline at end of file diff --git a/tests/src/parser/eslint-rules.ts b/tests/src/parser/eslint-rules.ts index 791b5f2d..ae8fa02f 100644 --- a/tests/src/parser/eslint-rules.ts +++ b/tests/src/parser/eslint-rules.ts @@ -41,7 +41,11 @@ describe("svelte-eslint-parser with ESLint rules", () => { inputFileName, config, getRuleOutputFileName, + meetRequirements, } of listupFixtures()) { + if (!meetRequirements("parse")) { + continue; + } const linter = createLinter(); describe(inputFileName, () => { for (const rule of RULES) { diff --git a/tests/src/parser/parser.ts b/tests/src/parser/parser.ts index c0791a3d..5459cbf2 100644 --- a/tests/src/parser/parser.ts +++ b/tests/src/parser/parser.ts @@ -27,6 +27,9 @@ describe("Check for AST.", () => { config, meetRequirements, } of listupFixtures()) { + if (!meetRequirements("parse")) { + continue; + } describe(inputFileName, () => { let result: any; diff --git a/tests/src/parser/test-utils.ts b/tests/src/parser/test-utils.ts index b580c18a..00cfe9ea 100644 --- a/tests/src/parser/test-utils.ts +++ b/tests/src/parser/test-utils.ts @@ -40,7 +40,7 @@ export function* listupFixtures(dir?: string): Iterable<{ scope?: Record; }; getRuleOutputFileName: (ruleName: string) => string; - meetRequirements: (key: "test" | "scope") => boolean; + meetRequirements: (key: "test" | "scope" | "parse") => boolean; }> { yield* listupFixturesImpl(dir || AST_FIXTURE_ROOT); } @@ -56,7 +56,7 @@ function* listupFixturesImpl(dir: string): Iterable<{ scope?: Record; }; getRuleOutputFileName: (ruleName: string) => string; - meetRequirements: (key: "test" | "scope") => boolean; + meetRequirements: (key: "test" | "scope" | "parse") => boolean; }> { for (const filename of fs.readdirSync(dir)) { const inputFileName = path.join(dir, filename); diff --git a/tools/update-fixtures.ts b/tools/update-fixtures.ts index 5a23f8bb..81c8e2ed 100644 --- a/tools/update-fixtures.ts +++ b/tools/update-fixtures.ts @@ -71,8 +71,12 @@ for (const { scopeFileName, typeFileName, config, + meetRequirements, getRuleOutputFileName, } of listupFixtures()) { + if (!meetRequirements("test") || !meetRequirements("parse")) { + continue; + } // if (!inputFileName.includes("test")) continue; try { // eslint-disable-next-line no-console -- ignore