metaplex-foundation / shank

Extracts IDL from Solana Rust contracts
https://docs.rs/crate/shank_macro/latest
130 stars 26 forks source link

[feat]: support macro generated types #39

Open febo opened 2 years ago

febo commented 2 years ago

Solita currently does not support Rust macro generated types, resulting in an error:

AssertionError [ERR_ASSERTION]: Unknown type GuardType is neither found in types nor an Account
    at TypeMapper.definedTypesImport (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/type-mapper.js:275:190)
    at TypeMapper.mapDefinedType (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/type-mapper.js:107:34)
    at TypeMapper.map (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/type-mapper.js:133:24)
    at TypeRenderer.renderTypeField (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/render-type.js:24:52)
    at /Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/render-type.js:44:34
    at Array.map (<anonymous>)
    at TypeRenderer.renderTypeScriptType (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/render-type.js:44:14)
    at TypeRenderer.renderDataStructs (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/render-type.js:91:37)
    at TypeRenderer.determineIsFixable (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/render-type.js:101:14)
    at determineTypeIsFixable (/Users/febo/Developer/metaplex-foundation/candy-guard/js/node_modules/@metaplex-foundation/solita/dist/src/render-type.js:127:21) {
  generatedMessage: false,
  code: 'ERR_ASSERTION',
  actual: undefined,
  expected: undefined,
  operator: 'fail'
}

A potential solution would be to use cargo expand to run the macros and then look up any type not found in the source code.

thlorenz commented 2 years ago

Yeah this would be tricky to implement since at this point we go through the written code and find structs that are annotated with either BorshSerialize or BorshDeserialize to include them as custom types.

cargo expand might work, but could also result in other issues due to annotations of expanded macros no longer being present in the result, etc. It's not gonna be a simple solution I'm afraid. At any rate the changes for this need to happen in shank, so I moved the issue here (from solita).

febo commented 2 years ago

Summarizing our chat here:

  1. Generated code does not have any macro annotations, since at that point all macros have been expanded;
  2. First-pass goes through the written code;
  3. Add a second-pass to the process, where any missing type from the first-pass is looked up on the expanded code (output of cargo expand). At this point, the types to be exported do not need to have any annotations. Any type referenced by the types exported in the first-pass would be included.