callgraph

package
v1.39.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package callgraph builds and queries call relationships between functions.

Index

Constants

View Source
const (
	BackendTreeSitter = "tree-sitter"
	BackendGoTypes    = "tree-sitter+go/types"
	BackendSCIP       = "tree-sitter+scip"
)

Backend identifies which resolution pass(es) contributed edges to a CallGraph. Plain strings by design (see docs/adr, "cut tier/backend provenance stamping" — internal/tier is orphaned and neither AGE-graph fixture needs a richer vocabulary); named as consts here only to keep the literal that SETS CallGraph.Backend and the literal that later COMPARES against it from drifting apart. Exported (not package-private) because codegraph/index.go's buildAGECallGraph also stamps and compares against these exact values — a second unexported copy in that package would be the same literal-drift risk these consts exist to prevent, just moved one package over.

View Source
const (

	// CrossLanguageFetchKind is the node Kind set on synthetic nodes injected
	// by the cross-language enrichment pass (HANDLES → FETCHES traversal).
	CrossLanguageFetchKind = "cross_language_fetch"
)

Variables

This section is empty.

Functions

func EagerWarmRepos

func EagerWarmRepos(ctx context.Context, dirs []string)

EagerWarmRepos enumerates immediate subdirectories of each path in dirs that contain a go.mod, then runs the GOCACHE prewarm for each in parallel (bounded by eagerWarmParallelism). Returns when all warmups have settled.

Intended to be invoked once at process startup from a goroutine so it does not block the MCP server bring-up. The caller is responsible for goroutine dispatch — this function blocks until completion to make tests deterministic.

func ExtractGoImplements added in v1.37.1

func ExtractGoImplements(ctx context.Context, root string) []parser.TypeRelationship

ExtractGoImplements computes structural interface-satisfaction relationships for a Go module via go/types and returns them as parser.TypeRelationship values of kind RelImplements, ready to flow through buildRelationshipEdges (code_graph) or be appended to cg.TypeRels (call_trace). One edge is produced per (concrete type T, interface I) where T or *T implements I.

Go-only and best-effort: returns nil (not an error) when the repo has no go.mod, when go/packages fails or times out, or when no satisfaction exists. Failures are non-fatal — they bump a counter and log, mirroring the graceful-degradation contract of the rest of the pipeline. The returned relationships' File field is the concrete type's ABSOLUTE declaration path, so buildRelationshipEdges keys the IMPLEMENTS edge's subject endpoint onto the same Symbol vertex (name + repo-relative file) that buildSymbolGraph created.

Called from EnrichWithTypedResolution (the shared composition seam) so both BuildFromRepo (call_trace/impact_analysis) and buildAGECallGraph (code_graph) get Go IMPLEMENTS edges. See issue #467.

func InjectHookEdges

func InjectHookEdges(cg *CallGraph, hookRoutes []HookRoute)

InjectHookEdges adds synthetic call edges for WordPress hook connections.

For each hook name that has both a registration (add_action/add_filter, Side="server") and an invocation (do_action/apply_filters, Side="client"), it creates a CallEdge from the invoking function to the callback function.

hookRoutes must come from routes.ExtractAll("php", ...) and symbols from the same repository's parsed symbol table.

func InvalidateBuildCache

func InvalidateBuildCache()

InvalidateBuildCache clears the entire BuildFromRepo cache. Used in tests and when a rebuild is explicitly requested.

func ResolveSpeculative

func ResolveSpeculative(ctx context.Context, client *oxcodes.Client, root, language string, nodes []CallChainNode)

ResolveSpeculative walks the call tree and fills Speculative candidates for unresolved nodes (Symbol.Kind == "external") using ox-codes text search. At most maxSpeculativePerTrace resolutions are attempted for performance.

func SetL2 added in v1.38.5

func SetL2(redisURL string)

SetL2 wires the process-level callgraph cache to Redis. Passing an empty redisURL disables L2. Called once from cmd/go-code/register.go at startup.

Types

type BuildOpts

type BuildOpts struct {
	// IncludeFieldAccess keeps heuristic argref/field-access call sites even
	// when they don't resolve to a known function symbol. Default false —
	// unresolved CallSite.IsArgRef entries are dropped to avoid reporting
	// vars (`ctx`, `localPath`) and member access (`opts.Slug`) as callees.
	IncludeFieldAccess bool
}

BuildOpts controls how parser.CallSite entries are converted into call graph edges.

type CallChainNode

