|
1 | 1 | use std::sync::Arc;
|
2 | 2 | use rustc_hash::FxHashMap;
|
3 | 3 |
|
4 |
| -use ra_syntax::{SmolStr, ast::AttrsOwner}; |
| 4 | +use ra_syntax::{SmolStr, TreeArc, ast::AttrsOwner}; |
5 | 5 |
|
6 | 6 | use crate::{
|
7 |
| - Crate, DefDatabase, Enum, Function, HirDatabase, ImplBlock, Module, Static, Struct, Trait, AstDatabase, |
| 7 | + Crate, DefDatabase, Enum, Function, HirDatabase, ImplBlock, Module, |
| 8 | + Static, Struct, Trait, ModuleDef, AstDatabase, HasSource |
8 | 9 | };
|
9 | 10 |
|
10 | 11 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
@@ -87,23 +88,51 @@ impl LangItems {
|
87 | 88 | let source = module.definition_source(db).ast;
|
88 | 89 | for (impl_id, _) in impl_blocks.impls.iter() {
|
89 | 90 | let impl_block = source_map.get(&source, impl_id);
|
90 |
| - let lang_item_name = impl_block |
91 |
| - .attrs() |
92 |
| - .filter_map(|a| a.as_key_value()) |
93 |
| - .filter(|(key, _)| key == "lang") |
94 |
| - .map(|(_, val)| val) |
95 |
| - .nth(0); |
96 |
| - if let Some(lang_item_name) = lang_item_name { |
| 91 | + if let Some(lang_item_name) = lang_item_name(&*impl_block) { |
97 | 92 | let imp = ImplBlock::from_id(*module, impl_id);
|
98 | 93 | self.items.entry(lang_item_name).or_insert_with(|| LangItemTarget::ImplBlock(imp));
|
99 | 94 | }
|
100 | 95 | }
|
101 | 96 |
|
102 |
| - // FIXME we should look for the other lang item targets (traits, structs, ...) |
| 97 | + for def in module.declarations(db) { |
| 98 | + match def { |
| 99 | + ModuleDef::Trait(trait_) => { |
| 100 | + self.collect_lang_item(db, trait_, LangItemTarget::Trait) |
| 101 | + } |
| 102 | + ModuleDef::Enum(e) => self.collect_lang_item(db, e, LangItemTarget::Enum), |
| 103 | + ModuleDef::Struct(s) => self.collect_lang_item(db, s, LangItemTarget::Struct), |
| 104 | + ModuleDef::Function(f) => self.collect_lang_item(db, f, LangItemTarget::Function), |
| 105 | + ModuleDef::Static(s) => self.collect_lang_item(db, s, LangItemTarget::Static), |
| 106 | + _ => {} |
| 107 | + } |
| 108 | + } |
103 | 109 |
|
104 | 110 | // Look for lang items in the children
|
105 | 111 | for child in module.children(db) {
|
106 | 112 | self.collect_lang_items_recursive(db, &child);
|
107 | 113 | }
|
108 | 114 | }
|
| 115 | + |
| 116 | + fn collect_lang_item<T, N>( |
| 117 | + &mut self, |
| 118 | + db: &(impl DefDatabase + AstDatabase), |
| 119 | + item: T, |
| 120 | + constructor: fn(T) -> LangItemTarget, |
| 121 | + ) where |
| 122 | + T: Copy + HasSource<Ast = TreeArc<N>>, |
| 123 | + N: AttrsOwner, |
| 124 | + { |
| 125 | + let node = item.source(db).ast; |
| 126 | + if let Some(lang_item_name) = lang_item_name(&*node) { |
| 127 | + self.items.entry(lang_item_name).or_insert(constructor(item)); |
| 128 | + } |
| 129 | + } |
| 130 | +} |
| 131 | + |
| 132 | +fn lang_item_name<T: AttrsOwner>(node: &T) -> Option<SmolStr> { |
| 133 | + node.attrs() |
| 134 | + .filter_map(|a| a.as_key_value()) |
| 135 | + .filter(|(key, _)| key == "lang") |
| 136 | + .map(|(_, val)| val) |
| 137 | + .nth(0) |
109 | 138 | }
|
0 commit comments