From 9ecc8bec82feac7191a7394b031655acabb17518 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 12 Jan 2025 13:34:06 +0900 Subject: [PATCH 1/3] try to fix --- src/parser/index.ts | 18 +--- src/parser/svelte-parse-context.ts | 96 ++++++++++++------- .../svelte-options01-input.svelte | 0 .../svelte-options01-output.json | 0 .../svelte-options01-scope-output.json | 0 .../svelte-options02-input.svelte | 0 .../svelte-options02-output.json | 0 .../svelte-options02-scope-output.json | 0 .../svelte5/svelte-options/svelte.config.js | 2 + 9 files changed, 70 insertions(+), 46 deletions(-) rename tests/fixtures/parser/ast/svelte5/{ => svelte-options}/svelte-options01-input.svelte (100%) rename tests/fixtures/parser/ast/svelte5/{ => svelte-options}/svelte-options01-output.json (100%) rename tests/fixtures/parser/ast/svelte5/{ => svelte-options}/svelte-options01-scope-output.json (100%) rename tests/fixtures/parser/ast/svelte5/{ => svelte-options}/svelte-options02-input.svelte (100%) rename tests/fixtures/parser/ast/svelte5/{ => svelte-options}/svelte-options02-output.json (100%) rename tests/fixtures/parser/ast/svelte5/{ => svelte-options}/svelte-options02-scope-output.json (100%) create mode 100644 tests/fixtures/parser/ast/svelte5/svelte-options/svelte.config.js diff --git a/src/parser/index.ts b/src/parser/index.ts index f7ad5aa8..877b1a64 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -50,7 +50,6 @@ import type { NormalizedParserOptions } from "./parser-options.js"; import { isTypeScript, normalizeParserOptions } from "./parser-options.js"; import { getFragmentFromRoot } from "./compat.js"; import { - isEnableRunes, resolveSvelteParseContextForSvelte, resolveSvelteParseContextForSvelteScript, type SvelteParseContext, @@ -117,20 +116,13 @@ export function parseForESLint(code: string, options?: any): ParseResult { const parserOptions = normalizeParserOptions(options); if ( - isEnableRunes(svelteConfig, parserOptions) && parserOptions.filePath && - !parserOptions.filePath.endsWith(".svelte") && - // If no `filePath` is set in ESLint, "" will be specified. - parserOptions.filePath !== "" + (parserOptions.filePath.endsWith(".svelte.js") || + parserOptions.filePath.endsWith(".svelte.ts")) ) { - const trimmed = code.trim(); - if (!trimmed.startsWith("<") && !trimmed.endsWith(">")) { - const svelteParseContext = resolveSvelteParseContextForSvelteScript( - svelteConfig, - parserOptions, - ); - return parseAsScript(code, parserOptions, svelteParseContext); - } + const svelteParseContext = + resolveSvelteParseContextForSvelteScript(svelteConfig); + return parseAsScript(code, parserOptions, svelteParseContext); } return parseAsSvelte(code, svelteConfig, parserOptions); diff --git a/src/parser/svelte-parse-context.ts b/src/parser/svelte-parse-context.ts index d28799eb..dc1d8d3f 100644 --- a/src/parser/svelte-parse-context.ts +++ b/src/parser/svelte-parse-context.ts @@ -1,8 +1,20 @@ import type * as Compiler from "./svelte-ast-types-for-v5.js"; import type * as SvAST from "./svelte-ast-types.js"; +import type * as ESTree from "estree"; import type { NormalizedParserOptions } from "./parser-options.js"; import { compilerVersion, svelteVersion } from "./svelte-version.js"; import type { SvelteConfig } from "../svelte-config/index.js"; +import { traverseNodes } from "../traverse.js"; + +const runeSymbols: string[] = [ + "$state", + "$derived", + "$effect", + "$props", + "$bindable", + "$inspect", + "$host", +] as const; /** The context for parsing. */ export type SvelteParseContext = { @@ -18,36 +30,13 @@ export type SvelteParseContext = { svelteConfig: SvelteConfig | null; }; -export function isEnableRunes( - svelteConfig: SvelteConfig | null, - parserOptions: NormalizedParserOptions, -): boolean { - if (!svelteVersion.gte(5)) return false; - if (parserOptions.svelteFeatures?.runes != null) { - return Boolean(parserOptions.svelteFeatures.runes); - } - if (svelteConfig?.compilerOptions?.runes != null) { - return Boolean(svelteConfig.compilerOptions.runes); - } - return true; -} - export function resolveSvelteParseContextForSvelte( svelteConfig: SvelteConfig | null, parserOptions: NormalizedParserOptions, svelteAst: Compiler.Root | SvAST.AstLegacy, ): SvelteParseContext { - const svelteOptions = (svelteAst as Compiler.Root).options; - if (svelteOptions?.runes != null) { - return { - runes: svelteOptions.runes, - compilerVersion, - svelteConfig, - }; - } - return { - runes: isEnableRunes(svelteConfig, parserOptions), + runes: isRunes(svelteConfig, parserOptions, svelteAst), compilerVersion, svelteConfig, }; @@ -55,18 +44,59 @@ export function resolveSvelteParseContextForSvelte( export function resolveSvelteParseContextForSvelteScript( svelteConfig: SvelteConfig | null, - parserOptions: NormalizedParserOptions, -): SvelteParseContext { - return resolveSvelteParseContext(svelteConfig, parserOptions); -} - -function resolveSvelteParseContext( - svelteConfig: SvelteConfig | null, - parserOptions: NormalizedParserOptions, ): SvelteParseContext { return { - runes: isEnableRunes(svelteConfig, parserOptions), + // .svelte.js files are always in Runes mode for Svelte 5. + runes: svelteVersion.gte(5), compilerVersion, svelteConfig, }; } + +function isRunes( + svelteConfig: SvelteConfig | null, + parserOptions: NormalizedParserOptions, + svelteAst: Compiler.Root | SvAST.AstLegacy, +): boolean { + // Svelte 3/4 does not support Runes mode. + if (!svelteVersion.gte(5)) { + return false; + } + + // Compiler option. + if (parserOptions.svelteFeatures?.runes != null) { + return parserOptions.svelteFeatures?.runes; + } + if (svelteConfig?.compilerOptions?.runes != null) { + return svelteConfig?.compilerOptions?.runes; + } + + // ``. + const svelteOptions = (svelteAst as Compiler.Root).options; + if (svelteOptions?.runes != null) { + return svelteOptions?.runes; + } + + // Static analysis. + const { module, instance } = svelteAst; + return ( + (module != null && hasRuneSymbol(module)) || + (instance != null && hasRuneSymbol(instance)) + ); +} + +function hasRuneSymbol(ast: Compiler.Script | SvAST.Script): boolean { + let hasRuneSymbol = false; + traverseNodes(ast as unknown as ESTree.Node, { + enterNode(node) { + if (node.type === "Identifier" && runeSymbols.includes(node.name)) { + hasRuneSymbol = true; + } + }, + leaveNode() { + // do nothing + }, + }); + + return hasRuneSymbol; +} diff --git a/tests/fixtures/parser/ast/svelte5/svelte-options01-input.svelte b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options01-input.svelte similarity index 100% rename from tests/fixtures/parser/ast/svelte5/svelte-options01-input.svelte rename to tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options01-input.svelte diff --git a/tests/fixtures/parser/ast/svelte5/svelte-options01-output.json b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options01-output.json similarity index 100% rename from tests/fixtures/parser/ast/svelte5/svelte-options01-output.json rename to tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options01-output.json diff --git a/tests/fixtures/parser/ast/svelte5/svelte-options01-scope-output.json b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options01-scope-output.json similarity index 100% rename from tests/fixtures/parser/ast/svelte5/svelte-options01-scope-output.json rename to tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options01-scope-output.json diff --git a/tests/fixtures/parser/ast/svelte5/svelte-options02-input.svelte b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options02-input.svelte similarity index 100% rename from tests/fixtures/parser/ast/svelte5/svelte-options02-input.svelte rename to tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options02-input.svelte diff --git a/tests/fixtures/parser/ast/svelte5/svelte-options02-output.json b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options02-output.json similarity index 100% rename from tests/fixtures/parser/ast/svelte5/svelte-options02-output.json rename to tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options02-output.json diff --git a/tests/fixtures/parser/ast/svelte5/svelte-options02-scope-output.json b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options02-scope-output.json similarity index 100% rename from tests/fixtures/parser/ast/svelte5/svelte-options02-scope-output.json rename to tests/fixtures/parser/ast/svelte5/svelte-options/svelte-options02-scope-output.json diff --git a/tests/fixtures/parser/ast/svelte5/svelte-options/svelte.config.js b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte.config.js new file mode 100644 index 00000000..cbc7a6c8 --- /dev/null +++ b/tests/fixtures/parser/ast/svelte5/svelte-options/svelte.config.js @@ -0,0 +1,2 @@ +/** Config for testing */ +export default {}; From 0e7282b5e5a1b3cb098a7ded2d420f48f273893b Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 12 Jan 2025 15:52:40 +0900 Subject: [PATCH 2/3] tidy --- src/parser/svelte-parse-context.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parser/svelte-parse-context.ts b/src/parser/svelte-parse-context.ts index dc1d8d3f..19871f00 100644 --- a/src/parser/svelte-parse-context.ts +++ b/src/parser/svelte-parse-context.ts @@ -89,6 +89,9 @@ function hasRuneSymbol(ast: Compiler.Script | SvAST.Script): boolean { let hasRuneSymbol = false; traverseNodes(ast as unknown as ESTree.Node, { enterNode(node) { + if (hasRuneSymbol) { + return; + } if (node.type === "Identifier" && runeSymbols.includes(node.name)) { hasRuneSymbol = true; } From 6de6d8d84e49ec49107f970bf09debf1b95f2830 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 12 Jan 2025 15:53:06 +0900 Subject: [PATCH 3/3] changeset --- .changeset/big-ligers-turn.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/big-ligers-turn.md diff --git a/.changeset/big-ligers-turn.md b/.changeset/big-ligers-turn.md new file mode 100644 index 00000000..48573e67 --- /dev/null +++ b/.changeset/big-ligers-turn.md @@ -0,0 +1,5 @@ +--- +"svelte-eslint-parser": patch +--- + +fix: assign actual `runes` value to `SvelteParseContext` pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy