Skip to content

feat: add Dart language support#204

Merged
magyargergo merged 8 commits into
abhigyanpatwari:mainfrom
mrwogu:feature/dart-language-support
Mar 26, 2026
Merged

feat: add Dart language support#204
magyargergo merged 8 commits into
abhigyanpatwari:mainfrom
mrwogu:feature/dart-language-support

Conversation

@mrwogu

@mrwogu mrwogu commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds Dart as the 13th supported language across both gitnexus (Node.js CLI) and gitnexus-web (WASM browser) packages
  • Vendored tree-sitter-dart grammar regenerated with ABI 14 for compatibility with tree-sitter@0.21.0
  • Loaded as an optionalDependency with graceful try/catch fallback (matching the Swift pattern)

What's included

  • Tree-sitter queries: classes, mixins, extensions, enums, type aliases, top-level functions, methods, constructors, factory constructors, getters/setters, imports, call extraction (direct + method calls), and heritage (extends / implements / with as trait-impl)
  • Import resolution: package: URI resolution (maps to lib/ path), dart: SDK skip, relative import fall-through
  • Flutter framework detection: path-based (main.dart, screens, BLoC, services, widgets) and AST-based (StatelessWidget, StatefulWidget, BuildContext, etc.)
  • Export detection: underscore-prefix convention (_ = private, like Python)
  • Call graph: findEnclosingFunctionId Dart-specific branches, Dart/Flutter BUILT_INS for noise suppression
  • Integration tests: 3 Dart-specific test cases (definitions, imports, heritage) with try/catch guards for optional dependency

Files changed (17 source + vendored grammar)

Area Files
Config supported-languages.ts (both packages)
Parsing tree-sitter-queries.ts, parsing-processor.ts, parse-worker.ts (both packages)
Tree-sitter parser-loader.ts (both packages)
Imports import-processor.ts, utils.ts (both packages)
Framework framework-detection.ts (both packages)
Dependencies package.json, package-lock.json
Tests tree-sitter-languages.test.ts, simple.dart fixture
Vendor vendor/tree-sitter-dart/ (ABI 14 grammar)

Test plan

  • npx tsc --noEmit — clean
  • npx vitest run — 851 tests pass (40 test files)
  • Dart definition parsing (classes, functions, mixins, enums, type aliases, constructors, getters/setters)
  • Dart import extraction (3 imports: dart:, package:, package: with alias)
  • Dart heritage extraction (extends, implements, with/mixins)
  • Cross-language assertions (Dart excluded from loop like Swift — optional dependency)

Co-Authored-By: @xFlaviews

@vercel

vercel Bot commented Mar 6, 2026

Copy link
Copy Markdown

@mrwogu is attempting to deploy a commit to the NexusCore Team on Vercel.

A member of the Team first needs to authorize it.

@mrwogu mrwogu force-pushed the feature/dart-language-support branch from 2977da9 to 73e92fe Compare March 6, 2026 21:52

@xkonjin xkonjin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick review pass:

  • Main risk area here is input validation, path handling, and malformed payload behavior.
  • Good to see test coverage move with the code; I’d still make sure it exercises the unhappy path around input validation, path handling, and malformed payload behavior rather than only the happy path.
  • Before merge, I’d smoke-test the behavior touched by supported-languages.ts, framework-detection.ts, parsing-processor.ts (+28 more) with malformed input / retry / rollback cases, since that’s where this class of change usually breaks.

@reversTeam reversTeam left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thorough and well-structured addition of Dart/Flutter language support. A few observations:

Strengths:

  • Comprehensive tree-sitter queries covering classes, mixins, extensions, enums, type aliases, constructors (including factory), getters/setters, and heritage relationships (extends, implements, with).
  • Dart import resolution is solid — correctly handles dart: SDK imports (skip), package: imports (resolve to lib/), and relative imports (fall through to standard resolution).
  • Good use of optionalDependencies for tree-sitter-dart, consistent with how Swift is handled.
  • The test fixture (simple.dart) is well-designed and covers most Dart constructs. Integration tests cover definitions, imports, and heritage extraction.
  • Framework detection for Flutter is comprehensive (main, screens, BLoC/cubit, services, widgets) with sensible multiplier values.
  • Visibility logic (_ prefix = private) is correct for Dart.

Minor notes:

  • The import resolution in processImports and processImportsFromExtracted has near-identical Dart handling blocks (~25 lines each). Consider extracting a shared helper to reduce duplication, though this is a nit and can be done as a follow-up.
  • The vendored tree-sitter-dart adds a lot of generated C code. If this grammar is published on npm, it might be worth switching to a versioned npm dependency in the future (like tree-sitter-swift), but vendoring is a reasonable approach for now given ABI compatibility concerns.
  • Missing newline at end of supported-languages.ts and tree-sitter-queries.ts — trivial but worth fixing.

LGTM. Nice contribution!

@mrwogu

mrwogu commented Mar 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the reviews!

Rebased onto latest main (resolved a conflict in tree-sitter-languages.test.ts — the new unhappy path tests from upstream now sit alongside the Dart tests).

Addressed the minor feedback:

  • Added missing newlines at EOF in supported-languages.ts (both packages)
  • Removed trailing whitespace in tree-sitter-queries.ts

Re the import resolution duplication (processImports / processImportsFromExtracted) — agreed it's worth extracting a shared helper. I'll tackle that as a follow-up to keep this PR focused on the Dart addition.

All tests passing locally (tsc --noEmit clean, 1000 tests green).

@mrwogu mrwogu force-pushed the feature/dart-language-support branch from 73e92fe to 91e19d7 Compare March 9, 2026 08:21
@magyargergo

Copy link
Copy Markdown
Collaborator

Duplicate of #83

@magyargergo magyargergo marked this as a duplicate of #83 Mar 16, 2026
@mrwogu mrwogu force-pushed the feature/dart-language-support branch from 91e19d7 to fcbd34c Compare March 25, 2026 13:44
@mrwogu

