Open ethanfrey opened 2 years ago
Agreed. The tragedy with Golang codegen is that you need to use reflection over types. In order to do that the code must be always valid so that you can create an intermediary file which reflects over a type and then generate the code from that (two step process). Using AST is really painful. 😖
So we just need to document how to best handle the limitations.
I think the following might help (they have helped me when trying to brute force this in the past):
types.go
not msg.go
and state.go
). With tinyjson for example, there were some issues with one file compiling in one pass and the other in a second pass and that causing a compile error in the middle.package src
) and then run codegen.I am not sure if (1) will help or if that was me making other mistakes. And (2) is my brute-force approach which helped me last time. Maybe you have an easier way, but let's document something.
Ah, one more idea... what if we have src/types/{msg,state}.go
?
Then this package would compile (and codegen) even if src/contract.go
was broken?
Ah, one more idea... what if we have
src/types/{msg,state}.go
? Then this package would compile (and codegen) even ifsrc/contract.go
was broken?
It might be a good idea to do it in this way, and maybe even a good practice enforcement.
I got this idea to simplify codegen for users. What if the //go:generate
directive instead of generating code ended up appending logic to a contract.yaml file (yaml for better human readability), this contract.yaml would be a contract description from types, state and handlers perspective and would be what the developer feeds to the generator to create the contract.
This way the generator can take care of proper generation ordering:
It could also be used to condensate all the generated contract logic into a single file.
Ex contract.yaml:
contract: Contract
stateObjects:
- Person:
primaryKey: ID
secondaryKeys:
- city
- postalCode
executeHandlers:
- name: CreatePerson
input: MsgCreatePerson
queryHandlers:
- name: GetPerson
input: GetPersonRequest
output: GetPersonResponse
From this file the codegen will know how to properly handle ordered code generation.
Pros:
Cons:
//go:generate
 makes you think you're generating code but you're just creating an intermediary type for the real codegen.^ I wouldn't focus on this in the immediate term because it's a considerable chunk of work at this stage. But we should consider it in the future milestones.
We use tinyjson and a custom state code generator.
Those are working with the example contracts here. However, they can be a bit finicky when updating (it won't compile if the code was not valid before... so if you change/remove a type, then it may complain).
Once we are happy with the flow, we should make it easy to embed in a 3rd party repo. We will want most example contracts in another repo (like cw-plus) not here, so that can be a first example of how to make this codegen tooling more portable. Maybe a docker image for it as well?