feat: full Dart language + Flutter ecosystem support#406
Open
dacianf wants to merge 2 commits intosafishamsi:v4from
Open
feat: full Dart language + Flutter ecosystem support#406dacianf wants to merge 2 commits intosafishamsi:v4from
dacianf wants to merge 2 commits intosafishamsi:v4from
Conversation
Replace the regex-based Dart extractor with a tree-sitter AST implementation that brings Dart to parity with the mature Go/Rust/Elixir extractors and adds Flutter-specific structural analysis. Three-layer architecture (each layer is conditional): 1. Pure Dart core (extract_dart.py) — classes, mixins, extensions, enums, typedefs, functions, imports, inheritance, call-graph via tree-sitter 2. Flutter layer (extract_flutter.py) — widget classification, StatefulWidget/ State pairing, nested composition from build(), InheritedWidget deps, Navigator API navigation edges. Only activates on package:flutter imports. 3. Framework layer (extract_dart_frameworks.py) — Riverpod watches_provider/ reads_provider, BLoC handles_event/emits_state, GoRouter navigates_to. Only activates on framework imports. Also adds: - pubspec.yaml parser (package dependencies) - melos.yaml parser (monorepo workspaces) - .arb parser (localization message keys) - Generated file exclusion (.freezed.dart, .g.dart, etc.) - .dart_tool/ directory skip - 57 new tests, 8 fixture files, 0 regressions (490/490 pass) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Correctness: - Fix part_directive emitting wrong relation (part_of → has_part) - Fix mixin `on` constraint target dart_kind (mixin → class) - Fix createState regex matching any Word() instead of return value - Fix context substring match → word boundary regex Security: - Add path traversal protection in extract_melos.py glob resolution Performance: - Move _CLASS_MODIFIERS to module-level frozenset (was rebuilt per class) - Move _SKIP_DEPS/_SKIP_DEV_DEPS to module-level frozensets - Compile _REF_WATCH/_REF_READ/_ON_EVENT/_EMIT_STATE regexes once at module level - Remove redundant _EMIT_CALL guard before _EMIT_STATE.finditer() Cleanness: - Remove project-specific names from _KNOWN_WIDGETS set - Remove unused class_label param from _walk_for_inherited - Use word-boundary matching for framework import detection (prevents false positives like "dio" matching "studio", "hive" matching "archive") - Create message key nodes in extract_arb.py (fixes dangling edges) - Remove redundant `import yaml as _yaml` in extract_melos.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Closed
Author
|
@safishamsi I oppend this PR to include a full flutter framework extraction. Let me know what you think about it |
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
Replaces the regex-based Dart extractor with a full tree-sitter AST implementation that brings Dart to parity with the mature Go/Rust/Elixir extractors and adds Flutter-specific structural analysis.
tree-sitter-dart-orchardfor deterministic AST parsing. Works for server-side/CLI Dart projects with zero Flutter overhead.package:flutterimports) — widget classification (stateless/stateful/state/inherited), StatefulWidget↔State pairing, nested widget composition frombuild()methods, InheritedWidget dependency detection, Navigator API navigation edges.ref.watch/ref.read→watches_provider/reads_provideredges, BLoCon<Event>→handles_eventedges, GoRouter route definitions +context.go/context.push→navigates_toedges. Follows the same pattern as the existing PHP/Laravelbound_to/listened_byedges.pubspec.yaml(package dependency graph),melos.yaml(monorepo workspaces),.arb(localization message keys)..freezed.dart,.g.dart,.gr.dart,.gen.dart,.mocks.dartskipped at detect phase..dart_tool/added to skip dirs.Architecture
Three-layer design where each layer is conditional and additive:
Pure Dart server projects get full structural extraction (21 nodes, 40 edges on the test fixture) with zero Flutter overhead. The existing regex extractor produced 15 nodes and 14 edges with only 2 edge types (
defines,imports) and no line numbers.Changes
graphify/extract_dart.py(new)graphify/extract_flutter.py(new)graphify/extract_dart_frameworks.py(new)graphify/extract_pubspec.py(new)graphify/extract_melos.py(new)graphify/extract_arb.py(new)graphify/extract.pygraphify/detect.py.dart_toolskippyproject.tomltree-sitter-dart-orchard,pyyamlTest plan
graphify.extract_dart(core only)graphify.extract(full orchestrated)confidence_scorefield (v4 schema)🤖 Generated with Claude Code