feat(kernel): R7b Dart walker — dart module, vendored-grammar-C d4d8f3e + wasm byte-copy vendor, dart default-routed (#1386)

R7b batch 4 #4 — the FINAL R7b language (docs/design/dart-kernel-port-checklist.md
is the authoritative quirk list). The fourth vendored-grammar-C language,
with a twist: production dart resolved its wasm from tree-sitter-wasms,
whose dart dependency is an UNPINNED github:UserNobody14/tree-sitter-dart —
a routine dependency update would have silently changed dart's grammar.
This PR byte-copies the shipping 0.1.13 artifact into src/extraction/wasm/
(VENDORED_WASM_LANGS += dart) and compiles the same-commit (d4d8f3e337d8)
parser.c/scanner.c in the kernel — table identity proven by the
kernel-grammar-parity row. crates.io tree-sitter-dart is the nielsenko
fork (different lineage) — rejected.

The center of gravity is THE SIBLING-BODY DOUBLE-WALK, reproduced
bug-for-bug: dart attaches every function/method body as a NEXT SIBLING of
its signature, and the TS walkers consume each body TWICE — once via
resolveBody (attributed to the function/method) and once via the enclosing
generic walk (attributed to the file/class). Duplicate local-function
nodes with the SAME id under different parents, duplicated
calls/instantiates refs, and file/class-attributed fn-ref twins all emit
in the exact observed interleave (a dedicated fixture pins the
duplicate-id rows; the bloc kind-census spot-check pins the counts).

Also preserved (probe-pinned): the extractBareCall selector matrix (the
first callTypes=[] language — cascades completely invisible, `?.` encodes
like `.`, the `ConfigT.load()` calls+references double emission with no
callee-of-call skip, capitalized-chain `Foo.create().run` re-encode,
const-object callee names); the constructor hooks (unnamed ctor skipped,
named ctors/factories renamed to the CTOR name with the class as
returnType, `@override (T) m()` record-misparse rescued by class-name
validation); operator methods minting `method "<anonymous>"`;
static_final_declaration constants via the visitNode hook while instance
fields mint NOTHING; the prefixed-return-type prefix bug (`other.OtherClass
f()` → returnType `other`); enum `with` mixins silent vs `implements`
working; anonymous extensions named after the ON type; deferred imports
invisible; named-argument callbacks NOT fn-ref-captured (the Flutter
`onPressed:` idiom — future accuracy PR, TS-side first); `async*`/`sync*`
NOT async; value-refs with the LIVE dart sibling-body pull and the
`$X`-vs-`${X}` interpolation asymmetry; dartdoc kept in all three comment
forms with the annotation-broken chain.

