callgraph

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 12, 2026 License: MIT Imports: 10 Imported by: 0

README

go-callgraph

A Go library for building and querying SSA-based call graphs. Wraps golang.org/x/tools/go/callgraph with a clean API for common use cases: caller/callee lookups, test discovery, and edge iteration for persistence layers.

Installation

go get github.com/urechandro/go-callgraph

Requires Go 1.23+ and a working Go toolchain in PATH (the SSA builder shells out to go list).

Quick start

import callgraph "github.com/urechandro/go-callgraph"

// Build a call graph for a module.
g, err := callgraph.Build([]string{"/path/to/module"}, callgraph.RTA)
if err != nil {
    log.Fatal(err)
}

// Find all functions named "ProcessOrder".
refs := g.FindFunctions("ProcessOrder")

// Who calls ProcessOrder?
for _, c := range g.DirectCallers(refs) {
    fmt.Printf("%s  %s:%d\n", c.Name, c.File, c.Line)
}

// Which tests exercise ProcessOrder transitively?
for _, t := range g.CallersToTests(refs) {
    fmt.Println(t.Name)
}

Algorithms

Algorithm Constant Precision Speed
Rapid Type Analysis callgraph.RTA High — tracks concrete types Slower
Class Hierarchy Analysis callgraph.CHA Conservative — may over-approximate Faster

Use RTA (default) when accuracy matters. Use CHA for quick scans or when the program has few interface-heavy dispatch sites.

Pre-loaded packages

If you already call packages.Load with your own config (custom exclusions, token.FileSet, etc.), skip the load step:

pkgs, err := packages.Load(myCfg, "./...")
g, err := callgraph.BuildFromPackages(pkgs, callgraph.RTA)

The callgraph.LoadMode constant exports the required packages.Config.Mode flags so you can compose them with your own.

Persisting edges

For indexers that store edges in a database:

g.ForEachEdgeInPackages(myPkgs, func(e callgraph.EdgeInfo) bool {
    fromID := callgraph.QualifiedID(e.Caller) // "pkg/path.Type.Method"
    toID   := callgraph.QualifiedID(e.Callee)
    if fromID != "" && toID != "" {
        db.Insert(fromID, toID)
    }
    return true // return false to stop
})

QualifiedObjID(pkgPath, obj) is also exported for consumers that build IDs from types.Object (e.g. during AST-level symbol indexing).

Multi-module support

Pass multiple roots to Build; each is analysed independently and the results are unified under a single *Graph:

g, err := callgraph.Build([]string{
    "/repo/service-a",
    "/repo/service-b",
}, callgraph.RTA)

API reference

See pkg.go.dev/github.com/urechandro/go-callgraph for the full godoc.

Core
Function Description
Build(roots, method) Load + build call graph for one or more module roots
BuildFromPackages(pkgs, method) Build from pre-loaded packages
LoadPackages(dir, patterns...) Load packages with the required mode flags
Query
Method Description
FindFunctions(name) Find all functions with an exact name match
DirectCallers(refs) Functions that directly call the given functions
DirectCallees(refs) Functions directly called by the given functions
CallersToTests(refs) Transitive walk upward until Test/Benchmark functions are reached
DirectCallerTests(refs) Tests that directly call the given functions (one level)
FindTestsByName(substrings) Find tests whose name contains any of the given substrings
TestsCovering(dirs, files, symbols) Tests in affected dirs reachable from changed symbols
FuncInfos(refs) Resolve refs to name/file/line info
Edges
Function Description
ForEachEdge(fn) Iterate all call edges
ForEachEdgeInPackages(pkgs, fn) Iterate edges where caller is in the given package set
Symbol IDs
Function Description
QualifiedID(fn) "pkg/path.Type.Method" for an *ssa.Function
FuncPkgPath(fn) Package import path of an *ssa.Function
QualifiedObjID(pkgPath, obj) Stable ID from a types.Object (AST-level indexing)

License

MIT — see LICENSE.

Documentation

Overview

Package callgraph builds SSA-based call graphs from Go source code and provides query methods for caller/callee lookups, test discovery, and edge iteration.

Algorithms

Two algorithms are supported:

  • CHA (Class Hierarchy Analysis) — conservative. Includes all possible dispatch targets for interface calls. Fast, may over-approximate.
  • RTA (Rapid Type Analysis) — precise. Tracks which concrete types are actually instantiated and reachable. Slower, fewer false edges.

RTA is the default for most use cases. Use CHA when you need faster builds and can tolerate some extra edges.

Quick start

g, err := callgraph.Build([]string{"/path/to/module"}, callgraph.RTA)
if err != nil { ... }

refs := g.FindFunctions("MyFunc")
callers := g.DirectCallers(refs)
for _, c := range callers {
    fmt.Println(c.Name, c.File, c.Line)
}

Integration with persistence layers

If you already load packages yourself (e.g. with custom config or exclusion filters), use BuildFromPackages to skip the load step. Combine with Graph.ForEachEdgeInPackages and QualifiedID to persist edges to a store:

g, _ := callgraph.BuildFromPackages(pkgs, callgraph.RTA)
g.ForEachEdgeInPackages(myPkgSet, func(e callgraph.EdgeInfo) bool {
    store.Insert(callgraph.QualifiedID(e.Caller), callgraph.QualifiedID(e.Callee))
    return true
})

Index

Constants

LoadMode is the packages.Config.Mode required for SSA construction. Exported so consumers can compose it with additional flags if needed.

Variables

This section is empty.

Functions

func FuncPkgPath

func FuncPkgPath(fn *ssa.Function) string

FuncPkgPath returns the package path of an SSA function, or "".

func LoadPackages

func LoadPackages(dir string, patterns ...string) ([]*packages.Package, error)

LoadPackages loads Go packages from dir with the standard mode flags required for SSA call graph construction. Tests are always included. If no patterns are given, "./..." is used.

func QualifiedID

func QualifiedID(fn *ssa.Function) string

QualifiedID returns a stable fully-qualified ID for an SSA function, in the form "pkg/path.FuncName" or "pkg/path.Type.MethodName". Returns "" for synthetic functions (wrappers, thunks) or builtins.

func QualifiedObjID

func QualifiedObjID(pkgPath string, obj types.Object) string

QualifiedObjID builds a stable fully-qualified ID from a package path and types.Object. For methods, the format is "pkg/path.TypeName.MethodName". For functions, "pkg/path.FuncName". This can be used for both SSA functions and AST-level symbol indexing.

Types

type EdgeInfo

type EdgeInfo struct {
	Caller *ssa.Function
	Callee *ssa.Function
}

EdgeInfo holds a caller-callee pair from the call graph.

type FuncInfo

type FuncInfo struct {
	Name string
	File string
	Line int
}

FuncInfo describes a function found in the call graph.

type FuncRef

type FuncRef struct {
	Fn   *ssa.Function
	Node *gocg.Node
	MG   *ModuleGraph
}

FuncRef is a reference to a function in the graph. Pass to DirectCallers, DirectCallees, CallersToTests, etc.

type Graph

type Graph struct {
	// contains filtered or unexported fields
}

Graph wraps one or more call graphs (one per module) and provides query methods for test discovery and caller/callee lookups.

func Build

func Build(modRoots []string, method Method) (*Graph, error)

Build loads packages from each module root, builds SSA, and runs the selected call graph algorithm. Each root is analysed independently.

func BuildFromPackages

func BuildFromPackages(pkgs []*packages.Package, method Method) (*Graph, error)

BuildFromPackages builds SSA and a call graph from pre-loaded packages. Use this when you have already called packages.Load yourself (e.g. with a custom Config). Returns a single-module Graph.

func (*Graph) CallersToTests

func (g *Graph) CallersToTests(refs []FuncRef) []FuncInfo

CallersToTests walks callers upward from the given functions through the call graph and returns all Test/Benchmark functions reached.

func (*Graph) DirectCallees

func (g *Graph) DirectCallees(refs []FuncRef) []FuncInfo

DirectCallees returns functions that any of the given functions directly call.

func (*Graph) DirectCallerTests

func (g *Graph) DirectCallerTests(refs []FuncRef) []FuncInfo

DirectCallerTests returns Test/Benchmark functions that directly call any of the given functions (one level up only, no transitive walk).

func (*Graph) DirectCallers

func (g *Graph) DirectCallers(refs []FuncRef) []FuncInfo

DirectCallers returns functions that directly call any of the given functions.

func (*Graph) FindFunctions

func (g *Graph) FindFunctions(symbol string) []FuncRef

FindFunctions returns references to SSA functions whose name matches symbol.

func (*Graph) FindTestsByName

func (g *Graph) FindTestsByName(names []string) []FuncInfo

FindTestsByName returns Test/Benchmark functions whose name contains any of the given substrings. For example, "GetLocation" matches "TestGetLocation", "Test_GetLocation", "TestGetLocation_NotFound".

func (*Graph) ForEachEdge

func (g *Graph) ForEachEdge(fn func(EdgeInfo) bool)

ForEachEdge iterates all call edges in the graph. The callback receives each caller-callee pair. Return false to stop iteration.

func (*Graph) ForEachEdgeInPackages

func (g *Graph) ForEachEdgeInPackages(pkgPaths map[string]bool, fn func(EdgeInfo) bool)

ForEachEdgeInPackages iterates call edges where the caller belongs to one of the given package paths. This is the filtered variant for consumers that only want edges originating from their own code.

func (*Graph) FuncInfos

func (g *Graph) FuncInfos(refs []FuncRef) []FuncInfo

FuncInfos returns position info for the given function references.

func (*Graph) Method

func (g *Graph) Method() Method

Method returns the algorithm used to build this graph.

func (*Graph) Modules

func (g *Graph) Modules() []*ModuleGraph

Modules returns the underlying module graphs for direct access.

func (*Graph) SymbolCount

func (g *Graph) SymbolCount() int

SymbolCount returns the total number of user-defined (non-synthetic) functions with valid source positions in the graph.

func (*Graph) TestsCovering

func (g *Graph) TestsCovering(affectedDirs map[string]bool, changedFiles []string, symbolNames []string) map[string][]string

TestsCovering finds functions defined in changedFiles whose name matches one of symbolNames, then walks callers upward through the call graph and collects Test/Benchmark functions that are in one of the affectedDirs. Returns dir → []testName.

type Method

type Method string

Method selects the call graph algorithm.

const (
	// CHA selects Class Hierarchy Analysis: conservative, fast, may over-approximate interface dispatch.
	CHA Method = "cha"
	// RTA selects Rapid Type Analysis: precise, tracks concrete types, recommended for most use cases.
	RTA Method = "rta"
)

type ModuleGraph

type ModuleGraph struct {
	CG     *gocg.Graph
	Prog   *ssa.Program
	ByFile map[string][]*ssa.Function // source file → SSA functions defined there
}

ModuleGraph holds the call graph and SSA program for a single module. Fields are exported so consumers can access the underlying data for custom traversal beyond what the query methods provide.

Jump to

Keyboard shortcuts

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