#1784·codegraph

Dart: `extension type` members stopped being indexed in #1780 — the `method_signature` gate has no language check

Author: bompusCreated Sep 8, 2026Updated Sep 14, 2026

Dart: extension type members stopped being indexed in #1780 — the method_signature gate has no language check

ee83636 (#1780, fixing #1638) gates a bodiless method_signature behind isInsideClassLikeNode(). That is correct for TypeScript, but Dart spells ordinary implemented methods method_signature too (src/extraction/languages/dart.tsmethodTypes: ['method_signature', 'constructor_signature']), and a Dart 3 extension type body is not class-like. Its members now miss the method branch and are dropped entirely.

Reproduction

extension type MetersT(double value) {
  double get km => value / 1000;
}
const r = await extractFromSource('probe.dart', src, 'dart');
r.nodes.filter(n => n.kind !== 'file').map(n => `${n.kind}:${n.qualifiedName}`)
commit result
8c04734 (parent) ["function:km"]
ee83636 (#1780) []
e720f6c (current main) []

Same working tree, same node_modules, same probe; only the checkout changed. km goes from indexed to invisible.

Scope — what is and isn't affected

Ran the same probe across the neighbouring constructs on both commits:

case 8c04734 e720f6c
Dart extension type function:km []
Dart extension class:StringHelpers, method:StringHelpers::shout unchanged
Dart mixin class:Logger, method:Logger::log unchanged
Dart class class:Widget, method:Widget::build unchanged
TS interface interface:Iface interface:Iface, method:Iface::go
TS type literal method:Handle::stop, type_alias:Handle unchanged

So #1780 does what it set out to do — the TS interface-member row is the fix working, and the type-literal row confirms it did not reintroduce the phantom free function from #359. extension, mixin and class are unaffected because their bodies satisfy isInsideClassLikeNode(). extension type is the only construct that regressed.

Cause

extension_type_declaration is a node type in the bundled src/extraction/wasm/tree-sitter-dart.wasm, but it appears nowhere in src/extraction/languages/dart.ts — not in classTypes (only class_definition), not in extraClassNodeTypes (only mixin_declaration, extension_declaration), not in enumTypes. Nothing mints a class-like parent for its body, so isInsideClassLikeNode() is false for double get km.

Note the pre-#1780 result was already imperfect — km was minted as a top-level function rather than a member of MetersT, since no class-like node exists for the extension type. The regression is that it went from mis-kinded to absent.

Two possible fixes

  1. Narrow the gate by language, which is what we carry downstream:

    const SIGNATURE_METHOD_LANGUAGES = new Set(['typescript', 'tsx', 'arkts']);
    // ...
    && (!SIGNATURE_METHOD_NODE_TYPES.has(nodeType)
      || !SIGNATURE_METHOD_LANGUAGES.has(this.language)
      || this.isInsideClassLikeNode())
    

    Restores function:km and keeps every TS row above green.

  2. Teach Dart about extension types — add extension_type_declaration to extraClassNodeTypes. Strictly better, because it also fixes the pre-existing mis-kinding: km would become method:MetersT::km rather than a top-level function. I have not measured this one, so treat it as a suggestion rather than a tested patch.

They are not exclusive; (2) alone would fix this case, but (1) is the general guard for any other language that reuses method_signature for implemented methods.

Why CI didn't catch it

There appears to be no Dart extraction fixture exercising extension type (or, as far as I can see, a Dart parity fixture at all). We caught this only because our downstream fork runs a Rust-kernel-vs-TypeScript parity suite over a Dart torture fixture, where it surfaced as a node-count mismatch (91 vs 90) across torture.dart and TortureCtors.dart including their CRLF variants. A extension type case in the Dart extraction tests would pin it.

Environment: Windows 11, Node v26.8.1, vitest 2.1.9, bundled tree-sitter-dart.wasm.