type CallChainNode struct {
	Symbol      *parser.Symbol    `json:"symbol"`
	Children    []CallChainNode   `json:"children,omitempty"`
	CallLine    uint32            `json:"callLine,omitempty"`
	Cycle       bool              `json:"cycle,omitempty"`
	Speculative []SpeculativeCall `json:"speculative,omitempty"` // candidates for unresolved calls
	Kind        string            `json:"kind,omitempty"`        // internal: empty = normal; CrossLanguageFetchKind for synthetic nodes
	Depth       int               `json:"depth,omitempty"`       // only set on synthetic cross-language nodes
	CallerKind  string            `json:"caller_kind,omitempty"` // production | test | example | benchmark
}

CallChainNode is a single node in the call chain tree.

type CallEdge

type CallEdge struct {
	Caller      *parser.Symbol // function containing the call
	Callee      *parser.Symbol // target function (nil if unresolved)
	CalleeName  string         // original name from source
	Receiver    string         // qualifier if method call
	Line        uint32         // 1-based call site line
	IsInterface bool           // true when resolved via interface dispatch (go/types or SCIP)
}

CallEdge is a resolved (or unresolved) call from one function to another.

func FilterStdlibCalls added in v1.37.1

func FilterStdlibCalls(edges []CallEdge) []CallEdge

FilterStdlibCalls removes unresolved call edges whose callee name is a known standard-library method/builtin (clone, unwrap, to_string, iter, map, len, push, format, …). These edges never resolve to a project node and only pollute call traces with unresolved "external" nodes.

Only edges with a nil Callee (unresolved) are filtered — a project function that happens to share a name with a stdlib method (e.g. a user-defined `Clone`) is kept because its Callee symbol is set.

Applied after EnrichWithTypedResolution in both BuildFromRepo (the call_trace/impact_analysis path) and buildAGECallGraph (the code_graph indexing path), so the tree-sitter pipeline gets the same stdlib noise filter the SCIP conversion path already applies in convert.go. The SCIP-level filter is kept too (defence in depth — fewer edges to convert). See issue #466.

type CallGraph

type CallGraph struct {
	Edges         []CallEdge
	Symbols       []*parser.Symbol
	TypeRels      []parser.TypeRelationship // interface/extends/embeds relationships
	HookCallbacks []string                  // function names registered as hook callbacks
	Tier          string                    // "basic" (tree-sitter), "enhanced" (go/types merged), "full" (future)
	Backend       string                    // resolution backend: "tree-sitter", "tree-sitter+go/types", "tree-sitter+scip"
	// UsesIndex maps a target file's relative path to a list of relative paths
	// of Astro files that render it as a component (<Foo />). Populated by
	// ResolveTemplateRefs during BuildFromRepo. Enables impact_analysis to
	// report file-level USES callers for Astro components.
	UsesIndex map[string][]string
}

CallGraph holds all call relationships for a repository.

func BuildCallGraph

func BuildCallGraph(symbols []*parser.Symbol, calls []parser.CallSite) *CallGraph

BuildCallGraph resolves call sites against the symbol table. Resolution: same-file -> same-package (directory) -> global name match.

Heuristic argref sites (parser.CallSite.IsArgRef==true) are dropped when they don't resolve to a function/method symbol — this filters noise like member access (`opts.Slug`) and local variable references (`ctx`, `localPath`) that the parser captures inside argument lists.

func BuildCallGraphWithOpts

func BuildCallGraphWithOpts(symbols []*parser.Symbol, calls []parser.CallSite, opts BuildOpts) *CallGraph

BuildCallGraphWithOpts is BuildCallGraph with explicit options.

func BuildFromRepo

func BuildFromRepo(ctx context.Context, input TraceRepoInput) (*CallGraph, error)

BuildFromRepo ingests a repo, parses files, and returns the call graph without tracing a specific symbol.

