Skip to content

Commit eb1659f

Browse files
committed
chore: add node ast parser
1 parent c89277d commit eb1659f

File tree

20 files changed

+495
-223
lines changed

20 files changed

+495
-223
lines changed

shared-lib/flowy-ast/src/ast.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
#![allow(clippy::all)]
22
#![allow(unused_attributes)]
33
#![allow(unused_assignments)]
4-
use crate::{attr, ty_ext::*, ASTResult, AttrsContainer};
4+
5+
use crate::event_attrs::EventEnumAttrs;
6+
use crate::node_attrs::NodeStructAttrs;
7+
use crate::{is_recognizable_field, pb_attrs, ty_ext::*, ASTResult, PBAttrsContainer, PBStructAttrs};
58
use syn::{self, punctuated::Punctuated};
69

710
pub struct ASTContainer<'a> {
811
/// The struct or enum name (without generics).
912
pub ident: syn::Ident,
1013
/// Attributes on the structure.
11-
pub attrs: AttrsContainer,
14+
pub attrs: PBAttrsContainer,
1215
/// The contents of the struct or enum.
1316
pub data: ASTData<'a>,
1417
}
1518

1619
impl<'a> ASTContainer<'a> {
1720
pub fn from_ast(ast_result: &ASTResult, ast: &'a syn::DeriveInput) -> Option<ASTContainer<'a>> {
18-
let attrs = AttrsContainer::from_ast(ast_result, ast);
21+
let attrs = PBAttrsContainer::from_ast(ast_result, ast);
1922
// syn::DeriveInput
2023
// 1. syn::DataUnion
2124
// 2. syn::DataStruct
@@ -55,7 +58,7 @@ impl<'a> ASTData<'a> {
5558
}
5659
}
5760

58-
pub fn all_variants(&'a self) -> Box<dyn Iterator<Item = &'a attr::ASTEnumAttrVariant> + 'a> {
61+
pub fn all_variants(&'a self) -> Box<dyn Iterator<Item = &'a EventEnumAttrs> + 'a> {
5962
match self {
6063
ASTData::Enum(variants) => {
6164
let iter = variants.iter().map(|variant| &variant.attrs);
@@ -85,7 +88,7 @@ impl<'a> ASTData<'a> {
8588
/// A variant of an enum.
8689
pub struct ASTEnumVariant<'a> {
8790
pub ident: syn::Ident,
88-
pub attrs: attr::ASTEnumAttrVariant,
91+
pub attrs: EventEnumAttrs,
8992
pub style: ASTStyle,
9093
pub fields: Vec<ASTField<'a>>,
9194
pub original: &'a syn::Variant,
@@ -106,7 +109,8 @@ pub enum BracketCategory {
106109

107110
pub struct ASTField<'a> {
108111
pub member: syn::Member,
109-
pub attrs: attr::ASTAttrField,
112+
pub pb_attrs: PBStructAttrs,
113+
pub node_attrs: NodeStructAttrs,
110114
pub ty: &'a syn::Type,
111115
pub original: &'a syn::Field,
112116
pub bracket_ty: Option<syn::Ident>,
@@ -161,7 +165,8 @@ impl<'a> ASTField<'a> {
161165
Some(ident) => syn::Member::Named(ident.clone()),
162166
None => syn::Member::Unnamed(index.into()),
163167
},
164-
attrs: attr::ASTAttrField::from_ast(cx, index, field),
168+
pb_attrs: PBStructAttrs::from_ast(cx, index, field),
169+
node_attrs: NodeStructAttrs::from_ast(cx, index, field),
165170
ty: &field.ty,
166171
original: field,
167172
bracket_ty,
@@ -185,10 +190,6 @@ impl<'a> ASTField<'a> {
185190
None
186191
}
187192
}
188-
189-
pub fn is_option(&self) -> bool {
190-
attr::is_option(self.ty)
191-
}
192193
}
193194

194195
#[derive(Copy, Clone)]
@@ -222,7 +223,7 @@ pub fn enum_from_ast<'a>(
222223
variants
223224
.iter()
224225
.flat_map(|variant| {
225-
let attrs = attr::ASTEnumAttrVariant::from_ast(cx, ident, variant, enum_attrs);
226+
let attrs = EventEnumAttrs::from_ast(cx, ident, variant, enum_attrs);
226227
let (style, fields) = struct_from_ast(cx, &variant.fields);
227228
Some(ASTEnumVariant {
228229
ident: variant.ident.clone(),
@@ -239,6 +240,12 @@ fn fields_from_ast<'a>(cx: &ASTResult, fields: &'a Punctuated<syn::Field, Token!
239240
fields
240241
.iter()
241242
.enumerate()
242-
.flat_map(|(index, field)| ASTField::new(cx, field, index).ok())
243+
.flat_map(|(index, field)| {
244+
if is_recognizable_field(field) {
245+
ASTField::new(cx, field, index).ok()
246+
} else {
247+
None
248+
}
249+
})
243250
.collect()
244251
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
use crate::{get_event_meta_items, parse_lit_str, symbol::*, ASTResult};
2+
3+
4+
use syn::{
5+
self,
6+
parse::{self, Parse},
7+
Meta::{List, NameValue, Path},
8+
NestedMeta::{Lit, Meta},
9+
};
10+
11+
#[derive(Debug, Clone)]
12+
pub struct EventAttrs {
13+
input: Option<syn::Path>,
14+
output: Option<syn::Path>,
15+
error_ty: Option<String>,
16+
pub ignore: bool,
17+
}
18+
19+
#[derive(Debug, Clone)]
20+
pub struct EventEnumAttrs {
21+
pub enum_name: String,
22+
pub enum_item_name: String,
23+
pub value: String,
24+
pub event_attrs: EventAttrs,
25+
}
26+
27+
impl EventEnumAttrs {
28+
pub fn from_ast(
29+
ast_result: &ASTResult,
30+
ident: &syn::Ident,
31+
variant: &syn::Variant,
32+
enum_attrs: &[syn::Attribute],
33+
) -> Self {
34+
let enum_item_name = variant.ident.to_string();
35+
let enum_name = ident.to_string();
36+
let mut value = String::new();
37+
if variant.discriminant.is_some() {
38+
if let syn::Expr::Lit(ref expr_list) = variant.discriminant.as_ref().unwrap().1 {
39+
let lit_int = if let syn::Lit::Int(ref int_value) = expr_list.lit {
40+
int_value
41+
} else {
42+
unimplemented!()
43+
};
44+
value = lit_int.base10_digits().to_string();
45+
}
46+
}
47+
let event_attrs = get_event_attrs_from(ast_result, &variant.attrs, enum_attrs);
48+
EventEnumAttrs {
49+
enum_name,
50+
enum_item_name,
51+
value,
52+
event_attrs,
53+
}
54+
}
55+
56+
pub fn event_input(&self) -> Option<syn::Path> {
57+
self.event_attrs.input.clone()
58+
}
59+
60+
pub fn event_output(&self) -> Option<syn::Path> {
61+
self.event_attrs.output.clone()
62+
}
63+
64+
pub fn event_error(&self) -> String {
65+
self.event_attrs.error_ty.as_ref().unwrap().clone()
66+
}
67+
}
68+
69+
fn get_event_attrs_from(
70+
ast_result: &ASTResult,
71+
variant_attrs: &[syn::Attribute],
72+
enum_attrs: &[syn::Attribute],
73+
) -> EventAttrs {
74+
let mut event_attrs = EventAttrs {
75+
input: None,
76+
output: None,
77+
error_ty: None,
78+
ignore: false,
79+
};
80+
81+
enum_attrs
82+
.iter()
83+
.filter(|attr| attr.path.segments.iter().any(|s| s.ident == EVENT_ERR))
84+
.for_each(|attr| {
85+
if let Ok(NameValue(named_value)) = attr.parse_meta() {
86+
if let syn::Lit::Str(s) = named_value.lit {
87+
event_attrs.error_ty = Some(s.value());
88+
} else {
89+
eprintln!("❌ {} should not be empty", EVENT_ERR);
90+
}
91+
} else {
92+
eprintln!("❌ Can not find any {} on attr: {:#?}", EVENT_ERR, attr);
93+
}
94+
});
95+
96+
let mut extract_event_attr = |attr: &syn::Attribute, meta_item: &syn::NestedMeta| match &meta_item {
97+
Meta(NameValue(name_value)) => {
98+
if name_value.path == EVENT_INPUT {
99+
if let syn::Lit::Str(s) = &name_value.lit {
100+
let input_type = parse_lit_str(s)
101+
.map_err(|_| {
102+
ast_result
103+
.error_spanned_by(s, format!("failed to parse request deserializer {:?}", s.value()))
104+
})
105+
.unwrap();
106+
event_attrs.input = Some(input_type);
107+
}
108+
}
109+
110+
if name_value.path == EVENT_OUTPUT {
111+
if let syn::Lit::Str(s) = &name_value.lit {
112+
let output_type = parse_lit_str(s)
113+
.map_err(|_| {
114+
ast_result
115+
.error_spanned_by(s, format!("failed to parse response deserializer {:?}", s.value()))
116+
})
117+
.unwrap();
118+
event_attrs.output = Some(output_type);
119+
}
120+
}
121+
}
122+
Meta(Path(word)) => {
123+
if word == EVENT_IGNORE && attr.path == EVENT {
124+
event_attrs.ignore = true;
125+
}
126+
}
127+
Lit(s) => ast_result.error_spanned_by(s, "unexpected attribute"),
128+
_ => ast_result.error_spanned_by(meta_item, "unexpected attribute"),
129+
};
130+
131+
let attr_meta_items_info = variant_attrs
132+
.iter()
133+
.flat_map(|attr| match get_event_meta_items(ast_result, attr) {
134+
Ok(items) => Some((attr, items)),
135+
Err(_) => None,
136+
})
137+
.collect::<Vec<(&syn::Attribute, Vec<syn::NestedMeta>)>>();
138+
139+
for (attr, nested_metas) in attr_meta_items_info {
140+
nested_metas
141+
.iter()
142+
.for_each(|meta_item| extract_event_attr(attr, meta_item))
143+
}
144+
145+
// eprintln!("😁{:#?}", event_attrs);
146+
event_attrs
147+
}

shared-lib/flowy-ast/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ extern crate syn;
55
extern crate quote;
66

77
mod ast;
8-
mod attr;
98
mod ctxt;
9+
mod pb_attrs;
1010

11+
mod event_attrs;
12+
mod node_attrs;
1113
pub mod symbol;
1214
pub mod ty_ext;
15+
1316
pub use self::{symbol::*, ty_ext::*};
1417
pub use ast::*;
15-
pub use attr::*;
1618
pub use ctxt::ASTResult;
19+
pub use event_attrs::*;
20+
pub use pb_attrs::*;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use crate::{get_node_meta_items, get_pb_meta_items, parse_lit_into_expr_path, symbol::*, ASTAttr, ASTResult};
2+
use proc_macro2::{Group, Span, TokenStream, TokenTree};
3+
use quote::ToTokens;
4+
use syn::{
5+
self,
6+
parse::{self, Parse},
7+
Meta::{List, NameValue, Path},
8+
NestedMeta::{Lit, Meta},
9+
};
10+
11+
pub struct NodeStructAttrs {
12+
node_index: Option<syn::LitInt>,
13+
get_node_value_with: Option<syn::ExprPath>,
14+
set_node_value_with: Option<syn::ExprPath>,
15+
}
16+
17+
impl NodeStructAttrs {
18+
/// Extract out the `#[node(...)]` attributes from a struct field.
19+
pub fn from_ast(ast_result: &ASTResult, index: usize, field: &syn::Field) -> Self {
20+
let mut node_index = ASTAttr::none(ast_result, NODE_INDEX);
21+
let mut get_node_value_with = ASTAttr::none(ast_result, GET_NODE_VALUE_WITH);
22+
let mut set_node_value_with = ASTAttr::none(ast_result, SET_NODE_VALUE_WITH);
23+
24+
let ident = match &field.ident {
25+
Some(ident) => ident.to_string(),
26+
None => index.to_string(),
27+
};
28+
29+
for meta_item in field
30+
.attrs
31+
.iter()
32+
.flat_map(|attr| get_node_meta_items(ast_result, attr))
33+
.flatten()
34+
{
35+
match &meta_item {
36+
// Parse '#[node(index = x)]'
37+
Meta(NameValue(m)) if m.path == NODE_INDEX => {
38+
if let syn::Lit::Int(lit) = &m.lit {
39+
node_index.set(&m.path, lit.clone());
40+
}
41+
}
42+
43+
// Parse `#[node(get_node_value_with = "...")]`
44+
Meta(NameValue(m)) if m.path == GET_NODE_VALUE_WITH => {
45+
if let Ok(path) = parse_lit_into_expr_path(ast_result, GET_NODE_VALUE_WITH, &m.lit) {
46+
get_node_value_with.set(&m.path, path);
47+
}
48+
}
49+
50+
// Parse `#[node(set_node_value_with= "...")]`
51+
Meta(NameValue(m)) if m.path == SET_NODE_VALUE_WITH => {
52+
if let Ok(path) = parse_lit_into_expr_path(ast_result, SET_NODE_VALUE_WITH, &m.lit) {
53+
set_node_value_with.set(&m.path, path);
54+
}
55+
}
56+
57+
Meta(meta_item) => {
58+
let path = meta_item.path().into_token_stream().to_string().replace(' ', "");
59+
ast_result.error_spanned_by(meta_item.path(), format!("unknown node field attribute `{}`", path));
60+
}
61+
62+
Lit(lit) => {
63+
ast_result.error_spanned_by(lit, "unexpected literal in field attribute");
64+
}
65+
}
66+
}
67+
68+
NodeStructAttrs {
69+
node_index: node_index.get(),
70+
get_node_value_with: get_node_value_with.get(),
71+
set_node_value_with: set_node_value_with.get(),
72+
}
73+
}
74+
75+
pub fn set_node_value_with(&self) -> Option<&syn::ExprPath> {
76+
self.set_node_value_with.as_ref()
77+
}
78+
79+
pub fn get_node_value_with(&self) -> Option<&syn::ExprPath> {
80+
self.get_node_value_with.as_ref()
81+
}
82+
}

0 commit comments

Comments
 (0)