Documentation
¶
Overview ¶
Command singlelinefunclint enforces the project's no-single-line-function rule (CODING_STYLE.md: "Never write single-line functions. Always spread function bodies across multiple lines, even for simple implementations.").
A function *declaration* violates the rule when its body has at least one statement and its opening and closing braces sit on the same source line. Empty bodies are exempt: there is nothing to spread.
Function *literals* (anonymous closures passed as arguments: predicate tables, comparators, field accessors) are NOT checked by this tool, even though CLAUDE.md's rule covers them ("named functions, methods, closures (inline, deferred, goroutine, or assigned), and function arguments... No exceptions."). This is a limitation of the linter, not a carve-out in the rule: the codebase currently contains ~40 one-line literals in predicate/comparator tables (e.g. `func(a, b rune) bool { return a < b }`), and widening here would flag all of them at once.
Same-line detection is a positional property the gocritic/ruleguard DSL cannot express (it matches AST shape, not brace lines), so this lives as a standalone go/ast pass, mirroring tools/cmd/typeswitchlint.
It exits non-zero when any violation is found, so it can gate `make lint`.
Usage:
go run ./tools/cmd/singlelinefunclint [dir...]
If no directories are given, it scans the current directory recursively. Test files (_test.go) are skipped, consistent with the ruleguard rules in tools/ruleguard/rules.go that exempt tests from the production-only conventions.