1use tokrepr::TokRepr;
4use tokrepr::proc_macro2::TokenStream;
5use tokrepr::quote::{format_ident, quote};
6
7use crate::{SyntaxNode, span::Spanned, syntax::*};
8
9trait NamedNode {
13 fn name(&self) -> Option<String>;
14}
15
16impl NamedNode for GlobalDeclaration {
17 fn name(&self) -> Option<String> {
18 self.ident().map(|id| id.to_string())
19 }
20}
21
22impl NamedNode for StructMember {
23 fn name(&self) -> Option<String> {
24 Some(self.ident.to_string())
25 }
26}
27
28impl NamedNode for Attribute {
29 fn name(&self) -> Option<String> {
30 if let Attribute::Custom(attr) = self {
31 Some(attr.name.to_string())
32 } else {
33 None
34 }
35 }
36}
37
38impl NamedNode for Expression {
39 fn name(&self) -> Option<String> {
40 if let Expression::TypeOrIdentifier(ty) = self {
41 Some(ty.ident.to_string())
42 } else {
43 None
44 }
45 }
46}
47
48impl NamedNode for Statement {
49 fn name(&self) -> Option<String> {
50 if let Statement::Compound(stmt) = self {
52 if stmt.statements.is_empty() {
53 if let [attr] = stmt.attributes.as_slice() {
54 if let Attribute::Custom(attr) = attr.node() {
55 return Some(attr.name.to_string());
56 }
57 }
58 }
59 }
60 None
61 }
62}
63
64impl<T: NamedNode + TokRepr> TokRepr for Spanned<T> {
65 fn tok_repr(&self) -> TokenStream {
66 let node = self.node().tok_repr();
67 let span = self.span().tok_repr();
68
69 if let Some(name) = self.name() {
70 if let Some(suffix) = name.strip_prefix("#") {
71 let ident = format_ident!("{}", suffix);
72
73 return quote! {
74 Spanned::new(#ident.to_owned().into(), #span)
75 };
76 }
77 }
78
79 quote! {
80 Spanned::new(#node, #span)
81 }
82 }
83}
84
85impl TokRepr for Ident {
86 fn tok_repr(&self) -> TokenStream {
87 let name = self.name();
88 if let Some(name) = name.strip_prefix("#") {
89 let ident = format_ident!("{}", name);
90 quote! {
91 Ident::from(#ident.to_owned())
92 }
93 } else {
94 let name = name.as_str();
95 quote! {
96 Ident::new(#name.to_string())
97 }
98 }
99 }
100}