rust_sitter_common/
lib.rs

1use std::collections::HashSet;
2
3use syn::{
4    parse::{Parse, ParseStream},
5    punctuated::Punctuated,
6    *,
7};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct NameValueExpr {
11    pub path: Ident,
12    pub eq_token: Token![=],
13    pub expr: Expr,
14}
15
16impl Parse for NameValueExpr {
17    fn parse(input: ParseStream) -> syn::Result<Self> {
18        Ok(NameValueExpr {
19            path: input.parse()?,
20            eq_token: input.parse()?,
21            expr: input.parse()?,
22        })
23    }
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct FieldThenParams {
28    pub field: Field,
29    pub comma: Option<Token![,]>,
30    pub params: Punctuated<NameValueExpr, Token![,]>,
31}
32
33impl Parse for FieldThenParams {
34    fn parse(input: ParseStream) -> syn::Result<Self> {
35        let field = Field::parse_unnamed(input)?;
36        let comma: Option<Token![,]> = input.parse()?;
37        let params = if comma.is_some() {
38            Punctuated::parse_terminated_with(input, NameValueExpr::parse)?
39        } else {
40            Punctuated::new()
41        };
42
43        Ok(FieldThenParams {
44            field,
45            comma,
46            params,
47        })
48    }
49}
50
51pub fn try_extract_inner_type(
52    ty: &Type,
53    inner_of: &str,
54    skip_over: &HashSet<&str>,
55) -> (Type, bool) {
56    if let Type::Path(p) = &ty {
57        let type_segment = p.path.segments.last().unwrap();
58        if type_segment.ident == inner_of {
59            let leaf_type = if let PathArguments::AngleBracketed(p) = &type_segment.arguments {
60                if let GenericArgument::Type(t) = p.args.first().unwrap().clone() {
61                    t
62                } else {
63                    panic!("Argument in angle brackets must be a type")
64                }
65            } else {
66                panic!("Expected angle bracketed path");
67            };
68
69            (leaf_type, true)
70        } else if skip_over.contains(type_segment.ident.to_string().as_str()) {
71            if let PathArguments::AngleBracketed(p) = &type_segment.arguments {
72                if let GenericArgument::Type(t) = p.args.first().unwrap().clone() {
73                    try_extract_inner_type(&t, inner_of, skip_over)
74                } else {
75                    panic!("Argument in angle brackets must be a type")
76                }
77            } else {
78                panic!("Expected angle bracketed path");
79            }
80        } else {
81            (ty.clone(), false)
82        }
83    } else {
84        (ty.clone(), false)
85    }
86}
87
88pub fn filter_inner_type(ty: &Type, skip_over: &HashSet<&str>) -> Type {
89    if let Type::Path(p) = &ty {
90        let type_segment = p.path.segments.last().unwrap();
91        if skip_over.contains(type_segment.ident.to_string().as_str()) {
92            if let PathArguments::AngleBracketed(p) = &type_segment.arguments {
93                if let GenericArgument::Type(t) = p.args.first().unwrap().clone() {
94                    filter_inner_type(&t, skip_over)
95                } else {
96                    panic!("Argument in angle brackets must be a type")
97                }
98            } else {
99                panic!("Expected angle bracketed path");
100            }
101        } else {
102            ty.clone()
103        }
104    } else {
105        ty.clone()
106    }
107}
108
109pub fn wrap_leaf_type(ty: &Type, skip_over: &HashSet<&str>) -> Type {
110    let mut ty = ty.clone();
111    if let Type::Path(p) = &mut ty {
112        let type_segment = p.path.segments.last_mut().unwrap();
113        if skip_over.contains(type_segment.ident.to_string().as_str()) {
114            if let PathArguments::AngleBracketed(args) = &mut type_segment.arguments {
115                for a in args.args.iter_mut() {
116                    if let syn::GenericArgument::Type(t) = a {
117                        *t = wrap_leaf_type(t, skip_over);
118                    }
119                }
120
121                ty
122            } else {
123                panic!("Expected angle bracketed path");
124            }
125        } else {
126            parse_quote!(rust_sitter::WithLeaf<#ty>)
127        }
128    } else {
129        parse_quote!(rust_sitter::WithLeaf<#ty>)
130    }
131}