cosmos-sdk
cosmos-sdk copied to clipboard
Add depinject codegen
In our discussions around app wiring, we agreed that depinject should generate code for dependency provisioning so that it is easier to review the dependency graph in PR reviews and so that appconfig/depinject are fully opt-in/opt-out.
Design Overview
The proposed design to do injection by reflection first and generating the code during the reflection process. We will require a certain template file that needs to be run to trigger codegen (which is signaled by the depinject.Codegen debug option):
//+build depinject // this build tag is used to separate the codegen template from the generated code
// this must be a static variable for depinject to use it for codegen
var appConfig depinject.Config = appconfig.LoadYaml(...)
// codegen template functions must follow a strict pattern or depinject will report an error
// all function parameters are runtime supplied dependencies, and all outputs are dependencies we're trying to resolve
func Build(appOpts servertypes.AppOptions) (appBuilder *runtime.AppBuilder, error) {
err = depinject.InjectDebug(
depinject.Codegen(), // the presence of this option tells depinject that the calling function is a codegen template and that codegen should be run
depinject.Configs(
appConfig, // 1 or more static vars are allowed here
depinject.Supply(appOpts) // all function parameters must be specified here
),
&appBuilder, // all function return values (beside error) must be specified here
)
return
}
If this file were called build.go, depinject would generate a file build.depinject.go.
TODO
- [ ] require that all provider/invoker functions and their input/output params are exported
- [ ] probably unexport
ProviderDescriptor
What action does a user take to generate build.depinject.go? Is go build -tags depinject enough?
What action does a user take to generate
build.depinject.go? Isgo build -tags depinjectenough?
They need to have some code that calls Build. I'm actually calling Build in a test file also with go:build depinject and then calling go test -tags depinject.
I think you mentioned that already, but we will definitely need something to improve the UX, so we can just do a make deps or smth. This is a bit unintuitive to have to run tests beforehand (at least for people used to wire).
cc @aljo242