aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/lang_item.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/lang_item.rs')
-rw-r--r--crates/ra_hir/src/lang_item.rs55
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;
4use ra_syntax::{SmolStr, ast::AttrsOwner}; 4use ra_syntax::{SmolStr, ast::AttrsOwner};
5 5
6use crate::{ 6use 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
140fn 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}