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.rs154
1 files changed, 0 insertions, 154 deletions
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
deleted file mode 100644
index 55f0c3a13..000000000
--- a/crates/ra_hir/src/lang_item.rs
+++ /dev/null
@@ -1,154 +0,0 @@
1//! FIXME: write short doc here
2
3use std::sync::Arc;
4
5use hir_def::{AdtId, AttrDefId, ModuleDefId};
6use ra_syntax::SmolStr;
7use rustc_hash::FxHashMap;
8
9use crate::{
10 db::{AstDatabase, DefDatabase, HirDatabase},
11 Crate, Enum, Function, ImplBlock, Module, Static, Struct, Trait,
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum LangItemTarget {
16 Enum(Enum),
17 Function(Function),
18 ImplBlock(ImplBlock),
19 Static(Static),
20 Struct(Struct),
21 Trait(Trait),
22}
23
24impl LangItemTarget {
25 pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
26 Some(match self {
27 LangItemTarget::Enum(e) => e.module(db).krate(),
28 LangItemTarget::Function(f) => f.module(db).krate(),
29 LangItemTarget::ImplBlock(i) => i.krate(db),
30 LangItemTarget::Static(s) => s.module(db).krate(),
31 LangItemTarget::Struct(s) => s.module(db).krate(),
32 LangItemTarget::Trait(t) => t.module(db).krate(),
33 })
34 }
35}
36
37#[derive(Default, Debug, Clone, PartialEq, Eq)]
38pub struct LangItems {
39 items: FxHashMap<SmolStr, LangItemTarget>,
40}
41
42impl LangItems {
43 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> {
44 self.items.get(item)
45 }
46
47 /// Salsa query. This will look for lang items in a specific crate.
48 pub(crate) fn crate_lang_items_query(
49 db: &(impl DefDatabase + AstDatabase),
50 krate: Crate,
51 ) -> Arc<LangItems> {
52 let mut lang_items = LangItems::default();
53
54 if let Some(module) = krate.root_module(db) {
55 lang_items.collect_lang_items_recursive(db, module);
56 }
57
58 Arc::new(lang_items)
59 }
60
61 pub(crate) fn module_lang_items_query(
62 db: &(impl DefDatabase + AstDatabase),
63 module: Module,
64 ) -> Option<Arc<LangItems>> {
65 let mut lang_items = LangItems::default();
66 lang_items.collect_lang_items(db, module);
67 if lang_items.items.is_empty() {
68 None
69 } else {
70 Some(Arc::new(lang_items))
71 }
72 }
73
74 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
75 /// traversing its dependencies.
76 pub(crate) fn lang_item_query(
77 db: &impl DefDatabase,
78 start_crate: Crate,
79 item: SmolStr,
80 ) -> Option<LangItemTarget> {
81 let lang_items = db.crate_lang_items(start_crate);
82 let start_crate_target = lang_items.items.get(&item);
83 if let Some(target) = start_crate_target {
84 Some(*target)
85 } else {
86 for dep in start_crate.dependencies(db) {
87 let dep_crate = dep.krate;
88 let dep_target = db.lang_item(dep_crate, item.clone());
89 if dep_target.is_some() {
90 return dep_target;
91 }
92 }
93 None
94 }
95 }
96
97 fn collect_lang_items(&mut self, db: &(impl DefDatabase + AstDatabase), module: Module) {
98 // Look for impl targets
99 let def_map = db.crate_def_map(module.id.krate);
100 let module_data = &def_map[module.id.module_id];
101 for &impl_block in module_data.impls.iter() {
102 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlock)
103 }
104
105 for def in module_data.scope.declarations() {
106 match def {
107 ModuleDefId::TraitId(trait_) => {
108 self.collect_lang_item(db, trait_, LangItemTarget::Trait)
109 }
110 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
111 self.collect_lang_item(db, e, LangItemTarget::Enum)
112 }
113 ModuleDefId::AdtId(AdtId::StructId(s)) => {
114 self.collect_lang_item(db, s, LangItemTarget::Struct)
115 }
116 ModuleDefId::FunctionId(f) => {
117 self.collect_lang_item(db, f, LangItemTarget::Function)
118 }
119 ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::Static),
120 _ => {}
121 }
122 }
123 }
124
125 fn collect_lang_items_recursive(
126 &mut self,
127 db: &(impl DefDatabase + AstDatabase),
128 module: Module,
129 ) {
130 if let Some(module_lang_items) = db.module_lang_items(module) {
131 self.items.extend(module_lang_items.items.iter().map(|(k, v)| (k.clone(), *v)))
132 }
133
134 // Look for lang items in the children
135 for child in module.children(db) {
136 self.collect_lang_items_recursive(db, child);
137 }
138 }
139
140 fn collect_lang_item<T, D>(
141 &mut self,
142 db: &(impl DefDatabase + AstDatabase),
143 item: T,
144 constructor: fn(D) -> LangItemTarget,
145 ) where
146 T: Into<AttrDefId> + Copy,
147 D: From<T>,
148 {
149 let attrs = db.attrs(item.into());
150 if let Some(lang_item_name) = attrs.find_string_value("lang") {
151 self.items.entry(lang_item_name).or_insert_with(|| constructor(D::from(item)));
152 }
153 }
154}