CosmWasm / cosmwasm-go

Enabling CosmWasm smart contracts in Go using TinyGo
Apache License 2.0
29 stars 8 forks source link

Improve usability of codegen tooling #139

Open ethanfrey opened 2 years ago

ethanfrey commented 2 years ago

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?

fdymylja commented 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. 😖

ethanfrey commented 2 years ago

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):

  1. Place all struct that will receive autogenerated methods in one file (eg. 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.
  2. Advice to comment out all code in contract.go and contract_test.go (except for 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.

ethanfrey commented 2 years ago

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?

fdymylja commented 2 years ago

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?

It might be a good idea to do it in this way, and maybe even a good practice enforcement.

fdymylja commented 2 years ago

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:

fdymylja commented 2 years ago

^ 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.