Gates: parity sweeps first-run 0-diff on shelf/bloc/flutter — 5,815 clean
files byte-parity, deferrals 10/21/1341 ≈ the survey's 10/21/~1340
(both-arm grammar reality: empty object patterns — the sealed-class
idiom — and unnamed `library;` dominate; --max-deferral 0.3); full-init
dumps byte-identical ×3 (shelf 7,959 / bloc 40,026 / flutter 1,855,319
dump lines); bloc per-kind node census identical across arms (the
double-walk duplicate rows survive the store identically);
kernel-dart-parity suite (7 fixtures + in-memory CRLF variants +
double-walk duplicate-id pin + generated-file skip pin + two defer pins);
full suite 2,688 green ×2 with CODEGRAPH_KERNEL_EXPECT=1.
DEFAULT_ROUTED += dart (20 langs — R7b COMPLETE).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-07-20 19:55:48 -05:00
committed by GitHub
co-authored by Claude Fable 5
parent bdd687b49f
commit d1b75a1a27
26 changed files with 204077 additions and 6 deletions
@@ -0,0 +1,39 @@
/** Block dartdoc for blockDoc. */
void blockDoc() {}
/// Line doc kept.
// Plain comment also kept?
void mixedDoc() {}
// Only plain.
void plainDoc() {}
extension type Meters(double value) {
double get km => value / 1000;
void report() {
print(km);
}
}
class Action {
@override
(int, String) reduce() => (1, 'a');
void caller() {
this.own();
super.parent();
generic<int>(5);
final t = reduce();
}
}
enum Flag { on, off }
void flagUse(Flag f) {
final v = Flag.on;
switch (f) {
case Flag.off:
use(v);
default:
break;
}
}
@@ -0,0 +1,82 @@
final topFinal = seedValue();
const topConst = 42;
var topVar = 7;
int topTyped = 8;
final multiA = 1, multiB = 2;
int seedValue() => 9;
void hostFn() {
void localFn(int n) {
inner(n);
}
localFn(3);
int localWithNew() {
final w = new Holder(1);
return w.n;
}
localWithNew();
}
class Holder {
final int n;
final untypedInit = 5;
static var mutable = 3;
Holder(this.n);
Holder.other() : n = compute();
void useNew() {
final h = new Holder(2);
void methodLocal() {
h.touch();
}
methodLocal();
}
int get computed => helperCall();
}
void takeConst() {
pad(const EdgeInsets.all(8.0));
make(const Holder(3));
}
Future<int> asyncFn() async => 1;
Stream<int> genFn() async* {
yield 1;
}
Iterable<int> syncGen() sync* {
yield 2;
}
/// Doc for annotated.
@deprecated
void annotated() {}
@Deprecated('use other')
class OldClass {}
@pragma('vm:entry-point')
void pragged() {}
class Cfg {
static const retries = 3;
}
void reader() {
use(Cfg.retries);
final msg = 'retry $topConst times ${topFinal}';
print(msg);
}
void shadower() {
final topConst = 1;
use(topConst);
}
void refTaker() {
register(seedValue);
obj.cb = seedValue;
final table = [seedValue, hostFn];
final map = {'k': seedValue, 'j': notDefinedHere};
reg2(cb: seedValue);
final alias = seedValue;
}
@@ -0,0 +1,26 @@
void assigned() {}
void listed() {}
void mapped() {}
void selfStore() {}
class H {
var cb;
void wire(dynamic selfStore) {
this.cb = assigned;
cb = selfStore;
}
}
final tableTop = [listed];
final mapTop = {'k': mapped};
void aliased() {}
final aliasTop = aliased;
class K {
static final aliasStatic = aliased;
}
void onlyNamed() {}
void otherFn() {}
void positional() {}
void taker() {
reg(cb: onlyNamed);
reg2(handler: otherFn, plain: 1);
reg3(positional);
}
@@ -0,0 +1,77 @@
import 'dart:async';
import 'package:foo/bar.dart' as bar show Baz hide Qux;
import 'pkg.dart' deferred as lazy;
export 'src/out.dart' show Pub;
part 'part1.dart';
/// Doc line one.
/// Doc line two.
void topFn(int a, String b) {
var local = 5;
int typed = 6;
final con = 7;
int uninit;
uninit = 8;
local = a;
helper(a);
obj.method(a);
Config.setting;
Config.load();
w?.render();
list..add(1)..add(2);
final w2 = Widget(1);
final w3 = new Widget(2);
const e = EdgeInsets.all(8.0);
Foo.create().run();
lower().chain();
print('sum ${a + compute()} $local');
}
// plain comment
int get topGetter => 42;
set topSetter(int v) {}
class Widget extends Base with Mix1, Mix2 implements Draw, Paint {
static const int kMax = 10;
static final shared = Widget(0);
final int size;
int count = 0;
var loose;
late String name;
Widget(this.size);
Widget.named(this.size) { init(); }
factory Widget.create() => Widget(1);
Widget._() : size = 0;
@override
void render(Canvas c) { c.draw(); }
static Widget make() => Widget(3);
int get area => size * size;
set area(int v) { count = v; }
Future<void> load() async { await fetch(); }
operator +(Widget o) => Widget(size + o.size);
}
mixin Mix1 on Base {
void mixMethod() { helper(0); }
}
extension WidgetExt on Widget {
void extMethod() { render(null); }
}
enum Color { red, green, blue }
enum Status with Mix1 implements Draw {
ok(200),
err(500);
final int code;
const Status(this.code);
bool get good => code < 400;
static Status parse(int c) => ok;
}
typedef IntFn = int Function(int);
typedef void OldStyle(int x);
abstract class Base {}
class Draw {}
@@ -0,0 +1,42 @@
library my.lib;
part of 'other.dart';
void params({int? a, required Widget child, String note = 'x'}) {}
void optional([int b = 0, Widget? w]) {}
void fnTypedParam(void cb(int x), int Function(String) modern) {}
num numRet(num n) => n;
dynamic dynRet(dynamic d) => d;
Object objRet(Object o) => o;
double dblRet(double d) => d;
external void externalFn();
class Redir {
Redir();
Redir.a() : this();
const factory Redir.b() = RedirImpl;
}
void lambdas(List<int> xs) {
xs.forEach((e) => use(e));
final f = (int a) {
helper(a);
};
f(1);
xs.map((e) => e * 2).toList();
}
void bodyTypes(Object x) {
if (x is Widget) {
use(x);
}
final y = x as Widget;
final list = <Widget>[];
final map = <String, Widget>{};
throw StateError('bad');
}
@override
@protected
void doubleAnno() {}
@@ -0,0 +1,61 @@
import 'package:foo/util.dart' as util;
const SHARED_MAX = 10;
const kLimit = 20;
final DERIVED = SHARED_MAX + 1;
const low = 30;
class Table {
static const COL_LIMIT = 5;
static const plain = 6;
void reads() {
use(SHARED_MAX);
use(Table.COL_LIMIT);
log('cap $kLimit and ${SHARED_MAX}');
}
void shadowed() {
final SHARED_MAX = 1;
use(SHARED_MAX);
}
}
void freeReader() {
use(kLimit);
}
void uninitShadow() {
int DERIVED;
DERIVED = 2;
use(DERIVED);
}
void assignOnly() {
low = 5;
}
void prefixedCalls() {
util.helper(1);
util.Config.load();
Widget.named(2);
}
/// Doc on classy.
class Classy {}
/// Doc on num const?
const DOCED = 1;
/// Doc on enum.
enum E2 { a }
/// Doc broken.
@override
void afterAnno() {}
/// Kept doc.
void unicodeNext() {}
// π and émoji 🎯 in a comment
void afterUnicode(String s) {
emit('café ☕ done');
}
@@ -0,0 +1,231 @@
/// File-level doc for torture (glued to import? no — imports precede nothing).
import 'dart:async';
import 'package:torture/other.dart' as other show OtherClass;
export 'src/reexported.dart' hide Hidden;
part 'torture_part.dart';
/// Doc line one.
/// Doc line two.
void topLevel(int count, String label) {
helper(count);
}
/** Block dartdoc kept. */
int blockDoc() => 1;
// Plain comment doc.
String plainDoc() => 'x';
/// Broken by annotation.
@deprecated
void annotated() {}
@Deprecated('with args')
@pragma('vm:entry-point')
void doubleAnno() {}
const SHARED_MAX = 10;
final DERIVED_VAL = SHARED_MAX + 1;
const lowercase_const = 1;
final typedTop = compute();
var topVar = 5;
int topTyped = 6;
final multiA = 1, multiB = 2;
int get topGetter => 7;
set topSetter(int v) {}
Future<String> asyncFn() async => 'a';
Stream<int> genStar() async* {
yield 1;
}
Iterable<int> syncStar() sync* {
yield 2;
}
num numback(num n) => n;
dynamic dyn(dynamic d) => d;
Object obj(Object o) => o;
List<WidgetT> listRet(Map<String, WidgetT> m) => [];
WidgetT? nullableRet() => null;
other.OtherClass prefixedRet() => other.OtherClass();
T generic<T>(T v) => v;
external void externalFn();
void params({int? named, required WidgetT child, String note = 'x'}) {}
void optionals([int pos = 0, WidgetT? w]) {}
void fnTyped(void cb(int x), int Function(String) modern) {}
void bodyShapes(List<int> xs, Object o) {
var local = 1;
int typed = 2;
final con = 3;
int uninit;
uninit = 4;
local = uninit;
helper(local);
obj.method(local);
this_like.deep.call3(local);
ConfigT.load();
ConfigT.setting;
w?.render();
y2..add(1)..add(2);
final w1 = WidgetT(1);
final w2 = new WidgetT(2);
pad(const EdgeInsetsT.all(8.0));
FactoryT.create().run();
lower().chain();
WidgetT.named(3).chainTail();
xs.map((e) => e * 2).toList();
xs.forEach((e) => use(e));
final lam = (int a) {
helper(a);
};
lam(5);
void localFn(int n) {
inner(n);
}
localFn(6);
if (o is WidgetT) {
use(o);
}
final cast = o as WidgetT;
final tl = <WidgetT>[];
throw StateError('bad');
}
void interpolation(int count) {
log('count $count and ${SHARED_MAX} via ${refresh()}');
}
void refTaker() {
register(topLevel);
obj.cb = topLevel;
final table = [topLevel, blockDoc];
final m = {'k': topLevel, 'x': undefinedName};
reg2(cb: topLevel);
forward(topLevel: topLevel);
final alias = topLevel;
}
/// Class doc.
@immutable
class WidgetT extends BaseT with MixA, MixB implements DrawT {
static const int K_MAX = 9;
static final sharedInst = WidgetT(0);
static var mutableStatic = 1;
final int size;
final untyped = 5;
int counter = 0;
late String title;
WidgetT(this.size);
WidgetT.named(this.size) {
init();
}
WidgetT.bodilessNamed() : size = seed();
factory WidgetT.create() => WidgetT(1);
const factory WidgetT.redir() = WidgetT2;
@override
void render(CanvasT c) {
c.draw();
}
static WidgetT make() => WidgetT(3);
int get area => size * size;
set area(int v) {
counter = v;
}
bool get privado => _check();
bool _check() => true;
Future<void> load() async {
await fetch();
}
WidgetT operator +(WidgetT o) => WidgetT(size + o.size);
void useLocalNew() {
final h = new HolderT(2);
use(h);
}
void readsConst() {
use(K_MAX);
}
}
class WidgetT2 extends WidgetT {
WidgetT2() : super(0);
void _privateMethod() {}
}
class BaseT {}
class DrawT {}
class OnlyMix with MixA {}
abstract class AbstractT {
void mustImpl(WidgetT w);
int get abstractGetter;
}
sealed class ShapeT {}
class CircleT extends ShapeT {}
mixin MixA on BaseT {
void mixMethod() {
helper(1);
}
}
mixin MixB implements DrawT {
int get mixGetter => 2;
}
extension WidgetTExt on WidgetT {
void extMethod() {
render(CanvasT());
}
int get extGetter => 4;
}
extension on String {
void anonExt() {}
}
enum ColorT { red, green, blue }
/// Enum doc.
enum StatusT with MixB implements DrawT {
ok(200),
err(500);
final int code;
const StatusT(this.code);
bool get good => code < 400;
static StatusT parse(int c) => ok;
}
typedef IntFn = int Function(int);
typedef void LegacyCb(int x);
typedef MapAlias = Map<String, WidgetT>;
extension type MetersT(double value) {
double get km => value / 1000;
}
void patternUser(Object o) {
final v = ColorT.red;
switch (o) {
case ColorT.blue:
use(v);
default:
break;
}
final (a, b) = (1, 2);
use(a);
}
// π unicode: “smart quotes” précède — column check ☕
void afterUnicode(String seance) {
emit('café ☕ done');
}