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
118 lines
3.6 KiB
Go
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})
|
|
}
|