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

125 lines
3.6 KiB
Go

package resolver
import (
"strconv"
"strings"
"github.com/zzet/gortex/internal/graph"
)
// vuexDispatchVia is the Meta["via"] tag the JS/TS extractors stamp on a
// Vuex dispatch/commit placeholder — a `dispatch('user/login')` /
// `commit('user/SET_TOKEN')` string-keyed call the static graph cannot
// resolve because the action is named by a runtime string.
const vuexDispatchVia = "vuex-dispatch"
// ResolveVuexDispatchCalls binds Vuex string-keyed dispatch/commit calls to
// the action/mutation node named by the key, with namespace
// disambiguation: `dispatch('user/login')` reaches the `user` module's
// login, never a root-level login. The extractor tags each action/mutation
// node with vuex_action + vuex_namespace + vuex_kind and stamps the
// placeholder with vuex_key (the full namespaced string) + vuex_kind. This
// is a string-keyed inference, so it lands at the heuristic tier.
//
// Returns the number of placeholders landed on a real action/mutation.
func ResolveVuexDispatchCalls(g graph.Store) int {
if g == nil {
return 0
}
// index: kind → "namespace\x00name" → nodes.
index := map[string]map[string][]*graph.Node{"action": {}, "mutation": {}}
for _, n := range nodesByKindsOrAll(g, graph.KindFunction, graph.KindMethod) {
if n == nil || n.Meta == nil {
continue
}
name, _ := n.Meta["vuex_action"].(string)
kind, _ := n.Meta["vuex_kind"].(string)
if name == "" || index[kind] == nil {
continue
}
ns, _ := n.Meta["vuex_namespace"].(string)
index[kind][ns+"\x00"+name] = append(index[kind][ns+"\x00"+name], n)
}
if len(index["action"]) == 0 && len(index["mutation"]) == 0 {
return 0
}
// dyn_shape sites, indexed for claimed-site speculative pre-emption.
dynBySite := map[string][]*graph.Edge{}
for e := range g.EdgesByKind(graph.EdgeCalls) {
if e == nil || e.Meta == nil {
continue
}
if shape, _ := e.Meta["dyn_shape"].(string); shape == "" {
continue
}
dynBySite[vuexSiteKey(e.From, e.Line)] = append(dynBySite[vuexSiteKey(e.From, e.Line)], e)
}
resolved := 0
claimed := map[string]bool{}
var reindex []graph.EdgeReindex
for e := range g.EdgesByKind(graph.EdgeCalls) {
if e == nil || e.Meta == nil {
continue
}
if v, _ := e.Meta["via"].(string); v != vuexDispatchVia {
continue
}
key, _ := e.Meta["vuex_key"].(string)
kind, _ := e.Meta["vuex_kind"].(string)
if key == "" || index[kind] == nil {
continue
}
ns, name := "", key
if i := strings.LastIndex(key, "/"); i >= 0 {
ns, name = key[:i], key[i+1:]
}
target := pickStoreAction(g, e, sameBoundaryCandidates(g, e.From, index[kind][ns+"\x00"+name]))
want := "unresolved::*." + name
if target != nil {
want = target.ID
}
if e.To == want {
if target != nil {
resolved++
claimed[vuexSiteKey(e.From, e.Line)] = true
}
continue
}
oldTo := e.To
e.To = want
if target != nil {
e.Origin = graph.OriginASTInferred
e.Confidence = ConfidenceHeuristic
e.ConfidenceLabel = graph.ConfidenceLabelFor(graph.EdgeCalls, ConfidenceHeuristic)
StampSynthesized(e, SynthVuexDispatch)
resolved++
claimed[vuexSiteKey(e.From, e.Line)] = true
} else {
e.Origin = graph.OriginASTInferred
e.Confidence = 0
e.ConfidenceLabel = ""
UnstampSynthesized(e)
}
reindex = append(reindex, graph.EdgeReindex{Edge: e, OldTo: oldTo})
}
for site := range claimed {
for _, de := range dynBySite[site] {
if de.Meta == nil {
de.Meta = map[string]any{}
}
de.Meta["registry_claimed"] = true
}
}
if len(reindex) > 0 {
g.ReindexEdges(reindex)
}
return resolved
}
func vuexSiteKey(from string, line int) string {
return from + "\x00" + strconv.Itoa(line)
}