constable is a static analysis tool for Go.
The first analyzer checks functions annotated with //constable:nonmutating.
An annotated function must not mutate caller-visible state through parameters or method receivers.
Standard go install installation,
go install github.com/nnutter/constable/cmd/constable@latestRun constable on your Go packages,
constable ./...This function is reported because it mutates through a pointer parameter,
//constable:nonmutating
func F(p *int) {
*p = 1
}This function is allowed because it only reads through the pointer parameter,
//constable:nonmutating
func F(p *int) int {
return *p
}This method is allowed because a scalar field assignment on a value receiver mutates only the receiver copy,
type Count struct{ n int }
//constable:nonmutating
func (c Count) Increment() Count {
c.n++
return c
}This method is reported because the slice field is mutated for the caller,
type Buffer struct{ data []byte }
//constable:nonmutating
func (b Buffer) ClearFirstByte() {
b.data[0] = 0
}The complexity analyzer reports functions and methods whose cyclomatic
complexity exceeds a limit. Complexity starts at 1 and adds 1 for each
if, for, range, case, select clause, &&, and ||. Closures
fold into the enclosing function and default clauses count.
constable ./...
constable -complexity.limit=15 ./...The limit defaults to 10 and is configured with -complexity.limit.
The predicates analyzer reports && and || operands, except the
first, that are not predicate-function calls. The first operand always
executes, so coverage observes short-circuiting through the rest.
if a && b { // reported: use a && isB()
}
if a && isB() { // allowed
}The check also covers for conditions and bool assignments such as
c := a && b, including negated variables, field and map access,
and comparisons.
Run all fixers,
mise run fixersRun all tests,
mise run testsRun all linters,
mise run linters