update syn to v2.0, large update
This commit is contained in:
@ -19,7 +19,7 @@ path = "../satrs-core"
|
||||
path = "codegen"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
version = "1"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
|
@ -12,18 +12,18 @@ name = "tests"
|
||||
path = "tests/tests.rs"
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1"
|
||||
proc-macro2 = "1"
|
||||
|
||||
[dependencies.satrs-core]
|
||||
path = "../../satrs-core"
|
||||
|
||||
[dev-dependencies]
|
||||
trybuild = { version = "1.0", features = ["diff"] }
|
||||
trybuild = { version = "1", features = ["diff"] }
|
||||
|
||||
[dev-dependencies.satrs-mib]
|
||||
path = ".."
|
||||
|
||||
[dependencies.syn]
|
||||
version = "1.0"
|
||||
features = ["extra-traits"]
|
||||
version = "2"
|
||||
features = ["full", "extra-traits"]
|
||||
|
@ -1,105 +1,42 @@
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{parse_macro_input, AttributeArgs, Item, Lit, LitStr, Meta, NestedMeta, Type};
|
||||
|
||||
#[derive(Default)]
|
||||
struct ResultExtGenerator {
|
||||
name_str: Option<Ident>,
|
||||
info_str: Option<LitStr>,
|
||||
}
|
||||
use syn::{parse_macro_input, ItemConst, LitStr};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn resultcode(
|
||||
args: proc_macro::TokenStream,
|
||||
item: proc_macro::TokenStream,
|
||||
) -> proc_macro::TokenStream {
|
||||
let args = parse_macro_input!(args as AttributeArgs);
|
||||
let input = parse_macro_input!(item as Item);
|
||||
let mut result_ext_generator = ResultExtGenerator::default();
|
||||
result_ext_generator.parse(args, input).into()
|
||||
}
|
||||
|
||||
impl ResultExtGenerator {
|
||||
pub fn parse(&mut self, args: AttributeArgs, input: Item) -> TokenStream {
|
||||
let mut output = input.to_token_stream();
|
||||
if let Err(e) = self.parse_args(args) {
|
||||
output.extend(e.into_compile_error());
|
||||
return output;
|
||||
}
|
||||
match self.gen_ext_struct(input) {
|
||||
Ok(ts) => output.extend(ts),
|
||||
Err(e) => output.extend(e.into_compile_error()),
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
pub fn parse_args(&mut self, args: AttributeArgs) -> syn::Result<()> {
|
||||
for arg in args {
|
||||
if let NestedMeta::Meta(Meta::NameValue(nvm)) = arg {
|
||||
if let Some(path) = nvm.path.segments.first() {
|
||||
if path.ident == "info" {
|
||||
if let Lit::Str(str) = nvm.lit {
|
||||
self.info_str = Some(str);
|
||||
} else {
|
||||
return Err(syn::Error::new(
|
||||
nvm.lit.span(),
|
||||
"Only literal strings are allowed as information",
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Err(syn::Error::new(
|
||||
path.span(),
|
||||
format!("Unknown attribute argument name {}", path.ident),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn gen_ext_struct(&mut self, input: Item) -> syn::Result<TokenStream> {
|
||||
if let Item::Const(const_item) = &input {
|
||||
self.name_str = Some(const_item.ident.clone());
|
||||
if let Type::Path(p) = &const_item.ty.as_ref() {
|
||||
let mut valid_type_found = false;
|
||||
for seg in &p.path.segments {
|
||||
if seg.ident == "ResultU16" {
|
||||
valid_type_found = true;
|
||||
}
|
||||
}
|
||||
if !valid_type_found {
|
||||
return Err(syn::Error::new(
|
||||
p.span(),
|
||||
"Can only be applied on items of type ResultU16",
|
||||
));
|
||||
}
|
||||
}
|
||||
// Handle attributes first.
|
||||
let mut info_str: Option<LitStr> = None;
|
||||
let res_code_parser = syn::meta::parser(|meta| {
|
||||
if meta.path.is_ident("info") {
|
||||
info_str = Some(meta.value()?.parse()?);
|
||||
Ok(())
|
||||
} else {
|
||||
return Err(syn::Error::new(
|
||||
input.span(),
|
||||
"Only const items are allowed to be use with this attribute",
|
||||
));
|
||||
Err(meta.error("unsupported property for resultcode attribute"))
|
||||
}
|
||||
let result_code_name = self.name_str.to_owned().unwrap();
|
||||
let name_as_str = result_code_name.to_string();
|
||||
let gen_struct_name = format_ident!("{}_EXT", result_code_name);
|
||||
let info_str = if let Some(info_str) = &self.info_str {
|
||||
info_str.value()
|
||||
} else {
|
||||
String::from("")
|
||||
};
|
||||
// TODO: Group string
|
||||
let gen_struct = quote! {
|
||||
const #gen_struct_name: satrs_mib::res_code::ResultU16Info =
|
||||
satrs_mib::res_code::ResultU16Info::const_new(
|
||||
#name_as_str,
|
||||
&#result_code_name,
|
||||
"",
|
||||
#info_str
|
||||
);
|
||||
};
|
||||
Ok(gen_struct)
|
||||
}
|
||||
});
|
||||
parse_macro_input!(args with res_code_parser);
|
||||
let item = parse_macro_input!(item as ItemConst);
|
||||
|
||||
// Generate additional generated info struct used for introspection.
|
||||
let result_code_name = item.ident.clone();
|
||||
let name_as_str = result_code_name.to_string();
|
||||
let gen_struct_name = format_ident!("{}_EXT", result_code_name);
|
||||
let info_str = info_str.map_or(String::from(""), |v| v.value());
|
||||
// TODO: Group string
|
||||
let generated_struct = quote! {
|
||||
const #gen_struct_name: satrs_mib::res_code::ResultU16Info =
|
||||
satrs_mib::res_code::ResultU16Info::const_new(
|
||||
#name_as_str,
|
||||
&#result_code_name,
|
||||
"",
|
||||
#info_str
|
||||
);
|
||||
};
|
||||
|
||||
// The input constant returncode is written to the output in any case.
|
||||
let mut output = item.to_token_stream();
|
||||
output.extend(generated_struct);
|
||||
output.into()
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
use satrs_core::res_code::ResultU16;
|
||||
use satrs_mib::resultcode;
|
||||
|
||||
#[resultcode(info = "This is a test result where the first parameter is foo")]
|
||||
#[resultcode]
|
||||
const _TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1);
|
||||
|
||||
fn main() {}
|
||||
|
8
satrs-mib/codegen/tests/basic_with_info.rs
Normal file
8
satrs-mib/codegen/tests/basic_with_info.rs
Normal file
@ -0,0 +1,8 @@
|
||||
//! Basic check which just verifies that everything compiles
|
||||
use satrs_core::res_code::ResultU16;
|
||||
use satrs_mib::resultcode;
|
||||
|
||||
#[resultcode(info = "This is a test result where the first parameter is foo")]
|
||||
const _TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1);
|
||||
|
||||
fn main() {}
|
@ -2,6 +2,7 @@
|
||||
fn tests() {
|
||||
let t = trybuild::TestCases::new();
|
||||
t.pass("tests/basic.rs");
|
||||
t.pass("tests/basic_with_info.rs");
|
||||
t.pass("tests/verify_gen_struct.rs");
|
||||
//t.pass("tests/group_in_enum.rs");
|
||||
}
|
||||
|
Reference in New Issue
Block a user