diff options
Diffstat (limited to 'crates/ra_hir_def/src/item_tree/lower.rs')
-rw-r--r-- | crates/ra_hir_def/src/item_tree/lower.rs | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 3bb437e81..88530af74 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs | |||
@@ -12,7 +12,7 @@ use ra_syntax::{ | |||
12 | SyntaxNode, | 12 | SyntaxNode, |
13 | }; | 13 | }; |
14 | use smallvec::SmallVec; | 14 | use smallvec::SmallVec; |
15 | use std::{mem, sync::Arc}; | 15 | use std::{collections::hash_map::Entry, mem, sync::Arc}; |
16 | 16 | ||
17 | fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { | 17 | fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { |
18 | FileItemTreeId { index, _p: PhantomData } | 18 | FileItemTreeId { index, _p: PhantomData } |
@@ -116,13 +116,24 @@ impl Ctx { | |||
116 | 116 | ||
117 | if !attrs.is_empty() { | 117 | if !attrs.is_empty() { |
118 | for item in items.iter().flat_map(|items| &items.0) { | 118 | for item in items.iter().flat_map(|items| &items.0) { |
119 | self.tree.attrs.insert(*item, attrs.clone()); | 119 | self.add_attrs(*item, attrs.clone()); |
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | items | 123 | items |
124 | } | 124 | } |
125 | 125 | ||
126 | fn add_attrs(&mut self, item: ModItem, attrs: Attrs) { | ||
127 | match self.tree.attrs.entry(item) { | ||
128 | Entry::Occupied(mut entry) => { | ||
129 | *entry.get_mut() = entry.get().merge(attrs); | ||
130 | } | ||
131 | Entry::Vacant(entry) => { | ||
132 | entry.insert(attrs); | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
126 | fn collect_inner_items(&mut self, container: &SyntaxNode) { | 137 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
127 | let forced_vis = self.forced_visibility.take(); | 138 | let forced_vis = self.forced_visibility.take(); |
128 | let mut inner_items = mem::replace(&mut self.tree.inner_items, FxHashMap::default()); | 139 | let mut inner_items = mem::replace(&mut self.tree.inner_items, FxHashMap::default()); |
@@ -147,7 +158,6 @@ impl Ctx { | |||
147 | } | 158 | } |
148 | 159 | ||
149 | fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<FileItemTreeId<Struct>> { | 160 | fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<FileItemTreeId<Struct>> { |
150 | let attrs = self.lower_attrs(strukt); | ||
151 | let visibility = self.lower_visibility(strukt); | 161 | let visibility = self.lower_visibility(strukt); |
152 | let name = strukt.name()?.as_name(); | 162 | let name = strukt.name()?.as_name(); |
153 | let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt); | 163 | let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt); |
@@ -158,7 +168,7 @@ impl Ctx { | |||
158 | ast::StructKind::Tuple(_) => StructDefKind::Tuple, | 168 | ast::StructKind::Tuple(_) => StructDefKind::Tuple, |
159 | ast::StructKind::Unit => StructDefKind::Unit, | 169 | ast::StructKind::Unit => StructDefKind::Unit, |
160 | }; | 170 | }; |
161 | let res = Struct { name, attrs, visibility, generic_params, fields, ast_id, kind }; | 171 | let res = Struct { name, visibility, generic_params, fields, ast_id, kind }; |
162 | Some(id(self.tree.structs.alloc(res))) | 172 | Some(id(self.tree.structs.alloc(res))) |
163 | } | 173 | } |
164 | 174 | ||
@@ -215,7 +225,6 @@ impl Ctx { | |||
215 | } | 225 | } |
216 | 226 | ||
217 | fn lower_union(&mut self, union: &ast::UnionDef) -> Option<FileItemTreeId<Union>> { | 227 | fn lower_union(&mut self, union: &ast::UnionDef) -> Option<FileItemTreeId<Union>> { |
218 | let attrs = self.lower_attrs(union); | ||
219 | let visibility = self.lower_visibility(union); | 228 | let visibility = self.lower_visibility(union); |
220 | let name = union.name()?.as_name(); | 229 | let name = union.name()?.as_name(); |
221 | let generic_params = self.lower_generic_params(GenericsOwner::Union, union); | 230 | let generic_params = self.lower_generic_params(GenericsOwner::Union, union); |
@@ -226,12 +235,11 @@ impl Ctx { | |||
226 | None => Fields::Record(self.next_field_idx()..self.next_field_idx()), | 235 | None => Fields::Record(self.next_field_idx()..self.next_field_idx()), |
227 | }; | 236 | }; |
228 | let ast_id = self.source_ast_id_map.ast_id(union); | 237 | let ast_id = self.source_ast_id_map.ast_id(union); |
229 | let res = Union { name, attrs, visibility, generic_params, fields, ast_id }; | 238 | let res = Union { name, visibility, generic_params, fields, ast_id }; |
230 | Some(id(self.tree.unions.alloc(res))) | 239 | Some(id(self.tree.unions.alloc(res))) |
231 | } | 240 | } |
232 | 241 | ||
233 | fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<FileItemTreeId<Enum>> { | 242 | fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<FileItemTreeId<Enum>> { |
234 | let attrs = self.lower_attrs(enum_); | ||
235 | let visibility = self.lower_visibility(enum_); | 243 | let visibility = self.lower_visibility(enum_); |
236 | let name = enum_.name()?.as_name(); | 244 | let name = enum_.name()?.as_name(); |
237 | let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); | 245 | let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_); |
@@ -240,7 +248,7 @@ impl Ctx { | |||
240 | None => self.next_variant_idx()..self.next_variant_idx(), | 248 | None => self.next_variant_idx()..self.next_variant_idx(), |
241 | }; | 249 | }; |
242 | let ast_id = self.source_ast_id_map.ast_id(enum_); | 250 | let ast_id = self.source_ast_id_map.ast_id(enum_); |
243 | let res = Enum { name, attrs, visibility, generic_params, variants, ast_id }; | 251 | let res = Enum { name, visibility, generic_params, variants, ast_id }; |
244 | Some(id(self.tree.enums.alloc(res))) | 252 | Some(id(self.tree.enums.alloc(res))) |
245 | } | 253 | } |
246 | 254 | ||
@@ -263,7 +271,6 @@ impl Ctx { | |||
263 | } | 271 | } |
264 | 272 | ||
265 | fn lower_function(&mut self, func: &ast::FnDef) -> Option<FileItemTreeId<Function>> { | 273 | fn lower_function(&mut self, func: &ast::FnDef) -> Option<FileItemTreeId<Function>> { |
266 | let attrs = self.lower_attrs(func); | ||
267 | let visibility = self.lower_visibility(func); | 274 | let visibility = self.lower_visibility(func); |
268 | let name = func.name()?.as_name(); | 275 | let name = func.name()?.as_name(); |
269 | 276 | ||
@@ -309,7 +316,6 @@ impl Ctx { | |||
309 | let ast_id = self.source_ast_id_map.ast_id(func); | 316 | let ast_id = self.source_ast_id_map.ast_id(func); |
310 | let mut res = Function { | 317 | let mut res = Function { |
311 | name, | 318 | name, |
312 | attrs, | ||
313 | visibility, | 319 | visibility, |
314 | generic_params: GenericParams::default(), | 320 | generic_params: GenericParams::default(), |
315 | has_self_param, | 321 | has_self_param, |
@@ -390,9 +396,13 @@ impl Ctx { | |||
390 | let items = trait_def.item_list().map(|list| { | 396 | let items = trait_def.item_list().map(|list| { |
391 | self.with_inherited_visibility(visibility.clone(), |this| { | 397 | self.with_inherited_visibility(visibility.clone(), |this| { |
392 | list.items() | 398 | list.items() |
393 | .flat_map(|item| { | 399 | .filter_map(|item| { |
400 | let attrs = Attrs::new(&item, &this.hygiene); | ||
394 | this.collect_inner_items(item.syntax()); | 401 | this.collect_inner_items(item.syntax()); |
395 | this.lower_assoc_item(&item) | 402 | this.lower_assoc_item(&item).map(|item| { |
403 | this.add_attrs(item.into(), attrs); | ||
404 | item | ||
405 | }) | ||
396 | }) | 406 | }) |
397 | .collect() | 407 | .collect() |
398 | }) | 408 | }) |
@@ -422,6 +432,8 @@ impl Ctx { | |||
422 | .filter_map(|item| { | 432 | .filter_map(|item| { |
423 | self.collect_inner_items(item.syntax()); | 433 | self.collect_inner_items(item.syntax()); |
424 | let assoc = self.lower_assoc_item(&item)?; | 434 | let assoc = self.lower_assoc_item(&item)?; |
435 | let attrs = Attrs::new(&item, &self.hygiene); | ||
436 | self.add_attrs(assoc.into(), attrs); | ||
425 | Some(assoc) | 437 | Some(assoc) |
426 | }) | 438 | }) |
427 | .collect(); | 439 | .collect(); |
@@ -506,6 +518,7 @@ impl Ctx { | |||
506 | list.extern_items() | 518 | list.extern_items() |
507 | .filter_map(|item| { | 519 | .filter_map(|item| { |
508 | self.collect_inner_items(item.syntax()); | 520 | self.collect_inner_items(item.syntax()); |
521 | let attrs = Attrs::new(&item, &self.hygiene); | ||
509 | let id = match item { | 522 | let id = match item { |
510 | ast::ExternItem::FnDef(ast) => { | 523 | ast::ExternItem::FnDef(ast) => { |
511 | let func = self.lower_function(&ast)?; | 524 | let func = self.lower_function(&ast)?; |
@@ -516,6 +529,7 @@ impl Ctx { | |||
516 | statik.into() | 529 | statik.into() |
517 | } | 530 | } |
518 | }; | 531 | }; |
532 | self.add_attrs(id, attrs); | ||
519 | Some(id) | 533 | Some(id) |
520 | }) | 534 | }) |
521 | .collect() | 535 | .collect() |
@@ -576,9 +590,6 @@ impl Ctx { | |||
576 | } | 590 | } |
577 | } | 591 | } |
578 | 592 | ||
579 | fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | ||
580 | Attrs::new(item, &self.hygiene) | ||
581 | } | ||
582 | fn lower_visibility(&self, item: &impl ast::VisibilityOwner) -> RawVisibility { | 593 | fn lower_visibility(&self, item: &impl ast::VisibilityOwner) -> RawVisibility { |
583 | if let Some(vis) = self.forced_visibility.as_ref() { | 594 | if let Some(vis) = self.forced_visibility.as_ref() { |
584 | vis.clone() | 595 | vis.clone() |