Skip to content

Dart: getter reads and enum-extension methods get no callers (1.6.2) #2338

Description

@brookly255-lv

Hi, and thanks for CodeGraph. It's been the most accurate code graph I've tried on a mixed Dart/TypeScript codebase.

While working on a project of mine I asked for the callers of a small getter I'd added on an enum, and CodeGraph said nothing calls it. In fact it's used in several places. I cut it down to a minimal example and found two separate gaps.

Version: CodeGraph 1.6.2 (standalone install, linux-x64), fresh codegraph index .

lib/shape.dart

enum Shape { circle, square }

extension ShapeInfo on Shape {
  String get label => name.toUpperCase();
  String shout() => name.toUpperCase();
}

class Box {
  const Box(this.size);
  final int size;
  int get area => size * size;
  int grow() => size + 1;
}

extension BoxActions on Box {
  int twice() => size * 2;
}

lib/use.dart

import 'shape.dart';

String a(Shape s) => s.label;   // getter, extension on enum
String b(Shape s) => s.shout(); // method, extension on enum
int c(Box x) => x.area;         // getter, plain class
int d(Box x) => x.grow();       // method, plain class
int e(Box x) => x.twice();      // method, extension on class
codegraph callers … expected got
grow d ✅ d
twice e ✅ e
area c ❌ 0 callers
label a ❌ 0 callers
shout b ❌ 0 callers

1. Getter reads are never recorded as calls, even on a plain class (x.area). The getter itself is indexed (Box::area), but nothing links to it, so callers and impact miss every place that reads it.

2. Extension members on an enum aren't resolved, while the same thing on a class works (twice).

It's the same inside block-bodied functions and inside class methods, not only => functions.

Happy to test a fix if that helps.

Activity

  1. colbymchenry commented on Oct 5, 2026

    @colbymchenry
    Owner

    Thanks @brookly255-lv for the kind words, and for cutting this down to one small example that covered both gaps.

    Both are fixed on main in #2360:

    • Getter reads. Dart only recorded member accesses that had an argument list, so x.area produced nothing. A read like x.area or s.label now counts as calling the getter. The getter is found through the receiver's declared type: on the class, inherited from a supertype or mixin, or added by an extension. A plain field read, a getter of a type from outside your project, or a receiver whose type isn't written down still links nothing, so callers doesn't fill up with guesses.
    • Extension members on an enum. Method lookup on a typed receiver didn't consider extensions. twice on Box only worked because it was the one twice in the project, and an enum receiver stopped lookup outright. When the type itself has no member of that name, lookup now goes on to members an extension adds, so s.shout() reaches ShapeInfo.shout.

    On your example, callers area, callers label and callers shout now return c, a and b, and grow and twice are unchanged. On bloc, riverpod and flutter/samples, this added several hundred getter-read links per project and removed none.

    This ships in the next release. Re-index after upgrading (codegraph index) to pick it up. You're credited in the changelog, and if you get a chance to try it on your mixed Dart/TypeScript project, feedback is very welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions