Skip to content

Svelte <script> function/call symbols never extracted — component call-graph is empty (imports work per #223, calls don't; Svelte analog of #1410) #1807

Closed

Description

@lcclcoder

Summary

For .svelte components, the <script>/<script lang="ts"> block is parsed structurally but its function definitions and call sites are never emitted as graph symbols. Each component yields only File + Module nodes. Imports are extracted (thanks to #223/#224) and SvelteKit routes too (#369), but the call graph inside components is absent.

This is the Svelte analog of #1410 (Vue <script setup>), with the same consequence: incomplete call graph and false-positive dead-code for component logic.

Environment

  • v0.10.8, macOS arm64 (darwin), npm install
  • tree-sitter Svelte grammar present (parses script_element)

Repro

  1. Index any repo containing a .svelte component whose <script lang="ts"> defines named functions (e.g. function toggleOpen() {…}).
  2. Query the graph:
    query_graph  MATCH (f:Function) WHERE f.file_path ENDS WITH '.svelte' RETURN count(*)
    query_graph  MATCH (n) WHERE n.file_path ENDS WITH '.svelte' RETURN n.name, labels(n)
    

Observed

Real-world index (a SvelteKit app, 294 components): 294/294 components have File+Module nodes and import edges, but zero <script>-internal function or call symbols.

Expected

<script> bodies re-parsed as JS/TS (language injection on script_element → TS grammar), with normal symbol + CALLS/DEFINES extraction and line offsets mapped back to the component — matching what already happens for a .ts file.

Evidence that injection is sufficient

Extracting a component's <script> verbatim into a sibling .ts file makes the same functions appear as full Function nodes with call edges:

Source Function nodes emitted
TreeNode.svelte (toggleOpen, transformDataForRecursiveTree in <script>) 0
identical body extracted to TreeNode.script.ts 2 (both, with edges)

So the grammar + extractor already handle the code — only the injection step from script_element into TS symbol/call extraction is missing (the imports path added in #223 is the precedent).

Activity

  1. DeusData commented on Aug 26, 2026

    @DeusData
    Owner

    Thank you for this — it is an unusually complete first report, and the A/B table is what makes it immediately actionable. Showing the same code producing two Function nodes as .ts and zero inside a .svelte <script> block isolates the problem exactly, with no guesswork left for us.

    You have diagnosed it correctly. Imports work because that path already handles the component wrapper (#223/#224), but the <script> block's contents are never handed to the TypeScript extractor, so no function or call symbols come out of it. The component call-graph is empty for precisely that reason.

    This is the same root cause as #1410, which reports it for Vue's <script setup>. Both need the same fix — injecting the embedded script region into the TS extractor rather than treating the component file as opaque past its imports — so I am linking them and they should be fixed together rather than separately. Your report and that one arrived from different angles at the same missing piece, which is good corroboration that it is worth doing properly rather than patching per-framework.

    No action needed from you. I will update both issues when the work is scheduled.

    One small note, purely so it does not surprise you: this issue briefly tripped our automated content screening, because the title contains <script> and a title cannot be code-formatted on GitHub. That was a false positive on our side and it has been fixed — the scanner now recognises a bare tag name in a title as inert. Nothing was wrong with how you wrote it, and it is a good illustration of why a tool that parses markup languages needs its own tooling to expect markup in bug reports.

    Thanks again for taking the time to build the repro.

  2. added
    bugSomething isn't working
    priority/normalStandard review queue; useful PR with ordinary maintainer urgency.
    on Aug 26, 2026
  3. DeusData commented on Aug 27, 2026

    @DeusData
    Owner

    Update, and a correction to what I told you earlier.

    I said #1410 and this issue "should be fixed together rather than separately". The Vue half has now landed on main in e678722 (#1852) — and it does not fix Svelte. I want to be straight about that rather than let you find it out from a release note.

    What that change actually built is the shared machinery, which is the part that was worth doing properly: it parses the embedded <script> region through ts_parser_set_included_ranges against the original buffer, so definitions and calls come out with correct byte and point coordinates (a naive re-slice gets both subtly wrong across CRLF and BOM), and it resolves lang="ts" / lang="js" and bails on src=. Svelte, HTML and Astro already declare the identical embedded-block spec, so the seam now works for them too — what is still switched off is structural extraction, which is gated on one boolean.

    Being fully honest about the current state: that change ships a control test asserting Svelte, HTML and Astro still produce zero functions and zero calls. That is your bug, pinned as expected behaviour. It is there so the follow-up has something to flip, not because we think it is correct — but you should know it is written down that way today.

    The follow-up is under way. @bmcnaboe proposed the generalization on #1410 independently and has a 212-SFC corpus to validate it against, so I have asked them to carry it and given them the remaining detail. I have not put a deadline on them, so I cannot give you a firm date. What I can commit to is this: I will report back here either way rather than leave it open-ended, and if it stalls we will land it ourselves.

    Your A/B table is still the thing that made this actionable, and the fix that lands will be verified by flipping that control test to assert exactly what your report says should happen. Thank you for the patience.

  4. bmcnaboe commented on Sep 4, 2026

    @bmcnaboe
    Contributor

    The generalization is up as #2056 — Svelte, HTML and Astro <script> blocks (and Astro's frontmatter fence) now extract definitions and calls in file coordinates, and the control test from #1852 is flipped to assert exactly the symbols your A/B table shows. Validated against the Vue corpus with identical results before and after. Thanks for the report; the two-row table is what made it precise.

  5. added
    priority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.
    and removed
    priority/normalStandard review queue; useful PR with ordinary maintainer urgency.
    on Sep 5, 2026
  6. DeusData commented on Sep 6, 2026

    @DeusData
    Owner

    Fixed on main by 2b030a5 (#2056, thanks to @bmcnaboe): structure inside Svelte, HTML and Astro inline scripts is now extracted.

  7. added a commit that references this issue on Sep 6, 2026
    24f54c0
  8. added a commit that references this issue on Sep 29, 2026
    26d05b7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions