Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use scale-typegen as a backend for the codegen #1260

Merged
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e163e57
integrate scale-typegen, remove types mod
tadeohepperle Nov 9, 2023
1760792
reintroduce default substitutes and derives
tadeohepperle Nov 10, 2023
b297fc8
support runtime_types only again
tadeohepperle Nov 13, 2023
7a2678a
generating polkadot.rs ok
tadeohepperle Nov 13, 2023
60c1e62
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Nov 13, 2023
297d2c6
update scale-typegen to discrete error types
tadeohepperle Nov 15, 2023
f47fd4e
scale-typegen-api-changes
tadeohepperle Nov 21, 2023
03591a6
add note about UncheckedExtrinsic in default substitutes
tadeohepperle Nov 21, 2023
9e56546
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Nov 21, 2023
50ed54e
add resursive attributes and derives
tadeohepperle Nov 28, 2023
dabc88c
adjust example where Clone bound recursive
tadeohepperle Nov 28, 2023
cd73d31
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Nov 29, 2023
fd718bf
move scale-typegen dependency to workspace
tadeohepperle Nov 29, 2023
985a46c
expose default typegen settings
tadeohepperle Nov 29, 2023
a6b580f
lightclient: Fix wasm socket closure called after being dropped (#1289)
lexnv Nov 29, 2023
44c42c3
workflows: Install rustup component for building substrate (#1295)
lexnv Nov 29, 2023
0724735
cli: Command to fetch chainSpec and optimise its size (#1278)
lexnv Nov 29, 2023
ee1e096
conflicts
tadeohepperle Nov 29, 2023
58b8fee
remove comments and unused args
tadeohepperle Nov 30, 2023
0c7d373
Update substrate- and signer-related dependencies (#1297)
tadeohepperle Nov 30, 2023
42643d8
fix lock file
tadeohepperle Nov 30, 2023
8196b63
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Nov 30, 2023
bbda16a
fix lock file again :|
tadeohepperle Nov 30, 2023
4259572
adjust to new interface in scale-typegen
tadeohepperle Dec 8, 2023
14775ab
use released scale typegen
tadeohepperle Jan 2, 2024
69af6d1
reintroduce type aliases
tadeohepperle Jan 2, 2024
f125b2b
introduce type aliases again using scale-typegen
tadeohepperle Jan 2, 2024
602d459
cargo fmt and clippy
tadeohepperle Jan 2, 2024
b18d472
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Jan 3, 2024
aaf9ded
reconcile changes with master branch
tadeohepperle Jan 3, 2024
05dbe3f
update polkadot.rs
tadeohepperle Jan 3, 2024
e54cb73
bump scale-typgen to fix substitution
tadeohepperle Jan 5, 2024
24cb3d7
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Jan 5, 2024
3d1fdec
implemented Alex suggestions, regenerated polkadot.rs (did not change)
tadeohepperle Jan 9, 2024
f0ef2a9
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Jan 9, 2024
72fee7d
Merge branch 'master' into tadeohepperle/implement-scale-typegen-for-…
tadeohepperle Jan 9, 2024
a96c90f
resolve conflicts in Cargo.lock
tadeohepperle Jan 10, 2024
70d3de0
make expect messages more clear
tadeohepperle Jan 11, 2024
00aee3d
correct typos
tadeohepperle Jan 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
737 changes: 453 additions & 284 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 3 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,13 @@ members = [
"macro",
"metadata",
"signer",
"subxt"
"subxt",
]

# We exclude any crates that would depend on non mutually
# exclusive feature flags and thus can't compile with the
# workspace:
exclude = [
"testing/wasm-rpc-tests",
"testing/wasm-lightclient-tests",
"signer/wasm-tests",
"examples/wasm-example",
"examples/parachain-example"
]
exclude = ["testing/wasm-rpc-tests", "testing/wasm-lightclient-tests", "signer/wasm-tests", "examples/wasm-example", "examples/parachain-example"]
resolver = "2"

[workspace.package]
Expand Down Expand Up @@ -80,6 +74,7 @@ trybuild = "1.0.85"
wabt = "0.10.0"
wasm-bindgen-test = "0.3.24"
which = "4.4.2"
scale-typegen = { git = "https://github.com/paritytech/scale-typegen", branch = "recursive-derives" }

# Light client support:
smoldot = { version = "0.12.0", default-features = false }
Expand Down
10 changes: 8 additions & 2 deletions cli/src/commands/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ fn codegen(
.map_err(|e| eyre!("Cannot parse derive for type {ty_str}: {e}"))?;
let derive = syn::parse_str(&derive)
.map_err(|e| eyre!("Cannot parse derive for type {ty_str}: {e}"))?;
codegen.add_derives_for_type(ty, std::iter::once(derive));
// Note: recursive derives and attributes not supported in the CLI => recursive: false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we want to support recursive derives in the CLI? Might be worth a separate issue to remind us of it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, maybe. Or maybe we just make everything recursive by default in the CLI, I think it is already quite hard to specify derives in the CLI.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great if you could open an issue for it :)

codegen.add_derives_for_type(ty, std::iter::once(derive), false);
}

// Configure attribtues:
Expand All @@ -185,7 +186,8 @@ fn codegen(
.map_err(|e| eyre!("Cannot parse attribute for type {ty_str}: {e}"))?;
let attribute: OuterAttribute = syn::parse_str(&attr)
.map_err(|e| eyre!("Cannot parse attribute for type {ty_str}: {e}"))?;
codegen.add_attributes_for_type(ty, std::iter::once(attribute.0));
// Note: recursive derives and attributes not supported in the CLI => recursive: false
codegen.add_attributes_for_type(ty, std::iter::once(attribute.0), false);
}

// Insert type substitutions:
Expand All @@ -201,6 +203,10 @@ fn codegen(
.map_err(|e| eyre!("Cannot decode the provided metadata: {e}"))?;
let code = codegen
.generate(metadata)
.map_err(|e| {
dbg!(&e);
e
})
.map_err(|e| eyre!("Cannot generate code: {e}"))?;

writeln!(output, "{code}")?;
Expand Down
3 changes: 1 addition & 2 deletions codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ jsonrpsee = { workspace = true, features = ["async-client", "client-ws-transport
hex = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread"], optional = true }
thiserror = { workspace = true }
scale-typegen = { workspace = true }

# Included if "web" feature is enabled, to enable its js feature.
getrandom = { workspace = true, optional = true }

[dev-dependencies]
bitvec = { workspace = true }
scale-info = { workspace = true, features = ["bit-vec"] }
pretty_assertions = { workspace = true }
38 changes: 18 additions & 20 deletions codegen/src/api/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
// see LICENSE for license details.

use super::CodegenError;
use crate::types::{CompositeDefFields, TypeGenerator};
use heck::{ToSnakeCase as _, ToUpperCamelCase as _};
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use scale_typegen::{typegen::ir::type_ir::CompositeIRKind, TypeGenerator};
use subxt_metadata::PalletMetadata;

/// Generate calls from the provided pallet's metadata. Each call returns a `StaticTxPayload`
Expand All @@ -21,48 +21,45 @@ use subxt_metadata::PalletMetadata;
pub fn generate_calls(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
types_mod_ident: &syn::Ident,
crate_path: &syn::Path,
should_gen_docs: bool,
) -> Result<TokenStream2, CodegenError> {
// Early return if the pallet has no calls.
let Some(call_ty) = pallet.call_ty_id() else {
return Ok(quote!());
};

let mut struct_defs = super::generate_structs_from_variants(
let struct_defs = super::generate_structs_from_variants(
type_gen,
call_ty,
|name| name.to_upper_camel_case().into(),
"Call",
crate_path,
should_gen_docs,
)?;
let (call_structs, call_fns): (Vec<_>, Vec<_>) = struct_defs
.iter_mut()
.map(|(variant_name, struct_def)| {
let (call_fn_args, call_args): (Vec<_>, Vec<_>) = match struct_def.fields {
CompositeDefFields::Named(ref named_fields) => named_fields
.into_iter()
.map(|(variant_name, composite)| {
let (call_fn_args, call_args): (Vec<_>, Vec<_>) = match &composite.kind {
CompositeIRKind::Named(named_fields) => named_fields
.iter()
.map(|(name, field)| {
let fn_arg_type = &field.type_path;
let call_arg = if field.is_boxed() {
let call_arg = if field.is_boxed {
quote! { #name: ::std::boxed::Box::new(#name) }
} else {
quote! { #name }
};
(quote!( #name: #fn_arg_type ), call_arg)
})
.unzip(),
CompositeDefFields::NoFields => Default::default(),
CompositeDefFields::Unnamed(_) => {
CompositeIRKind::NoFields => Default::default(),
CompositeIRKind::Unnamed(_) => {
return Err(CodegenError::InvalidCallVariant(call_ty))
}
};

let pallet_name = pallet.name();
let call_name = &variant_name;
let struct_name = &struct_def.name;
let struct_name = &composite.name;
let Some(call_hash) = pallet.call_hash(call_name) else {
return Err(CodegenError::MissingCallMetadata(
pallet_name.into(),
Expand All @@ -72,8 +69,10 @@ pub fn generate_calls(
let fn_name = format_ident!("{}", variant_name.to_snake_case());
// Propagate the documentation just to `TransactionApi` methods, while
// draining the documentation of inner call structures.
let docs = should_gen_docs.then_some(struct_def.docs.take()).flatten();
let docs = &composite.docs;

// this converts the composite into a full struct type. No Type Parameters needed here.
let struct_def = type_gen.upcast_composite(&composite);
// The call structure's documentation was stripped above.
let call_struct = quote! {
#struct_def
Expand Down Expand Up @@ -105,12 +104,11 @@ pub fn generate_calls(
.into_iter()
.unzip();

let call_type = type_gen.resolve_type_path(call_ty);
let call_ty = type_gen.resolve_type(call_ty);
let docs = &call_ty.docs;
let docs = should_gen_docs
.then_some(quote! { #( #[doc = #docs ] )* })
.unwrap_or_default();
let call_type = type_gen.resolve_type_path(call_ty)?;
let call_ty = type_gen.resolve_type(call_ty)?;
let docs = type_gen.docs_from_scale_info(&call_ty.docs);

let types_mod_ident = type_gen.types_mod_ident();

Ok(quote! {
#docs
Expand Down
12 changes: 7 additions & 5 deletions codegen/src/api/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.

use crate::types::TypeGenerator;
use heck::ToSnakeCase as _;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use scale_typegen::TypeGenerator;
use subxt_metadata::PalletMetadata;

use super::CodegenError;
Expand Down Expand Up @@ -36,9 +36,7 @@ use super::CodegenError;
pub fn generate_constants(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
types_mod_ident: &syn::Ident,
crate_path: &syn::Path,
should_gen_docs: bool,
) -> Result<TokenStream2, CodegenError> {
// Early return if the pallet has no constants.
if pallet.constants().len() == 0 {
Expand All @@ -58,9 +56,11 @@ pub fn generate_constants(
));
};

let return_ty = type_gen.resolve_type_path(constant.ty());
let return_ty = type_gen.resolve_type_path(constant.ty())?;
let docs = constant.docs();
let docs = should_gen_docs
let docs = type_gen
.settings()
.should_gen_docs
.then_some(quote! { #( #[doc = #docs ] )* })
.unwrap_or_default();

Expand All @@ -77,6 +77,8 @@ pub fn generate_constants(
})
.collect::<Result<Vec<_>, _>>()?;

let types_mod_ident = type_gen.types_mod_ident();

Ok(quote! {
pub mod constants {
use super::#types_mod_ident;
Expand Down
6 changes: 3 additions & 3 deletions codegen/src/api/custom_values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.

use std::collections::HashSet;

use crate::types::TypeGenerator;
use heck::ToSnakeCase as _;
use scale_typegen::TypeGenerator;
use std::collections::HashSet;
use subxt_metadata::{CustomValueMetadata, Metadata};

use proc_macro2::TokenStream as TokenStream2;
Expand Down Expand Up @@ -60,6 +59,7 @@ fn generate_custom_value_fn(
let (return_ty, decodable) = if type_is_valid {
let return_ty = type_gen
.resolve_type_path(custom_value.type_id())
.expect("expected to contain type id")
.to_token_stream();
let decodable = quote!(#crate_path::custom_values::Yes);
(return_ty, decodable)
Expand Down
7 changes: 3 additions & 4 deletions codegen/src/api/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use scale_typegen::TypeGenerator;
use subxt_metadata::PalletMetadata;

use crate::types::TypeGenerator;

use super::CodegenError;

/// Generate error type alias from the provided pallet metadata.
Expand All @@ -20,8 +19,8 @@ pub fn generate_error_type_alias(
return Ok(quote!());
};

let error_type = type_gen.resolve_type_path(error_ty);
let error_ty = type_gen.resolve_type(error_ty);
let error_type = type_gen.resolve_type_path(error_ty)?;
let error_ty = type_gen.resolve_type(error_ty)?;
let docs = &error_ty.docs;
let docs = should_gen_docs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be infered from the type_gen.settings()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, totally! Good catch!

.then_some(quote! { #( #[doc = #docs ] )* })
Expand Down
22 changes: 12 additions & 10 deletions codegen/src/api/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.

use crate::types::TypeGenerator;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use scale_typegen::TypeGenerator;
use subxt_metadata::PalletMetadata;

use super::CodegenError;
Expand Down Expand Up @@ -41,9 +41,7 @@ use super::CodegenError;
pub fn generate_events(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
types_mod_ident: &syn::Ident,
crate_path: &syn::Path,
should_gen_docs: bool,
) -> Result<TokenStream2, CodegenError> {
// Early return if the pallet has no events.
let Some(event_ty) = pallet.event_ty_id() else {
Expand All @@ -56,29 +54,33 @@ pub fn generate_events(
|name| name.into(),
"Event",
crate_path,
should_gen_docs,
)?;

let event_structs = struct_defs.iter().map(|(variant_name, struct_def)| {
let event_structs = struct_defs.into_iter().map(|(variant_name, composite)| {
let pallet_name = pallet.name();
let event_struct = &struct_def.name;
let event_struct_name = &composite.name;
let event_name = variant_name;

let struct_def = type_gen.upcast_composite(&composite);
quote! {
#struct_def

impl #crate_path::events::StaticEvent for #event_struct {
impl #crate_path::events::StaticEvent for #event_struct_name {
const PALLET: &'static str = #pallet_name;
const EVENT: &'static str = #event_name;
}
}
});
let event_type = type_gen.resolve_type_path(event_ty);
let event_ty = type_gen.resolve_type(event_ty);

let event_type = type_gen.resolve_type_path(event_ty)?;
let event_ty = type_gen.resolve_type(event_ty)?;
let docs = &event_ty.docs;
let docs = should_gen_docs
let docs = type_gen
.settings()
.should_gen_docs
.then_some(quote! { #( #[doc = #docs ] )* })
.unwrap_or_default();
let types_mod_ident = type_gen.types_mod_ident();

Ok(quote! {
#docs
Expand Down
Loading