kanna

kanna / kanna

kanna gen

v0.3.0 Go 1.26 pkg.go.dev

日本語

The kanna command runs the kanna family of Go code generators in the order they need, so that a project keeps no list of packages for it. It adds no configuration: what it runs is the //go:generate go tool kanna-* lines already there, and each generator goes on working without it.

Install

go get -tool github.com/go-kanna/kanna@latest

Each generator it runs has to be a release that answers -deps, which kanna gen tells you when one is not.

Usage

$ go tool kanna gen
  internal/feature/todo/model/todo_model.go:15      kanna-value     wrote internal/feature/todo/model/value_gen.go
  internal/feature/todo/model/todo_model.go:42      kanna-fixture   unchanged
  internal/feature/todo/usecase/generate.go:3       kanna-validate  wrote internal/feature/todo/usecase/validate_gen.go
  ...
11 tasks, 2 files changed

With nothing to do it says 11 tasks, 0 files changed, and no more. The first task to fail stops the run, and what the tasks before it wrote stays:

completed    internal/feature/todo/model/todo_model.go:15    kanna-value   wrote internal/feature/todo/model/value_gen.go
failed       internal/feature/todo/mapper/todo_mapper.go:10  kanna-mapper
  ./todo_mapper.go:32:13: error: cannot use "x" (untyped string constant) as int value in variable declaration
not run      internal/feature/todo/handler/todo_handler.go:15  kanna-di

1 completed, 1 failed, 1 not run
1 file changed; completed changes remain in the working tree

Packages narrow it down, as for the go command. ./... is the default. The packages bring along what writes what they read, and not what reads them.

go tool kanna gen --plan prints what would run, and why in that order, running nothing:

$ go tool kanna gen --plan
...
8. internal/feature/todo/usecase/generate.go:3
   run:    go tool kanna-validate
   writes: internal/feature/todo/usecase/validate_gen.go
   after:  5 — reads internal/feature/todo/scopes, which kanna-orm writes into
   after:  7 — reads internal/messages, which kanna-i18n writes into

9. internal/feature/todo/usecase/generate.go:4
   run:    go tool kanna-di
   writes: internal/feature/todo/usecase/di_gen.go
   after:  2 — its tests read internal/di, which kanna-di writes into
   after:  4 — its tests read internal/feature/todo/model/fixture, which kanna-fixture writes into
   after:  6 — its tests read internal/feature/todo/postgres, which kanna-orm writes into
   after:  8 — code in internal/feature/todo/usecase calls what kanna-validate generates
...
external prerequisites:
  internal/gen/showcase/todo/v1 — generated by protoc-gen-go, protoc-gen-go-grpc

go tool kanna gen --check compares what is on disk with what would be generated, and writes nothing. It fails on a file that differs, and on a task it could not check, which is one that reads what a differing task would write:

- run: go tool kanna gen --check

What it does and does not run

A task is one //go:generate go tool kanna-* line, run as go generate runs it: in its package's directory, with GOFILE and the rest, and with the line's quotes and $ variables read the same way. The same line twice in a package runs once.

Before starting, it refuses a plan with tasks waiting for each other, two tasks writing one file, an input that is not there, or a line that means to run a generator some other way: a -command alias, a shell, another executable, or kanna-orm describe. Other generators' lines it leaves alone, so what buf or sqlc write has to be there first, and is theirs to check.

How the order is worked out

Each generator answers -deps with what a run reads and writes, and the module's hand-written files say what imports what. A task comes after what writes into a package it reads. What generators wrote is left out of all of it, so that a plan is the same before they have run and after.

Two tasks writing into a package they both read are told apart by what the code calls: a task checks that code once its output is in place, so it comes after what writes what the code calls. When the code calls what both write, no order compiles, and go generate cannot get through it from nothing. kanna gen runs one first and tells it the other's names are coming, and the last to run finds them there, or reports them.

Developing the family

DEVELOPING.md says how to change the family across repositories: the workspace of every checkout in dev, a script running every repository's tests against it, and the order releases go in.

Earlier versions of this module

github.com/go-kanna/kanna used to be another module, kanna v0.2.x with the first kanna-orm. Its versions, v0.0.1 to v0.2.0, stay in the Go module proxy, retracted so that go get warns of them, and its code on the archive/v0.2 branch of the site's repository. The kanna command starts above them, at v0.3.0.

License

MIT