extract event_err ty info from Flowy_Event macro

This commit is contained in:
appflowy 2021-07-12 11:41:08 +08:00
parent 6f3a03fa07
commit e998c9a532
7 changed files with 108 additions and 66 deletions

View File

@ -29,7 +29,7 @@ impl<'a> ASTContainer<'a> {
},
syn::Data::Enum(data) => {
// https://docs.rs/syn/1.0.48/syn/struct.DataEnum.html
ASTData::Enum(enum_from_ast(cx, &data.variants))
ASTData::Enum(enum_from_ast(cx, &data.variants, &ast.attrs))
},
};
@ -209,11 +209,12 @@ pub fn struct_from_ast<'a>(cx: &Ctxt, fields: &'a syn::Fields) -> (ASTStyle, Vec
pub fn enum_from_ast<'a>(
cx: &Ctxt,
variants: &'a Punctuated<syn::Variant, Token![,]>,
enum_attrs: &Vec<syn::Attribute>,
) -> Vec<ASTEnumVariant<'a>> {
variants
.iter()
.flat_map(|variant| {
let attrs = attr::ASTEnumAttrVariant::from_ast(cx, variant);
let attrs = attr::ASTEnumAttrVariant::from_ast(cx, variant, enum_attrs);
let (style, fields) = struct_from_ast(cx, &variant.fields);
Some(ASTEnumVariant {

View File

@ -5,6 +5,7 @@ use syn::{
self,
parse::{self, Parse},
Meta::{List, NameValue, Path},
NestedMeta,
NestedMeta::{Lit, Meta},
};
@ -260,6 +261,7 @@ pub enum Default {
pub struct EventAttrs {
input: Option<syn::Path>,
output: Option<syn::Path>,
error_ty: Option<String>,
pub ignore: bool,
}
@ -271,7 +273,7 @@ pub struct ASTEnumAttrVariant {
}
impl ASTEnumAttrVariant {
pub fn from_ast(ctxt: &Ctxt, variant: &syn::Variant) -> Self {
pub fn from_ast(ctxt: &Ctxt, variant: &syn::Variant, enum_attrs: &Vec<syn::Attribute>) -> Self {
let name = variant.ident.to_string();
let mut value = String::new();
if variant.discriminant.is_some() {
@ -287,60 +289,7 @@ impl ASTEnumAttrVariant {
_ => {},
}
}
let mut event_attrs = EventAttrs {
input: None,
output: None,
ignore: false,
};
variant.attrs.iter().for_each(|attr| match get_meta_items(ctxt, attr) {
Ok(meta_items) => {
for meta_item in meta_items {
match &meta_item {
Meta(NameValue(name_value)) => {
if name_value.path == EVENT_INPUT {
if let syn::Lit::Str(s) = &name_value.lit {
let input_type = parse_lit_str(s)
.map_err(|_| {
ctxt.error_spanned_by(
s,
format!("failed to parse request deserializer {:?}", s.value()),
)
})
.unwrap();
event_attrs.input = Some(input_type);
}
}
if name_value.path == EVENT_OUTPUT {
if let syn::Lit::Str(s) = &name_value.lit {
let output_type = parse_lit_str(s)
.map_err(|_| {
ctxt.error_spanned_by(
s,
format!("failed to parse response deserializer {:?}", s.value()),
)
})
.unwrap();
event_attrs.output = Some(output_type);
}
}
},
Meta(Path(word)) => {
if word == EVENT_IGNORE && attr.path == EVENT {
event_attrs.ignore = true;
}
},
Lit(s) => {
ctxt.error_spanned_by(s, "unexpected type in cqrs container attribute");
},
_ => {
ctxt.error_spanned_by(meta_item, "unexpected type in cqrs container attribute");
},
}
}
},
Err(_) => {},
});
let event_attrs = get_event_attrs_from(ctxt, &variant.attrs, enum_attrs);
ASTEnumAttrVariant {
name,
value,
@ -353,6 +302,101 @@ impl ASTEnumAttrVariant {
pub fn event_output(&self) -> Option<syn::Path> { self.event_attrs.output.clone() }
}
fn get_event_attrs_from(
ctxt: &Ctxt,
variant_attrs: &Vec<syn::Attribute>,
enum_attrs: &Vec<syn::Attribute>,
) -> EventAttrs {
let mut event_attrs = EventAttrs {
input: None,
output: None,
error_ty: None,
ignore: false,
};
enum_attrs
.iter()
.filter(|attr| {
attr.path
.segments
.iter()
.find(|s| s.ident == EVENT_ERR)
.is_some()
})
.for_each(|attr| {
if let Ok(NameValue(named_value)) = attr.parse_meta() {
if let syn::Lit::Str(s) = named_value.lit {
event_attrs.error_ty = Some(s.value());
} else {
eprintln!("{} should not be empty", EVENT_ERR);
}
} else {
eprintln!("❌ Can not find any {} on attr: {:#?}", EVENT_ERR, attr);
}
});
let mut extract_event_attr =
|attr: &syn::Attribute, meta_item: &syn::NestedMeta| match &meta_item {
Meta(NameValue(name_value)) => {
if name_value.path == EVENT_INPUT {
if let syn::Lit::Str(s) = &name_value.lit {
let input_type = parse_lit_str(s)
.map_err(|_| {
ctxt.error_spanned_by(
s,
format!("failed to parse request deserializer {:?}", s.value()),
)
})
.unwrap();
event_attrs.input = Some(input_type);
}
}
if name_value.path == EVENT_OUTPUT {
if let syn::Lit::Str(s) = &name_value.lit {
let output_type = parse_lit_str(s)
.map_err(|_| {
ctxt.error_spanned_by(
s,
format!(
"failed to parse response deserializer {:?}",
s.value()
),
)
})
.unwrap();
event_attrs.output = Some(output_type);
}
}
},
Meta(Path(word)) => {
if word == EVENT_IGNORE && attr.path == EVENT {
event_attrs.ignore = true;
}
},
Lit(s) => ctxt.error_spanned_by(s, "unexpected attribute"),
_ => ctxt.error_spanned_by(meta_item, "unexpected attribute"),
};
let attr_meta_items_info = variant_attrs
.iter()
.flat_map(|attr| match get_meta_items(ctxt, attr) {
Ok(items) => Some((attr, items)),
Err(_) => None,
})
.collect::<Vec<(&syn::Attribute, Vec<syn::NestedMeta>)>>();
for (attr, nested_metas) in attr_meta_items_info {
nested_metas
.iter()
.for_each(|meta_item| extract_event_attr(attr, meta_item))
}
// eprintln!("😁{:#?}", event_attrs);
event_attrs
}
pub fn get_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result<Vec<syn::NestedMeta>, ()> {
if attr.path != PB_ATTRS && attr.path != EVENT {
return Ok(Vec::new());

View File

@ -18,6 +18,7 @@ pub const EVENT_INPUT: Symbol = Symbol("input");
pub const EVENT_OUTPUT: Symbol = Symbol("output");
pub const EVENT_IGNORE: Symbol = Symbol("ignore");
pub const EVENT: Symbol = Symbol("event");
pub const EVENT_ERR: Symbol = Symbol("event_err");
impl PartialEq<Symbol> for Ident {
fn eq(&self, word: &Symbol) -> bool { self == word.0 }

View File

@ -1,4 +1,6 @@
use proc_macro2::TokenStream;
// #[proc_macro_derive(DartEvent, attributes(event_ty))]
pub fn expand_enum_derive(_input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
Ok(TokenStream::default())
}

View File

@ -29,7 +29,7 @@ pub fn derive_proto_buf_enum(input: TokenStream) -> TokenStream {
.into()
}
#[proc_macro_derive(Flowy_Event, attributes(event))]
#[proc_macro_derive(Flowy_Event, attributes(event, event_err))]
pub fn derive_dart_event(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
dart_event::expand_enum_derive(&input)

View File

@ -78,13 +78,6 @@ impl flowy_dispatch::Error for UserError {
}
}
macro_rules! static_error {
($name:ident, $status:expr) => {
#[allow(non_snake_case, missing_docs)]
pub fn $name() -> ErrorBuilder { ErrorBuilder::new($status) }
};
}
pub struct ErrorBuilder {
pub code: UserErrorCode,
pub msg: Option<String>,

View File

@ -2,6 +2,7 @@ use derive_more::Display;
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
#[event_err = "UserError"]
pub enum UserEvent {
#[display(fmt = "GetStatus")]
#[event(output = "UserDetail")]
@ -13,6 +14,6 @@ pub enum UserEvent {
#[event(input = "SignUpRequest", output = "UserDetail")]
SignUp = 2,
#[display(fmt = "SignOut")]
#[event()]
#[event(passthrough)]
SignOut = 3,
}