Skip to content

Dart: class field 'children' list never populated (dead identifier-scan in extractDartClassMembers) #2475

Description

@carlos-alm

Context

Discovered while implementing #2319 (Dart typeMap population for field/parameter types).

src/extractors/dart.ts's extractDartClassMembers has a "Field declarations" loop meant to push each field into the class definition's children: SubDeclaration[] array (used to list a class's properties, e.g. for codegraph show ClassName-style output):

// Field declarations
for (let j = 0; j < member.childCount; j++) {
  const decl = member.child(j);
  if (decl?.type === 'identifier') {
    children.push({ name: decl.text, kind: 'property', line: member.startPosition.row + 1 });
    break;
  }
}

This scans member's (a declaration node) DIRECT children for a node of type identifier. But for every real Dart field-declaration shape (final Foo x;, Foo x;, late Foo x;, Foo? x;, final Foo a, b;), the field's identifier is nested TWO levels deep — declaration -> initialized_identifier_list -> initialized_identifier -> identifier — never a direct child of declaration itself. Dart requires every field to carry a var/final/const/late/type modifier, so there is no legal field-declaration shape where identifier IS a direct child of declaration.

Confirmed empirically: parsing class UserService { final UserRepository _repo; UserService(this._repo); } and checking symbols.definitions.find(d => d.name === 'UserService').children returns undefined — the field is silently never recorded.

Net effect: Dart class definitions' children array is always empty for real code — this loop is dead code that has presumably never fired since Dart support was added.

Suggested fix direction

Rewrite the loop to walk initialized_identifier_list -> initialized_identifier -> identifier, mirroring the (already-correct) same-shape traversal added in #2319's handleDartFieldDeclTypeMap/extractDartDeclaredTypeName. Also verify/fix the Rust mirror in crates/codegraph-core/src/extractors/dart.rs's extract_dart_class_methods, which has the analogous gap (it currently continues on any class_member that isn't a method/bodyless-signature, without ever recording a field child either).

Low-severity — doesn't affect call resolution or the resolution benchmark, only the children listing on Dart class definitions — but worth fixing since it's presumably surprising to anyone using codegraph show or similar against Dart code today.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions