chore: import upstream snapshot with attribution
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/zzet/gortex/internal/graph"
|
||||
)
|
||||
|
||||
// flutterSetStateVia marks a synthesized Flutter setState→build reachability
|
||||
// edge.
|
||||
const flutterSetStateVia = "flutter.setstate"
|
||||
|
||||
// ResolveFlutterSetStateCalls is the framework-dispatch synthesizer for the
|
||||
// Flutter widget re-build hop. `setState(() { … })` schedules the State's
|
||||
// `build(...)` to re-run, but that hop is framework-internal — no static edge —
|
||||
// so a flow dead-ends at setState even though everything `build` reaches is
|
||||
// call-connected. This pass bridges it: for each State class that has a `build`
|
||||
// method, it links every sibling method whose body calls `setState(` to that
|
||||
// `build`. The setState call is the gate that keeps this to Flutter State
|
||||
// classes — a plain class with a `build` method that never calls `setState`
|
||||
// produces no edge.
|
||||
//
|
||||
// Over-approximation by design, full recompute and idempotent; edges ride at
|
||||
// ast_inferred and carry synthesizer provenance. Returns the number of
|
||||
// setState→build edges synthesized.
|
||||
func ResolveFlutterSetStateCalls(g graph.Store) int {
|
||||
if g == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
classByMethod := map[string]string{}
|
||||
buildByClass := map[string]*graph.Node{}
|
||||
for _, n := range nodesByKindsOrAll(g, graph.KindMethod) {
|
||||
if n == nil {
|
||||
continue
|
||||
}
|
||||
for _, e := range g.GetOutEdges(n.ID) {
|
||||
if e == nil || e.Kind != graph.EdgeMemberOf {
|
||||
continue
|
||||
}
|
||||
classByMethod[n.ID] = e.To
|
||||
if n.Name == "build" {
|
||||
buildByClass[e.To] = n
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(buildByClass) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
var setStateMethods []*graph.Node
|
||||
for _, n := range nodesByKindsOrAll(g, graph.KindMethod) {
|
||||
if n == nil {
|
||||
continue
|
||||
}
|
||||
build := buildByClass[classByMethod[n.ID]]
|
||||
if build == nil || build.ID == n.ID {
|
||||
continue
|
||||
}
|
||||
if !methodCallsSetState(g, n.ID) {
|
||||
continue
|
||||
}
|
||||
setStateMethods = append(setStateMethods, n)
|
||||
}
|
||||
sort.Slice(setStateMethods, func(i, j int) bool {
|
||||
return setStateMethods[i].ID < setStateMethods[j].ID
|
||||
})
|
||||
|
||||
var batch []*graph.Edge
|
||||
synthesized := 0
|
||||
for _, m := range setStateMethods {
|
||||
build := buildByClass[classByMethod[m.ID]]
|
||||
batch = append(batch, flutterSetStateEdge(m, build, classByMethod[m.ID]))
|
||||
synthesized++
|
||||
}
|
||||
|
||||
for _, e := range batch {
|
||||
g.AddEdge(e)
|
||||
}
|
||||
return synthesized
|
||||
}
|
||||
|
||||
// flutterSetStateEdge builds one setState-method → build synthesized edge.
|
||||
func flutterSetStateEdge(from, build *graph.Node, class string) *graph.Edge {
|
||||
return &graph.Edge{
|
||||
From: from.ID,
|
||||
To: build.ID,
|
||||
Kind: graph.EdgeCalls,
|
||||
FilePath: from.FilePath,
|
||||
Line: from.StartLine,
|
||||
Confidence: 0.6,
|
||||
ConfidenceLabel: graph.ConfidenceLabelFor(graph.EdgeCalls, 0.6),
|
||||
Origin: graph.OriginASTInferred,
|
||||
Meta: map[string]any{
|
||||
"via": flutterSetStateVia,
|
||||
"state_class": class,
|
||||
MetaSynthesizedBy: SynthFlutterSetState,
|
||||
MetaProvenance: ProvenanceHeuristic,
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user