Skip to content

feat(parsing): add Svelte parser#105

Open
antono wants to merge 4 commits into
bartolli:mainfrom
antono:svelte-support
Open

feat(parsing): add Svelte parser#105
antono wants to merge 4 commits into
bartolli:mainfrom
antono:svelte-support

Conversation

@antono
Copy link
Copy Markdown
Contributor

@antono antono commented May 21, 2026

Summary

  • Adds .svelte file support via a new SvelteParser that uses tree-sitter-svelte-next to locate <script> blocks and re-parses their content with the existing JavaScriptParser
  • All symbol ranges are offset back to file-level positions so line/column numbers refer to the .svelte file, not the script fragment
  • Svelte 5 {#snippet name(...)} blocks are detected directly in the Svelte AST and emitted as Function symbols
  • New crate: tree-sitter-svelte-next = "0.1.1"

Files changed

File Role
src/parsing/svelte/parser.rs Core parser — script extraction, range offsetting, snippet collection, all find_* delegation to JS sub-parser
src/parsing/svelte/behavior.rs LanguageBehavior — visibility via export, source roots for SvelteKit layout
src/parsing/svelte/definition.rs LanguageDefinition registration, is_enabled() config check
src/parsing/svelte/mod.rs Module re-exports + register()
src/parsing/language.rs Language::Svelte enum variant + extensions, config_key, name
src/parsing/mod.rs pub mod svelte + re-exports
src/parsing/registry.rs super::svelte::register(registry) in initialize_registry()
src/parsing/factory.rs Language::Svelte match arm in create_parser_with_behavior() and enabled_languages()

Design notes

Why re-parse with JavaScriptParser instead of walking the Svelte tree?
The tree-sitter-svelte-next grammar represents <script> content as an opaque raw_text node — there is no embedded JS/TS subtree. Re-parsing the raw text with JavaScriptParser reuses all existing JS symbol extraction, call/import/method-call logic, and future improvements for free.

Range offset: raw_text.start_position() gives the file-level row/column where the script begins. Every range produced by the JS sub-parser is shifted by this offset. Only the first line of a multi-line symbol gets the column offset applied (subsequent lines start at column 0 in the source).

Test results

Tested against 11 real .svelte files from two GitHub projects (svelte-realworld and svelte/examples). All files parsed with zero tree-sitter errors.

Assertions (all PASSED ✓)

=== Range offset verification ===
  [Function] 'hello' at file line 2  → expected 2 ✓
  [Variable] 'x'     at file line 3  → expected 3 ✓

=== Snippet detection verification ===
  Snippet 'greet' at file line 4     → expected 4 ✓

=== Counter.svelte function extraction ===
  [Function] 'increment' at file line 12  → expected 12 ✓
  [Function] 'decrement' at file line 17  → expected 17 ✓

Symbol extraction summary

File Extracted symbols
Nav.svelte 1 import ($app/state)
Pagination.svelte range (Constant), result (Constant), i (Variable)
+layout.svelte 4 imports
+page.svelte (realworld) 3 imports, 4 constants
Counter.svelte (svelte 5) 1 import, increment (Function), decrement (Function)
+page.svelte (todomvc) 6 imports, 15 variables/constants
+page.svelte (file-uploads) 7 imports, 7 variables/constants, handle_large_submit (Function)

Note on in-crate unit tests

src/parsing/svelte/parser.rs contains 5 unit tests (test_svelte_parser_loads, test_validate_grammar_node_kinds, test_parse_script_symbols, test_snippet_symbols, test_range_offset). These cannot run locally because sysinfo@0.39.2 (an existing dependency) requires rustc 1.95+, while the current Nix flake provides 1.94.0. The tests are expected to pass once the flake toolchain is updated.

- Add tree-sitter-svelte-next = "0.1.1" dependency
- New src/parsing/svelte/: SvelteParser, SvelteBehavior, SvelteLanguage
- SvelteParser re-parses <script> block via JavaScriptParser with line-offset correction
- Snippet functions ({#snippet name}) extracted from Svelte AST as Function symbols
- Language::Svelte wired into registry, factory, and extension detection (.svelte)
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

❌ Quick checks failure

@bartolli
Copy link
Copy Markdown
Owner

Hey @antono, thanks for tackling Svelte! A few things worth a second pass:

running nix flake update (or your local rustup) will bump to 1.95+ and unblock the 5 unit tests in parser.rs. Could you paste the passing cargo test output here just to confirm the offset math checks out?

resolution.rs: Delegating to JS makes sense, but since our standard pattern (Lua, Go, Python) ships the four-file set, could you either wrap JavaScriptResolutionContext in a SvelteResolutionContext, or just add a quick note in
mod.rs and the PR description so it doesn't look like a forgotten file?

audit pipeline: Every existing language ships src/parsing/<lang>/audit.rs plus a matching tests/exploration/abi15_grammar_audit/<lang>.rs, which generates the four artifacts under contributing/parsers/<lang>/ (node-types.json, node_discovery.txt, AUDIT_REPORT.md, GRAMMAR_ANALYSIS.md). The Nix PR follows this. could you wire the same for Svelte so we have an ABI coverage record before review?

since <script lang="ts"> is the default in Svelte 5, we should either support it now (re-parsing with TypeScriptParser), or explicitly scope this PR to JS-only and track TS support in a follow-up issue.

as you did with the Nix PR, let's add an examples/svelte/comprehensive.svelte file. Ideally, it should include imports, snippets, functions, $state / $derived, and both js/ts blocks to give the parser a proper stress test during review.

Thanks again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants