ordo

module
v0.0.0-...-ebf9fc4 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2026 License: MIT

README

ordo

CI

ordo works out the order to review Go functions in — callees before callers, so you never read a function before the things it depends on.

$ ordo ./cmd/generate
Review order — callee before caller (7 step(s), 7 function(s)):

  1. github.com/nikolaydubina/go-featureprocessing/cmd/generate.writeCodeToFile$1
     cmd/generate/main.go:85
  2. github.com/nikolaydubina/go-featureprocessing/cmd/generate.writeCodeToFile
     cmd/generate/main.go:71
  3. github.com/nikolaydubina/go-featureprocessing/cmd/generate.parseCode
     cmd/generate/parser.go:83
  4. github.com/nikolaydubina/go-featureprocessing/cmd/generate.generate
     cmd/generate/main.go:55
  5. github.com/nikolaydubina/go-featureprocessing/cmd/generate.run
     cmd/generate/main.go:18
  6. github.com/nikolaydubina/go-featureprocessing/cmd/generate.parseCode$1
     cmd/generate/parser.go:96
  7. github.com/nikolaydubina/go-featureprocessing/cmd/generate.main
     cmd/generate/main.go:93

Why

Reviewing functions in file order means reading code before its dependencies: you hit a function without knowing what it calls or who calls it, and you build the mental model backwards. ordo reads the call graph and gives you an order where every dependency comes before the code that uses it — the same order you'd naturally want to read unfamiliar code in.

Install

go install github.com/Spot2025/ordo/cmd/ordo@latest

Requires Go 1.25+. This drops an ordo binary in your $GOBIN (usually ~/go/bin).

Usage

ordo [flags] <path>, where <path> is a Go package directory or pattern — ., ./..., or a folder.

Whole module. Order every function in the module, callees first:

ordo ./...

Review a pull request — the one to reach for. Restrict the order to just the functions your branch touched:

ordo --diff --diff-base main .

--diff compares the working tree against the merge base of --diff-base and HEAD — so it shows the functions your branch added or changed, not commits that landed on main after you forked. --diff-base defaults to HEAD, which means just your uncommitted changes. It is a pure post-filter: the full graph is always built first, then narrowed to the changed functions (add --with-callees to also pull in what they call directly).

$ ordo --diff ./cmd/generate      # after editing the run function
Review order — callee before caller (1 step(s), 1 function(s)):

  1. github.com/nikolaydubina/go-featureprocessing/cmd/generate.run
     cmd/generate/main.go:18

For agents and scripts. A stable JSON contract — an object with a steps array, each step carrying order, cycle, an optional artifact flag, and a functions list (id, file, line, and, with --with-code, code). The first 2 of 7 steps:

{
  "steps": [
    {
      "order": 1,
      "cycle": false,
      "functions": [
        {
          "id": "github.com/nikolaydubina/go-featureprocessing/cmd/generate.writeCodeToFile$1",
          "file": "cmd/generate/main.go",
          "line": 85
        }
      ]
    },
    {
      "order": 2,
      "cycle": false,
      "functions": [
        {
          "id": "github.com/nikolaydubina/go-featureprocessing/cmd/generate.writeCodeToFile",
          "file": "cmd/generate/main.go",
          "line": 71
        }
      ]
    }
  ]
}

With source inline. Print each function's code under its entry, so the review order reads top to bottom without jumping around:

ordo --with-code ./...

Artifact controls. Interface-heavy code can produce a large false cycle (see Accuracy). ordo detects these and collapses them by default:

  • --show-artifacts — expand a probable-artifact group to list its members (still labelled as an artifact).
  • --artifact-threshold N — a cycle is flagged as a probable artifact when it exceeds both N% of all functions (default 25) and an absolute floor of 20 functions.

How it works

Not a regex — a real whole-program analysis:

  1. go/packages parses and type-checks the requested packages and their dependencies.
  2. SSA (golang.org/x/tools/go/ssa) lowers everything to an intermediate form.
  3. CHA (Class Hierarchy Analysis) builds a whole-program call graph.
  4. Tarjan's algorithm finds strongly-connected components — the mutually-recursive cycles.
  5. A topological sort of the SCC condensation, reversed, yields the review order: every callee before its callers, with each cycle emitted as one group.

Accuracy and limitations

Being honest about this matters more than looking clean:

  • CHA reports a conservative superset of edges. It errs toward more edges than can actually happen, never fewer — the safe direction for review (better an extra dependency than a missed one). But some edges are false positives.
  • Interface and callback calls create false edges. For a call through an interface (a.Sound()) or a function value (a func() in a variable or field), CHA has no data-flow information, so it links the caller to every method or function with a matching signature — including ones that can never reach that call site.
  • Funnel artifacts. On interface-heavy projects, those false edges can close a loop and collapse a large slice of the program into one bogus "review together" SCC (on lazygit, ~2625 functions — 36% of the codebase). ordo detects an over-large cycle and labels it as a probable artifact rather than passing it off as real mutual recursion; use --show-artifacts to inspect it.
  • cgo. Packages using cgo may leak generated _cgo_* symbols into the output.

Planned: an optional VTA (Variable Type Analysis) engine for a cleaner order — measured to remove ~74% of CHA's false edges on real code. Note it does not fix funnel cycles (a shared dispatch helper defeats any context-insensitive engine), so the artifact detection stays regardless. Not implemented yet.

Contributing

Issues and pull requests welcome. go test ./... must stay green, and code is expected to be gofmt-clean and pass go vet — CI enforces all three.

License

MIT.

Directories

Path Synopsis
cmd
ordo command
Command ordo prints a code-review order for Go packages: callees before callers, with mutually recursive functions grouped to review together.
Command ordo prints a code-review order for Go packages: callees before callers, with mutually recursive functions grouped to review together.
internal
goanalyzer
Package goanalyzer extracts a function call graph from real Go source and projects it onto the dependency-free graph model in internal/graph.
Package goanalyzer extracts a function call graph from real Go source and projects it onto the dependency-free graph model in internal/graph.
graph
Package graph models a directed call graph and computes the order in which its functions should be reviewed: a function's callees are reviewed before the function itself, so a reviewer always sees a dependency before the code that relies on it.
Package graph models a directed call graph and computes the order in which its functions should be reviewed: a function's callees are reviewed before the function itself, so a reviewer always sees a dependency before the code that relies on it.
review
Package review glues the call-graph extractor (internal/goanalyzer) to the ordering core (internal/graph) and renders the result for humans (text) and machines (json).
Package review glues the call-graph extractor (internal/goanalyzer) to the ordering core (internal/graph) and renders the result for humans (text) and machines (json).
vcs
Package vcs turns a git diff into the set of changed source lines, so the review order can be restricted to the functions a change actually touches.
Package vcs turns a git diff into the set of changed source lines, so the review order can be restricted to the functions a change actually touches.

Jump to

Keyboard shortcuts

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