-
Notifications
You must be signed in to change notification settings - Fork 4.9k
feat(core): add Dart language support via workspace-vendored WASM#435
Open
thejesh23 wants to merge 18 commits into
Open
feat(core): add Dart language support via workspace-vendored WASM #435thejesh23 wants to merge 18 commits into
thejesh23 wants to merge 18 commits into
Conversation
Adds the brainstormed design for landing deep Dart support at parity with the recent Kotlin add (PR Egonex-AI#347): LanguageConfig + tree-sitter WASM grammar (tree-sitter-dart@1.0.0, verified ships a prebuilt .wasm in its tarball) + DartExtractor + ~22 vitest cases. Six file changes, no edits to shared schemas/registries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Live verification during planning surfaced two facts that change the shipping strategy: 1. tree-sitter-dart@1.0.0's prebuilt wasm uses the pre-`dylink.0` format and fails to load in web-tree-sitter@0.26.x (the version this project uses). Verified by directly loading the upstream wasm and catching the failure in getDylinkMetadata. 2. The grammar source itself is sound — rebuilding with the current tree-sitter-cli@0.26.x + wasi-sdk-29 toolchain produces a working dylink.0-format wasm that parses every construct the extractor needs. Revised packaging: ship the freshly-built wasm as a workspace-internal package (@understand-anything/tree-sitter-dart-wasm) rather than depending on the broken upstream npm artifact. No loader changes required; existing TreeSitterPlugin resolves it the same way it resolves other tree-sitter packages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Thirteen-task TDD plan walking from vendoring the workspace wasm package through scaffolding the extractor and adding extraction logic in test-first slices: functions, classes, constructors, mixins, extensions, enums, imports, exports, visibility, and call graph. Every code block reflects AST shapes confirmed via a live probe against a freshly-built tree-sitter-dart wasm in the project's own web-tree-sitter at 0.26.x. No placeholder code, no "fill in later" references. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The upstream tree-sitter-dart@1.0.0 ships a pre-`dylink.0` wasm that fails to load in web-tree-sitter@0.26.x. The grammar source itself is sound — rebuilding with the current tree-sitter-cli + wasi-sdk produces a working dylink.0 wasm. Vendor that artifact as a workspace-internal package so @understand-anything/core can depend on it via workspace:*. BUILD.md documents the provenance and rebuild instructions.
Adds the Dart language config and wires it into builtinLanguageConfigs so .dart files are recognized by the language registry. References the vendored @understand-anything/tree-sitter-dart-wasm package for grammar loading. No extractor yet — structural extraction lands in the next commit.
Empty extractor that satisfies the LanguageExtractor interface so the plugin pipeline can load it. Real extraction logic lands in subsequent TDD commits.
Add TDD tests and implement extractTopLevelFunction with helpers for extracting function name, params, and return type (including generics where the grammar emits type_identifier + type_arguments as siblings). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add constructorName() helper and extend collectClassBody() to surface unnamed constructors as "ClassName", named constructors as "Class.named", and factory named constructors as "Class.named" in methods[]/functions[]. Probe confirmed plan's AST shapes match exactly; extractReturnType returns undefined for all constructor forms (factory keyword is an unnamed node). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add mixin_declaration handling to extractStructure, folding mixins into classes[] (same convention as class_definition). The `on` constraint sibling is intentionally ignored for graph purposes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds enum_declaration handling to DartExtractor: enum constants are surfaced as properties[] so the structural graph captures Color.red / Color.green etc. Implements Task 9 of the Dart language support plan (TDD, 16/16 dart tests pass, full suite 708/708). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
...as) + export directives Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements extractCallGraph with a sibling-aware walk that pairs each function_signature with its subsequent function_body sibling (Dart's AST differs from Kotlin's: signature and body are siblings, not parent/child). Detects call sites via selector nodes containing argument_part; uses startIndex for sibling lookup (web-tree-sitter returns new wrapper objects per child() call, making === unreliable). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
thejesh23
commented
Jun 13, 2026
Author
Opened #436 to retroactively satisfy the README's "please open an issue first for major changes" guideline — apologies for the order. The issue summarizes the three open Dart PRs (#348, #415, this one) and asks maintainers to pick a shipping approach before reviewing diffs. Happy to close this PR in favour of either alternative if that's the call.
Per maintainer feedback on Egonex-AI#436 — these are personal brainstorm/plan artifacts produced via the superpowers skill flow, not repo documentation. The BUILD.md provenance note in packages/tree-sitter-dart-wasm/ stays since that's repo-level docs about the vendored wasm.
Incorporates stronger pieces from the prior Dart attempts (Egonex-AI#348, Egonex-AI#415) that @Lum1104 called out: - `extractParams` now walks `optional_formal_parameters` (covers both optional positional `[...]` AND named `{...}` parameters — the Dart grammar uses one wrapper for both). - New `extractParamName` helper extracts the user-visible field name from `this.field` and `super.field` initializer parameters by unwrapping `constructor_param` / `super_formal_parameter`. - `collectClassBody` now routes `getter_signature` and `setter_signature` in both shapes: - concrete: `method_signature > getter_signature` + sibling function_body - abstract: `declaration > getter_signature` Setters use the same path. The previous limitation assertion (`methods).not.toContain("value")`) flipped to a positive `.toContain("value")`. - Added import/export edge-case tests: `dart:` SDK URIs, multi-import declaration-order preservation, and `export ... show` clauses. - Added a comma-list field test (`int a, b, c;`). Underscore-prefix visibility carries through naturally to all new code paths via the existing `isExported` gate inside `pushMethod`; explicit test added for an underscore-prefixed getter. Test counts: 28 → 41 dart cases; full core suite 720 → 733; no regressions.
thejesh23
commented
Jun 13, 2026
Author
|
@Lum1104 thanks for the direction. Addressed in two new commits:
Verification (all green)
Branch is up-to-date with |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Dart to the tree-sitter pipeline so Flutter / Dart codebases get the same structural analysis (functions, classes with fields/constructors, mixins, extensions, enums, imports, exports) and call-graph edges that other languages already produce. Ships the freshly-built
dylink.0-format wasm as a workspace-internal package so no upstream-republish or third-party-bundle dependency is required.Linked issue(s)
Refs #226 — Dart is the third leg of the iOS-repo case (Swift + Objective-C + Flutter/Dart) where files currently group by domain but produce no reference edges.
Related PRs (this is the third Dart attempt — flagging explicitly)
There are already two open Dart PRs against
main. This PR is opened to give maintainers a third angle with explicit trade-off comparison; happy to close it in favour of either of the others if that's the call.tirth8205, May 31, 957 additions) — uses@repomix/tree-sitter-wasms@0.1.17for the grammar (a community bundle). Implements the full call graph and references iOS project only groups files by domain, but no reference relationship edges are generated #226 explicitly. Closest sibling to this PR.junddao, Jun 8, 822 additions) — depends on the broken upstreamtree-sitter-dart@1.0.0, bundles a freshly-rebuilt wasm undercore/wasm-grammars/, and adds a generic loader fallback toTreeSitterPluginfor stale-npm-wasm cases. Skips the structural call graph (returns[]).What this PR does differently
@understand-anything/tree-sitter-dart-wasm/consumed viaworkspace:*. The existingTreeSitterPlugin.init()resolves it throughrequire.resolve()unchanged. Ifamaanq/tree-sitter-dartever publishes a refresheddylink.0wasm, the workspace package is a single-commit delete + dependency-flip.startIndexto compare sibling-identity (web-tree-sitter's.child(i)returns a fresh JS wrapper per call, so===always fails — confirmed via probe; PR feat(core): add Dart structural analysis via tree-sitter (#226) #348 hit the same gotcha and uses.idfor the same purpose).function_signature/function_bodyare siblings not parent/child; abstract methods land atclass_body > declaration > function_signature(nomethod_signaturewrapper); anonymous extensions surface as ```on ``` so the graph builder doesn't drop them;hidecombinators are skipped (not added as specifiers).docs/superpowers/specs/2026-06-13-dart-support-design.md).docs/superpowers/for review traceability.Honest trade-offs vs. the alternatives
extractParamscurrently surfaces only required positional parameters; named ({...}) and optional positional ([...]) parameters are wrapped in container nodes and dropped. Documented inline in the helper's doc comment.int get value => count;) are not surfaced as methods — they appear asgetter_signature, which the extractor doesn't currently route. Documented with an explicit test asserting the current (limited) behaviour so the gap can't silently regress.How I tested this
pnpm lint— cleanpnpm --filter @understand-anything/core build— tsc cleanpnpm --filter @understand-anything/core test— 720/720 (+ 22 new Dart cases, + 1 count-assertion update from 40 → 41 inlanguage-registry.test.ts)pnpm --filter @understand-anything/skill build— cleanpnpm test— 201/201 (one pre-existing failure intests/skill/merge-recover-imports.test.mjsexists onorigin/mainunrelated to this branch)TreeSitterPluginwith the sample Flutter snippet (Counterclass +main()callingincrement()):analyzeFilereturns the expectedfunctions/classes/imports/exports, andextractCallGraphreturns{ caller: "main", callee: "increment" }plus{ caller: "main", callee: "Counter" }.Versioning
understand-anything-plugin/package.json,understand-anything-plugin/.claude-plugin/plugin.json,.claude-plugin/plugin.json,.cursor-plugin/plugin.json,.copilot-plugin/plugin.json.🤖 Generated with Claude Code