From e998c9a5328c3d85454354db1127d8814f17eae4 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 12 Jul 2021 11:41:08 +0800 Subject: [PATCH] extract event_err ty info from Flowy_Event macro --- rust-lib/flowy-ast/src/ast.rs | 5 +- rust-lib/flowy-ast/src/attr.rs | 154 +++++++++++++------- rust-lib/flowy-ast/src/symbol.rs | 1 + rust-lib/flowy-derive/src/dart_event/mod.rs | 2 + rust-lib/flowy-derive/src/lib.rs | 2 +- rust-lib/flowy-user/src/errors.rs | 7 - rust-lib/flowy-user/src/event.rs | 3 +- 7 files changed, 108 insertions(+), 66 deletions(-) diff --git a/rust-lib/flowy-ast/src/ast.rs b/rust-lib/flowy-ast/src/ast.rs index 5163c07c7c..3990e123a2 100644 --- a/rust-lib/flowy-ast/src/ast.rs +++ b/rust-lib/flowy-ast/src/ast.rs @@ -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, + enum_attrs: &Vec, ) -> Vec> { 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 { diff --git a/rust-lib/flowy-ast/src/attr.rs b/rust-lib/flowy-ast/src/attr.rs index 48634d2272..bfbc1ed717 100644 --- a/rust-lib/flowy-ast/src/attr.rs +++ b/rust-lib/flowy-ast/src/attr.rs @@ -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, output: Option, + error_ty: Option, 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) -> 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 { self.event_attrs.output.clone() } } +fn get_event_attrs_from( + ctxt: &Ctxt, + variant_attrs: &Vec, + enum_attrs: &Vec, +) -> 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::)>>(); + + 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, ()> { if attr.path != PB_ATTRS && attr.path != EVENT { return Ok(Vec::new()); diff --git a/rust-lib/flowy-ast/src/symbol.rs b/rust-lib/flowy-ast/src/symbol.rs index d80d0feab7..6b9e01f05e 100644 --- a/rust-lib/flowy-ast/src/symbol.rs +++ b/rust-lib/flowy-ast/src/symbol.rs @@ -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 for Ident { fn eq(&self, word: &Symbol) -> bool { self == word.0 } diff --git a/rust-lib/flowy-derive/src/dart_event/mod.rs b/rust-lib/flowy-derive/src/dart_event/mod.rs index df54745b81..3fc2b83fce 100644 --- a/rust-lib/flowy-derive/src/dart_event/mod.rs +++ b/rust-lib/flowy-derive/src/dart_event/mod.rs @@ -1,4 +1,6 @@ use proc_macro2::TokenStream; + +// #[proc_macro_derive(DartEvent, attributes(event_ty))] pub fn expand_enum_derive(_input: &syn::DeriveInput) -> Result> { Ok(TokenStream::default()) } diff --git a/rust-lib/flowy-derive/src/lib.rs b/rust-lib/flowy-derive/src/lib.rs index 3265ae2b10..82f0002fb3 100644 --- a/rust-lib/flowy-derive/src/lib.rs +++ b/rust-lib/flowy-derive/src/lib.rs @@ -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) diff --git a/rust-lib/flowy-user/src/errors.rs b/rust-lib/flowy-user/src/errors.rs index aaa147c757..f1f05e42d6 100644 --- a/rust-lib/flowy-user/src/errors.rs +++ b/rust-lib/flowy-user/src/errors.rs @@ -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, diff --git a/rust-lib/flowy-user/src/event.rs b/rust-lib/flowy-user/src/event.rs index 502ec1d566..d21eb7acbf 100644 --- a/rust-lib/flowy-user/src/event.rs +++ b/rust-lib/flowy-user/src/event.rs @@ -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, }