* Phase 4b: Flutter setState → build (the Dart analog of react-render). In a * StatefulWidget's State class, `setState(() {…})` re-runs `build(context)`, but * that hop is framework-internal (Flutter calls build), so a flow like * "onPressed → _increment → setState → rebuilt UI" dead-ends at setS
(queries: QueryBuilder, ctx: ResolutionContext, onYield: MaybeYield)
| 454 | * Flutter State classes. Over-approximation accepted (reachability-correct). |
| 455 | */ |
| 456 | async function flutterBuildEdges(queries: QueryBuilder, ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]> { |
| 457 | let scanned255 = 0; |
| 458 | const edges: Edge[] = []; |
| 459 | const seen = new Set<string>(); |
| 460 | for (const cls of queries.iterateNodesByKind('class')) { |
| 461 | if ((++scanned255 & 63) === 0) await onYield(); |
| 462 | const children = queries.getOutgoingEdges(cls.id, ['contains']) |
| 463 | .map((e) => queries.getNodeById(e.target)) |
| 464 | .filter((n): n is Node => !!n && n.kind === 'method'); |
| 465 | const build = children.find((n) => n.name === 'build'); |
| 466 | if (!build || !build.filePath.endsWith('.dart')) continue; |
| 467 | let added = 0; |
| 468 | for (const m of children) { |
| 469 | if (added >= MAX_CALLBACKS_PER_CHANNEL) break; |
| 470 | if (m.id === build.id) continue; |
| 471 | const content = ctx.readFile(m.filePath); |
| 472 | const src = content && sliceLines(content, m.startLine, m.endLine); |
| 473 | if (!src || !FLUTTER_SETSTATE_RE.test(src)) continue; |
| 474 | const key = `${m.id}>${build.id}`; |
| 475 | if (seen.has(key)) continue; |
| 476 | seen.add(key); |
| 477 | edges.push({ |
| 478 | source: m.id, target: build.id, kind: 'calls', line: m.startLine, |
| 479 | provenance: 'heuristic', |
| 480 | metadata: { synthesizedBy: 'flutter-build', via: 'setState', registeredAt: `${build.filePath}:${build.startLine}` }, |
| 481 | }); |
| 482 | added++; |
| 483 | } |
| 484 | } |
| 485 | return edges; |
| 486 | } |
| 487 | |
| 488 | /** |
| 489 | * Reactive ArkUI property decorators: assigning a property carrying one of |
no test coverage detected