rust_sitter_common/
lib.rs1use 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}