diff --git a/.changeset/red-pots-shake.md b/.changeset/red-pots-shake.md new file mode 100644 index 00000000..c3d1b551 --- /dev/null +++ b/.changeset/red-pots-shake.md @@ -0,0 +1,5 @@ +--- +"svelte-eslint-parser": minor +--- + +feat: add AST node for function bindings diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 338810d1..e590073e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -29,7 +29,7 @@ body: - type: textarea id: eslint-plugin-svelte-version attributes: - label: What version of `eslint-plugin-svelte` and ` svelte-eslint-parser` are you using? + label: What version of `eslint-plugin-svelte` and `svelte-eslint-parser` are you using? value: | - svelte-eslint-parser@0.0.0 - eslint-plugin-svelte@0.0.0 diff --git a/docs/AST.md b/docs/AST.md index a7066e01..b8eec7b4 100644 --- a/docs/AST.md +++ b/docs/AST.md @@ -278,7 +278,7 @@ interface SvelteBindingDirective extends Node { kind: "Binding"; key: SvelteDirectiveKey; shorthand: boolean; - expression: null | Expression; + expression: null | Expression | SvelteFunctionBindingsExpression; } interface SvelteClassDirective extends Node { type: "SvelteDirective"; @@ -601,3 +601,20 @@ interface SvelteReactiveStatement extends Node { body: Statement; } ``` + +### SvelteFunctionBindingsExpression + +This node is a function bindings expression in `bind:name={get, set}`.\ +`SvelteFunctionBindingsExpression` is a special node to avoid confusing ESLint check rules with `SequenceExpression`. + +```ts +interface SvelteFunctionBindingsExpression extends Node { + type: "SvelteFunctionBindingsExpression"; + expressions: [ + /** Getter */ + Expression, + /** Setter */ + Expression, + ]; +} +``` diff --git a/src/ast/html.ts b/src/ast/html.ts index 86e11f1d..cd1756f4 100644 --- a/src/ast/html.ts +++ b/src/ast/html.ts @@ -2,6 +2,7 @@ import type ESTree from "estree"; import type { TSESTree } from "@typescript-eslint/types"; import type { BaseNode } from "./base.js"; import type { Token, Comment } from "./common.js"; +import type { SvelteFunctionBindingsExpression } from "./script.js"; export type SvelteHTMLNode = | SvelteProgram @@ -595,7 +596,7 @@ export interface SvelteBindingDirective extends BaseSvelteDirective { kind: "Binding"; key: SvelteDirectiveKeyTextName; shorthand: boolean; - expression: null | ESTree.Expression; + expression: null | ESTree.Expression | SvelteFunctionBindingsExpression; } export interface SvelteClassDirective extends BaseSvelteDirective { kind: "Class"; diff --git a/src/ast/script.ts b/src/ast/script.ts index 328af5f5..d0e0366e 100644 --- a/src/ast/script.ts +++ b/src/ast/script.ts @@ -1,7 +1,9 @@ import type ESTree from "estree"; import type { BaseNode } from "./base.js"; -export type SvelteScriptNode = SvelteReactiveStatement; +export type SvelteScriptNode = + | SvelteReactiveStatement + | SvelteFunctionBindingsExpression; /** Node of `$` statement. */ export interface SvelteReactiveStatement extends BaseNode { @@ -10,3 +12,14 @@ export interface SvelteReactiveStatement extends BaseNode { body: ESTree.Statement; parent: ESTree.Node; } + +/** Node of `bind:name={get, set}` expression. */ +export interface SvelteFunctionBindingsExpression extends BaseNode { + type: "SvelteFunctionBindingsExpression"; + expressions: [ + /** Getter */ + ESTree.Expression, + /** Setter */ + ESTree.Expression, + ]; +} diff --git a/src/context/script-let.ts b/src/context/script-let.ts index 1bddc2e1..9b828274 100644 --- a/src/context/script-let.ts +++ b/src/context/script-let.ts @@ -79,27 +79,72 @@ function getNodeRange( leadingComments?: Comment[]; trailingComments?: Comment[]; }, + code: string, ): [number, number] { - let start = null; - let end = null; + const loc = + "range" in node + ? { start: node.range![0], end: node.range![1] } + : getWithLoc(node); + + let start = loc.start; + let end = loc.end; + + let openingParenCount = 0; + let closingParenCount = 0; if (node.leadingComments) { - start = getWithLoc(node.leadingComments[0]).start; + const commentStart = getWithLoc(node.leadingComments[0]).start; + if (commentStart < start) { + start = commentStart; + + // Extract the number of parentheses before the node. + let leadingEnd = loc.start; + for (let index = node.leadingComments.length - 1; index >= 0; index--) { + const comment = node.leadingComments[index]; + const loc = getWithLoc(comment); + for (const c of code.slice(loc.end, leadingEnd).trim()) { + if (c === "(") openingParenCount++; + } + leadingEnd = loc.start; + } + } } if (node.trailingComments) { - end = getWithLoc( + const commentEnd = getWithLoc( node.trailingComments[node.trailingComments.length - 1], ).end; + if (end < commentEnd) { + end = commentEnd; + + // Extract the number of parentheses after the node. + let trailingStart = loc.end; + for (const comment of node.trailingComments) { + const loc = getWithLoc(comment); + for (const c of code.slice(trailingStart, loc.start).trim()) { + if (c === ")") closingParenCount++; + } + trailingStart = loc.end; + } + } } - const loc = - "range" in node - ? { start: node.range![0], end: node.range![1] } - : getWithLoc(node); + // Adjust the range so that the parentheses match up. + if (openingParenCount < closingParenCount) { + for (; openingParenCount < closingParenCount && start >= 0; start--) { + const c = code[start].trim(); + if (c) continue; + if (c !== "(") break; + openingParenCount++; + } + } else if (openingParenCount > closingParenCount) { + for (; openingParenCount > closingParenCount && end < code.length; end++) { + const c = code[end].trim(); + if (c) continue; + if (c !== ")") break; + closingParenCount++; + } + } - return [ - start ? Math.min(start, loc.start) : loc.start, - end ? Math.max(end, loc.end) : loc.end, - ]; + return [start, end]; } type StatementNodeType = `${TSESTree.Statement["type"]}`; @@ -154,7 +199,7 @@ export class ScriptLetContext { typing?: string | null, ...callbacks: ScriptLetCallback[] ): ScriptLetCallback[] { - const range = getNodeRange(expression); + const range = getNodeRange(expression, this.ctx.code); return this.addExpressionFromRange(range, parent, typing, ...callbacks); } @@ -221,7 +266,7 @@ export class ScriptLetContext { parent: SvelteNode, ...callbacks: ScriptLetCallback[] ): void { - const range = getNodeRange(identifier); + const range = getNodeRange(identifier, this.ctx.code); const part = this.ctx.code.slice(...range); this.appendScript( `({${part}});`, @@ -260,8 +305,11 @@ export class ScriptLetContext { const range = declarator.type === "VariableDeclarator" ? // As of Svelte v5-next.65, VariableDeclarator nodes do not have location information. - [getNodeRange(declarator.id)[0], getNodeRange(declarator.init!)[1]] - : getNodeRange(declarator); + [ + getNodeRange(declarator.id, this.ctx.code)[0], + getNodeRange(declarator.init!, this.ctx.code)[1], + ] + : getNodeRange(declarator, this.ctx.code); const part = this.ctx.code.slice(...range); this.appendScript( `const ${part};`, @@ -398,7 +446,7 @@ export class ScriptLetContext { ifBlock: SvelteIfBlock, callback: ScriptLetCallback, ): void { - const range = getNodeRange(expression); + const range = getNodeRange(expression, this.ctx.code); const part = this.ctx.code.slice(...range); const restore = this.appendScript( `if(${part}){`, @@ -442,8 +490,8 @@ export class ScriptLetContext { index: ESTree.Identifier | null, ) => void, ): void { - const exprRange = getNodeRange(expression); - const ctxRange = context && getNodeRange(context); + const exprRange = getNodeRange(expression, this.ctx.code); + const ctxRange = context && getNodeRange(context, this.ctx.code); let source = "Array.from("; const exprOffset = source.length; source += `${this.ctx.code.slice(...exprRange)}).forEach((`; @@ -563,7 +611,7 @@ export class ScriptLetContext { callback: (id: ESTree.Identifier, params: ESTree.Pattern[]) => void, ): void { const scopeKind = kind || this.currentScriptScopeKind; - const idRange = getNodeRange(id); + const idRange = getNodeRange(id, this.ctx.code); const part = this.ctx.code.slice(idRange[0], closeParentIndex + 1); const restore = this.appendScript( `function ${part}{`, @@ -660,7 +708,7 @@ export class ScriptLetContext { .map((d) => { return { ...d, - range: getNodeRange(d.node), + range: getNodeRange(d.node, this.ctx.code), }; }) .sort((a, b) => { diff --git a/src/parser/converts/attr.ts b/src/parser/converts/attr.ts index e306b682..db0d0b9b 100644 --- a/src/parser/converts/attr.ts +++ b/src/parser/converts/attr.ts @@ -20,6 +20,7 @@ import type { SvelteStyleElement, SvelteElseBlock, SvelteAwaitBlock, + SvelteFunctionBindingsExpression, } from "../../ast/index.js"; import type ESTree from "estree"; import type { Context } from "../../context/index.js"; @@ -367,6 +368,12 @@ function convertBindingDirective( null, (es, { getScope }) => { directive.expression = es; + if (isFunctionBindings(ctx, es)) { + ( + directive.expression as any as SvelteFunctionBindingsExpression + ).type = "SvelteFunctionBindingsExpression"; + return; + } const scope = getScope(es); const reference = scope.references.find( (ref) => ref.identifier === es, @@ -386,6 +393,34 @@ function convertBindingDirective( return directive; } +/** + * Checks whether the given expression is Function bindings (added in Svelte 5.9.0) or not. + * See https://svelte.dev/docs/svelte/bind#Function-bindings + */ +function isFunctionBindings( + ctx: Context, + expression: ESTree.Expression, +): expression is ESTree.SequenceExpression { + // Svelte 3/4 does not support Function bindings. + if (!svelteVersion.gte(5)) { + return false; + } + if ( + expression.type !== "SequenceExpression" || + expression.expressions.length !== 2 + ) { + return false; + } + const bindValueOpenIndex = ctx.code.lastIndexOf("{", expression.range![0]); + if (bindValueOpenIndex < 0) return false; + const betweenText = ctx.code + .slice(bindValueOpenIndex + 1, expression.range![0]) + // Strip comments + .replace(/\/\/[^\n]*\n|\/\*[\s\S]*?\*\//g, "") + .trim(); + return !betweenText; +} + /** Convert for EventHandler Directive */ function convertEventHandlerDirective( node: SvAST.DirectiveForExpression | Compiler.OnDirective, @@ -774,7 +809,10 @@ function buildLetDirectiveType( type DirectiveProcessors< D extends SvAST.Directive | StandardDirective, S extends SvelteDirective, - E extends D["expression"] & S["expression"], + E extends Exclude< + D["expression"] & S["expression"], + SvelteFunctionBindingsExpression + >, > = | { processExpression: ( @@ -801,7 +839,10 @@ type DirectiveProcessors< function processDirective< D extends SvAST.Directive | StandardDirective, S extends SvelteDirective, - E extends D["expression"] & S["expression"], + E extends Exclude< + D["expression"] & S["expression"], + SvelteFunctionBindingsExpression + >, >( node: D & { expression: null | E }, directive: S, @@ -878,7 +919,7 @@ function processDirectiveKey< function processDirectiveExpression< D extends SvAST.Directive | StandardDirective, S extends SvelteDirective, - E extends D["expression"], + E extends Exclude, >( node: D & { expression: null | E }, directive: S, @@ -901,7 +942,12 @@ function processDirectiveExpression< } if (processors.processExpression) { processors.processExpression(node.expression, shorthand).push((es) => { - if (node.expression && es.type !== node.expression.type) { + if ( + node.expression && + ((es.type as string) === "SvelteFunctionBindingsExpression" + ? "SequenceExpression" + : es.type) !== node.expression.type + ) { throw new ParseError( `Expected ${node.expression.type}, but ${es.type} found.`, es.range![0], diff --git a/src/visitor-keys.ts b/src/visitor-keys.ts index 47eb204d..f9a2e0e2 100644 --- a/src/visitor-keys.ts +++ b/src/visitor-keys.ts @@ -51,6 +51,7 @@ const svelteKeys: SvelteKeysType = { SvelteText: [], SvelteHTMLComment: [], SvelteReactiveStatement: ["label", "body"], + SvelteFunctionBindingsExpression: ["expressions"], }; export const KEYS: SourceCode.VisitorKeys = unionWith( diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-input.svelte b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-input.svelte new file mode 100644 index 00000000..a0e82ddc --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-input.svelte @@ -0,0 +1,4 @@ + value, + (v) => value = v.toLowerCase()} +/> diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-no-undef-result.json b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-no-undef-result.json new file mode 100644 index 00000000..6d8ca1e5 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-no-undef-result.json @@ -0,0 +1,14 @@ +[ + { + "ruleId": "no-undef", + "code": "value", + "line": 2, + "column": 8 + }, + { + "ruleId": "no-undef", + "code": "value", + "line": 3, + "column": 9 + } +] \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-output.json b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-output.json new file mode 100644 index 00000000..d9067288 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-output.json @@ -0,0 +1,814 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "html", + "name": { + "type": "SvelteName", + "name": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteDirective", + "kind": "Binding", + "key": { + "type": "SvelteDirectiveKey", + "name": { + "type": "SvelteName", + "name": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "modifiers": [], + "range": [ + 7, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "expression": { + "type": "SvelteFunctionBindingsExpression", + "expressions": [ + { + "type": "ArrowFunctionExpression", + "async": false, + "body": { + "type": "Identifier", + "name": "value", + "range": [ + 27, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + "expression": true, + "generator": false, + "id": null, + "params": [], + "range": [ + 21, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + { + "type": "ArrowFunctionExpression", + "async": false, + "body": { + "type": "AssignmentExpression", + "left": { + "type": "Identifier", + "name": "value", + "range": [ + 42, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + } + }, + "operator": "=", + "right": { + "type": "CallExpression", + "arguments": [], + "callee": { + "type": "MemberExpression", + "computed": false, + "object": { + "type": "Identifier", + "name": "v", + "range": [ + 50, + 51 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 17 + } + } + }, + "optional": false, + "property": { + "type": "Identifier", + "name": "toLowerCase", + "range": [ + 52, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 18 + }, + "end": { + "line": 3, + "column": 29 + } + } + }, + "range": [ + 50, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 29 + } + } + }, + "optional": false, + "range": [ + 50, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 31 + } + } + }, + "range": [ + 42, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 31 + } + } + }, + "expression": true, + "generator": false, + "id": null, + "params": [ + { + "type": "Identifier", + "name": "v", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + } + } + ], + "range": [ + 35, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 31 + } + } + } + ], + "range": [ + 21, + 65 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 3, + "column": 31 + } + } + }, + "shorthand": false, + "range": [ + 7, + 66 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 3, + "column": 32 + } + } + } + ], + "selfClosing": true, + "range": [ + 0, + 69 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 2 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 0, + 69 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 2 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "bind", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 2 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 3 + } + } + }, + { + "type": "Punctuator", + "value": "=>", + "range": [ + 24, + 26 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 6 + } + } + }, + { + "type": "Identifier", + "value": "value", + "range": [ + 27, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + { + "type": "Punctuator", + "value": ",", + "range": [ + 32, + 33 + ], + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 13 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 2 + } + } + }, + { + "type": "Identifier", + "value": "v", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 37, + 38 + ], + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 4 + } + } + }, + { + "type": "Punctuator", + "value": "=>", + "range": [ + 39, + 41 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 7 + } + } + }, + { + "type": "Identifier", + "value": "value", + "range": [ + 42, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 48, + 49 + ], + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 15 + } + } + }, + { + "type": "Identifier", + "value": "v", + "range": [ + 50, + 51 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": ".", + "range": [ + 51, + 52 + ], + "loc": { + "start": { + "line": 3, + "column": 17 + }, + "end": { + "line": 3, + "column": 18 + } + } + }, + { + "type": "Identifier", + "value": "toLowerCase", + "range": [ + 52, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 18 + }, + "end": { + "line": 3, + "column": 29 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 63, + 64 + ], + "loc": { + "start": { + "line": 3, + "column": 29 + }, + "end": { + "line": 3, + "column": 30 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 64, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 30 + }, + "end": { + "line": 3, + "column": 31 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 65, + 66 + ], + "loc": { + "start": { + "line": 3, + "column": 31 + }, + "end": { + "line": 3, + "column": 32 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 67, + 68 + ], + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 4, + "column": 1 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 68, + 69 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 2 + } + } + } + ], + "range": [ + 0, + 70 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-scope-output.json b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-scope-output.json new file mode 100644 index 00000000..3216468e --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/01-scope-output.json @@ -0,0 +1,561 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [], + "childScopes": [ + { + "type": "function", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 27, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 27, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + "from": "function", + "init": null, + "resolved": null + } + ] + }, + { + "type": "function", + "variables": [ + { + "name": "v", + "identifiers": [ + { + "type": "Identifier", + "name": "v", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + } + } + ], + "defs": [ + { + "type": "Parameter", + "name": { + "type": "Identifier", + "name": "v", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + } + }, + "node": { + "type": "ArrowFunctionExpression", + "async": false, + "body": { + "type": "AssignmentExpression", + "left": { + "type": "Identifier", + "name": "value", + "range": [ + 42, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + } + }, + "operator": "=", + "right": { + "type": "CallExpression", + "arguments": [], + "callee": { + "type": "MemberExpression", + "computed": false, + "object": { + "type": "Identifier", + "name": "v", + "range": [ + 50, + 51 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 17 + } + } + }, + "optional": false, + "property": { + "type": "Identifier", + "name": "toLowerCase", + "range": [ + 52, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 18 + }, + "end": { + "line": 3, + "column": 29 + } + } + }, + "range": [ + 50, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 29 + } + } + }, + "optional": false, + "range": [ + 50, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 31 + } + } + }, + "range": [ + 42, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 31 + } + } + }, + "expression": true, + "generator": false, + "id": null, + "params": [ + { + "type": "Identifier", + "name": "v", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + } + } + ], + "range": [ + 35, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 31 + } + } + } + } + ], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "v", + "range": [ + 50, + 51 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 17 + } + } + }, + "from": "function", + "init": null, + "resolved": { + "type": "Identifier", + "name": "v", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + } + } + } + ] + } + ], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 42, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + } + }, + "from": "function", + "init": false, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "v", + "range": [ + 50, + 51 + ], + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 17 + } + } + }, + "from": "function", + "init": null, + "resolved": { + "type": "Identifier", + "name": "v", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + } + } + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 42, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + } + }, + "from": "function", + "init": false, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 27, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + "from": "function", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 42, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + } + }, + "from": "function", + "init": false, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 27, + 32 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + "from": "function", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "value", + "range": [ + 42, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 13 + } + } + }, + "from": "function", + "init": false, + "resolved": null + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-input.svelte b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-input.svelte new file mode 100644 index 00000000..d8b9e668 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-input.svelte @@ -0,0 +1,4 @@ +
...
diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-no-undef-result.json b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-no-undef-result.json new file mode 100644 index 00000000..042d4002 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-no-undef-result.json @@ -0,0 +1,14 @@ +[ + { + "ruleId": "no-undef", + "code": "redraw", + "line": 2, + "column": 26 + }, + { + "ruleId": "no-undef", + "code": "redraw", + "line": 3, + "column": 27 + } +] \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-output.json b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-output.json new file mode 100644 index 00000000..c0d69be3 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-output.json @@ -0,0 +1,806 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "html", + "name": { + "type": "SvelteName", + "name": "div", + "range": [ + 1, + 4 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 4 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteDirective", + "kind": "Binding", + "key": { + "type": "SvelteDirectiveKey", + "name": { + "type": "SvelteName", + "name": "clientWidth", + "range": [ + 11, + 22 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 17 + } + } + }, + "modifiers": [], + "range": [ + 6, + 22 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 17 + } + } + }, + "expression": { + "type": "SvelteFunctionBindingsExpression", + "expressions": [ + { + "type": "Literal", + "raw": "null", + "value": null, + "range": [ + 24, + 28 + ], + "loc": { + "start": { + "line": 2, + "column": 19 + }, + "end": { + "line": 2, + "column": 23 + } + } + }, + { + "type": "Identifier", + "name": "redraw", + "range": [ + 30, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 25 + }, + "end": { + "line": 2, + "column": 31 + } + } + } + ], + "range": [ + 24, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 19 + }, + "end": { + "line": 2, + "column": 31 + } + } + }, + "shorthand": false, + "range": [ + 6, + 37 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 32 + } + } + }, + { + "type": "SvelteDirective", + "kind": "Binding", + "key": { + "type": "SvelteDirectiveKey", + "name": { + "type": "SvelteName", + "name": "clientHeight", + "range": [ + 44, + 56 + ], + "loc": { + "start": { + "line": 3, + "column": 6 + }, + "end": { + "line": 3, + "column": 18 + } + } + }, + "modifiers": [], + "range": [ + 39, + 56 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 18 + } + } + }, + "expression": { + "type": "SvelteFunctionBindingsExpression", + "expressions": [ + { + "type": "Literal", + "raw": "null", + "value": null, + "range": [ + 58, + 62 + ], + "loc": { + "start": { + "line": 3, + "column": 20 + }, + "end": { + "line": 3, + "column": 24 + } + } + }, + { + "type": "Identifier", + "name": "redraw", + "range": [ + 64, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 32 + } + } + } + ], + "range": [ + 58, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 20 + }, + "end": { + "line": 3, + "column": 32 + } + } + }, + "shorthand": false, + "range": [ + 39, + 71 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 33 + } + } + } + ], + "selfClosing": false, + "range": [ + 0, + 73 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 1 + } + } + }, + "children": [ + { + "type": "SvelteText", + "value": "...", + "range": [ + 73, + 76 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 4 + } + } + } + ], + "endTag": { + "type": "SvelteEndTag", + "range": [ + 76, + 82 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 10 + } + } + }, + "range": [ + 0, + 82 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 4, + "column": 10 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "div", + "range": [ + 1, + 4 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 4 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "bind", + "range": [ + 6, + 10 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 10, + 11 + ], + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "clientWidth", + "range": [ + 11, + 22 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 2, + "column": 18 + }, + "end": { + "line": 2, + "column": 19 + } + } + }, + { + "type": "Null", + "value": "null", + "range": [ + 24, + 28 + ], + "loc": { + "start": { + "line": 2, + "column": 19 + }, + "end": { + "line": 2, + "column": 23 + } + } + }, + { + "type": "Punctuator", + "value": ",", + "range": [ + 28, + 29 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 2, + "column": 24 + } + } + }, + { + "type": "Identifier", + "value": "redraw", + "range": [ + 30, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 25 + }, + "end": { + "line": 2, + "column": 31 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 2, + "column": 31 + }, + "end": { + "line": 2, + "column": 32 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "bind", + "range": [ + 39, + 43 + ], + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 43, + 44 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "clientHeight", + "range": [ + 44, + 56 + ], + "loc": { + "start": { + "line": 3, + "column": 6 + }, + "end": { + "line": 3, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 56, + 57 + ], + "loc": { + "start": { + "line": 3, + "column": 18 + }, + "end": { + "line": 3, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 57, + 58 + ], + "loc": { + "start": { + "line": 3, + "column": 19 + }, + "end": { + "line": 3, + "column": 20 + } + } + }, + { + "type": "Null", + "value": "null", + "range": [ + 58, + 62 + ], + "loc": { + "start": { + "line": 3, + "column": 20 + }, + "end": { + "line": 3, + "column": 24 + } + } + }, + { + "type": "Punctuator", + "value": ",", + "range": [ + 62, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 24 + }, + "end": { + "line": 3, + "column": 25 + } + } + }, + { + "type": "Identifier", + "value": "redraw", + "range": [ + 64, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 32 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 70, + 71 + ], + "loc": { + "start": { + "line": 3, + "column": 32 + }, + "end": { + "line": 3, + "column": 33 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 72, + 73 + ], + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 4, + "column": 1 + } + } + }, + { + "type": "HTMLText", + "value": "...", + "range": [ + 73, + 76 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 4 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 76, + 77 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 77, + 78 + ], + "loc": { + "start": { + "line": 4, + "column": 5 + }, + "end": { + "line": 4, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "div", + "range": [ + 78, + 81 + ], + "loc": { + "start": { + "line": 4, + "column": 6 + }, + "end": { + "line": 4, + "column": 9 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 81, + 82 + ], + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 4, + "column": 10 + } + } + } + ], + "range": [ + 0, + 83 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-scope-output.json b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-scope-output.json new file mode 100644 index 00000000..8e4ea3d1 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/docs/template-syntax/11-bind/function-bindings/02-scope-output.json @@ -0,0 +1,217 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "redraw", + "range": [ + 30, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 25 + }, + "end": { + "line": 2, + "column": 31 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "redraw", + "range": [ + 64, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 32 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "redraw", + "range": [ + 30, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 25 + }, + "end": { + "line": 2, + "column": 31 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "redraw", + "range": [ + 64, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 32 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "redraw", + "range": [ + 30, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 25 + }, + "end": { + "line": 2, + "column": 31 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "redraw", + "range": [ + 64, + 70 + ], + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 32 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-input.svelte b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-input.svelte new file mode 100644 index 00000000..b73856d6 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-input.svelte @@ -0,0 +1,6 @@ + diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-no-undef-result.json b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-no-undef-result.json new file mode 100644 index 00000000..8e8705e4 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-no-undef-result.json @@ -0,0 +1,14 @@ +[ + { + "ruleId": "no-undef", + "code": "x", + "line": 3, + "column": 5 + }, + { + "ruleId": "no-undef", + "code": "y", + "line": 5, + "column": 5 + } +] \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-output.json b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-output.json new file mode 100644 index 00000000..700cfdc0 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-output.json @@ -0,0 +1,462 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "html", + "name": { + "type": "SvelteName", + "name": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteDirective", + "kind": "Binding", + "key": { + "type": "SvelteDirectiveKey", + "name": { + "type": "SvelteName", + "name": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "modifiers": [], + "range": [ + 7, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "expression": { + "type": "SvelteFunctionBindingsExpression", + "expressions": [ + { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + { + "type": "Identifier", + "name": "y", + "range": [ + 61, + 62 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + } + ], + "range": [ + 39, + 62 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "shorthand": false, + "range": [ + 7, + 64 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 6, + "column": 1 + } + } + } + ], + "selfClosing": true, + "range": [ + 0, + 66 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 3 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 0, + 66 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 3 + } + } + } + ], + "sourceType": "module", + "comments": [ + { + "type": "Block", + "value": "* Foo ", + "range": [ + 24, + 34 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 14 + } + } + }, + { + "type": "Block", + "value": "* Bar ", + "range": [ + 46, + 56 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 14 + } + } + } + ], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "bind", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "Identifier", + "value": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": ",", + "range": [ + 40, + 41 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + { + "type": "Identifier", + "value": "y", + "range": [ + 61, + 62 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 63, + 64 + ], + "loc": { + "start": { + "line": 6, + "column": 0 + }, + "end": { + "line": 6, + "column": 1 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 64, + 65 + ], + "loc": { + "start": { + "line": 6, + "column": 1 + }, + "end": { + "line": 6, + "column": 2 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 65, + 66 + ], + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 3 + } + } + } + ], + "range": [ + 0, + 67 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 7, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-scope-output.json b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-scope-output.json new file mode 100644 index 00000000..027d29e9 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment01-scope-output.json @@ -0,0 +1,217 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 61, + 62 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 61, + 62 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 61, + 62 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-input.svelte b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-input.svelte new file mode 100644 index 00000000..314d1cb6 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-input.svelte @@ -0,0 +1,6 @@ + diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-no-undef-result.json b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-no-undef-result.json new file mode 100644 index 00000000..8e8705e4 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-no-undef-result.json @@ -0,0 +1,14 @@ +[ + { + "ruleId": "no-undef", + "code": "x", + "line": 3, + "column": 5 + }, + { + "ruleId": "no-undef", + "code": "y", + "line": 5, + "column": 5 + } +] \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-output.json b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-output.json new file mode 100644 index 00000000..e254112b --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-output.json @@ -0,0 +1,462 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "html", + "name": { + "type": "SvelteName", + "name": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteDirective", + "kind": "Binding", + "key": { + "type": "SvelteDirectiveKey", + "name": { + "type": "SvelteName", + "name": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "modifiers": [], + "range": [ + 7, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "expression": { + "type": "SvelteFunctionBindingsExpression", + "expressions": [ + { + "type": "Identifier", + "name": "x", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + { + "type": "Identifier", + "name": "y", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + } + ], + "range": [ + 35, + 54 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "shorthand": false, + "range": [ + 7, + 56 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 6, + "column": 1 + } + } + } + ], + "selfClosing": true, + "range": [ + 0, + 58 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 3 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 0, + 58 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 3 + } + } + } + ], + "sourceType": "module", + "comments": [ + { + "type": "Line", + "value": " Foo", + "range": [ + 24, + 30 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 10 + } + } + }, + { + "type": "Line", + "value": " Bar", + "range": [ + 42, + 48 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 10 + } + } + } + ], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "bind", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "Identifier", + "value": "x", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": ",", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + { + "type": "Identifier", + "value": "y", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 55, + 56 + ], + "loc": { + "start": { + "line": 6, + "column": 0 + }, + "end": { + "line": 6, + "column": 1 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 56, + 57 + ], + "loc": { + "start": { + "line": 6, + "column": 1 + }, + "end": { + "line": 6, + "column": 2 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 57, + 58 + ], + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 3 + } + } + } + ], + "range": [ + 0, + 59 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 7, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-scope-output.json b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-scope-output.json new file mode 100644 index 00000000..4cff688f --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/function-binding-with-comment02-scope-output.json @@ -0,0 +1,217 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding01-input.svelte b/tests/fixtures/parser/ast/svelte5/non-function-binding01-input.svelte new file mode 100644 index 00000000..c447b449 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding01-input.svelte @@ -0,0 +1 @@ + diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding01-no-undef-result.json b/tests/fixtures/parser/ast/svelte5/non-function-binding01-no-undef-result.json new file mode 100644 index 00000000..e1335012 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding01-no-undef-result.json @@ -0,0 +1,14 @@ +[ + { + "ruleId": "no-undef", + "code": "x", + "line": 1, + "column": 21 + }, + { + "ruleId": "no-undef", + "code": "y", + "line": 1, + "column": 24 + } +] \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding01-output.json b/tests/fixtures/parser/ast/svelte5/non-function-binding01-output.json new file mode 100644 index 00000000..c8bcd970 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding01-output.json @@ -0,0 +1,461 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "html", + "name": { + "type": "SvelteName", + "name": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteDirective", + "kind": "Binding", + "key": { + "type": "SvelteDirectiveKey", + "name": { + "type": "SvelteName", + "name": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "modifiers": [], + "range": [ + 7, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "expression": { + "type": "SequenceExpression", + "expressions": [ + { + "type": "Identifier", + "name": "x", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "Identifier", + "name": "y", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 24 + } + } + } + ], + "range": [ + 20, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 24 + } + } + }, + "shorthand": false, + "range": [ + 7, + 26 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 26 + } + } + } + ], + "selfClosing": true, + "range": [ + 0, + 28 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 0, + 28 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "bind", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 19, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 20 + } + } + }, + { + "type": "Identifier", + "value": "x", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "Punctuator", + "value": ",", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 22 + } + } + }, + { + "type": "Identifier", + "value": "y", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 24 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 24, + 25 + ], + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 25 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 25, + 26 + ], + "loc": { + "start": { + "line": 1, + "column": 25 + }, + "end": { + "line": 1, + "column": 26 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 26, + 27 + ], + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 27 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 27, + 28 + ], + "loc": { + "start": { + "line": 1, + "column": 27 + }, + "end": { + "line": 1, + "column": 28 + } + } + } + ], + "range": [ + 0, + 29 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding01-scope-output.json b/tests/fixtures/parser/ast/svelte5/non-function-binding01-scope-output.json new file mode 100644 index 00000000..0ff50376 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding01-scope-output.json @@ -0,0 +1,217 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 24 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 24 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 24 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding02-input.svelte b/tests/fixtures/parser/ast/svelte5/non-function-binding02-input.svelte new file mode 100644 index 00000000..2ac2211e --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding02-input.svelte @@ -0,0 +1,5 @@ + diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding02-no-undef-result.json b/tests/fixtures/parser/ast/svelte5/non-function-binding02-no-undef-result.json new file mode 100644 index 00000000..bdfdff79 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding02-no-undef-result.json @@ -0,0 +1,14 @@ +[ + { + "ruleId": "no-undef", + "code": "x", + "line": 3, + "column": 6 + }, + { + "ruleId": "no-undef", + "code": "y", + "line": 4, + "column": 5 + } +] \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding02-output.json b/tests/fixtures/parser/ast/svelte5/non-function-binding02-output.json new file mode 100644 index 00000000..31144756 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding02-output.json @@ -0,0 +1,480 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteElement", + "kind": "html", + "name": { + "type": "SvelteName", + "name": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteDirective", + "kind": "Binding", + "key": { + "type": "SvelteDirectiveKey", + "name": { + "type": "SvelteName", + "name": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "modifiers": [], + "range": [ + 7, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "expression": { + "type": "SequenceExpression", + "expressions": [ + { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + { + "type": "Identifier", + "name": "y", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + } + } + ], + "range": [ + 39, + 47 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 4, + "column": 5 + } + } + }, + "shorthand": false, + "range": [ + 7, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 5, + "column": 5 + } + } + } + ], + "selfClosing": true, + "range": [ + 0, + 56 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 7 + } + } + }, + "children": [], + "endTag": null, + "range": [ + 0, + 56 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 7 + } + } + } + ], + "sourceType": "module", + "comments": [ + { + "type": "Block", + "value": " Foo ", + "range": [ + 24, + 33 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 13 + } + } + } + ], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "input", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "bind", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": ":", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "value", + "range": [ + 12, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": "{", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 38, + 39 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 5 + } + } + }, + { + "type": "Identifier", + "value": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + { + "type": "Punctuator", + "value": ",", + "range": [ + 40, + 41 + ], + "loc": { + "start": { + "line": 3, + "column": 6 + }, + "end": { + "line": 3, + "column": 7 + } + } + }, + { + "type": "Identifier", + "value": "y", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 47, + 48 + ], + "loc": { + "start": { + "line": 4, + "column": 5 + }, + "end": { + "line": 4, + "column": 6 + } + } + }, + { + "type": "Punctuator", + "value": "}", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 54, + 55 + ], + "loc": { + "start": { + "line": 5, + "column": 5 + }, + "end": { + "line": 5, + "column": 6 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 55, + 56 + ], + "loc": { + "start": { + "line": 5, + "column": 6 + }, + "end": { + "line": 5, + "column": 7 + } + } + } + ], + "range": [ + 0, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/svelte5/non-function-binding02-scope-output.json b/tests/fixtures/parser/ast/svelte5/non-function-binding02-scope-output.json new file mode 100644 index 00000000..3026bffa --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/non-function-binding02-scope-output.json @@ -0,0 +1,217 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$state", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$derived", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$effect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$bindable", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$inspect", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$host", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ], + "childScopes": [], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] + } + ], + "through": [ + { + "identifier": { + "type": "Identifier", + "name": "x", + "range": [ + 39, + 40 + ], + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + } + }, + "from": "module", + "init": null, + "resolved": null + }, + { + "identifier": { + "type": "Identifier", + "name": "y", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + } + }, + "from": "module", + "init": null, + "resolved": null + } + ] +} \ No newline at end of file diff --git a/tests/src/parser/eslint-rules.ts b/tests/src/parser/eslint-rules.ts index 742d5d48..a437059c 100644 --- a/tests/src/parser/eslint-rules.ts +++ b/tests/src/parser/eslint-rules.ts @@ -2,12 +2,12 @@ import { Linter } from "eslint"; import assert from "assert"; import fs from "fs"; import globals from "globals"; -import * as parser from "../../../src/index"; +import * as parser from "../../../src/index.js"; import { generateParserOptions, getMessageData, listupFixtures, -} from "./test-utils"; +} from "./test-utils.js"; //------------------------------------------------------------------------------ // Tests @@ -26,6 +26,7 @@ const RULES = [ "spaced-comment", "no-redeclare", "template-curly-spacing", + "no-sequences", ]; describe("svelte-eslint-parser with ESLint rules", () => { diff --git a/tools/update-fixtures.ts b/tools/update-fixtures.ts index 64a13fb3..84bd0056 100644 --- a/tools/update-fixtures.ts +++ b/tools/update-fixtures.ts @@ -57,6 +57,7 @@ const RULES = [ "spaced-comment", "no-redeclare", "template-curly-spacing", + "no-sequences", ]; /**