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
95 lines
3.6 KiB
Go
95 lines
3.6 KiB
Go
package indexer
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/zzet/gortex/internal/graph"
|
|
)
|
|
|
|
// scopedGlobalPassesEnabled reports whether incremental reindex should scope
|
|
// the global inference passes (InferImplements / InferOverrides) to the
|
|
// changed-affected type set instead of re-running them over the whole graph.
|
|
// GORTEX_INDEX_SCOPED_GLOBAL_PASSES overrides the config key. ON by default.
|
|
func (idx *Indexer) scopedGlobalPassesEnabled() bool {
|
|
if v := os.Getenv("GORTEX_INDEX_SCOPED_GLOBAL_PASSES"); v != "" {
|
|
return v == "1" || strings.EqualFold(v, "true")
|
|
}
|
|
return idx.config.ScopedGlobalPassesEnabledOrDefault()
|
|
}
|
|
|
|
// affectedTypeSet computes the type/interface IDs whose inferred
|
|
// implements/override edges a set of changed (stale) files can affect:
|
|
// - every KindType / KindInterface the changed files define (their inferred
|
|
// out/in edges were dropped on eviction), and
|
|
// - the owning type of every KindMethod in a changed file (a method add/remove
|
|
// changes the type's method-set, which can newly satisfy / break an
|
|
// interface defined in an unchanged file).
|
|
//
|
|
// types is the full re-check set; ifaces is the subset of changed interfaces
|
|
// (every type must be re-checked against a changed interface). Re-checking
|
|
// every (type, interface) pair with an endpoint in these sets re-lands exactly
|
|
// the edges eviction dropped — add-parity with the full pass.
|
|
func (idx *Indexer) affectedTypeSet(graphPaths []string) (types, ifaces map[string]bool) {
|
|
types = map[string]bool{}
|
|
ifaces = map[string]bool{}
|
|
for _, p := range graphPaths {
|
|
for _, n := range idx.graph.GetFileNodes(p) {
|
|
if n == nil {
|
|
continue
|
|
}
|
|
switch n.Kind {
|
|
case graph.KindType, graph.KindInterface:
|
|
types[n.ID] = true
|
|
if n.Kind == graph.KindInterface {
|
|
ifaces[n.ID] = true
|
|
}
|
|
case graph.KindMethod:
|
|
for _, e := range idx.graph.GetOutEdges(n.ID) {
|
|
if e.Kind == graph.EdgeMemberOf {
|
|
types[e.To] = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return types, ifaces
|
|
}
|
|
|
|
// staleFilesAffectDerivedEdges reports whether any stale file carries code
|
|
// structure (functions / methods / types / fields / …) that the capability
|
|
// and framework-dispatch synthesizers derive edges from. When every stale
|
|
// file is non-code — a README, a JSON/YAML config, a data file — those
|
|
// whole-graph passes cannot produce or change any edge, so the caller skips
|
|
// them (the doc/config-edit fast path). Sound by construction: a file with
|
|
// no structural nodes contributes no calls / reads / writes / dispatch
|
|
// sites, which is the only input those synthesizers read.
|
|
func (idx *Indexer) staleFilesAffectDerivedEdges(staleFiles []string) bool {
|
|
for _, p := range idx.graphFilePaths(staleFiles) {
|
|
for _, n := range idx.graph.GetFileNodes(p) {
|
|
if n != nil && isStructuralKind(n.Kind) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// runScopedInferencePasses runs the implements/override inference passes scoped
|
|
// to the types/interfaces a set of stale files can affect. Returns false when
|
|
// scoping is disabled (caller should run the full passes). When nothing
|
|
// type/interface-shaped changed, the passes are skipped entirely (the common
|
|
// case for a function-body edit).
|
|
func (idx *Indexer) runScopedInferencePasses(staleFiles []string) bool {
|
|
if !idx.scopedGlobalPassesEnabled() {
|
|
return false
|
|
}
|
|
types, ifaces := idx.affectedTypeSet(idx.graphFilePaths(staleFiles))
|
|
if len(types) == 0 && len(ifaces) == 0 {
|
|
return true // no type/interface change → no inferred edges to re-derive
|
|
}
|
|
idx.resolver.InferImplementsScoped(types, ifaces)
|
|
idx.resolver.InferOverridesScoped(types)
|
|
return true
|
|
}
|