rust_analyzer_modules/tree/
builder.rs1use ra_ap_hir::{self as hir};
6use ra_ap_ide::{self as ide, Edition};
7
8use crate::{item::Item, tree::Tree};
9
10type Node = Item;
11
12#[derive(Debug)]
13pub struct TreeBuilder<'a> {
14 db: &'a ide::RootDatabase,
15 krate: hir::Crate,
16}
17
18impl<'a> TreeBuilder<'a> {
19 pub fn new(db: &'a ide::RootDatabase, krate: hir::Crate) -> Self {
20 Self { db, krate }
21 }
22
23 pub fn build(mut self) -> anyhow::Result<Tree<Node>> {
24 let _span = tracing::trace_span!("target").entered();
25
26 let tree = self
27 .process_crate(self.krate)
28 .expect("Expected tree node for crate root module");
29
30 Ok(tree)
31 }
32
33 fn process_crate(&mut self, crate_hir: hir::Crate) -> Option<Tree<Node>> {
34 let _span = tracing::trace_span!(
35 "crate",
36 crate = crate_hir
37 .display_name(self.db)
38 .map(|name| name.to_string())
39 .unwrap_or_else(|| "<ANONYMOUS>".to_owned())
40 )
41 .entered();
42
43 let module = crate_hir.root_module();
44
45 self.process_module(module)
46 }
47
48 fn process_impl(&mut self, impl_hir: hir::Impl) -> Vec<Tree<Node>> {
49 let _span = tracing::trace_span!("impl").entered();
50
51 impl_hir
52 .items(self.db)
53 .into_iter()
54 .filter_map(|item| match item {
55 hir::AssocItem::Function(function_hir) => self.process_function(function_hir),
56 hir::AssocItem::Const(const_hir) => self.process_const(const_hir),
57 hir::AssocItem::TypeAlias(type_alias_hir) => {
58 self.process_type_alias(type_alias_hir)
59 }
60 })
61 .collect()
62 }
63
64 fn process_moduledef(&mut self, module_def_hir: hir::ModuleDef) -> Option<Tree<Node>> {
65 match module_def_hir {
66 hir::ModuleDef::Module(module_hir) => self.process_module(module_hir),
67 hir::ModuleDef::Function(function_hir) => self.process_function(function_hir),
68 hir::ModuleDef::Adt(adt_hir) => self.process_adt(adt_hir),
69 hir::ModuleDef::Variant(variant_hir) => self.process_variant(variant_hir),
70 hir::ModuleDef::Const(const_hir) => self.process_const(const_hir),
71 hir::ModuleDef::Static(static_hir) => self.process_static(static_hir),
72 hir::ModuleDef::Trait(trait_hir) => self.process_trait(trait_hir),
73 hir::ModuleDef::TraitAlias(trait_alias_hir) => {
74 self.process_trait_alias(trait_alias_hir)
75 }
76 hir::ModuleDef::TypeAlias(type_alias_hir) => self.process_type_alias(type_alias_hir),
77 hir::ModuleDef::BuiltinType(builtin_type_hir) => {
78 self.process_builtin_type(builtin_type_hir)
79 }
80 hir::ModuleDef::Macro(macro_hir) => self.process_macro(macro_hir),
81 }
82 }
83
84 fn process_module(&mut self, module_hir: hir::Module) -> Option<Tree<Node>> {
85 let _span = tracing::trace_span!(
86 "module",
87 module = module_hir
88 .name(self.db)
89 .map(|name| name.display(self.db, Edition::CURRENT).to_string())
90 .unwrap_or_else(|| "<ROOT>".to_owned())
91 )
92 .entered();
93
94 let item = Item::new(hir::ModuleDef::Module(module_hir));
95 let mut node = Tree::new(item, vec![]);
96
97 let subtrees = module_hir
98 .declarations(self.db)
99 .into_iter()
100 .filter_map(|module_def_hir| self.process_moduledef(module_def_hir));
101
102 for subtree in subtrees {
103 node.push_subtree(subtree);
104 }
105
106 Some(node)
107 }
108
109 fn process_function(&mut self, function_hir: hir::Function) -> Option<Tree<Node>> {
110 let _span = tracing::trace_span!(
111 "function",
112 function = function_hir
113 .name(self.db)
114 .display(self.db, Edition::CURRENT)
115 .to_string()
116 )
117 .entered();
118
119 self.simple_node(hir::ModuleDef::Function(function_hir))
120 }
121
122 fn process_adt(&mut self, adt_hir: hir::Adt) -> Option<Tree<Node>> {
123 let mut node = match adt_hir {
124 hir::Adt::Struct(struct_hir) => self.process_struct(struct_hir),
125 hir::Adt::Union(union_hir) => self.process_union(union_hir),
126 hir::Adt::Enum(enum_hir) => self.process_enum(enum_hir),
127 };
128
129 if let Some(node) = node.as_mut() {
130 for impl_hir in hir::Impl::all_for_type(self.db, adt_hir.ty(self.db)) {
131 for subtree in self.process_impl(impl_hir) {
132 node.push_subtree(subtree);
133 }
134 }
135 }
136
137 node
138 }
139
140 fn process_struct(&mut self, struct_hir: hir::Struct) -> Option<Tree<Node>> {
141 let _span = tracing::trace_span!(
142 "struct",
143 struct = struct_hir
144 .name(self.db)
145 .display(self.db, Edition::CURRENT)
146 .to_string()
147 )
148 .entered();
149
150 self.simple_node(hir::ModuleDef::Adt(hir::Adt::Struct(struct_hir)))
151 }
152
153 fn process_enum(&mut self, enum_hir: hir::Enum) -> Option<Tree<Node>> {
154 let _span = tracing::trace_span!(
155 "enum",
156 enum = enum_hir
157 .name(self.db)
158 .display(self.db, Edition::CURRENT)
159 .to_string()
160 )
161 .entered();
162
163 self.simple_node(hir::ModuleDef::Adt(hir::Adt::Enum(enum_hir)))
164 }
165
166 fn process_union(&mut self, union_hir: hir::Union) -> Option<Tree<Node>> {
167 let _span = tracing::trace_span!(
168 "union",
169 union = union_hir
170 .name(self.db)
171 .display(self.db, Edition::CURRENT)
172 .to_string()
173 )
174 .entered();
175
176 self.simple_node(hir::ModuleDef::Adt(hir::Adt::Union(union_hir)))
177 }
178
179 fn process_variant(&mut self, variant_hir: hir::Variant) -> Option<Tree<Node>> {
180 let _span = tracing::trace_span!(
181 "variant",
182 variant = variant_hir
183 .name(self.db)
184 .display(self.db, Edition::CURRENT)
185 .to_string()
186 )
187 .entered();
188
189 None
190 }
191
192 fn process_const(&mut self, const_hir: hir::Const) -> Option<Tree<Node>> {
193 let _span = tracing::trace_span!(
194 "const",
195 const = const_hir
196 .name(self.db)
197 .map(|name| name.display(self.db, Edition::CURRENT).to_string())
198 .unwrap_or_else(|| "_".to_owned())
199 )
200 .entered();
201
202 None
203 }
204
205 fn process_static(&mut self, static_hir: hir::Static) -> Option<Tree<Node>> {
206 let _span = tracing::trace_span!(
207 "static",
208 static = static_hir
209 .name(self.db)
210 .display(self.db, Edition::CURRENT)
211 .to_string()
212 )
213 .entered();
214
215 self.simple_node(hir::ModuleDef::Static(static_hir))
216 }
217
218 fn process_trait(&mut self, trait_hir: hir::Trait) -> Option<Tree<Node>> {
219 let _span = tracing::trace_span!("trait",
220 trait = trait_hir
221 .name(self.db)
222 .display(self.db, Edition::CURRENT)
223 .to_string())
224 .entered();
225
226 self.simple_node(hir::ModuleDef::Trait(trait_hir))
227 }
228
229 fn process_trait_alias(&mut self, trait_alias_hir: hir::TraitAlias) -> Option<Tree<Node>> {
230 let _span = tracing::trace_span!(
231 "trait alias",
232 trait_alias = trait_alias_hir
233 .name(self.db)
234 .display(self.db, Edition::CURRENT)
235 .to_string()
236 )
237 .entered();
238
239 self.simple_node(hir::ModuleDef::TraitAlias(trait_alias_hir))
240 }
241
242 fn process_type_alias(&mut self, type_alias_hir: hir::TypeAlias) -> Option<Tree<Node>> {
243 let _span = tracing::trace_span!(
244 "type alias",
245 type_alias = type_alias_hir
246 .name(self.db)
247 .display(self.db, Edition::CURRENT)
248 .to_string()
249 )
250 .entered();
251
252 self.simple_node(hir::ModuleDef::TypeAlias(type_alias_hir))
253 }
254
255 fn process_builtin_type(&mut self, builtin_type_hir: hir::BuiltinType) -> Option<Tree<Node>> {
256 let _span = tracing::trace_span!(
257 "builtin type",
258 builtin_type = builtin_type_hir
259 .name()
260 .display(self.db, Edition::CURRENT)
261 .to_string()
262 )
263 .entered();
264
265 self.simple_node(hir::ModuleDef::BuiltinType(builtin_type_hir))
266 }
267
268 fn process_macro(&mut self, macro_hir: hir::Macro) -> Option<Tree<Node>> {
269 let _span = tracing::trace_span!("macro",
270 macro = macro_hir
271 .name(self.db)
272 .display(self.db, Edition::CURRENT)
273 .to_string())
274 .entered();
275
276 let _ = macro_hir;
277
278 None
279 }
280
281 fn simple_node(&mut self, module_def_hir: hir::ModuleDef) -> Option<Tree<Node>> {
282 let item = Item::new(module_def_hir);
283 Some(Tree::new(item, vec![]))
284 }
285}