Skip to content

feat(scanner): add Dart and Flutter dependency analysis - #145

Merged
JordanCoin merged 2 commits into
JordanCoin:mainfrom
jasontitus:feat/dart-flutter-support
Aug 26, 2026
Merged

feat(scanner): add Dart and Flutter dependency analysis#145
JordanCoin merged 2 commits into
JordanCoin:mainfrom
jasontitus:feat/dart-flutter-support

Conversation

@jasontitus

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds first-class Dart and Flutter dependency analysis across the scanner pipeline:

  • recognizes .dart files in the canonical language registry
  • extracts Dart imports, exports, conditional imports, part directives, top-level functions, and methods through embedded ast-grep rules
  • discovers dependencies and dev dependencies from pubspec.yaml
  • resolves relative Dart URIs and local package: URIs across multi-package workspaces
  • fails closed when package names are ambiguous
  • ignores generated .dart_tool content
  • renders Dart dependencies and documents the new language support

The pinned ast-grep 0.42.1 release already includes its Dart parser, so this does not require a separate grammar download or release-workflow change.

Type of change

  • Bug fix
  • New feature
  • New language support
  • Documentation
  • Other (describe below)

Checklist

  • I've tested this locally with go build && ./codemap .
  • I've read CONTRIBUTING.md (for new language support)
  • I've updated documentation if needed

Verification

  • go test ./...
  • go test -race ./scanner ./render
  • go vet ./...
  • staticcheck ./...
  • git diff --check

Tested against a real multi-package Flutter repository: 166 Dart files, 1,178 functions, 366 resolved dependency edges. This covered same-package imports, cross-package workspace imports, generated localization sources, tests, and vendored Flutter packages.

Additional notes

The existing language-contribution instructions reference the retired tree-sitter query layout. This implementation follows the current embedded ast-grep rule architecture used by scanner/astgrep.go and scanner/sg-rules.

Copy link
Copy Markdown
Owner

Thanks for this — it's a strong contribution: the rules were verified empirically across the full directive surface (conditional imports, deferred/show/hide, both part of forms, comment/string negatives all correct), resolution is fail-closed where it counts (duplicate names, missing generated files), the registry tables are complete, and the race claim holds. Two items block merge; both have concrete fixes.

1. BLOCKING — the bundled ast-grep 0.42.1 rejects two rule kinds, which kills the ENTIRE scan for bundle users

I downloaded the actual pinned bundle (scripts/download-bundled-astgrep.sh, 0.42.1) and ran your rules against it:

  • kind: uri (dart-imports) — works on 0.42.1. The dependency extraction itself is fine.
  • kind: function_declaration / kind: method_declarationinvalid in 0.42.1's Dart grammar. And ast-grep fails the whole --inline-rules document on one invalid kind: exit 8, zero matches for all 21 languages. TestAstGrepDartFlutter fails against the bundled binary (passes on PATH-installed 0.45.1, which is also what CI installs — so green CI doesn't cover this).

Two workable fixes, verified against both versions:

  • (a) Swap the kinds to the older grammar's names: function_signature and method_signature match on both 0.42.1 and 0.45.1 with identical counts across versions (8/8 and 2/2 on my fixture). Note the node shape differs from *_declaration (a signature node excludes the body), so the name-extraction capture needs a matching adjustment — please verify function names still extract on both versions.
  • (b) Bump the pinned AST_GREP_VERSION to a release whose Dart grammar has the *_declaration kinds (0.45.1 verified working), accepting the re-validation of the other languages that a bump implies.

Either way, please run AST_GREP_VERSION=<pin> scripts/download-bundled-astgrep.sh + go test ./scanner with that binary first on PATH before pushing — that's the config CI misses.

2. BLOCKING — package: URIs resolve repo-wide by name, without checking the importer's declared dependencies

scanner/dartworkspace.go resolves package:NAME/... to any pubspec in the repo with a matching name:. Demonstrated: app depends on hosted http, an unrelated vendored third_party/http/pubspec.yaml exists → app/lib/main.dart gets a false edge to third_party/http/lib/http.dart (at runtime pub uses the hosted package). The JS resolver (scanner/jsworkspace.go:349-366) shows the house pattern: resolve only when NAME is the importer's own package or is declared in its dependencies/dev_dependencies/dependency_overrides (any form — so melos-style monorepos keep working, since apps do declare their siblings). ~20 lines with the fields decodePubspec already parses.

Non-blocking

  • Reject .. segments in the package: URI path portion (package:app/../tool/x.dart currently escapes lib/ — invalid Dart, but fail-closed hygiene is cheap).
  • cmd/context.go's manifest tables don't know pubspec.yaml → dart (two map entries).
  • parsePubspec skips dependency_overrides for the external-deps display.
  • You're right that CONTRIBUTING.md still documents the retired tree-sitter layout — that's a pre-existing docs issue, not on this PR.

Rebase note

#143/#144 merged (no overlap with your diff). #146 (CUE) is still open and shares two one-line regions with yours (render/depgraph.go langOrder, README language sentence); current plan is to land yours first so you don't have to resolve anything.


Generated by Claude Code

@jasontitus

Copy link
Copy Markdown
Contributor Author

Addressed in c84dc9d.

  • Switched Dart function matching to function_signature / method_signature under the existing two-rule convention and verified name extraction on ast-grep 0.42.1 and 0.45.1.
  • Scoped package: resolution to the importer package or names declared in dependencies, dev_dependencies, or dependency_overrides; duplicate names still fail closed.
  • Rejected package paths that escape the target package's lib/ directory, including Windows separators.
  • Added both pubspec.yaml -> dart context manifest mappings.
  • Included dependency_overrides in displayed Dart dependencies.
  • Added the Dart resolution docs row and tightened the resolver dispatch/tests during the cleanup pass.

Verification:

  • PATH="$PWD/bundled-tools/darwin_arm64:$PATH" go test ./... -count=1
  • PATH="$PWD/bundled-tools/darwin_arm64:$PATH" go test -race ./scanner ./render -count=1
  • targeted Dart tests on ast-grep 0.45.1
  • go vet ./...
  • go run honnef.co/go/tools/cmd/staticcheck@latest ./...
  • git diff --check

@JordanCoin
JordanCoin merged commit 2d02160 into JordanCoin:main Aug 26, 2026

Copy link
Copy Markdown
Owner

Verified and merged. Re-ran the Dart suite against the actual bundled linux 0.42.1 binary and against 0.45.1 — green on both, so the whole-scan poisoning case is closed; the dependency-scoped package: resolution and lib/ containment guard check out in the diff and tests; full go vet + go test ./... clean against main. Nice turnaround, and welcome aboard — Dart lands as the 21st language.

Heads-up for the future: #146 (CUE) will resolve a couple of one-line conflicts against your language-table entries when it lands; nothing needed from you.


Generated by Claude Code

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