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