rust_analyzer_modules/tree/
builder.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use 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}