cxmeasure

command
v1.20.0 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Command cxmeasure reports cyclomatic and cognitive complexity per function, file, and package, so that refactoring is aimed at measured density rather than at whichever file someone happened to be reading.

It is a REPORTER, not a gate: it always exits 0 on a successful scan and is deliberately not wired into `make lint`. Its three siblings under tools/cmd (singlelinefunclint, typeswitchlint, nestinglint) do gate the build; this one answers "where is the complexity" rather than "is this line legal".

The two metrics, and why both

Cyclomatic complexity counts decision points. It cannot distinguish a 78-arm dispatch table from a 78-branch thicket: both score alike.

Cognitive complexity (Campbell) charges each break in linear control flow 1 point PLUS the current nesting depth. A flat table stays cheap; a deeply nested body gets expensive fast. The gap between the two metrics is the signal: cyclomatic >= cognitive means the function is WIDE, and wide is fine.

The wide-structure test (-arms)

A large function built around one dispatch switch scores high on cognitive complexity purely from the nesting penalty its arms pay, even when every arm is trivial read on its own. Before filing such a function as a refactoring candidate, re-measure its arms in isolation:

go run ./tools/cmd/cxmeasure -arms pkg/machine/machine_context.go:Run

If the extracted total collapses, the function is wide, not complex, and splitting it would relocate the score without making any arm easier to read. This is exactly the case for MachineContext.Run: cognitive 305 as written, 98 with its 78 arms extracted, 77 of which score below 5.

Known limits

Nesting is charged from the function body, so a switch at depth 0 costs 1 and its arms are charged at depth 1. An else-if continuation does not re-nest, mirroring gofmt and tools/cmd/nestinglint. Binary && and || each cost 1 without Campbell's sequence-collapsing, so long boolean chains read slightly high. Test files are skipped, consistent with the standalone linters.

Usage:

go run ./tools/cmd/cxmeasure [-by func|file|pkg] [-top N] [dir...]
go run ./tools/cmd/cxmeasure -arms <file.go>:<FuncName> [dir...]

If no directories are given, it scans the current directory recursively.

Jump to

Keyboard shortcuts

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