Skip to content

About

A golangci-lint linter that forces your Clanker to write shorter code comments.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

laconiccomments

laconic /ləˈkɒnɪk/ adj. — using few words; terse. After Laconia, the region around Sparta, whose people were famed for it: Philip II of Macedon is said to have written "If I invade Laconia, I will level Lacedaemon to the ground," and to have been answered, "If."

A golangci-lint linter that forces your Clanker to write shorter code comments.

Two limits, both configurable:

  • a comment line longer than max-line-length (default 120)
  • a comment group taller than max-lines (default 5)

A comment group is a run of comments with no blank line and no other tokens between them, so 6 consecutive // lines are one group, not 6 comments.

foo.go:80:1: comment line is 158 characters long, limit is 120 (laconiccomments)
bar.go:192:1: comment spans 89 lines, limit is 5 (laconiccomments)

What it will not flag

Findings you cannot act on are worse than no findings, so:

  • Tooling directives — //go:generate, //nolint:..., //lint:ignore. Reflowing these breaks them.
  • Generated files — anything carrying the // Code generated ... DO NOT EDIT. marker from go.dev/s/generatedcode.
  • File headers — copyright, license and build-constraint blocks above the package clause. Boilerplate you did not write and cannot shorten. The package doc comment is not a header: it sits directly on package with no blank line, and gets checked like the prose it is.
  • Unbreakable tokens — a line whose excess comes from a single token no rewrap could shorten: a URL, a commit hash, a template literal. Without this exemption, every reference link in a codebase is a finding with no fix. On the first codebase this ran against, 2 of 5 findings in a module were bare reference links.

//nolint:laconiccomments works too, because golangci-lint applies nolint directives to plugins like any other linter.

Use it with golangci-lint

golangci-lint has no runtime plugin loading, so a linter has to be compiled in. That is what module plugins are, and it takes two files plus one command.

.custom-gcl.yml — the build recipe:

version: v2.13.2          # the golangci-lint release to build from
name: custom-gcl
destination: ./bin
plugins:
  - module: github.com/hidalgopl/laconiccomments
    version: v0.1.0
    import: github.com/hidalgopl/laconiccomments/plugin

.golangci.yml — enable it like any built-in:

version: "2"
linters:
  enable:
    - laconiccomments
  settings:
    custom:
      laconiccomments:
        type: module
        description: Forces your Clanker to write shorter code comments.
        settings:
          max-line-length: 120
          max-lines: 5

Then:

golangci-lint custom     # writes ./bin/custom-gcl
./bin/custom-gcl run

./bin/custom-gcl is golangci-lint plus this linter. Use it everywhere you used golangci-lint, including in CI.

Expect this if you forget

Error: build linters: plugin(laconiccomments): plugin "laconiccomments" not found

A plain golangci-lint refuses to start on a config that names a plugin it was not built with. The config and the binary travel together — wire the golangci-lint custom step into whatever builds your lint target, so nobody has to remember.

While iterating on the linter

Swap version: for a local checkout; relative paths work:

plugins:
  - module: github.com/hidalgopl/laconiccomments
    path: ../laconiccomments
    import: github.com/hidalgopl/laconiccomments/plugin

Use it without golangci-lint

It is an ordinary go/analysis analyzer, so it also runs standalone or under go vet. You lose nolint directives, which are a golangci-lint feature.

On Go 1.24 or newer, a tool directive is the shortest path in: the version is pinned in your own go.mod, there is no binary to install, and CI needs no build step.

go get -tool github.com/hidalgopl/laconiccomments/cmd/laconiccomments@v0.1.0

go tool laconiccomments ./...
go tool laconiccomments -max-line-length=80 ./...

go get -tool records the tool in your go.mod and its dependencies in your go.sum, so golang.org/x/tools joins your module graph.

Without a tool directive, install the binary yourself:

go install github.com/hidalgopl/laconiccomments/cmd/laconiccomments@latest

laconiccomments -max-line-length=80 ./...
go vet -vettool=$(which laconiccomments) ./...

Development

make test     # go test ./...
make cover    # statement coverage over every package, plugin wiring included
make lint     # builds bin/custom-gcl, then dogfoods this linter on itself

Tests use analysistest over testdata/src, a GOPATH-style tree, matching each diagnostic against a // want "regexp" comment on the same line. Two consequences shape that testdata, and will bite you if you extend it:

  • The annotation counts toward its own line's length, so patterns use \d+ rather than a fixed character count.
  • A want inside a /* ... */ registers on the line of the opening /*, and everything after want in that comment is parsed as further expectations. A multi-line block comment therefore cannot carry its own annotation; testdata/src/groups covers block comments with a run of consecutive one-line /* */ comments instead.

Those two limits are why analyzer_test.go exists alongside them: it runs the analyzer over in-memory sources through a hand-built analysis.Pass, so a case can assert the exact line, column and character count, block comments included. Reach for it when the position or the number in the message is the point, and for testdata when the case reads better as a real Go file.

License

MIT. See LICENSE.

About

A golangci-lint linter that forces your Clanker to write shorter code comments.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages