Files
wehub-resource-sync a06f331eb8
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
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

118 lines
3.6 KiB
Go

package resolver
import (
"github.com/zzet/gortex/internal/graph"
)
// rtkQueryVia is the Meta["via"] tag the JS/TS extractors stamp on a
// generated-hook → endpoint placeholder. RTK Query's createApi declares
// data endpoints and auto-generates a React hook per endpoint
// (`useGetUserQuery`) that has no source node — the extractor synthesizes
// both nodes and this placeholder, which this pass binds.
const rtkQueryVia = "rtk-query"
// ResolveRTKQueryCalls binds the two RTK Query edges: the synthesized
// generated-hook → endpoint placeholder (by endpoint name, gated to the
// same createApi file), and any still-unresolved component → generated-hook
// call (so a component's `useGetUserQuery()` reaches the endpoint's query
// body). The naming convention is RTK-contractual, so these land at the
// typed framework tier (ConfidenceTyped / ProvenanceFramework).
//
// Returns the number of edges landed on a real node.
func ResolveRTKQueryCalls(g graph.Store) int {
if g == nil {
return 0
}
// endpointByFileName: createApi file → endpoint name → endpoint node.
endpointByFileName := map[string]map[string]*graph.Node{}
// hookByName: generated-hook name → nodes.
hookByName := map[string][]*graph.Node{}
for _, n := range nodesByKindsOrAll(g, graph.KindFunction) {
if n == nil || n.Meta == nil {
continue
}
if ep, _ := n.Meta["rtk_endpoint"].(string); ep != "" {
if endpointByFileName[n.FilePath] == nil {
endpointByFileName[n.FilePath] = map[string]*graph.Node{}
}
endpointByFileName[n.FilePath][ep] = n
}
if gen, _ := n.Meta["rtk_generated_hook"].(bool); gen {
hookByName[n.Name] = append(hookByName[n.Name], n)
}
}
if len(endpointByFileName) == 0 {
return 0
}
resolved := 0
var reindex []graph.EdgeReindex
for e := range g.EdgesByKind(graph.EdgeCalls) {
if e == nil {
continue
}
// (1) generated-hook → endpoint placeholder.
if e.Meta != nil {
if v, _ := e.Meta["via"].(string); v == rtkQueryVia {
ep, _ := e.Meta["rtk_endpoint"].(string)
hookFile := ""
if hn := g.GetNode(e.From); hn != nil {
hookFile = hn.FilePath
}
var target *graph.Node
if m := endpointByFileName[hookFile]; m != nil {
target = m[ep]
}
rtkRebind(e, target, "unresolved::*."+ep, &reindex, &resolved)
continue
}
}
// (2) component → generated-hook call the generic resolver left
// unresolved (e.g. the hook is imported cross-file).
if !graph.IsUnresolvedTarget(e.To) {
continue
}
cands := hookByName[graph.UnresolvedName(e.To)]
if len(cands) == 0 {
continue
}
if target := pickStoreAction(g, e, sameBoundaryCandidates(g, e.From, cands)); target != nil {
rtkRebind(e, target, e.To, &reindex, &resolved)
}
}
if len(reindex) > 0 {
g.ReindexEdges(reindex)
}
return resolved
}
// rtkRebind points e at target (typed tier) or re-orphans it to
// unresolvedTo, recording the reindex and bumping resolved on a hit.
func rtkRebind(e *graph.Edge, target *graph.Node, unresolvedTo string, reindex *[]graph.EdgeReindex, resolved *int) {
want := unresolvedTo
if target != nil {
want = target.ID
}
if e.To == want {
if target != nil {
*resolved++
}
return
}
oldTo := e.To
e.To = want
if target != nil {
e.Origin = graph.OriginASTInferred
e.Confidence = ConfidenceTyped
e.ConfidenceLabel = graph.ConfidenceLabelFor(graph.EdgeCalls, ConfidenceTyped)
StampSynthesizedTyped(e, SynthRTKQuery)
*resolved++
} else {
e.Origin = graph.OriginASTInferred
e.Confidence = 0
e.ConfidenceLabel = ""
UnstampSynthesized(e)
}
*reindex = append(*reindex, graph.EdgeReindex{Edge: e, OldTo: oldTo})
}