Delegates to BuildAndEnrich (the unified pipeline, issue #463) and caches the result. The background go/types warm-up is kept here because it is call_trace-specific (it targets the cgCache entry, not the pipeline result).

func ConvertToCallGraph

func ConvertToCallGraph(typedEdges []goanalysis.TypedEdge, tsSymbols []*parser.Symbol) *CallGraph

ConvertToCallGraph converts typed edges to the existing CallGraph format by matching callers/callees against tree-sitter symbols by name and file.

func EnrichWithTypedResolution added in v1.23.0

func EnrichWithTypedResolution(ctx context.Context, root string, base *CallGraph, symbols []*parser.Symbol, files []*ingest.File) *CallGraph

EnrichWithTypedResolution is the single shared composition seam for typed call-edge enrichment: given a base (tree-sitter-only) CallGraph, it attempts go/types resolution for Go modules, then — only if that made no progress — SCIP resolution for non-Go languages, merging any successful pass additively via MergeCallGraphs. Route ANY new typed-edge source through this seam (and MergeCallGraphs) rather than composing typed enrichment ad hoc at a second call site; BuildFromRepo is the reference caller.

Both passes are bounded and non-fatal: on any failure (no go.mod, cold GOCACHE, no indexer, timeout) base is returned with Tier/Backend unchanged, exactly the tree-sitter-only degrade contract callers already depend on. root and files are needed independently of base/symbols because SCIP resolution walks the raw ingested file set for the dominant language, not the already-parsed symbol table.

func MergeCallGraphs

func MergeCallGraphs(tsGraph, typedGraph *CallGraph) *CallGraph

MergeCallGraphs merges a tree-sitter call graph with a typed call graph. Typed edges take priority; unmatched tree-sitter edges are appended. HookCallbacks are preserved from the tree-sitter graph. Returns nil only if both inputs are nil.

type HookRoute

type HookRoute struct {
	Method  string // "ACTION" or "FILTER"
	Path    string // hook name
	Handler string // callback function name (empty for client-side)
	Side    string // "server" or "client"
	Line    uint32
}

HookRoute is a minimal representation of a WordPress hook route used by InjectHookEdges. It mirrors the fields needed from routes.Route without importing the routes package (to avoid circular dependencies).

type PipelineOpts added in v1.37.2

type PipelineOpts struct {
	Root               string
	Focus              string
	Language           string
	IncludeFieldAccess bool
	MaxFileBytes       int64
	ExcludeTests       bool
	// TypedEnrich controls whether EnrichWithTypedResolution runs.
	// When false, the pipeline returns a tree-sitter-only graph (used by
	// code_graph when CODEGRAPH_TYPED_ENRICH is unset).
	TypedEnrich bool
}

PipelineOpts controls the unified pipeline behaviour.

type PipelineResult added in v1.37.2

type PipelineResult struct {
	CG           *CallGraph
	Symbols      []*parser.Symbol
	Files        []*ingest.File
	Rels         []parser.TypeRelationship
	FileImports  map[string][]string
	TemplateRefs []TemplateRef
	HookRoutes   []HookRoute
}

PipelineResult is the output of the unified ingest→parse→build→enrich pipeline (BuildAndEnrich). It carries everything a consumer needs:

  • CG: the enriched call graph (tree-sitter + go/types + SCIP + IMPLEMENTS)
  • Symbols: all parsed symbols (for analyze, embeddings)
  • Files: the ingested file list (for explore, compare, codesearch)
  • Rels: type relationships (IMPLEMENTS + INHERITS) from enrichment
  • FileImports: per-file import paths (for code_graph's import edges)
  • TemplateRefs: resolved Astro component tag refs (for code_graph's USES edges)
  • HookRoutes: WordPress hook routes (for code_graph's HOOK edges)

See issue #463. This is the single shared pipeline that subsumes the previously-duplicated ingest→parse→build→enrich sequences in BuildFromRepo (call_trace) and ingestAndParse+buildAGECallGraph (code_graph).

func BuildAndEnrich added in v1.37.2

func BuildAndEnrich(ctx context.Context, opts PipelineOpts) (*PipelineResult, error)

BuildAndEnrich is the single shared ingest→parse→build→enrich pipeline.

It replaces the duplicated sequences in BuildFromRepo (call_trace) and ingestAndParse+buildAGECallGraph (code_graph) with one code path:

ingest.IngestRepo (cached — #464)
→ parseFilesParallel (unified — #469)
→ BuildCallGraphWithOpts
→ EnrichWithTypedResolution (go/types + SCIP + IMPLEMENTS — #467)
→ return *PipelineResult

Consumers:

  • call_trace: traces over result.CG in memory
  • code_graph: persists result to AGE via buildGraph
  • analyze: reads result.Symbols + result.Files

See issue #463.

type SpeculativeCall

type SpeculativeCall struct {
	Name       string  `json:"name"`
	File       string  `json:"file"`
	Line       int     `json:"line"`
	Confidence float64 `json:"confidence"` // 0.0-1.0
}

SpeculativeCall represents a candidate callee found via text search.

type TemplateRef added in v1.37.2

type TemplateRef struct {
	RelFile    string // Astro file that contains the tag usage
	ResolvedTo string // relative path of the imported component file
	Line       uint32
}

TemplateRef is a resolved Astro USES relationship ready for AGE insertion. Resolution (tag name → file path) is performed in BuildAndEnrich via ResolveTemplateRefs; unresolved refs are dropped before storage.

type TemplateUsage added in v1.22.0

type TemplateUsage struct {
	// From is the relative path of the file that contains the template ref.
	From string
	// To is the relative path of the imported component file.
	To string
	// Line is the 1-based line number of the tag usage in the source file.
	Line uint32
}

TemplateUsage represents a resolved USES relationship from a component file (Astro or Svelte) to the file it renders as a child component.

func ResolveTemplateRefs

func ResolveTemplateRefs(src []byte, refs []preproc.TemplateRef, fileRel, root string) []TemplateUsage

ResolveTemplateRefs joins TemplateRefs against a file's import bindings to produce file-level USES relationships.

The import-binding source depends on the file kind:

  • Astro (.astro and any non-.svelte): imports declared in the leading --- frontmatter block (scanFrontmatterBindings).
  • Svelte (.svelte): imports declared in the component's <script> blocks (scanSvelteScriptBindings).

The binding→ref join and path resolution below are generic over both kinds.

Resolution order:

  1. Relative imports (./…, ../…) — resolved directly against the file's directory.
  2. Alias imports (~/…, @/…, any non-relative path) — looked up in the repo's tsconfig.json compilerOptions.paths (and astro.config vite.resolve.alias as fallback). The alias map is loaded once per root and cached process-wide.
  3. Unresolved — either (a) no alias key matched (bare/scoped npm package such as 'svelte', '@guide/core', 'astro:transitions') — silently dropped without incrementing the counter; or (b) an alias prefix matched but the resolved path does not exist on disk — the gocode_parser_unresolved_alias_total counter is incremented and the ref is dropped (broken declared alias).

type TraceOpts

type TraceOpts struct {
	Direction string // "callees" (default) or "callers"
	MaxDepth  int    // default 5, max 10

	// CrossRefs, when non-nil, extends the trace through HANDLES/FETCHES
	// edges at +1 depth beyond the existing call graph. Noop when nil.
	CrossRefs graphx.CrossRefs
	// Repo is the repo key used for CrossRefs lookups. Required when CrossRefs is set.
	Repo string
}

TraceOpts controls the call chain traversal.

type TraceRepoInput

type TraceRepoInput struct {
	Root     string
	Symbol   string
	Focus    string
	Language string
	Opts     TraceOpts

	// IncludeFieldAccess keeps heuristic argref/field-access call sites even
	// when they don't resolve to a known function symbol. Default false —
	// unresolved argref captures (`opts.Slug`, `ctx`, `localPath`) are
	// dropped. Set via the `field_access=true` MCP tool flag for legacy
	// permissive behaviour.
	IncludeFieldAccess bool

	// Refresh forces a cache bypass — re-parses the repo and re-runs
	// SCIP/go/types enrichment instead of returning the cached call graph.
	// Use when the repo has changed (git checkout, new commit) and the
	// in-memory cgCache is stale.
	Refresh bool
}

TraceRepoInput configures a full repo call chain trace.

type TraceResult

type TraceResult struct {
	Root       *parser.Symbol  `json:"root,omitempty"`
	Tree       []CallChainNode `json:"tree"`
	MaxDepth   int             `json:"maxDepth"`
	TotalNodes int             `json:"totalNodes"`
	Resolved   int             `json:"resolved"`
	Unresolved int             `json:"unresolved"`
	Tier       string          `json:"tier,omitempty"`
}

TraceResult holds the complete call chain traversal output.

func Trace

func Trace(ctx context.Context, g *CallGraph, symbolName string, opts TraceOpts) TraceResult

Trace walks the call graph from the named symbol, building a tree of call chains. Direction "callees" follows outgoing calls; "callers" follows incoming calls.

When opts.CrossRefs is non-nil and opts.Repo is non-empty, a single extra pass runs after the main BFS/DFS: for each discovered node at depth <= MaxDepth-1 it checks whether the symbol HANDLES an HTTP route, then queries FetchedBy for upstream callers. Results are appended as synthetic CallChainNode values with Kind == CrossLanguageFetchKind. The pass never recurses. CrossRefs errors are swallowed (slog.Debug) — the feature is purely opportunistic.

func TraceRepo

func TraceRepo(ctx context.Context, input TraceRepoInput) (*TraceResult, error)

TraceRepo ingests a repo, extracts symbols and calls, builds call graph, traces from symbol.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL