fix_getters_utils/
scope.rs1use std::{cell::RefCell, fmt, rc::Rc, string::ToString};
4
5#[derive(Debug)]
7pub enum Scope {
8 Attribute(String),
9 Const(String),
10 Documentation,
11 Fn(String),
12 Macro(String),
13 Static(String),
14 StructImpl(String),
15 Trait(String),
16 TraitImpl { trait_: String, type_: String },
17 Unexpected,
18}
19
20impl Default for Scope {
21 fn default() -> Self {
22 Scope::Unexpected
23 }
24}
25
26impl From<&syn::Item> for Scope {
27 fn from(node: &syn::Item) -> Self {
28 match node {
29 syn::Item::Const(item) => Scope::Const(item.ident.to_string()),
30 syn::Item::Fn(fn_) => Scope::Fn(fn_.sig.ident.to_string()),
31 syn::Item::Impl(impl_) => {
32 let type_ident = format_type_name(&impl_.self_ty);
33
34 if let Some((_, trait_path, _)) = &impl_.trait_ {
35 let trait_ident = path_ident(&trait_path);
36
37 Scope::TraitImpl {
38 trait_: trait_ident,
39 type_: type_ident,
40 }
41 } else {
42 Scope::StructImpl(type_ident)
43 }
44 }
45 syn::Item::Macro(macro_) => Scope::Macro(
46 macro_
47 .ident
48 .as_ref()
49 .map(|ident| ident.to_string())
50 .unwrap_or_else(|| "unnamed".to_string()),
51 ),
52 syn::Item::Macro2(macro2) => Scope::Macro(macro2.ident.to_string()),
53 syn::Item::Static(static_) => Scope::Static(static_.ident.to_string()),
54 syn::Item::Trait(trait_) => Scope::Trait(trait_.ident.to_string()),
55 _ => Scope::Unexpected,
56 }
57 }
58}
59
60impl From<&syn::Attribute> for Scope {
61 fn from(node: &syn::Attribute) -> Self {
62 Scope::Attribute(path_ident(&node.path))
63 }
64}
65
66impl From<&syn::Macro> for Scope {
67 fn from(node: &syn::Macro) -> Self {
68 Scope::Macro(path_ident(&node.path))
69 }
70}
71
72impl From<Scope> for Rc<RefCell<Scope>> {
73 fn from(scope: Scope) -> Self {
74 Rc::new(RefCell::new(scope))
75 }
76}
77
78impl fmt::Display for Scope {
79 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
80 use Scope::*;
81
82 match self {
83 Attribute(name) => write!(f, "attr {}", name),
84 Const(name) => write!(f, "const {}", name),
85 Documentation => f.write_str("doc code"),
86 Fn(name) => write!(f, "fn {}", name),
87 Macro(name) => write!(f, "macro! {}", name),
88 Static(name) => write!(f, "static {}", name),
89 StructImpl(struct_) => f.write_str(struct_),
90 Trait(trait_) => f.write_str(trait_),
91 TraitImpl { trait_, type_ } => write!(f, "impl {} for {}", trait_, type_),
92 Unexpected => f.write_str("**Unexpected scope**"),
93 }
94 }
95}
96
97fn path_ident(path: &syn::Path) -> String {
98 if path.segments.is_empty() {
99 return String::default();
100 }
101 path.segments.last().unwrap().ident.to_string()
102}
103
104fn format_type_name(self_ty: &syn::Type) -> String {
105 match self_ty {
106 syn::Type::Path(path) => path_ident(&path.path),
107 syn::Type::Reference(ref_) => {
108 let prefix = match &ref_.lifetime {
109 None => if ref_.mutability.is_some() {
110 "&mut "
111 } else {
112 "&"
113 }
114 .to_string(),
115 Some(lifetime) => {
116 if ref_.mutability.is_some() {
117 format!("&{} mut ", lifetime.to_string())
118 } else {
119 format!("&{} ", lifetime.to_string())
120 }
121 }
122 };
123
124 format!("{}{}", prefix, format_type_name(&ref_.elem))
125 }
126 syn::Type::Slice(slice) => format!("[{}]", format_type_name(&slice.elem)),
127 syn::Type::TraitObject(trait_obj) => {
128 let mut trait_bound = "dyn ".to_string();
129 for (idx, bound) in trait_obj.bounds.iter().enumerate() {
130 if idx > 0 {
131 trait_bound += " + ";
132 }
133
134 if let syn::TypeParamBound::Trait(trait_) = bound {
135 trait_bound += &path_ident(&trait_.path);
136 }
137 }
138 trait_bound
139 }
140 syn::Type::Tuple(tuple) => {
141 let mut tuple_str = "(".to_string();
142 for (idx, elem) in tuple.elems.iter().enumerate() {
143 if idx > 0 {
144 tuple_str += ", ";
145 }
146
147 tuple_str += &format_type_name(elem);
148 }
149 tuple_str + ")"
150 }
151 syn::Type::Paren(paren) => {
152 format!("({})", format_type_name(&paren.elem))
153 }
154 syn::Type::Ptr(ptr) => {
155 format!("*{}", format_type_name(&ptr.elem))
156 }
157 _ => unimplemented!("format type formatting for {:#?}", self_ty),
158 }
159}