diff options
Diffstat (limited to 'crates/ra_hir/src/lang_item.rs')
-rw-r--r-- | crates/ra_hir/src/lang_item.rs | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs index cdc9182d6..ada8aeb5b 100644 --- a/crates/ra_hir/src/lang_item.rs +++ b/crates/ra_hir/src/lang_item.rs | |||
@@ -4,7 +4,7 @@ use rustc_hash::FxHashMap; | |||
4 | use ra_syntax::{SmolStr, ast::AttrsOwner}; | 4 | use ra_syntax::{SmolStr, ast::AttrsOwner}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | Crate, DefDatabase, Enum, Function, HirDatabase, ImplBlock, Module, Static, Struct, Trait, AstDatabase, | 7 | Crate, DefDatabase, Enum, Function, HirDatabase, ImplBlock, Module, Static, Struct, Trait, ModuleDef, AstDatabase, HasSource |
8 | }; | 8 | }; |
9 | 9 | ||
10 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 10 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -87,19 +87,48 @@ impl LangItems { | |||
87 | let source = module.definition_source(db).ast; | 87 | let source = module.definition_source(db).ast; |
88 | for (impl_id, _) in impl_blocks.impls.iter() { | 88 | for (impl_id, _) in impl_blocks.impls.iter() { |
89 | let impl_block = source_map.get(&source, impl_id); | 89 | let impl_block = source_map.get(&source, impl_id); |
90 | let lang_item_name = impl_block | 90 | if let Some(lang_item_name) = 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 { | ||
97 | let imp = ImplBlock::from_id(*module, impl_id); | 91 | let imp = ImplBlock::from_id(*module, impl_id); |
98 | self.items.entry(lang_item_name).or_insert_with(|| LangItemTarget::ImplBlock(imp)); | 92 | self.items.entry(lang_item_name).or_insert_with(|| LangItemTarget::ImplBlock(imp)); |
99 | } | 93 | } |
100 | } | 94 | } |
101 | 95 | ||
102 | // FIXME we should look for the other lang item targets (traits, structs, ...) | 96 | // FIXME make this nicer |
97 | for def in module.declarations(db) { | ||
98 | match def { | ||
99 | ModuleDef::Trait(trait_) => { | ||
100 | let node = trait_.source(db).ast; | ||
101 | if let Some(lang_item_name) = lang_item_name(&*node) { | ||
102 | self.items.entry(lang_item_name).or_insert(LangItemTarget::Trait(trait_)); | ||
103 | } | ||
104 | } | ||
105 | ModuleDef::Enum(e) => { | ||
106 | let node = e.source(db).ast; | ||
107 | if let Some(lang_item_name) = lang_item_name(&*node) { | ||
108 | self.items.entry(lang_item_name).or_insert(LangItemTarget::Enum(e)); | ||
109 | } | ||
110 | } | ||
111 | ModuleDef::Struct(s) => { | ||
112 | let node = s.source(db).ast; | ||
113 | if let Some(lang_item_name) = lang_item_name(&*node) { | ||
114 | self.items.entry(lang_item_name).or_insert(LangItemTarget::Struct(s)); | ||
115 | } | ||
116 | } | ||
117 | ModuleDef::Function(f) => { | ||
118 | let node = f.source(db).ast; | ||
119 | if let Some(lang_item_name) = lang_item_name(&*node) { | ||
120 | self.items.entry(lang_item_name).or_insert(LangItemTarget::Function(f)); | ||
121 | } | ||
122 | } | ||
123 | ModuleDef::Static(s) => { | ||
124 | let node = s.source(db).ast; | ||
125 | if let Some(lang_item_name) = lang_item_name(&*node) { | ||
126 | self.items.entry(lang_item_name).or_insert(LangItemTarget::Static(s)); | ||
127 | } | ||
128 | } | ||
129 | _ => {} | ||
130 | } | ||
131 | } | ||
103 | 132 | ||
104 | // Look for lang items in the children | 133 | // Look for lang items in the children |
105 | for child in module.children(db) { | 134 | for child in module.children(db) { |
@@ -107,3 +136,11 @@ impl LangItems { | |||
107 | } | 136 | } |
108 | } | 137 | } |
109 | } | 138 | } |
139 | |||
140 | fn lang_item_name<T: AttrsOwner>(node: &T) -> Option<SmolStr> { | ||
141 | node.attrs() | ||
142 | .filter_map(|a| a.as_key_value()) | ||
143 | .filter(|(key, _)| key == "lang") | ||
144 | .map(|(_, val)| val) | ||
145 | .nth(0) | ||
146 | } | ||