mrwogu commented Mar 25, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main and adapted to the new SICP-informed LanguageProvider architecture (#488).

Changes from the rebase:

  • Created languages/dart.ts — Dart language provider following the defineLanguage() pattern
  • Created import-resolvers/dart.ts — handles package:, dart: SDK, and relative imports via the ImportResolverFn interface
  • Created type-extractors/dart.ts — minimal type config (Dart has static types in AST, no comment-based extraction needed)
  • Added dartExportChecker to export-detection.ts (public if no leading _ underscore)
  • Registered Dart in languages/index.ts, framework-detection.ts, and entry-point-scoring.ts (exhaustive satisfies Record<SupportedLanguages, ...> tables)
  • Removed inline dart cases from import-processor.ts, parsing-processor.ts, and parse-worker.ts — now handled through the provider dispatch

All tree-sitter queries, vendor bindings, test fixtures, and web package changes are unchanged from the original PR.

@magyargergo

Copy link
Copy Markdown
Collaborator

@claude ultra-think while identifying Dart-language gaps. Perform this analysis on this pull request and verify those findings. Act as a senior compiler font-end engineer and expert in static analysis tools and review this change from that perspective and review the architectural fit. Also check out previous comments and reason with their requests.

@github-actions

github-actions Bot commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 5m 41s —— View job


Deep Dart Language Support Review

Tasks:

  • Initialize review
  • Read tree-sitter queries (both packages)
  • Read language provider, import resolver, type extractor
  • Read framework detection, export detection, entry-point scoring
  • Read test fixtures and integration tests
  • Compare against Swift/existing language patterns
  • Synthesize findings and post comprehensive review

Review: Dart Language Support (feat: add Dart language support)

Acting as a senior compiler front-end engineer and static analysis tooling expert. I've read all 17 source files introduced or modified by this PR.

Architecture and Overall Fit

The rebase-to-LanguageProvider architecture is well-executed. languages/dart.ts correctly follows the defineLanguage() contract, the importResolver and typeConfig are properly modular, and the satisfies Record<SupportedLanguages, ...> exhaustiveness checks in entry-point-scoring.ts and framework-detection.ts give compile-time safety. The optional-dependency pattern (try/catch in parse-worker.ts and parser-loader.ts) matches the Swift precedent exactly.


🔴 Critical Issues

1. Flutter framework detection completely absent from the CLI (gitnexus) package

gitnexus/src/core/ingestion/framework-detection.ts — the changed file shows +1/-0 (only the [SupportedLanguages.Dart]: [] line was added). The web package (gitnexus-web) received full Flutter path-based detection:

/main.dart              → 3.0×  (flutter-main)
/lib/screens/**.dart    → 2.5×  (flutter-screen)
/lib/pages/**.dart      → 2.5×
/lib/bloc/**.dart       → 2.0×  (flutter-state-management)
/lib/cubit/**.dart      → 2.0×
/lib/services/**.dart   → 1.8×  (flutter-service)
/lib/widgets/**.dart    → 1.5×  (flutter-widget)

None of this landed in the CLI package. A Flutter project analyzed by the CLI will get no entry-point boost on any file. The web and CLI packages now behave differently for the same Dart input. Fix this →

2. Flutter AST patterns wired in neither package

Both gitnexus and gitnexus-web have AST_FRAMEWORK_PATTERNS_BY_LANGUAGE[Dart] = []. The web package defines the patterns in FRAMEWORK_AST_PATTERNS.flutter:

'flutter': ['StatelessWidget', 'StatefulWidget', 'BuildContext', 'Widget build',
            'ChangeNotifier', 'GetxController', 'Cubit<', 'Bloc<'],

…but they are never wired to [SupportedLanguages.Dart] in either package's AST_FRAMEWORK_PATTERNS_BY_LANGUAGE. This means detectFrameworkFromAST() returns null for every Dart file, and the Flutter widget inheritance boost is dead code. Fix this →


🟠 High Severity Issues

3. scanConstructorBinding can never match a constructor call

gitnexus/src/core/ingestion/type-extractors/dart.ts:51

const funcName = value.type === 'identifier' ? value : null;

scanConstructorBinding checks for a bare identifier as the value — this matches var x = SomeVar (an assignment, not a constructor call). The constructor call form var user = User() produces a selector_expression node (as correctly handled in extractInitializer). scanConstructorBinding therefore never captures constructor instantiations, so TypeEnv won't populate for Dart receiver types. Method call resolution on user.save() will silently fail to resolve the receiver type.

4. Entry-point name patterns empty for Dart

gitnexus/src/core/ingestion/entry-point-scoring.ts:217

[SupportedLanguages.Dart]: [],

Flutter lifecycle methods are never scored as entry points. Missing patterns:

/^build$/,        // Widget.build — the fundamental Flutter render entry point
/^initState$/,    // State lifecycle
/^dispose$/,      // State lifecycle teardown
/^runApp$/,       // App entry
/^onEvent$/,      // BLoC event handler (Bloc library)
/^on[A-Z]/,       // BLoC typed event handler pattern (already in UNIVERSAL but worth confirming)
/^mapEventToState$/, // legacy BLoC

Without these, build() in every Flutter widget gets no name-pattern boost, making BLoC/cubit patterns invisible to the scorer.

5. Dart/Flutter built-ins absent from noise filter

gitnexus/src/core/ingestion/utils/noise-filter.tsBUILT_IN_NAMES has no Dart section. High-frequency Flutter noise that will pollute the call graph:

  • setState, build, initState, dispose (State lifecycle — called thousands of times)
  • runApp, debugPrint, mounted
  • Widget construction idioms: Navigator, showDialog, showModalBottomSheet, ScaffoldMessenger
  • Stream/Future: then, catchError, whenComplete (overlaps with JS but absent for Dart explicitly)

print is already covered via the Python entry. Fix this →


🟡 Medium Severity Issues

6. Call extraction covers only expression_statement context

gitnexus/src/core/ingestion/tree-sitter-queries.ts:1073–1083

Both call queries anchor on expression_statement. Flutter code overwhelmingly places calls inside:

  • return statements: return Builder(builder: (ctx) => ...)
  • Variable declarations: final bloc = UserBloc(userRepo)
  • Conditional guards: if (mounted) setState(() => ...)
  • await expressions: await Navigator.push(...)
  • Cascade chains: ..addListener(...)..dispose()

This is a shared limitation with other languages in this codebase, but the impact is disproportionately large for Dart/Flutter because widget build() methods almost never have top-level expression_statement calls — every call is nested in a widget tree return or assigned. The call graph for Flutter projects will be sparse.

7. Call queries may produce phantom captures

(expression_statement
  (identifier) @call.name
  .
  (selector (argument_part))) @call

The . anchor (sibling adjacency) is fragile for Dart's grammar because Dart chains calls using selector as a recursive suffix. foo.bar() at the statement level has the form (identifier) (selector (unconditional_assignable_selector)) (selector (argument_part)) — the extra intermediary selector breaks the adjacency constraint and the call is silently dropped.

8. mixin_declaration query lacks explicit field accessor

gitnexus/src/core/ingestion/tree-sitter-queries.ts:1016

(mixin_declaration
  (identifier) @name) @definition.trait

Every other query uses name: (identifier) @name (explicit field). The mixin query matches the first identifier child positionally. If the grammar adds/reorders children (e.g., a base keyword in future Dart 3.x base mixin), this captures the wrong node without a compile error or runtime error — just silently wrong data.


🟢 Low Severity / Nitpicks

9. Extension types (Dart 3.x) not covered

Dart 3.0 introduced extension types (extension type Meters(double _) implements double {}). These use a different grammar node (extension_type_declaration) from classic extensions (extension_declaration). The vendored grammar would need to be checked for Dart 3.x support; if it doesn't cover this, real-world Dart 3.x codebases will silently drop these definitions.

10. @definition.class for extensions conflates semantics

extension_declaration is tagged as @definition.class. Semantically, extensions don't declare new types — they augment existing ones. This affects class-level analysis (e.g., heritage, coupling metrics). Consider @definition.extension as a dedicated tag, as the codebase already has @definition.trait and @definition.enum as distinct types.

11. Test coverage gaps

The 3 integration tests cover the happy path well, but these are missing:

  • Getters and setters (captured as definition.property)
  • Factory constructors
  • Extensions
  • Abstract method declarations
  • Private symbol filtered by _ prefix (export detection)
  • Call extraction (even for expression_statement)
  • Framework detection scoring with actual Dart paths

12. Package import resolver doesn't scope by package name

gitnexus/src/core/ingestion/import-resolvers/dart.ts:23–39

const relPath = stripped.slice(slashIdx + 1); // strips package name entirely
const candidates = [`lib/${relPath}`, relPath];

package:flutter/material.dart → tries lib/material.dart in the local repo (correctly returns null for external packages). However, package:external_lib/util.dart where external_lib is vendored into the repo as lib/external_lib/util.dart would resolve incorrectly. More importantly, in a Dart monorepo, package:package_b/src/model.dart from package_a would resolve to package_a/lib/src/model.dart instead of package_b/lib/src/model.dart. This is probably acceptable for single-package projects but worth noting.

13. Duplicate PR concern

@magyargergo flagged this as a duplicate of #83. If #83 was closed/merged, verify there are no conflicting implementations or test regressions. If both PRs define Dart support, the latest one should win — but the git history should be clean.


Summary Table

Area Status Severity
LanguageProvider architecture fit ✅ Correct
importResolver (dart: skip, package: resolve, relative) ✅ Correct
exportChecker (_ prefix convention) ✅ Correct
Grammar + tree-sitter queries (definitions, heritage, imports) ✅ Functionally correct
CLI Flutter framework path detection ❌ Missing Critical
AST Flutter pattern wiring ❌ Dead code Critical
scanConstructorBinding constructor call match ❌ Bug High
Dart entry-point name patterns ❌ Empty High
Dart/Flutter noise filter built-ins ❌ Missing High
Call extraction coverage (non-statement contexts) ⚠️ Partial Medium
mixin_declaration positional field capture ⚠️ Fragile Medium
Extension type (Dart 3.x) ⚠️ Not covered Low
@definition.class for extensions ⚠️ Semantic conflation Low
Test coverage depth ⚠️ Happy path only Low

The foundation is solid. The import resolver, export checker, grammar vendoring, and provider registration are all done correctly. The CLI/web divergence on framework detection and the wired-but-inactive AST patterns are the two items that should be resolved before merge.

@magyargergo

Copy link
Copy Markdown
Collaborator

@claude do we need to include the tree-sitter-dart native code just to support ABI 14? Is there any other way to go about it? I don't really want to the 3rd-party code here. research about alternatives.

@mrwogu

mrwogu commented Mar 25, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all critical and high-severity findings from the review:

Critical:

  • Flutter path-based framework detection added to CLI package (was only in web) — main.dart 3.0×, screens/pages 2.5×, bloc/cubit 2.0×, services 1.8×, widgets 1.5×
  • Flutter AST patterns (StatelessWidget, StatefulWidget, BuildContext, etc.) wired into AST_FRAMEWORK_PATTERNS_BY_LANGUAGE[Dart] in CLI package

High:

  • Fixed scanConstructorBinding — now handles selector_expression for User.named() constructor calls, not just bare identifiers
  • Added Dart/Flutter entry-point name patterns: build, initState, dispose, didChangeDependencies, didUpdateWidget, runApp, onEvent, mapEventToState
  • Added Dart/Flutter built-ins to noise filter: setState, mounted, debugPrint, Navigator.push/pop, showDialog, showModalBottomSheet, ScaffoldMessenger, async helpers (then, catchError, whenComplete, listen)

Medium:

  • Fixed mixin_declaration query to use explicit name: field accessor instead of positional match (both packages)

Items intentionally deferred:

@github-actions

github-actions Bot commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 2m 14s —— View job


Tasks:

  • Initialize comment
  • Research tree-sitter ABI compatibility and alternatives to vendoring
  • Read relevant files (parser-loader, package.json, vendor structure)
  • Summarize findings and post response

Why the vendor code exists

The problem is an ABI mismatch. tree-sitter-dart grammars are generated by tree-sitter generate, which hardcodes a specific ABI version into parser.c. The project pins tree-sitter@0.22.4 (ABI 14). As of this PR, the npm-published tree-sitter-dart packages had been regenerated with ABI 15 (targeting tree-sitter 0.23+), so they cannot be loaded by tree-sitter 0.22.x at runtime. The PR author worked around this by regenerating parser.c with --abi 14 and vendoring the result. The 199,812-line vendor/tree-sitter-dart/src/parser.c is entirely a consequence of this regeneration step.


Alternatives (ranked by desirability)

✅ Option 1 — Upgrade tree-sitter to 0.23.x (recommended)

This is the cleanest path and solves multiple issues at once:

  • tree-sitter@0.23.x uses ABI 15, which matches the latest published grammar packages on npm
  • The entire vendor/tree-sitter-dart/ directory is deleted; you just use tree-sitter-dart from npm like any other grammar
  • The scripts/patch-tree-sitter-swift.cjs postinstall workaround is also deleted — the patch script's own comment says "TODO: Remove this script when tree-sitter is upgraded to ^0.22.x" (the project is already there) but the deeper fix — using tree-sitter-swift@0.7.1+ which ships prebuilds — works cleanly once tree-sitter is on 0.23.x
  • All 12 other grammar packages (tree-sitter-javascript, tree-sitter-python, etc.) have published 0.23.x-compatible releases

What it takes: Bump tree-sitter to ^0.23.0, update the overrides field, verify each grammar package has a compatible release, and re-run tests. This is a single focused PR.


🟡 Option 2 — Publish the regenerated grammar as a standalone npm package

Create a minimal scoped package (e.g. @gitnexus/tree-sitter-dart) containing only the ABI-14 parser.c + binding.gyp, published to npm. The vendor directory disappears from this repo; package.json points to the scoped package like any other dependency.

Downside: Adds an external package to maintain. If tree-sitter is upgraded later, the scoped package also needs a new publish. This trades repo bloat for registry maintenance burden.


🟡 Option 3 — Ship only the WASM file, use web-tree-sitter in the CLI

gitnexus-web already loads Dart via a tree-sitter-dart.wasm file. A WASM binary compiled from the grammar source has no ABI coupling — it runs identically everywhere. The CLI could load the WASM via web-tree-sitter for Dart only.

Downside: Introduces web-tree-sitter as a CLI dependency, creating an architectural inconsistency (all other CLI grammars use native Node bindings; only Dart uses WASM). It also adds async WASM initialization overhead in the CLI path. Not worth it for one language.


❌ Option 4 — Wait for an ABI-14-compatible npm release

There is no active upstream publishing a tree-sitter-dart npm package with ABI 14 prebuilds that works with tree-sitter@0.22.4. This is not a viable path without external action.


Recommendation

Don't merge this PR with the vendor directory as-is. Open a companion PR that upgrades tree-sitter to ^0.23.0. Once that lands on main, rebase this branch, drop the vendor/ directory, add tree-sitter-dart as a normal optionalDependency from npm, and remove scripts/patch-tree-sitter-swift.cjs. The Dart support code itself (queries, provider, import resolver, tests) is solid and doesn't change; only the grammar loading wiring changes.

If the tree-sitter upgrade is too large to bundle with this feature PR, Option 2 (scoped npm package) is the next cleanest choice.

@magyargergo

Copy link
Copy Markdown
Collaborator

We cannot upgrade to 0.23.x tree-sitter as there are other language tree-sitters that are not yet upgraded to that version.

@magyargergo

magyargergo commented Mar 25, 2026

Copy link
Copy Markdown
Collaborator

Maybe an older version of tree-sitter-dart could work? Would we loose a lot of language features?

@mrwogu

mrwogu commented Mar 25, 2026

Copy link
Copy Markdown
Contributor Author

Tested tree-sitter-dart@1.0.0 from npm (the only published version, from Feb 2023):

npm tree-sitter-dart@1.0.0:  { name, nodeTypeInfo }        ← missing `language` field
vendored tree-sitter-dart:    { name, language, nodeTypeInfo } ← works

The npm package uses nan bindings and doesn't export the language property that tree-sitter@0.22.4 requires (parser.setLanguage() throws "Invalid language object"). The vendored version uses node-addon-api + our binding.gyp which produces the correct ABI 14 binding.

In short: No npm version of tree-sitter-dart works with our pinned tree-sitter@0.22.4. The npm package has 316 node types (older grammar) vs our vendored 354 (newer grammar with Dart 3.x constructs like records, patterns, sealed classes). Using the npm version would both fail at runtime AND lose Dart 3.x coverage.

I've opened #516 to upgrade tree-sitter to 0.25.0 — once that lands, tree-sitter-dart@1.0.0 from npm should work with the new ABI and we can drop the vendor directory. I'll rebase this PR after #516 is merged.

@mrwogu mrwogu mentioned this pull request Mar 25, 2026
4 tasks
@magyargergo

Copy link
Copy Markdown
Collaborator

#83 also implements this. You could work together with @xFlaviews to deliver this language and I'm more than happy to merge your changes in. :)

mrwogu added 3 commits March 25, 2026 23:03
Add Dart as the 13th supported language across both gitnexus (Node.js)
and gitnexus-web (WASM) packages.

- Vendored tree-sitter-dart grammar (ABI 14) as optionalDependency
  with graceful try/catch loading (matching Swift pattern)
- Tree-sitter queries: classes, mixins, extensions, enums, type aliases,
  functions, methods, constructors, getters/setters, imports, calls,
  heritage (extends/implements/with as trait-impl)
- Dart import resolution: package: URIs, dart: SDK skip, relative imports
- Flutter framework detection: path-based and AST-based patterns
- Export detection: underscore-prefix convention (like Python)
- Call graph: findEnclosingFunctionId Dart branches, Dart/Flutter BUILT_INS
- Integration tests with try/catch guards for optional dependency
Addresses review feedback — adds trailing newline to
supported-languages.ts (both packages) and removes trailing
whitespace from tree-sitter-queries.ts.
…oint patterns

- Add Flutter path-based framework detection to CLI (was only in web package)
- Wire Flutter AST patterns into AST_FRAMEWORK_PATTERNS_BY_LANGUAGE[Dart]
- Fix scanConstructorBinding to handle selector_expression (User.named())
- Add Dart/Flutter entry-point name patterns (build, initState, dispose, runApp)
- Add Dart/Flutter built-ins to noise filter (setState, Navigator, etc.)
- Fix mixin_declaration query to use explicit field accessor (name:)
@mrwogu mrwogu force-pushed the feature/dart-language-support branch from 3f8ae6d to b027ab8 Compare March 25, 2026 22:20
@mrwogu

mrwogu commented Mar 25, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for pointing to #83, @magyargergo@xFlaviews did excellent work there, especially on type resolution.

I've rebased onto the tree-sitter 0.25.0 upgrade (#516, now merged) and incorporated the best parts from both PRs:

Adopted from #83:

  • Full type extractor (Tier 0–2) replacing my stub — explicit annotations with nullable unwrapping, constructor inference via parseDartRHS() (handles tree-sitter-dart's flat sibling AST), assignment chain propagation, for-loop element types with await support, virtual dispatch, literal type inference
  • importSemantics: 'wildcard' — Dart imports bring everything public into scope, not named
  • Broader framework detection — removed /lib/ prefix requirement on path patterns, added app.dart, routes/, views/, presentation/, domain/
  • Riverpod AST patterns@riverpod, ref.watch, ref.read, AsyncNotifier, Notifier, ConsumerWidget
  • Class-suffix entry-point patternsWidget$, Page$, Screen$, Controller$, Notifier$, Provider$

Kept from this PR (not in #83):

  • Web package (gitnexus-web) Dart support
  • Test fixtures and integration tests
  • Definition queries: constructors, factory constructors, getters, setters, abstract methods
  • Heritage semantics: mixins as @definition.trait / @heritage.trait (not @definition.class / @heritage.implements)
  • Mixin query with explicit name: field accessor
  • Additional call queries: return-statement calls, variable-assignment calls, re-exports

Tree-sitter-dart dependency: Now using github:UserNobody14/tree-sitter-dart#0fc19c3 (pinned SHA) instead of vendored code or npm ^1.0.0. The npm package still uses legacy nan bindings that don't work with tree-sitter 0.25 — see UserNobody14/tree-sitter-dart#94. Once a new npm version is published with NAPI bindings, we can switch to a simple version range.

@mrwogu mrwogu force-pushed the feature/dart-language-support branch 2 times, most recently from 29a27ae to 41c7957 Compare March 25, 2026 22:29
@github-actions

github-actions Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 1m 45s —— View job


Tasks:

  • Initialize comment
  • Read type extractor (dart.ts)
  • Read existing unit tests (dart-type-extractor.test.ts)
  • Read fixture files (simple.dart, dart-advanced.dart)
  • Analyze gaps and formulate recommendations

Recommended Tests for Dart Type Resolution

After reading the type extractor (dart.ts) and current dart-type-extractor.test.ts (24 tests), here are the highest-value additions, grouped by what's missing.


1. extractDartForLoopBinding — zero coverage (entire function untested)

This is the most significant gap. The function has four distinct paths, none of which are exercised:

// Path A: explicit typed loop variable
it('extracts type from explicit for-loop annotation', async () => {
  const code = `void f(List<User> users) { for (User u in users) { u.save(); } }`;
  const nodes = parseAndFindNodes(parser, code, 'for_statement');
  const scopeEnv = new Map<string, string>();
  const ctx = {
    scopeEnv, declarationTypeNodes: new Map(), scope: nodes[0],
    returnTypeLookup: { lookupRawReturnType: () => undefined }
  };
  typeConfig.extractForLoopBinding!(nodes[0], ctx);
  expect(scopeEnv.get('u')).toBe('User');
});

// Path B: infer element type from List<User> in scope
it('infers element type from List<T> iterable in scope', async () => {
  const code = `void f(List<User> users) { for (var u in users) {} }`;
  // declarationTypeNodes needs the `users: List<User>` type node from the param
  // ... assert scopeEnv.get('u') === 'User'
});

// Path C: infer from method call return type
it('infers element type from method call iterable', async () => {
  const code = `void f() { for (var u in repo.getUsers()) {} }`;
  const returnTypeLookup = { lookupRawReturnType: (name: string) => name === 'getUsers' ? 'List<User>' : undefined };
  // ... assert scopeEnv.get('u') === 'User'
});

// Path D: await iterable
it('resolves element type through await iterable', async () => {
  const code = `void f() async { for (var u in await fetchUsers()) {} }`;
  // ... similar to Path C with isAwait wrapping
});

2. Literal type inference — missing variants

Only int, String, and true are tested. Three cases are uncovered:

it('infers double literal', async () => {
  // parse `var x = 3.14;`, find decimal_floating_point_literal
  expect(typeConfig.inferLiteralType!(node)).toBe('double');
});

it('infers false literal', async () => {
  // parse `var x = false;`, find false node
  expect(typeConfig.inferLiteralType!(node)).toBe('bool');
});

it('infers null literal', async () => {
  // parse `var x = null;`, find null_literal node
  expect(typeConfig.inferLiteralType!(node)).toBe('null');
});

it('returns undefined for unknown node type', async () => {
  // pass any non-literal node
  expect(typeConfig.inferLiteralType!({ type: 'identifier' } as any)).toBeUndefined();
});

3. await in extractPendingAssignment — the isAwait flag is parsed but never tested

it('extracts call result from await expression', async () => {
  const nodes = parseAndFindNodes(parser, 'void f() async { var user = await getUser(); }', 'initialized_variable_definition');
  const result = typeConfig.extractPendingAssignment!(nodes[0], new Map());
  expect(result).toEqual({ kind: 'callResult', lhs: 'user', callee: 'getUser' });
});

it('extracts method call result from await expression', async () => {
  const nodes = parseAndFindNodes(parser, 'void f() async { var user = await svc.fetch(); }', 'initialized_variable_definition');
  const result = typeConfig.extractPendingAssignment!(nodes[0], new Map());
  expect(result).toEqual({ kind: 'methodCallResult', lhs: 'user', receiver: 'svc', method: 'fetch' });
});

4. detectConstructorType — named constructor returns class name (not member)

The current test only covers Dog(). The named constructor path (rhs.member && classNames.has(rhs.callee)) is untested:

it('detects constructor type for named constructor call', async () => {
  const classNames = new Set(['Dog']);
  const nodes = parseAndFindNodes(parser, 'void f() { var d = Dog.unknown(); }', 'initialized_variable_definition');
  const result = typeConfig.detectConstructorType!(nodes[0], classNames);
  expect(result).toBe('Dog');  // class name, not 'unknown'
});

it('returns undefined when callee is not a known class', async () => {
  const classNames = new Set<string>();
  const nodes = parseAndFindNodes(parser, 'void f() { var x = getUser(); }', 'initialized_variable_definition');
  const result = typeConfig.detectConstructorType!(nodes[0], classNames);
  expect(result).toBeUndefined();
});

5. Generic typed declarations

extractDartDeclaration is called with List<String> names = [] in the fixture, but never asserted in tests:

it('extracts outer type from generic declaration (List<String>)', async () => {
  const env = new Map<string, string>();
  const nodes = parseAndFindNodes(parser, 'void f() { List<String> names = []; }', 'initialized_variable_definition');
  typeConfig.extractDeclaration(nodes[0], env);
  expect(env.get('names')).toBe('List');  // outer container, not type arg
});

it('extracts type from generic constructor inference', async () => {
  const env = new Map<string, string>();
  const classNames = new Set(['Repository']);
  const nodes = parseAndFindNodes(parser, 'void f() { var repo = Repository<User>(); }', 'initialized_variable_definition');
  typeConfig.extractInitializer!(nodes[0], env, classNames);
  expect(env.get('repo')).toBe('Repository');
});

6. const/final constructor declarations

it('infers type from const constructor call', async () => {
  const env = new Map<string, string>();
  const classNames = new Set(['Config']);
  const nodes = parseAndFindNodes(parser, 'void f() { const config = Config(); }', 'initialized_variable_definition');
  typeConfig.extractInitializer!(nodes[0], env, classNames);
  expect(env.get('config')).toBe('Config');
});

7. End-to-end type env scenario

The most valuable integration-level addition: a test that verifies all tiers cooperate correctly through a realistic method dispatch scenario. This would live in the integration test file:

it('resolves receiver type for method dispatch through multi-tier inference', async () => {
  if (!(await loadDartOrSkip())) return;
  // Tier 0: param annotation → admin: User
  // Tier 1: constructor call → repo: Repository
  // Tier 2 copy: alias = admin → alias: User
  const code = `
    void process(User admin) {
      var repo = Repository();
      var alias = admin;
      alias.save();
      repo.findAll();
    }
  `;
  // Use buildTypeEnv (if exposed) or assert via call-graph integration
  // that alias.save resolves to User.save and repo.findAll resolves to Repository.findAll
});

Priority Summary

Test Area Current Coverage Value
extractDartForLoopBinding ❌ 0 tests High — 4 distinct paths
await in pending assignment ❌ 0 tests High — common Dart pattern
Named constructor in detectConstructorType ❌ 0 tests Medium
Missing literal variants (double, false, null) ⚠️ partial Medium
Generic type declarations ❌ 0 tests Medium
const/final constructor ❌ 0 tests Low — likely works, good to confirm
End-to-end multi-tier dispatch ❌ 0 tests High — validates tier interaction

For-loop element type resolution (3 tests):
- Explicit typed loop variable (for (User u in users))
- Call iterable return type inference (for (var u in getUsers()))
- Non-for_statement node rejection

Await in pending assignments (2 tests):
- Call result through await (var user = await getUser())
- Method call result through await (var user = await svc.fetch())

Virtual dispatch named constructor (2 tests):
- Named constructor returns class name (Dog.unknown() → Dog)
- Non-class callee returns undefined

Literal type inference full coverage (4 tests):
- double, false, null literals
- Unknown node type returns undefined

Generic and const declarations (3 tests):
- Generic List<String> extracts outer type
- Generic constructor call inference
- const constructor call inference

Total Dart tests: 88 (was 74)
@mrwogu

mrwogu commented Mar 26, 2026

Copy link
Copy Markdown
Contributor Author

Added the recommended type resolution tests:

For-loop element type resolution (3 tests):

  • Explicit typed loop variable (for (User u in users))
  • Call iterable return type inference (for (var u in getUsers()))
  • Non-for_statement node rejection

Await in pending assignments (2 tests):

  • var user = await getUser() → callResult
  • var user = await svc.fetch() → methodCallResult

Virtual dispatch — named constructor (2 tests):

  • Dog.unknown() returns Dog (class name, not member)
  • Non-class callee returns undefined

Literal types full coverage (4 tests):

  • double, false, null literals + unknown node returns undefined

Generic and const declarations (3 tests):

  • List<String> extracts outer type, generic constructor, const constructor

Total Dart tests now: 88 (was 58 → +30 new tests covering all recommended gaps)

Full local test suite: 113/114 pass, 4048 tests (1 pre-existing flaky lbug lock).

@magyargergo

Copy link
Copy Markdown
Collaborator

@claude Let's run a final review if this PR is production ready and ready to be merged

@github-actions

github-actions Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 3m 18s —— View job


Final Production-Readiness Review

Tasks:

  • Initialize review
  • Read current state of key changed files (queries, noise-filter, entry-point-scoring, type-extractor)
  • Verify all previously flagged issues are resolved
  • Check test coverage quality
  • Assess overall production readiness
  • Post final verdict

Verdict: ✅ Merge-Ready

CI is green (4320/4320 tests pass, tsc clean). All critical and high-severity issues from prior reviews have been resolved. The web module divergence is explicitly waived by @magyargergo.


✅ All Prior Issues Confirmed Resolved

Issue Resolution
CLI Flutter path detection (missing originally) main.dart/app.dart 3.0×, screens/pages/views 2.5×, routes 2.5×, bloc/cubit/presentation 2.0×, services/domain 1.8×, widgets 1.5×
Flutter + Riverpod AST patterns wired to SupportedLanguages.Dart ✅ Both entries in AST_FRAMEWORK_PATTERNS_BY_LANGUAGE[Dart]
context/of cross-language pollution in BUILT_IN_NAMES ✅ Removed — current filter has only Dart-specific entries
Suffix entry-point patterns (Widget$, Page$, Screen$, etc.) ✅ Removed — Dart entry-point patterns are now function-name-based only (build, initState, dispose, createState, etc.)
Vendored 200k-line parser.c ✅ Replaced with github:UserNobody14/tree-sitter-dart#0fc19c3 SHA dep
mixin_declaration positional vs. named field ✅ Confirmed correct — grammar does not expose a name: field; positional (identifier) is the right approach; Dart 3.x modifiers are keyword tokens, not identifiers, so they don't interfere
scanConstructorBinding constructor call match ✅ Fixed via parseDartRHS() with proper sibling AST traversal
Dart entry-point name patterns build, initState, dispose, createState, didChangeDependencies, didUpdateWidget, runApp, onEvent, mapEventToState
initialized_variable_definition value: field ✅ Confirmed works — parseDartRHS() additionally handles await/cascade cases

Architecture Assessment — Solid

  • defineLanguage() provider contract correctly implemented with all hooks: importResolver, typeConfig, exportChecker, importSemantics: 'wildcard'
  • satisfies Record<SupportedLanguages, ...> exhaustiveness checks give compile-time safety across all tables
  • Optional-dependency pattern (try/catch in parser-loader.ts) matches Swift precedent exactly
  • Type extractor tier 0→1→2 cascade is well-implemented; parseDartRHS() correctly models Dart's flat-sibling AST
  • Import resolver correctly handles dart: SDK skip, package: → lib/ resolution, relative fall-through
  • Export checker (_ prefix = private) is semantically correct

Test Coverage — Comprehensive

Test File Lines Scope
dart-type-extractor.test.ts 393 All type resolution tiers: annotations, for-loop, constructor inference, named constructors, await, literals, generics, const/final
dart-import-resolver.test.ts 79 dart: skip, package: resolution, external skip, relative delegation
tree-sitter-languages.test.ts (Dart section) ~200 Definitions, exports, imports, re-exports, heritage, calls (all 3 contexts), framework path detection with multiplier assertions

⚠️ Minor Items (Post-Merge Follow-Ups, Not Blocking)

1. Broad noise-filter entriespush, pop, add, close, emit were added to the global BUILT_IN_NAMES as "Dart async" entries. These exist in JavaScript (array.push/pop), Java (List.add, stream.close), Go (io.Close), and Node.js (EventEmitter.emit). They were not in the filter before this PR. Worth a targeted audit in a follow-up to confirm cross-language impact is acceptable given the existing broad precedent (e.g. map, filter, iter are already global).

2. Factory constructor name capturefactory Dog.unknown() captures Dog (class name) rather than unknown (variant name) due to positional match on factory_constructor_signature. Low severity; tests verify presence but not the specific captured name.

3. Extension type (Dart 3.x)extension type Meters(double _) uses a different grammar node (extension_type_declaration) not covered by current queries. Deferred by author.


Summary

The foundation is solid and the implementation is complete. All prior review rounds' critical and high-severity findings are resolved, CI is fully green, and test coverage is now comprehensive (88+ Dart-specific tests). Ready to merge. 🎯

@magyargergo

Copy link
Copy Markdown
Collaborator

Would you help us with looking into splitting up the BUILT_INS per languages? 🙏

…name capture

- Remove `add`, `close`, `emit` from global BUILT_IN_NAMES — `close` was
  previously removed intentionally for C POSIX, `add` hits Java/Python
- Fix factory constructor query: use adjacency operator to capture variant
  name (`unknown`) not class name (`Dog`) in `factory Dog.unknown()`
- Update test to assert exact factory constructor name capture
@mrwogu

mrwogu commented Mar 26, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the remaining post-merge items from the review:

  • Removed add/close/emit from global BUILT_IN_NAMESclose was previously removed intentionally for C POSIX (see the NOTE comment in noise-filter.ts), add collides with Java List.add() / Python set.add()
  • Fixed factory constructor name capture — used . adjacency operator so factory Dog.unknown() captures unknown (variant name), not Dog (class name). Test now asserts exact name.

Regarding splitting BUILT_IN_NAMES per language — happy to take that on as a separate PR. The current global Set has accumulated entries from 14 languages and there are clear collision risks (e.g. push/pop are JS array methods but also stack operations in C, map/filter appear in JS/Python/Rust/Swift). A per-language approach would eliminate false-positive noise suppression across languages. I'll open a follow-up issue for it.

@magyargergo

Copy link
Copy Markdown
Collaborator

@claude Let's run a final review if this PR is production ready and ready to be merged

@github-actions

github-actions Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 2m 36s —— View job


Tasks:

  • Initialize review
  • Read current state of key changed files
  • Verify all previously flagged issues are resolved
  • Check test coverage quality
  • Assess overall production readiness
  • Post final verdict

Final Production-Readiness Review

Verdict: ✅ Merge-Ready

CI is green (4320/4320 tests pass, tsc --noEmit clean). All critical and high-severity issues from prior review rounds are resolved. The web module divergence is explicitly waived by @magyargergo pending a unification effort.


✅ All Prior Issues Confirmed Resolved

Issue Status
CLI Flutter path detection (missing originally) main.dart/app.dart 3.0×, screens/pages/views 2.5×, routes 2.5×, bloc/cubit/presentation 2.0×, services/domain 1.8×, widgets 1.5×
Flutter + Riverpod AST patterns wired to SupportedLanguages.Dart ✅ Both flutter and riverpod keys in AST_FRAMEWORK_PATTERNS_BY_LANGUAGE[Dart]
context/of cross-language pollution ✅ Removed — only Dart-specific identifiers remain in the Dart section
add/close/emit cross-language pollution ✅ Removed — confirmed by reading noise-filter.ts:158–165
Suffix entry-point patterns (Widget$, Page$, etc.) ✅ Removed — Dart entry-point patterns are now function-name-based only
Vendored 200k-line parser.c ✅ Replaced with github:UserNobody14/tree-sitter-dart#0fc19c3 SHA dep
mixin_declaration positional vs. named field ✅ Confirmed correct — grammar has no name: field; Dart 3.x modifiers are keyword tokens, not identifiers
scanConstructorBinding constructor call match ✅ Fixed via parseDartRHS() with flat-sibling AST traversal
Entry-point name patterns build, initState, dispose, createState, didChangeDependencies, didUpdateWidget, runApp, onEvent, mapEventToState
Factory constructor name capture (Dog.unknown()Dog) ✅ Fixed with . adjacency operator — (identifier) @name . (formal_parameter_list) captures unknown, test asserts exact name
initialized_variable_definition value: field ✅ Field exists and works; parseDartRHS() additionally handles await/cascade
type_alias query ordering ✅ Confirmed correct — generic type_parameters between identifier and = makes . adjacency impossible; presence check is sufficient

Architecture Assessment — Solid

  • defineLanguage() provider contract fully implemented: importResolver, typeConfig, exportChecker, importSemantics: 'wildcard'
  • satisfies Record<SupportedLanguages, ...> exhaustiveness checks give compile-time safety across all tables (entry-point-scoring.ts, framework-detection.ts, language-queries.ts)
  • Optional-dependency pattern (try/catch in parser-loader.ts) matches Swift precedent exactly
  • parseDartRHS() correctly models Dart's flat-sibling AST (no nested call_expression wrapper)
  • Import resolver correctly handles dart: SDK skip, package: → lib/ resolution, relative fall-through
  • Export checker (_ prefix = private) is semantically correct for Dart

Test Coverage — Comprehensive (88 Dart-specific tests)

Test File Scope
dart-type-extractor.test.ts (54 tests) All type resolution tiers: annotations, nullable unwrapping, for-loop paths, constructor inference (direct + named), await, literals (int/double/bool/null/unknown), generics, const/final, virtual dispatch, copy/field/call/method result pending assignments
dart-import-resolver.test.ts (7 tests) dart: skip, package: → lib/, external package skip, relative delegation, quote stripping
tree-sitter-languages.test.ts — Dart section (27 tests) Definitions (all types), factory constructor name, getter/setter, typedef without duplicates, private _ filtering, imports, re-exports, heritage (extends/implements/with), calls in all 3 contexts, framework path detection with multiplier assertions

⚠️ Minor Post-Merge Follow-Ups (Non-Blocking)

1. push/pop in global BUILT_IN_NAMES — these were already present in the JS section (line 25) and Rust section (line 143) before this PR; the Dart section duplicates them in a Set so there's no net change. The de-facto cross-language collision was pre-existing. The broader BUILT_INS-per-language refactor (which @mrwogu has agreed to open as a follow-up issue) is the right venue.

2. Navigator as a class name in BUILT_IN_NAMES — slightly unusual to filter class names rather than method names, but it's a Flutter-specific symbol unlikely to appear as a meaningful call node in non-Flutter code.

3. Extension types (Dart 3.x)extension type Meters(double _) uses extension_type_declaration node, not covered. Intentionally deferred.

4. @definition.class for extension_declaration — semantic conflation deferred by author.

5. Web module divergence — explicitly waived; @magyargergo is working on unifying the two modules.


Summary

The implementation is production-quality. The architecture is clean, all blocking issues from three prior review rounds are resolved, test coverage is comprehensive, CI is fully green, and the tree-sitter-dart dependency is correctly pinned via GitHub SHA (tracking upstream NAPI migration). Ready to merge. 🎯

@magyargergo magyargergo merged commit 8864a02 into abhigyanpatwari:main Mar 26, 2026
9 of 10 checks passed
@mrwogu mrwogu deleted the feature/dart-language-support branch March 26, 2026 08:43
xFlaviews added a commit to xFlaviews/GitNexus that referenced this pull request Mar 26, 2026
Four issues that were not addressed in PR abhigyanpatwari#204:

1. extractFunctionName: add function_signature/method_signature handlers
   and add both to FUNCTION_NODE_TYPES. Without this, findEnclosingFunctionId
   cannot resolve Dart function scopes — all calls inside Dart functions
   have no sourceId, breaking CALLS edge attribution.

2. formal_parameter_list: add to paramListTypes in extractMethodSignature.
   Dart's tree-sitter grammar uses this node type (not formal_parameters),
   so parameter counting returns 0 for all Dart functions.

3. Write-access queries: add @assignment patterns for obj.field = value
   and this.field = value. Without these, no ACCESSES write edges are
   emitted for Dart code.

4. initialized_identifier guard in extractDartDeclaration: comma-separated
   declarations (String a, b, c) produce initialized_identifier nodes
   which are in DART_DECLARATION_NODE_TYPES but were unhandled — the type
   lives on the parent node.

Also adds Dart column to the feature matrix in type-resolution-system.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@xFlaviews

Copy link
Copy Markdown
Contributor

Hey @mrwogu @magyargergo — glad my type resolution work from #83 was useful!

Since the maintainer suggested we collaborate and my Tier 0-2 type extractor was adopted directly, could a Co-Authored-By: Flavius flaviusmironcatalin@gmail.com be added?

A code comment is appreciated but doesn't show up in GitHub contributions haha. Thanks!

@magyargergo

Copy link
Copy Markdown
Collaborator

@xFlaviews i'll add you to the contributors when we release :) Thank you both for your contributions! I found one unhandled case but I'm now adding a fix to it in a separate PR :)

xFlaviews added a commit to xFlaviews/GitNexus that referenced this pull request Mar 26, 2026
Dart was added as the 14th supported language in PR abhigyanpatwari#204 but the README
was not updated. Adds Dart row to the supported languages table and
updates the language count from 13 to 14.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
magyargergo pushed a commit that referenced this pull request Mar 26, 2026
Dart was added as the 14th supported language in PR #204 but the README
was not updated. Adds Dart row to the supported languages table and
updates the language count from 13 to 14.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
magyargergo added a commit that referenced this pull request Mar 26, 2026
* fix: close remaining Dart language support gaps

Four issues that were not addressed in PR #204:

1. extractFunctionName: add function_signature/method_signature handlers
   and add both to FUNCTION_NODE_TYPES. Without this, findEnclosingFunctionId
   cannot resolve Dart function scopes — all calls inside Dart functions
   have no sourceId, breaking CALLS edge attribution.

2. formal_parameter_list: add to paramListTypes in extractMethodSignature.
   Dart's tree-sitter grammar uses this node type (not formal_parameters),
   so parameter counting returns 0 for all Dart functions.

3. Write-access queries: add @assignment patterns for obj.field = value
   and this.field = value. Without these, no ACCESSES write edges are
   emitted for Dart code.

4. initialized_identifier guard in extractDartDeclaration: comma-separated
   declarations (String a, b, c) produce initialized_identifier nodes
   which are in DART_DECLARATION_NODE_TYPES but were unhandled — the type
   lives on the parent node.

Also adds Dart column to the feature matrix in type-resolution-system.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dart): field-type resolution, call attribution, import resolution, and integration tests

Fixes five Dart language support gaps with integration tests and
architectural alignment:

**Tree-sitter queries** — Add field declaration patterns for typed and
nullable class fields (`String name = ''`, `String? name`).  Without
these, Dart class fields were invisible to the pipeline (zero Property
nodes, zero HAS_PROPERTY edges).

**Import resolution** — Dart relative imports (`import 'models.dart'`)
don't use a leading `./`.  The standard resolver only recognises paths
starting with `.` as relative; bare paths fell through to a Java-style
dot-to-slash conversion that mangled `models.dart` into `models/dart`.
Fix: prepend `./` before calling resolveStandard.

**Call attribution** — Dart's tree-sitter grammar places `function_body`
as a sibling of `function_signature`, not as a child wrapping both.  The
`findEnclosingFunction` parent-walk never found the function because the
call lives inside `function_body` which is a sibling of the signature.
Fix: add `enclosingFunctionFinder` hook to LanguageProvider interface
(following the same strategy pattern as `labelOverride`), with the
Dart-specific logic in `languages/dart.ts`.  Both `parse-worker.ts` and
`call-processor.ts` consume the hook generically — no Dart-specific code
in the generic processors.

**Receiver chain extraction** — Add `unconditional_assignable_selector`
to `MEMBER_ACCESS_NODE_TYPES` so `inferCallForm` returns `'member'` for
Dart method calls.  Add Dart-specific receiver extraction blocks in
`extractReceiverName`, `extractReceiverNode`, and a `selector` handler
in `extractMixedChain` for Dart's flat sibling-selector model (vs the
nested member-expression model used by all other languages).

**Integration tests** — New `dart.test.ts` with field-type resolution
and call-result-binding describe blocks.  Fixtures: `dart-field-types/`
(models.dart + app.dart) and `dart-call-result-binding/` (models.dart +
app.dart).  9 passing tests, 1 skipped (ACCESSES edges for field reads
depend on type-env parameter binding propagation — tracked for follow-up).

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>
@xFlaviews

Copy link
Copy Markdown
Contributor

Hey @magyargergo just noticed I'm not in the v1.4.9 contributors list 🙈

@magyargergo

Copy link
Copy Markdown
Collaborator

Hey @magyargergo just noticed I'm not in the v1.4.9 contributors list 🙈

Now you are on ;)

motolese pushed a commit to motolese/datamoto-gitnexus that referenced this pull request Apr 23, 2026
motolese pushed a commit to motolese/datamoto-gitnexus that referenced this pull request Apr 23, 2026
…i#525)

Dart was added as the 14th supported language in PR abhigyanpatwari#204 but the README
was not updated. Adds Dart row to the supported languages table and
updates the language count from 13 to 14.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
motolese pushed a commit to motolese/datamoto-gitnexus that referenced this pull request Apr 23, 2026
* fix: close remaining Dart language support gaps

Four issues that were not addressed in PR abhigyanpatwari#204:

1. extractFunctionName: add function_signature/method_signature handlers
   and add both to FUNCTION_NODE_TYPES. Without this, findEnclosingFunctionId
   cannot resolve Dart function scopes — all calls inside Dart functions
   have no sourceId, breaking CALLS edge attribution.

2. formal_parameter_list: add to paramListTypes in extractMethodSignature.
   Dart's tree-sitter grammar uses this node type (not formal_parameters),
   so parameter counting returns 0 for all Dart functions.

3. Write-access queries: add @assignment patterns for obj.field = value
   and this.field = value. Without these, no ACCESSES write edges are
   emitted for Dart code.

4. initialized_identifier guard in extractDartDeclaration: comma-separated
   declarations (String a, b, c) produce initialized_identifier nodes
   which are in DART_DECLARATION_NODE_TYPES but were unhandled — the type
   lives on the parent node.

Also adds Dart column to the feature matrix in type-resolution-system.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(dart): field-type resolution, call attribution, import resolution, and integration tests

Fixes five Dart language support gaps with integration tests and
architectural alignment:

**Tree-sitter queries** — Add field declaration patterns for typed and
nullable class fields (`String name = ''`, `String? name`).  Without
these, Dart class fields were invisible to the pipeline (zero Property
nodes, zero HAS_PROPERTY edges).

**Import resolution** — Dart relative imports (`import 'models.dart'`)
don't use a leading `./`.  The standard resolver only recognises paths
starting with `.` as relative; bare paths fell through to a Java-style
dot-to-slash conversion that mangled `models.dart` into `models/dart`.
Fix: prepend `./` before calling resolveStandard.

**Call attribution** — Dart's tree-sitter grammar places `function_body`
as a sibling of `function_signature`, not as a child wrapping both.  The
`findEnclosingFunction` parent-walk never found the function because the
call lives inside `function_body` which is a sibling of the signature.
Fix: add `enclosingFunctionFinder` hook to LanguageProvider interface
(following the same strategy pattern as `labelOverride`), with the
Dart-specific logic in `languages/dart.ts`.  Both `parse-worker.ts` and
`call-processor.ts` consume the hook generically — no Dart-specific code
in the generic processors.

**Receiver chain extraction** — Add `unconditional_assignable_selector`
to `MEMBER_ACCESS_NODE_TYPES` so `inferCallForm` returns `'member'` for
Dart method calls.  Add Dart-specific receiver extraction blocks in
`extractReceiverName`, `extractReceiverNode`, and a `selector` handler
in `extractMixedChain` for Dart's flat sibling-selector model (vs the
nested member-expression model used by all other languages).

**Integration tests** — New `dart.test.ts` with field-type resolution
and call-result-binding describe blocks.  Fixtures: `dart-field-types/`
(models.dart + app.dart) and `dart-call-result-binding/` (models.dart +
app.dart).  9 passing tests, 1 skipped (ACCESSES edges for field reads
depend on type-env parameter binding propagation — tracked for follow-up).

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>
@xFlaviews

Copy link
Copy Markdown
Contributor

@magyargergo last mention sorry haha

saw i'm not on the contributors list, any clue why?

thank you very much man and sorry for the bother!

@magyargergo

Copy link
Copy Markdown
Collaborator

@magyargergo last mention sorry haha

saw i'm not on the contributors list, any clue why?

thank you very much man and sorry for the bother!

You are on!

image

I just checked https://github.com/abhigyanpatwari/GitNexus/graphs/contributors

@xFlaviews

Copy link
Copy Markdown
Contributor

I'm blind haha

Thank you man!!! You're rocking!!

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.

5 participants