diff --git a/Cargo.lock b/Cargo.lock index e2b6bba2a56bdd125475db9f94084b56e52c89d6..470e820e88447c0d3410d45b388dc1c55a14a82a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8947,6 +8947,22 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "tera" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d4685e72cb35f0eb74319c8fe2d3b61e93da5609841cde2cb87fcc3bea56d20" +dependencies = [ + "globwalk", + "lazy_static", + "pest", + "pest_derive", + "regex", + "serde", + "serde_json", + "unic-segment", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -9374,9 +9390,9 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.3", - "rand 0.7.3", + "rand 0.8.4", "static_assertions", ] @@ -9415,6 +9431,56 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" +dependencies = [ + "unic-ucd-segment", +] + +[[package]] +name = "unic-ucd-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicase" version = "2.6.0" @@ -10159,6 +10225,7 @@ dependencies = [ "scale-info", "serde", "serde_json", + "tera", "tokio", "version-compare", "version_check", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index d6d2b863ec30be89fae189dfb89cfc7309a5388d..528564f2a932edc8287ee4c414ba88f258f85de0 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -29,3 +29,4 @@ serde_json = "1.0" tokio = { version = "1.15.0", features = ["macros"] } version_check = "0.9.2" version-compare = "0.0.11" +tera = { version = "1", default-features = false } \ No newline at end of file diff --git a/xtask/res/templates/runtime-calls-category.md b/xtask/res/templates/runtime-calls-category.md new file mode 100644 index 0000000000000000000000000000000000000000..2553bfb355d4981a29d4db5a6ce04048a221e4b7 --- /dev/null +++ b/xtask/res/templates/runtime-calls-category.md @@ -0,0 +1,25 @@ +There are **{{ calls_counter }}** {{ category_name }} calls from **{{ pallets | length }}** pallets. + +{% for pallet in pallets -%} +### {{ pallet.name }} - {{ pallet.index }} + +{% for call in pallet.calls -%} +#### {{ call.name }} - {{ call.index }} + +<details><summary><code>{{ call.name }}( + {%- for param in call.params -%} + {{ param.name }}{% if loop.last != true %}, {% endif %} + {%- endfor -%} + )</code></summary> + +```rust +{% for param in call.params -%} +{{ param.name }}: {{ param.type_name }} +{% endfor -%} +``` +</details> + +{{ call.documentation }} + +{% endfor -%} +{% endfor -%} diff --git a/xtask/res/templates/runtime-calls.md b/xtask/res/templates/runtime-calls.md new file mode 100644 index 0000000000000000000000000000000000000000..d2c4c0fd0fa7b200551f074cd5d7d97dbce630d5 --- /dev/null +++ b/xtask/res/templates/runtime-calls.md @@ -0,0 +1,34 @@ +# Runtime calls + +Calls are categorized according to the dispatch origin they require: + +1. **User calls**: the dispatch origin for this kind of call must be signed by +the transactor. This is the only call category that can be submitted with an extrinsic. +1. **Root calls**: This kind of call requires a special origin that can only be invoked +through on-chain governance mechanisms. +1. **Inherent calls**: This kind of call is invoked by the author of the block itself +(usually automatically by the node). +1. **Disabled calls**: These calls are disabled for different reasons (to be documented). + + +{% set pallets = user_calls_pallets -%} +{% set calls_counter = user_calls_counter -%} +{% set category_name = "user" -%} +## User calls + +{% include "runtime-calls-category.md" %} + +{% set pallets = root_calls_pallets -%} +{% set calls_counter = root_calls_counter -%} +{% set category_name = "root" -%} +## Root calls + +{% include "runtime-calls-category.md" %} + +{% set pallets = disabled_calls_pallets %} +{% set calls_counter = disabled_calls_counter %} +{% set category_name = "disabled" %} +## Disabled calls + +{% include "runtime-calls-category.md" -%} + diff --git a/xtask/src/gen_calls_doc.rs b/xtask/src/gen_calls_doc.rs index af07b82e4a64ae85f2c4727f5f118362140fbace..e1bd5e97d6db79da22ce44397a10b9865194a4e8 100644 --- a/xtask/src/gen_calls_doc.rs +++ b/xtask/src/gen_calls_doc.rs @@ -17,15 +17,88 @@ use anyhow::{bail, Context, Result}; use codec::Decode; use scale_info::form::PortableForm; +use serde::Serialize; use std::{ fs::File, io::{Read, Write}, }; +use tera::Tera; + +// consts const CALLS_DOC_FILEPATH: &str = "docs/api/runtime-calls.md"; +const TEMPLATES_GLOB: &str = "xtask/res/templates/*.md"; + +// define structs and implementations type RuntimeCalls = Vec<Pallet>; +#[derive(Clone, Serialize)] +struct Pallet { + index: u8, + name: String, + calls: Vec<Call>, +} + +impl Pallet { + fn new( + index: u8, + name: String, + scale_type_def: &scale_info::TypeDef<PortableForm>, + ) -> Result<Self> { + if let scale_info::TypeDef::Variant(calls_enum) = scale_type_def { + Ok(Self { + index, + name, + calls: calls_enum.variants().iter().map(Into::into).collect(), + }) + } else { + bail!("Invalid metadata") + } + } +} + +#[derive(Clone, Serialize)] +struct Call { + documentation: String, + index: u8, + name: String, + params: Vec<CallParam>, +} + +impl From<&scale_info::Variant<PortableForm>> for Call { + fn from(variant: &scale_info::Variant<PortableForm>) -> Self { + Self { + documentation: variant + .docs() + .to_vec() + .iter() + .take_while(|line| !line.starts_with("# <weight>")) + .cloned() + .collect::<Vec<_>>() + .join("\n"), + index: variant.index(), + name: variant.name().to_owned(), + params: variant.fields().iter().map(Into::into).collect(), + } + } +} + +#[derive(Clone, Serialize)] +struct CallParam { + name: String, + type_name: String, +} + +impl From<&scale_info::Field<PortableForm>> for CallParam { + fn from(field: &scale_info::Field<PortableForm>) -> Self { + Self { + name: field.name().cloned().unwrap_or_default(), + type_name: field.type_name().cloned().unwrap_or_default(), + } + } +} + enum CallCategory { Disabled, Inherent, @@ -81,65 +154,7 @@ impl CallCategory { } } -#[derive(Clone)] -struct Pallet { - index: u8, - name: String, - calls: Vec<Call>, -} - -impl Pallet { - fn new( - index: u8, - name: String, - scale_type_def: &scale_info::TypeDef<PortableForm>, - ) -> Result<Self> { - if let scale_info::TypeDef::Variant(calls_enum) = scale_type_def { - Ok(Self { - index, - name, - calls: calls_enum.variants().iter().map(Into::into).collect(), - }) - } else { - bail!("Invalid metadata") - } - } -} - -#[derive(Clone)] -struct Call { - docs: Vec<String>, - index: u8, - name: String, - params: Vec<CallParam>, -} - -impl From<&scale_info::Variant<PortableForm>> for Call { - fn from(variant: &scale_info::Variant<PortableForm>) -> Self { - Self { - docs: variant.docs().to_vec(), - index: variant.index(), - name: variant.name().to_owned(), - params: variant.fields().iter().map(Into::into).collect(), - } - } -} - -#[derive(Clone)] -struct CallParam { - name: String, - type_name: String, -} - -impl From<&scale_info::Field<PortableForm>> for CallParam { - fn from(field: &scale_info::Field<PortableForm>) -> Self { - Self { - name: field.name().cloned().unwrap_or_default(), - type_name: field.type_name().cloned().unwrap_or_default(), - } - } -} - +/// generate runtime calls documentation pub(super) fn gen_calls_doc() -> Result<()> { // Read metadata let mut file = std::fs::File::open("resources/metadata.scale") @@ -192,7 +207,9 @@ fn get_calls_from_metadata_v14( Ok(pallets) } +/// use template to render markdown file with runtime calls documentation fn print_runtime_calls(pallets: RuntimeCalls) -> String { + // init variables let mut user_calls_counter = 0; let user_calls_pallets: RuntimeCalls = pallets .iter() @@ -245,109 +262,24 @@ fn print_runtime_calls(pallets: RuntimeCalls) -> String { }) .collect(); - let mut output = String::new(); - - output.push_str("# Runtime calls\n\n"); - output.push_str("Calls are categorized according to the dispatch origin they require:\n\n"); - output.push_str( - r#"1. User calls: the dispatch origin for this kind of call must be Signed by -the transactor. This is the only call category that can be submitted with an extrinsic. -"#, - ); - output.push_str( - r#"1. Root calls: This kind of call requires a special origin that can only be invoked -through on-chain governance mechanisms. -"#, - ); - output.push_str( - r#"1. Inherent calls: This kind of call is invoked by the author of the block itself -(usually automatically by the node). -"#, - ); - output.push_str( - r#"1. Disabled calls: These calls are disabled for different reasons (to be documented). -"#, - ); - - output.push_str("\n\n## User calls\n\n"); - output.push_str(&print_calls_category( - user_calls_counter, - "user", - user_calls_pallets, - )); - - output.push_str("\n\n## Root calls\n\n"); - output.push_str(&print_calls_category( - root_calls_counter, - "root", - root_calls_pallets, - )); - - output.push_str("\n\n## Disabled calls\n\n"); - output.push_str(&print_calls_category( - disabled_calls_counter, - "disabled", - disabled_calls_pallets, - )); - - output -} - -fn print_calls_category(calls_counter: usize, category_name: &str, pallets: Vec<Pallet>) -> String { - let mut output = String::new(); - output.push_str(&format!( - "There are **{}** {} calls organized in **{}** pallets.\n", - calls_counter, - category_name, - pallets.len() - )); - - for pallet in pallets { - output.push_str(&format!("\n### {}: {}\n\n", pallet.index, pallet.name)); - for call in pallet.calls { - output.push_str(&format!( - "<details><summary>{}: {}({})</summary>\n<p>\n\n{}</p>\n</details>\n\n", - call.index, - call.name, - print_call_params(&call.params), - print_call_details(&call), - )); + // compile template + let tera = match Tera::new(TEMPLATES_GLOB) { + Ok(t) => t, + Err(e) => { + println!("Parsing error(s): {}", e); + ::std::process::exit(1); } - } - output -} + }; -fn print_call_details(call: &Call) -> String { - let mut output = String::new(); - output.push_str(&format!("### Index\n\n`{}`\n\n", call.index)); - output.push_str(&format!( - "### Documentation\n\n{}\n\n", - call.docs - .iter() - .take_while(|line| !line.starts_with("# <weight>")) - .cloned() - .collect::<Vec<_>>() - .join("\n") - )); - if !call.params.is_empty() { - output.push_str("### Types of parameters\n\n```rust\n"); - output.push_str( - &call - .params - .iter() - .map(|param| format!("{}: {}", param.name, param.type_name)) - .collect::<Vec<_>>() - .join(",\n"), - ); - output.push_str("\n```\n\n"); - } - output -} + // fills tera context for rendering + let mut context = tera::Context::new(); + context.insert("user_calls_counter", &user_calls_counter); + context.insert("user_calls_pallets", &user_calls_pallets); + context.insert("root_calls_counter", &root_calls_counter); + context.insert("root_calls_pallets", &root_calls_pallets); + context.insert("disabled_calls_counter", &disabled_calls_counter); + context.insert("disabled_calls_pallets", &disabled_calls_pallets); -fn print_call_params(call_params: &[CallParam]) -> String { - call_params - .iter() - .map(|param| param.name.clone()) - .collect::<Vec<_>>() - .join(", ") + tera.render("runtime-calls.md", &context) + .expect("template error") }