git.delta.rocks / unique-network / refs/commits / 12eee8195c76

difftreelog

misk: Generate solidity docs for struct

Trubnikov Sergey2022-11-21parent: #3e03fdf.patch.diff
in: master

4 files changed

modifiedcrates/evm-coder/procedural/src/abi_derive.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive.rs
+++ b/crates/evm-coder/procedural/src/abi_derive.rs
@@ -2,6 +2,29 @@
 
 pub(crate) fn impl_abi_macro(ast: &syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
 	let name = &ast.ident;
+	let docs = ast
+		.attrs
+		.iter()
+		.filter_map(|attr| {
+			if let Some(ps) = attr.path.segments.first() {
+				if ps.ident == "doc" {
+					let meta = match attr.parse_meta() {
+						Ok(meta) => meta,
+						Err(e) => return Some(Err(e)),
+					};
+					match meta {
+						syn::Meta::NameValue(mnv) => match &mnv.lit {
+							syn::Lit::Str(ls) => return Some(Ok(ls.value())),
+							_ => unreachable!(),
+						},
+						_ => unreachable!(),
+					}
+				}
+			}
+			None
+		})
+		.collect::<syn::Result<Vec<_>>>()?;
+
 	let (is_named_fields, field_names, field_types, params_count) = match &ast.data {
 		syn::Data::Struct(ds) => match ds.fields {
 			syn::Fields::Named(ref fields) => Ok((
@@ -37,7 +60,8 @@
 	let abi_write = impl_abi_write(name, is_named_fields, params_count, field_names.clone());
 	let solidity_type = impl_solidity_type(name, field_types.clone(), params_count);
 	let solidity_type_name = impl_solidity_type_name(name, field_types.clone(), params_count);
-	let solidity_struct_collect = impl_solidity_struct_collect(name, field_names, field_types);
+	let solidity_struct_collect =
+		impl_solidity_struct_collect(name, field_names, field_types, &docs);
 
 	Ok(quote! {
 		#can_be_plcaed_in_vec
@@ -259,6 +283,7 @@
 	name: &syn::Ident,
 	field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,
 	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
+	docs: &Vec<String>,
 ) -> proc_macro2::TokenStream {
 	let string_name = name.to_string();
 	let name_type = field_names
@@ -271,6 +296,13 @@
 				write!(str, "{};", #name).unwrap();
 			)
 		});
+	let docs = docs.iter().enumerate().map(|(i, doc)| {
+		let doc = doc.trim();
+		let dev = if i == 0 { " @dev" } else { "" };
+		quote! {
+			writeln!(str, "///{} {}", #dev, #doc).unwrap();
+		}
+	});
 
 	quote! {
 		#[cfg(feature = "stubgen")]
@@ -283,7 +315,7 @@
 				use std::fmt::Write;
 
 				let mut str = String::new();
-				writeln!(str, "/// @dev Cross account struct").unwrap();
+				#(#docs)*
 				writeln!(str, "struct {} {{", Self::name()).unwrap();
 				#(#name_type)*
 				writeln!(str, "}}").unwrap();
modifiedcrates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth
before · crates/evm-coder/src/solidity/impls.rs
1use super::{TypeCollector, SolidityTypeName, SolidityType, StructCollect};2use crate::{sealed, types::*};3use core::fmt;45macro_rules! solidity_type_name {6    ($($ty:ty => $name:literal $simple:literal = $default:literal),* $(,)?) => {7        $(8            impl SolidityTypeName for $ty {9                fn solidity_name(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {10                    write!(writer, $name)11                }12				fn is_simple() -> bool {13					$simple14				}15				fn solidity_default(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {16					write!(writer, $default)17				}18            }1920			impl StructCollect for $ty {21				fn name() -> String {22					$name.to_string()23				}2425				fn declaration() -> String {26					String::default()27				}28			}29        )*30    };31}3233solidity_type_name! {34	uint8 => "uint8" true = "0",35	uint32 => "uint32" true = "0",36	uint64 => "uint64" true = "0",37	uint128 => "uint128" true = "0",38	uint256 => "uint256" true = "0",39	bytes4 => "bytes4" true = "bytes4(0)",40	address => "address" true = "0x0000000000000000000000000000000000000000",41	string => "string" false = "\"\"",42	bytes => "bytes" false = "hex\"\"",43	bool => "bool" true = "false",44}4546impl SolidityTypeName for void {47	fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {48		Ok(())49	}50	fn is_simple() -> bool {51		true52	}53	fn solidity_default(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {54		Ok(())55	}56	fn is_void() -> bool {57		true58	}59}6061impl<T: SolidityTypeName + sealed::CanBePlacedInVec> SolidityTypeName for Vec<T> {62	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {63		T::solidity_name(writer, tc)?;64		write!(writer, "[]")65	}66	fn is_simple() -> bool {67		false68	}69	fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {70		write!(writer, "new ")?;71		T::solidity_name(writer, tc)?;72		write!(writer, "[](0)")73	}74}7576macro_rules! count {77    () => (0usize);78    ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));79}8081macro_rules! impl_tuples {82	($($ident:ident)+) => {83		impl<$($ident: SolidityTypeName + 'static),+> SolidityType for ($($ident,)+) {84			fn names(tc: &TypeCollector) -> Vec<string> {85				let mut collected = Vec::with_capacity(Self::len());86				$({87					let mut out = string::new();88					$ident::solidity_name(&mut out, tc).expect("no fmt error");89					collected.push(out);90				})*;91				collected92			}9394			fn len() -> usize {95				count!($($ident)*)96			}97		}98		impl<$($ident: SolidityTypeName + 'static),+> SolidityTypeName for ($($ident,)+) {99			fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {100				write!(writer, "{}", tc.collect_tuple::<Self>())101			}102			fn is_simple() -> bool {103				false104			}105			#[allow(unused_assignments)]106			fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {107				write!(writer, "{}(", tc.collect_tuple::<Self>())?;108				let mut first = true;109				$(110					if !first {111						write!(writer, ",")?;112					} else {113						first = false;114					}115					<$ident>::solidity_default(writer, tc)?;116				)*117				write!(writer, ")")118			}119		}120	};121}122123impl_tuples! {A}124impl_tuples! {A B}125impl_tuples! {A B C}126impl_tuples! {A B C D}127impl_tuples! {A B C D E}128impl_tuples! {A B C D E F}129impl_tuples! {A B C D E F G}130impl_tuples! {A B C D E F G H}131impl_tuples! {A B C D E F G H I}132impl_tuples! {A B C D E F G H I J}133134impl sealed::CanBePlacedInVec for Property {}135impl StructCollect for Property {136	fn name() -> String {137		"Property".into()138	}139140	fn declaration() -> String {141		let mut str = String::new();142		writeln!(str, "/// @dev Property struct").unwrap();143		writeln!(str, "struct {} {{", Self::name()).unwrap();144		writeln!(str, "\tstring key;").unwrap();145		writeln!(str, "\tbytes value;").unwrap();146		writeln!(str, "}}").unwrap();147		str148	}149}150151impl SolidityTypeName for Property {152	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {153		write!(writer, "{}", tc.collect_struct::<Self>())154	}155156	fn is_simple() -> bool {157		false158	}159160	fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {161		write!(writer, "{}(", tc.collect_struct::<Self>())?;162		address::solidity_default(writer, tc)?;163		write!(writer, ",")?;164		uint256::solidity_default(writer, tc)?;165		write!(writer, ")")166	}167}168169impl SolidityTupleType for Property {170	fn names(tc: &TypeCollector) -> Vec<string> {171		let mut collected = Vec::with_capacity(Self::len());172		{173			let mut out = string::new();174			string::solidity_name(&mut out, tc).expect("no fmt error");175			collected.push(out);176		}177		{178			let mut out = string::new();179			bytes::solidity_name(&mut out, tc).expect("no fmt error");180			collected.push(out);181		}182		collected183	}184185	fn len() -> usize {186		2187	}188}
modifiedcrates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/abi_derive_generation.rs
+++ b/crates/evm-coder/tests/abi_derive_generation.rs
@@ -57,10 +57,16 @@
 	_b: TypeStruct2DynamicParam,
 }
 
+/// Some docs
+/// At multi
+/// line
 #[derive(AbiCoder, PartialEq, Debug)]
 struct TypeStruct3DerivedMixedParam {
+	/// Docs for A
 	_a: TypeStruct1SimpleParam,
+	/// Docs for B
 	_b: TypeStruct2DynamicParam,
+	/// Docs for C
 	_c: TypeStruct2MixedParam,
 }
 
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -113,6 +113,7 @@
 	}
 }
 
+/// Cross account struct
 #[derive(Debug, Default, AbiCoder)]
 pub struct EthCrossAccount {
 	pub(crate) eth: address,