aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assists/add_new.rs2
-rw-r--r--crates/ra_assists/src/assists/fill_match_arms.rs2
-rw-r--r--crates/ra_assists/src/test_db.rs1
-rw-r--r--crates/ra_db/src/fixture.rs19
-rw-r--r--crates/ra_db/src/input.rs138
-rw-r--r--crates/ra_db/src/lib.rs2
-rw-r--r--crates/ra_hir/src/code_model.rs305
-rw-r--r--crates/ra_hir/src/code_model/attrs.rs92
-rw-r--r--crates/ra_hir/src/code_model/docs.rs97
-rw-r--r--crates/ra_hir/src/code_model/src.rs112
-rw-r--r--crates/ra_hir/src/db.rs51
-rw-r--r--crates/ra_hir/src/debug.rs2
-rw-r--r--crates/ra_hir/src/from_id.rs46
-rw-r--r--crates/ra_hir/src/impl_block.rs8
-rw-r--r--crates/ra_hir/src/lang_item.rs160
-rw-r--r--crates/ra_hir/src/lib.rs14
-rw-r--r--crates/ra_hir/src/source_binder.rs40
-rw-r--r--crates/ra_hir/src/test_db.rs3
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs7
-rw-r--r--crates/ra_hir/src/ty/infer.rs21
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs7
-rw-r--r--crates/ra_hir/src/ty/lower.rs14
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs55
-rw-r--r--crates/ra_hir/src/ty/tests.rs38
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs5
-rw-r--r--crates/ra_hir/src/type_alias.rs31
-rw-r--r--crates/ra_hir_def/src/adt.rs161
-rw-r--r--crates/ra_hir_def/src/attr.rs112
-rw-r--r--crates/ra_hir_def/src/body.rs16
-rw-r--r--crates/ra_hir_def/src/body/lower.rs6
-rw-r--r--crates/ra_hir_def/src/body/scope.rs6
-rw-r--r--crates/ra_hir_def/src/data.rs217
-rw-r--r--crates/ra_hir_def/src/db.rs60
-rw-r--r--crates/ra_hir_def/src/docs.rs68
-rw-r--r--crates/ra_hir_def/src/generics.rs8
-rw-r--r--crates/ra_hir_def/src/impls.rs86
-rw-r--r--crates/ra_hir_def/src/lang_item.rs120
-rw-r--r--crates/ra_hir_def/src/lib.rs163
-rw-r--r--crates/ra_hir_def/src/nameres.rs83
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs79
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs17
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs54
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/tests/mod_resolution.rs2
-rw-r--r--crates/ra_hir_def/src/per_ns.rs (renamed from crates/ra_hir_def/src/nameres/per_ns.rs)0
-rw-r--r--crates/ra_hir_def/src/resolver.rs75
-rw-r--r--crates/ra_hir_def/src/test_db.rs2
-rw-r--r--crates/ra_hir_def/src/trace.rs49
-rw-r--r--crates/ra_hir_def/src/traits.rs66
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs232
-rw-r--r--crates/ra_hir_expand/src/db.rs7
-rw-r--r--crates/ra_hir_expand/src/lib.rs8
-rw-r--r--crates/ra_hir_expand/src/name.rs3
-rw-r--r--crates/ra_hir_expand/src/test_db.rs50
-rw-r--r--crates/ra_ide_api/src/call_info.rs4
-rw-r--r--crates/ra_ide_api/src/change.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs3
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs10
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs29
-rw-r--r--crates/ra_ide_api/src/db.rs1
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs4
-rw-r--r--crates/ra_ide_api/src/expand_macro.rs98
-rw-r--r--crates/ra_ide_api/src/lib.rs4
-rw-r--r--crates/ra_ide_api/src/mock_analysis.rs12
-rw-r--r--crates/ra_ide_api/src/parent_module.rs11
-rw-r--r--crates/ra_ide_api/src/typing.rs34
-rw-r--r--crates/ra_lsp_server/src/lib.rs24
-rw-r--r--crates/ra_lsp_server/src/main.rs3
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs68
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs4
-rw-r--r--crates/ra_project_model/src/lib.rs25
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs4
-rw-r--r--docs/user/README.md5
74 files changed, 2000 insertions, 1375 deletions
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs
index b5f8afb4e..ee8bff346 100644
--- a/crates/ra_assists/src/assists/add_new.rs
+++ b/crates/ra_assists/src/assists/add_new.rs
@@ -36,7 +36,7 @@ pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
36 36
37 // We want to only apply this to non-union structs with named fields 37 // We want to only apply this to non-union structs with named fields
38 let field_list = match (strukt.kind(), strukt.is_union()) { 38 let field_list = match (strukt.kind(), strukt.is_union()) {
39 (StructKind::Named(named), false) => named, 39 (StructKind::Record(named), false) => named,
40 _ => return None, 40 _ => return None,
41 }; 41 };
42 42
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index 9354466d9..8482897c5 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -101,7 +101,7 @@ fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> {
101 iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count()); 101 iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count());
102 make::tuple_struct_pat(path, pats).into() 102 make::tuple_struct_pat(path, pats).into()
103 } 103 }
104 ast::StructKind::Named(field_list) => { 104 ast::StructKind::Record(field_list) => {
105 let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into()); 105 let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into());
106 make::record_pat(path, pats).into() 106 make::record_pat(path, pats).into()
107 } 107 }
diff --git a/crates/ra_assists/src/test_db.rs b/crates/ra_assists/src/test_db.rs
index 5be7383ed..5f96c974b 100644
--- a/crates/ra_assists/src/test_db.rs
+++ b/crates/ra_assists/src/test_db.rs
@@ -10,7 +10,6 @@ use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath
10 hir::db::InternDatabaseStorage, 10 hir::db::InternDatabaseStorage,
11 hir::db::AstDatabaseStorage, 11 hir::db::AstDatabaseStorage,
12 hir::db::DefDatabaseStorage, 12 hir::db::DefDatabaseStorage,
13 hir::db::DefDatabase2Storage,
14 hir::db::HirDatabaseStorage 13 hir::db::HirDatabaseStorage
15)] 14)]
16#[derive(Debug, Default)] 15#[derive(Debug, Default)]
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs
index ade187629..e8f335e33 100644
--- a/crates/ra_db/src/fixture.rs
+++ b/crates/ra_db/src/fixture.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
8use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; 8use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
9 9
10use crate::{ 10use crate::{
11 CrateGraph, CrateId, Edition, FileId, FilePosition, RelativePathBuf, SourceDatabaseExt, 11 CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf, SourceDatabaseExt,
12 SourceRoot, SourceRootId, 12 SourceRoot, SourceRootId,
13}; 13};
14 14
@@ -53,7 +53,12 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, text: &str) -> FileId {
53 source_root.insert_file(rel_path.clone(), file_id); 53 source_root.insert_file(rel_path.clone(), file_id);
54 54
55 let mut crate_graph = CrateGraph::default(); 55 let mut crate_graph = CrateGraph::default();
56 crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default()); 56 crate_graph.add_crate_root(
57 file_id,
58 Edition::Edition2018,
59 CfgOptions::default(),
60 Env::default(),
61 );
57 62
58 db.set_file_text(file_id, Arc::new(text.to_string())); 63 db.set_file_text(file_id, Arc::new(text.to_string()));
59 db.set_file_relative_path(file_id, rel_path); 64 db.set_file_relative_path(file_id, rel_path);
@@ -93,7 +98,8 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
93 assert!(meta.path.starts_with(&source_root_prefix)); 98 assert!(meta.path.starts_with(&source_root_prefix));
94 99
95 if let Some(krate) = meta.krate { 100 if let Some(krate) = meta.krate {
96 let crate_id = crate_graph.add_crate_root(file_id, meta.edition, meta.cfg); 101 let crate_id =
102 crate_graph.add_crate_root(file_id, meta.edition, meta.cfg, Env::default());
97 let prev = crates.insert(krate.clone(), crate_id); 103 let prev = crates.insert(krate.clone(), crate_id);
98 assert!(prev.is_none()); 104 assert!(prev.is_none());
99 for dep in meta.deps { 105 for dep in meta.deps {
@@ -123,7 +129,12 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
123 129
124 if crates.is_empty() { 130 if crates.is_empty() {
125 let crate_root = default_crate_root.unwrap(); 131 let crate_root = default_crate_root.unwrap();
126 crate_graph.add_crate_root(crate_root, Edition::Edition2018, CfgOptions::default()); 132 crate_graph.add_crate_root(
133 crate_root,
134 Edition::Edition2018,
135 CfgOptions::default(),
136 Env::default(),
137 );
127 } else { 138 } else {
128 for (from, to) in crate_deps { 139 for (from, to) in crate_deps {
129 let from_id = crates[&from]; 140 let from_id = crates[&from];
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index c0d95a13f..b6d851776 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -6,14 +6,14 @@
6//! actual IO. See `vfs` and `project_model` in the `ra_lsp_server` crate for how 6//! actual IO. See `vfs` and `project_model` in the `ra_lsp_server` crate for how
7//! actual IO is done and lowered to input. 7//! actual IO is done and lowered to input.
8 8
9use rustc_hash::FxHashMap; 9use std::{fmt, str::FromStr};
10 10
11use ra_cfg::CfgOptions; 11use ra_cfg::CfgOptions;
12use ra_syntax::SmolStr; 12use ra_syntax::SmolStr;
13use rustc_hash::FxHashMap;
13use rustc_hash::FxHashSet; 14use rustc_hash::FxHashSet;
14 15
15use crate::{RelativePath, RelativePathBuf}; 16use crate::{RelativePath, RelativePathBuf};
16use std::str::FromStr;
17 17
18/// `FileId` is an integer which uniquely identifies a file. File paths are 18/// `FileId` is an integer which uniquely identifies a file. File paths are
19/// messy and system-dependent, so most of the code should work directly with 19/// messy and system-dependent, so most of the code should work directly with
@@ -80,56 +80,27 @@ pub struct CrateGraph {
80 arena: FxHashMap<CrateId, CrateData>, 80 arena: FxHashMap<CrateId, CrateData>,
81} 81}
82 82
83#[derive(Debug)]
84pub struct CyclicDependencies;
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 83#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
87pub struct CrateId(pub u32); 84pub struct CrateId(pub u32);
88 85
89impl CrateId {
90 pub fn shift(self, amount: u32) -> CrateId {
91 CrateId(self.0 + amount)
92 }
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
96pub enum Edition {
97 Edition2018,
98 Edition2015,
99}
100
101#[derive(Debug)]
102pub struct ParseEditionError {
103 pub msg: String,
104}
105
106impl FromStr for Edition {
107 type Err = ParseEditionError;
108 fn from_str(s: &str) -> Result<Self, Self::Err> {
109 match s {
110 "2015" => Ok(Edition::Edition2015),
111 "2018" => Ok(Edition::Edition2018),
112 _ => Err(ParseEditionError { msg: format!("unknown edition: {}", s) }),
113 }
114 }
115}
116
117#[derive(Debug, Clone, PartialEq, Eq)] 86#[derive(Debug, Clone, PartialEq, Eq)]
118struct CrateData { 87struct CrateData {
119 file_id: FileId, 88 file_id: FileId,
120 edition: Edition, 89 edition: Edition,
121 dependencies: Vec<Dependency>,
122 cfg_options: CfgOptions, 90 cfg_options: CfgOptions,
91 env: Env,
92 dependencies: Vec<Dependency>,
123} 93}
124 94
125impl CrateData { 95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
126 fn new(file_id: FileId, edition: Edition, cfg_options: CfgOptions) -> CrateData { 96pub enum Edition {
127 CrateData { file_id, edition, dependencies: Vec::new(), cfg_options } 97 Edition2018,
128 } 98 Edition2015,
99}
129 100
130 fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) { 101#[derive(Default, Debug, Clone, PartialEq, Eq)]
131 self.dependencies.push(Dependency { name, crate_id }) 102pub struct Env {
132 } 103 entries: FxHashMap<String, String>,
133} 104}
134 105
135#[derive(Debug, Clone, PartialEq, Eq)] 106#[derive(Debug, Clone, PartialEq, Eq)]
@@ -138,21 +109,17 @@ pub struct Dependency {
138 pub name: SmolStr, 109 pub name: SmolStr,
139} 110}
140 111
141impl Dependency {
142 pub fn crate_id(&self) -> CrateId {
143 self.crate_id
144 }
145}
146
147impl CrateGraph { 112impl CrateGraph {
148 pub fn add_crate_root( 113 pub fn add_crate_root(
149 &mut self, 114 &mut self,
150 file_id: FileId, 115 file_id: FileId,
151 edition: Edition, 116 edition: Edition,
152 cfg_options: CfgOptions, 117 cfg_options: CfgOptions,
118 env: Env,
153 ) -> CrateId { 119 ) -> CrateId {
120 let data = CrateData::new(file_id, edition, cfg_options, env);
154 let crate_id = CrateId(self.arena.len() as u32); 121 let crate_id = CrateId(self.arena.len() as u32);
155 let prev = self.arena.insert(crate_id, CrateData::new(file_id, edition, cfg_options)); 122 let prev = self.arena.insert(crate_id, data);
156 assert!(prev.is_none()); 123 assert!(prev.is_none());
157 crate_id 124 crate_id
158 } 125 }
@@ -166,9 +133,9 @@ impl CrateGraph {
166 from: CrateId, 133 from: CrateId,
167 name: SmolStr, 134 name: SmolStr,
168 to: CrateId, 135 to: CrateId,
169 ) -> Result<(), CyclicDependencies> { 136 ) -> Result<(), CyclicDependenciesError> {
170 if self.dfs_find(from, to, &mut FxHashSet::default()) { 137 if self.dfs_find(from, to, &mut FxHashSet::default()) {
171 return Err(CyclicDependencies); 138 return Err(CyclicDependenciesError);
172 } 139 }
173 self.arena.get_mut(&from).unwrap().add_dep(name, to); 140 self.arena.get_mut(&from).unwrap().add_dep(name, to);
174 Ok(()) 141 Ok(())
@@ -239,16 +206,70 @@ impl CrateGraph {
239 } 206 }
240} 207}
241 208
209impl CrateId {
210 pub fn shift(self, amount: u32) -> CrateId {
211 CrateId(self.0 + amount)
212 }
213}
214
215impl CrateData {
216 fn new(file_id: FileId, edition: Edition, cfg_options: CfgOptions, env: Env) -> CrateData {
217 CrateData { file_id, edition, dependencies: Vec::new(), cfg_options, env }
218 }
219
220 fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) {
221 self.dependencies.push(Dependency { name, crate_id })
222 }
223}
224
225impl FromStr for Edition {
226 type Err = ParseEditionError;
227
228 fn from_str(s: &str) -> Result<Self, Self::Err> {
229 let res = match s {
230 "2015" => Edition::Edition2015,
231 "2018" => Edition::Edition2018,
232 _ => Err(ParseEditionError { invalid_input: s.to_string() })?,
233 };
234 Ok(res)
235 }
236}
237
238impl Dependency {
239 pub fn crate_id(&self) -> CrateId {
240 self.crate_id
241 }
242}
243
244#[derive(Debug)]
245pub struct ParseEditionError {
246 invalid_input: String,
247}
248
249impl fmt::Display for ParseEditionError {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 write!(f, "invalid edition: {:?}", self.invalid_input)
252 }
253}
254
255impl std::error::Error for ParseEditionError {}
256
257#[derive(Debug)]
258pub struct CyclicDependenciesError;
259
242#[cfg(test)] 260#[cfg(test)]
243mod tests { 261mod tests {
244 use super::{CfgOptions, CrateGraph, Edition::Edition2018, FileId, SmolStr}; 262 use super::{CfgOptions, CrateGraph, Edition::Edition2018, Env, FileId, SmolStr};
245 263
246 #[test] 264 #[test]
247 fn it_should_panic_because_of_cycle_dependencies() { 265 fn it_should_panic_because_of_cycle_dependencies() {
248 let mut graph = CrateGraph::default(); 266 let mut graph = CrateGraph::default();
249 let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default()); 267 let crate1 =
250 let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default()); 268 graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default(), Env::default());
251 let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default()); 269 let crate2 =
270 graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default(), Env::default());
271 let crate3 =
272 graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default(), Env::default());
252 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok()); 273 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
253 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok()); 274 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
254 assert!(graph.add_dep(crate3, SmolStr::new("crate1"), crate1).is_err()); 275 assert!(graph.add_dep(crate3, SmolStr::new("crate1"), crate1).is_err());
@@ -257,9 +278,12 @@ mod tests {
257 #[test] 278 #[test]
258 fn it_works() { 279 fn it_works() {
259 let mut graph = CrateGraph::default(); 280 let mut graph = CrateGraph::default();
260 let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default()); 281 let crate1 =
261 let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default()); 282 graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default(), Env::default());
262 let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default()); 283 let crate2 =
284 graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default(), Env::default());
285 let crate3 =
286 graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default(), Env::default());
263 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok()); 287 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
264 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok()); 288 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
265 } 289 }
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index b6bfd531d..f9d012cb0 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -10,7 +10,7 @@ use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit};
10 10
11pub use crate::{ 11pub use crate::{
12 cancellation::Canceled, 12 cancellation::Canceled,
13 input::{CrateGraph, CrateId, Dependency, Edition, FileId, SourceRoot, SourceRootId}, 13 input::{CrateGraph, CrateId, Dependency, Edition, Env, FileId, SourceRoot, SourceRootId},
14}; 14};
15pub use relative_path::{RelativePath, RelativePathBuf}; 15pub use relative_path::{RelativePath, RelativePathBuf};
16pub use salsa; 16pub use salsa;
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 5690040a7..fd7776fb7 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,8 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3pub(crate) mod src; 3pub(crate) mod src;
4pub(crate) mod docs;
5pub(crate) mod attrs;
6 4
7use std::sync::Arc; 5use std::sync::Arc;
8 6
@@ -10,29 +8,30 @@ use hir_def::{
10 adt::VariantData, 8 adt::VariantData,
11 body::scope::ExprScopes, 9 body::scope::ExprScopes,
12 builtin_type::BuiltinType, 10 builtin_type::BuiltinType,
13 nameres::per_ns::PerNs, 11 docs::Documentation,
12 per_ns::PerNs,
14 resolver::{HasResolver, TypeNs}, 13 resolver::{HasResolver, TypeNs},
15 traits::TraitData, 14 type_ref::TypeRef,
16 type_ref::{Mutability, TypeRef}, 15 ContainerId, HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId,
17 ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, 16 LocalStructFieldId, Lookup, ModuleId, UnionId,
18 ModuleId, UnionId,
19}; 17};
20use hir_expand::{ 18use hir_expand::{
21 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
22 name::{self, AsName}, 20 name::{self, AsName},
21 AstId,
23}; 22};
24use ra_db::{CrateId, Edition}; 23use ra_db::{CrateId, Edition, FileId, FilePosition};
25use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 24use ra_syntax::{ast, AstNode, SyntaxNode};
26 25
27use crate::{ 26use crate::{
28 db::{AstDatabase, DefDatabase, HirDatabase}, 27 db::{DefDatabase, HirDatabase},
29 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
30 ids::{ 29 ids::{
31 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, 30 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId,
32 TypeAliasId, 31 TypeAliasId,
33 }, 32 },
34 ty::{InferenceResult, Namespace, TraitRef}, 33 ty::{InferenceResult, Namespace, TraitRef},
35 Either, HasSource, ImportId, Name, Source, Ty, 34 Either, HasSource, Name, Source, Ty,
36}; 35};
37 36
38/// hir::Crate describes a single crate. It's the main interface with which 37/// hir::Crate describes a single crate. It's the main interface with which
@@ -80,6 +79,64 @@ impl Crate {
80 } 79 }
81} 80}
82 81
82pub enum ModuleSource {
83 SourceFile(ast::SourceFile),
84 Module(ast::Module),
85}
86
87impl ModuleSource {
88 pub fn new(
89 db: &impl DefDatabase,
90 file_id: Option<FileId>,
91 decl_id: Option<AstId<ast::Module>>,
92 ) -> ModuleSource {
93 match (file_id, decl_id) {
94 (Some(file_id), _) => {
95 let source_file = db.parse(file_id).tree();
96 ModuleSource::SourceFile(source_file)
97 }
98 (None, Some(item_id)) => {
99 let module = item_id.to_node(db);
100 assert!(module.item_list().is_some(), "expected inline module");
101 ModuleSource::Module(module)
102 }
103 (None, None) => panic!(),
104 }
105 }
106
107 // FIXME: this methods do not belong here
108 pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource {
109 let parse = db.parse(position.file_id);
110 match &ra_syntax::algo::find_node_at_offset::<ast::Module>(
111 parse.tree().syntax(),
112 position.offset,
113 ) {
114 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
115 _ => {
116 let source_file = parse.tree();
117 ModuleSource::SourceFile(source_file)
118 }
119 }
120 }
121
122 pub fn from_child_node(db: &impl DefDatabase, child: Source<&SyntaxNode>) -> ModuleSource {
123 if let Some(m) =
124 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
125 {
126 ModuleSource::Module(m)
127 } else {
128 let file_id = child.file_id.original_file(db);
129 let source_file = db.parse(file_id).tree();
130 ModuleSource::SourceFile(source_file)
131 }
132 }
133
134 pub fn from_file_id(db: &impl DefDatabase, file_id: FileId) -> ModuleSource {
135 let source_file = db.parse(file_id).tree();
136 ModuleSource::SourceFile(source_file)
137 }
138}
139
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
84pub struct Module { 141pub struct Module {
85 pub(crate) id: ModuleId, 142 pub(crate) id: ModuleId,
@@ -111,10 +168,10 @@ impl_froms!(
111 BuiltinType 168 BuiltinType
112); 169);
113 170
114pub use hir_def::ModuleSource; 171pub use hir_def::attr::Attrs;
115 172
116impl Module { 173impl Module {
117 pub(crate) fn new(krate: Crate, crate_module_id: CrateModuleId) -> Module { 174 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
118 Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } } 175 Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } }
119 } 176 }
120 177
@@ -131,17 +188,6 @@ impl Module {
131 }) 188 })
132 } 189 }
133 190
134 /// Returns the syntax of the last path segment corresponding to this import
135 pub fn import_source(
136 self,
137 db: &impl HirDatabase,
138 import: ImportId,
139 ) -> Either<ast::UseTree, ast::ExternCrateItem> {
140 let src = self.definition_source(db);
141 let (_, source_map) = db.raw_items_with_source_map(src.file_id);
142 source_map.get(&src.value, import)
143 }
144
145 /// Returns the crate this module is part of. 191 /// Returns the crate this module is part of.
146 pub fn krate(self) -> Crate { 192 pub fn krate(self) -> Crate {
147 Crate { crate_id: self.id.krate } 193 Crate { crate_id: self.id.krate }
@@ -191,11 +237,13 @@ impl Module {
191 } 237 }
192 238
193 /// Returns a `ModuleScope`: a set of items, visible in this module. 239 /// Returns a `ModuleScope`: a set of items, visible in this module.
194 pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<ImportId>)> { 240 pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<Import>)> {
195 db.crate_def_map(self.id.krate)[self.id.module_id] 241 db.crate_def_map(self.id.krate)[self.id.module_id]
196 .scope 242 .scope
197 .entries() 243 .entries()
198 .map(|(name, res)| (name.clone(), res.def.into(), res.import)) 244 .map(|(name, res)| {
245 (name.clone(), res.def.into(), res.import.map(|id| Import { parent: self, id }))
246 })
199 .collect() 247 .collect()
200 } 248 }
201 249
@@ -233,11 +281,16 @@ impl Module {
233 def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() 281 def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect()
234 } 282 }
235 283
236 fn with_module_id(self, module_id: CrateModuleId) -> Module { 284 fn with_module_id(self, module_id: LocalModuleId) -> Module {
237 Module::new(self.krate(), module_id) 285 Module::new(self.krate(), module_id)
238 } 286 }
239} 287}
240 288
289pub struct Import {
290 pub(crate) parent: Module,
291 pub(crate) id: LocalImportId,
292}
293
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242pub struct StructField { 295pub struct StructField {
243 pub(crate) parent: VariantDef, 296 pub(crate) parent: VariantDef,
@@ -561,77 +614,6 @@ pub struct Function {
561 pub(crate) id: FunctionId, 614 pub(crate) id: FunctionId,
562} 615}
563 616
564#[derive(Debug, Clone, PartialEq, Eq)]
565pub struct FnData {
566 pub(crate) name: Name,
567 pub(crate) params: Vec<TypeRef>,
568 pub(crate) ret_type: TypeRef,
569 /// True if the first param is `self`. This is relevant to decide whether this
570 /// can be called as a method.
571 pub(crate) has_self_param: bool,
572}
573
574impl FnData {
575 pub(crate) fn fn_data_query(
576 db: &(impl DefDatabase + AstDatabase),
577 func: Function,
578 ) -> Arc<FnData> {
579 let src = func.source(db);
580 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
581 let mut params = Vec::new();
582 let mut has_self_param = false;
583 if let Some(param_list) = src.value.param_list() {
584 if let Some(self_param) = param_list.self_param() {
585 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
586 TypeRef::from_ast(type_ref)
587 } else {
588 let self_type = TypeRef::Path(name::SELF_TYPE.into());
589 match self_param.kind() {
590 ast::SelfParamKind::Owned => self_type,
591 ast::SelfParamKind::Ref => {
592 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
593 }
594 ast::SelfParamKind::MutRef => {
595 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
596 }
597 }
598 };
599 params.push(self_type);
600 has_self_param = true;
601 }
602 for param in param_list.params() {
603 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
604 params.push(type_ref);
605 }
606 }
607 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
608 TypeRef::from_ast(type_ref)
609 } else {
610 TypeRef::unit()
611 };
612
613 let sig = FnData { name, params, ret_type, has_self_param };
614 Arc::new(sig)
615 }
616 pub fn name(&self) -> &Name {
617 &self.name
618 }
619
620 pub fn params(&self) -> &[TypeRef] {
621 &self.params
622 }
623
624 pub fn ret_type(&self) -> &TypeRef {
625 &self.ret_type
626 }
627
628 /// True if the first arg is `self`. This is relevant to decide whether this
629 /// can be called as a method.
630 pub fn has_self_param(&self) -> bool {
631 self.has_self_param
632 }
633}
634
635impl Function { 617impl Function {
636 pub fn module(self, db: &impl DefDatabase) -> Module { 618 pub fn module(self, db: &impl DefDatabase) -> Module {
637 self.id.lookup(db).module(db).into() 619 self.id.lookup(db).module(db).into()
@@ -642,7 +624,15 @@ impl Function {
642 } 624 }
643 625
644 pub fn name(self, db: &impl HirDatabase) -> Name { 626 pub fn name(self, db: &impl HirDatabase) -> Name {
645 self.data(db).name.clone() 627 db.function_data(self.id).name.clone()
628 }
629
630 pub fn has_self_param(self, db: &impl HirDatabase) -> bool {
631 db.function_data(self.id).has_self_param
632 }
633
634 pub fn params(self, db: &impl HirDatabase) -> Vec<TypeRef> {
635 db.function_data(self.id).params.clone()
646 } 636 }
647 637
648 pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> { 638 pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
@@ -657,10 +647,6 @@ impl Function {
657 db.type_for_def(self.into(), Namespace::Values) 647 db.type_for_def(self.into(), Namespace::Values)
658 } 648 }
659 649
660 pub fn data(self, db: &impl HirDatabase) -> Arc<FnData> {
661 db.fn_data(self)
662 }
663
664 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 650 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
665 db.infer(self.into()) 651 db.infer(self.into())
666 } 652 }
@@ -711,12 +697,8 @@ impl Const {
711 Some(self.module(db).krate()) 697 Some(self.module(db).krate())
712 } 698 }
713 699
714 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
715 db.const_data(self)
716 }
717
718 pub fn name(self, db: &impl HirDatabase) -> Option<Name> { 700 pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
719 self.data(db).name().cloned() 701 db.const_data(self.id).name.clone()
720 } 702 }
721 703
722 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 704 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
@@ -748,45 +730,6 @@ impl Const {
748 } 730 }
749} 731}
750 732
751#[derive(Debug, Clone, PartialEq, Eq)]
752pub struct ConstData {
753 pub(crate) name: Option<Name>,
754 pub(crate) type_ref: TypeRef,
755}
756
757impl ConstData {
758 pub fn name(&self) -> Option<&Name> {
759 self.name.as_ref()
760 }
761
762 pub fn type_ref(&self) -> &TypeRef {
763 &self.type_ref
764 }
765
766 pub(crate) fn const_data_query(
767 db: &(impl DefDatabase + AstDatabase),
768 konst: Const,
769 ) -> Arc<ConstData> {
770 let node = konst.source(db).value;
771 const_data_for(&node)
772 }
773
774 pub(crate) fn static_data_query(
775 db: &(impl DefDatabase + AstDatabase),
776 konst: Static,
777 ) -> Arc<ConstData> {
778 let node = konst.source(db).value;
779 const_data_for(&node)
780 }
781}
782
783fn const_data_for<N: NameOwner + TypeAscriptionOwner>(node: &N) -> Arc<ConstData> {
784 let name = node.name().map(|n| n.as_name());
785 let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
786 let sig = ConstData { name, type_ref };
787 Arc::new(sig)
788}
789
790#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 733#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
791pub struct Static { 734pub struct Static {
792 pub(crate) id: StaticId, 735 pub(crate) id: StaticId,
@@ -801,10 +744,6 @@ impl Static {
801 Some(self.module(db).krate()) 744 Some(self.module(db).krate())
802 } 745 }
803 746
804 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
805 db.static_data(self)
806 }
807
808 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 747 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
809 db.infer(self.into()) 748 db.infer(self.into())
810 } 749 }
@@ -821,11 +760,11 @@ impl Trait {
821 } 760 }
822 761
823 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 762 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
824 self.trait_data(db).name.clone() 763 db.trait_data(self.id).name.clone()
825 } 764 }
826 765
827 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { 766 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> {
828 self.trait_data(db).items.iter().map(|it| (*it).into()).collect() 767 db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect()
829 } 768 }
830 769
831 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> { 770 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
@@ -871,7 +810,7 @@ impl Trait {
871 } 810 }
872 811
873 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { 812 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
874 let trait_data = self.trait_data(db); 813 let trait_data = db.trait_data(self.id);
875 let res = 814 let res =
876 trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?; 815 trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?;
877 Some(res) 816 Some(res)
@@ -885,16 +824,12 @@ impl Trait {
885 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name)) 824 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
886 } 825 }
887 826
888 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
889 db.trait_data(self.id)
890 }
891
892 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { 827 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
893 TraitRef::for_trait(db, self) 828 TraitRef::for_trait(db, self)
894 } 829 }
895 830
896 pub fn is_auto(self, db: &impl DefDatabase) -> bool { 831 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
897 self.trait_data(db).auto 832 db.trait_data(self.id).auto
898 } 833 }
899} 834}
900 835
@@ -937,7 +872,7 @@ impl TypeAlias {
937 } 872 }
938 873
939 pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> { 874 pub fn type_ref(self, db: &impl DefDatabase) -> Option<TypeRef> {
940 db.type_alias_data(self).type_ref.clone() 875 db.type_alias_data(self.id).type_ref.clone()
941 } 876 }
942 877
943 pub fn ty(self, db: &impl HirDatabase) -> Ty { 878 pub fn ty(self, db: &impl HirDatabase) -> Ty {
@@ -945,7 +880,7 @@ impl TypeAlias {
945 } 880 }
946 881
947 pub fn name(self, db: &impl DefDatabase) -> Name { 882 pub fn name(self, db: &impl DefDatabase) -> Name {
948 db.type_alias_data(self).name.clone() 883 db.type_alias_data(self.id).name.clone()
949 } 884 }
950} 885}
951 886
@@ -1110,3 +1045,51 @@ impl From<PerNs> for ScopeDef {
1110 .unwrap_or(ScopeDef::Unknown) 1045 .unwrap_or(ScopeDef::Unknown)
1111 } 1046 }
1112} 1047}
1048
1049#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1050pub enum AttrDef {
1051 Module(Module),
1052 StructField(StructField),
1053 Adt(Adt),
1054 Function(Function),
1055 EnumVariant(EnumVariant),
1056 Static(Static),
1057 Const(Const),
1058 Trait(Trait),
1059 TypeAlias(TypeAlias),
1060 MacroDef(MacroDef),
1061}
1062
1063impl_froms!(
1064 AttrDef: Module,
1065 StructField,
1066 Adt(Struct, Enum, Union),
1067 EnumVariant,
1068 Static,
1069 Const,
1070 Function,
1071 Trait,
1072 TypeAlias,
1073 MacroDef
1074);
1075
1076pub trait HasAttrs {
1077 fn attrs(self, db: &impl DefDatabase) -> Attrs;
1078}
1079
1080impl<T: Into<AttrDef>> HasAttrs for T {
1081 fn attrs(self, db: &impl DefDatabase) -> Attrs {
1082 let def: AttrDef = self.into();
1083 db.attrs(def.into())
1084 }
1085}
1086
1087pub trait Docs {
1088 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
1089}
1090impl<T: Into<AttrDef> + Copy> Docs for T {
1091 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
1092 let def: AttrDef = (*self).into();
1093 db.documentation(def.into())
1094 }
1095}
diff --git a/crates/ra_hir/src/code_model/attrs.rs b/crates/ra_hir/src/code_model/attrs.rs
deleted file mode 100644
index 9e304217c..000000000
--- a/crates/ra_hir/src/code_model/attrs.rs
+++ /dev/null
@@ -1,92 +0,0 @@
1//! FIXME: write short doc here
2
3use crate::{
4 db::{AstDatabase, DefDatabase, HirDatabase},
5 Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static,
6 Struct, StructField, Trait, TypeAlias, Union,
7};
8use hir_def::attr::Attr;
9use hir_expand::hygiene::Hygiene;
10use ra_syntax::ast;
11use std::sync::Arc;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum AttrDef {
15 Module(Module),
16 StructField(StructField),
17 Adt(Adt),
18 Function(Function),
19 EnumVariant(EnumVariant),
20 Static(Static),
21 Const(Const),
22 Trait(Trait),
23 TypeAlias(TypeAlias),
24 MacroDef(MacroDef),
25}
26
27impl_froms!(
28 AttrDef: Module,
29 StructField,
30 Adt(Struct, Enum, Union),
31 EnumVariant,
32 Static,
33 Const,
34 Function,
35 Trait,
36 TypeAlias,
37 MacroDef
38);
39
40pub trait Attrs {
41 fn attrs(&self, db: &impl HirDatabase) -> Option<Arc<[Attr]>>;
42}
43
44pub(crate) fn attributes_query(
45 db: &(impl DefDatabase + AstDatabase),
46 def: AttrDef,
47) -> Option<Arc<[Attr]>> {
48 match def {
49 AttrDef::Module(it) => {
50 let src = it.declaration_source(db)?;
51 let hygiene = Hygiene::new(db, src.file_id);
52 Attr::from_attrs_owner(&src.value, &hygiene)
53 }
54 AttrDef::StructField(it) => match it.source(db).value {
55 FieldSource::Named(named) => {
56 let src = it.source(db);
57 let hygiene = Hygiene::new(db, src.file_id);
58 Attr::from_attrs_owner(&named, &hygiene)
59 }
60 FieldSource::Pos(..) => None,
61 },
62 AttrDef::Adt(it) => match it {
63 Adt::Struct(it) => attrs_from_ast(it, db),
64 Adt::Enum(it) => attrs_from_ast(it, db),
65 Adt::Union(it) => attrs_from_ast(it, db),
66 },
67 AttrDef::EnumVariant(it) => attrs_from_ast(it, db),
68 AttrDef::Static(it) => attrs_from_ast(it, db),
69 AttrDef::Const(it) => attrs_from_ast(it, db),
70 AttrDef::Function(it) => attrs_from_ast(it, db),
71 AttrDef::Trait(it) => attrs_from_ast(it, db),
72 AttrDef::TypeAlias(it) => attrs_from_ast(it, db),
73 AttrDef::MacroDef(it) => attrs_from_ast(it, db),
74 }
75}
76
77fn attrs_from_ast<T, D>(node: T, db: &D) -> Option<Arc<[Attr]>>
78where
79 T: HasSource,
80 T::Ast: ast::AttrsOwner,
81 D: DefDatabase + AstDatabase,
82{
83 let src = node.source(db);
84 let hygiene = Hygiene::new(db, src.file_id);
85 Attr::from_attrs_owner(&src.value, &hygiene)
86}
87
88impl<T: Into<AttrDef> + Copy> Attrs for T {
89 fn attrs(&self, db: &impl HirDatabase) -> Option<Arc<[Attr]>> {
90 db.attrs((*self).into())
91 }
92}
diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/code_model/docs.rs
deleted file mode 100644
index e40efef34..000000000
--- a/crates/ra_hir/src/code_model/docs.rs
+++ /dev/null
@@ -1,97 +0,0 @@
1//! FIXME: write short doc here
2
3use std::sync::Arc;
4
5use ra_syntax::ast;
6
7use crate::{
8 db::{AstDatabase, DefDatabase, HirDatabase},
9 Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static,
10 Struct, StructField, Trait, TypeAlias, Union,
11};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum DocDef {
15 Module(Module),
16 StructField(StructField),
17 Adt(Adt),
18 EnumVariant(EnumVariant),
19 Static(Static),
20 Const(Const),
21 Function(Function),
22 Trait(Trait),
23 TypeAlias(TypeAlias),
24 MacroDef(MacroDef),
25}
26
27impl_froms!(
28 DocDef: Module,
29 StructField,
30 Adt(Struct, Enum, Union),
31 EnumVariant,
32 Static,
33 Const,
34 Function,
35 Trait,
36 TypeAlias,
37 MacroDef
38);
39
40/// Holds documentation
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct Documentation(Arc<str>);
43
44impl Documentation {
45 fn new(s: &str) -> Documentation {
46 Documentation(s.into())
47 }
48
49 pub fn as_str(&self) -> &str {
50 &*self.0
51 }
52}
53
54impl Into<String> for Documentation {
55 fn into(self) -> String {
56 self.as_str().to_owned()
57 }
58}
59
60pub trait Docs {
61 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
62}
63
64pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
65 node.doc_comment_text().map(|it| Documentation::new(&it))
66}
67
68pub(crate) fn documentation_query(
69 db: &(impl DefDatabase + AstDatabase),
70 def: DocDef,
71) -> Option<Documentation> {
72 match def {
73 DocDef::Module(it) => docs_from_ast(&it.declaration_source(db)?.value),
74 DocDef::StructField(it) => match it.source(db).value {
75 FieldSource::Named(named) => docs_from_ast(&named),
76 FieldSource::Pos(..) => None,
77 },
78 DocDef::Adt(it) => match it {
79 Adt::Struct(it) => docs_from_ast(&it.source(db).value),
80 Adt::Enum(it) => docs_from_ast(&it.source(db).value),
81 Adt::Union(it) => docs_from_ast(&it.source(db).value),
82 },
83 DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).value),
84 DocDef::Static(it) => docs_from_ast(&it.source(db).value),
85 DocDef::Const(it) => docs_from_ast(&it.source(db).value),
86 DocDef::Function(it) => docs_from_ast(&it.source(db).value),
87 DocDef::Trait(it) => docs_from_ast(&it.source(db).value),
88 DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).value),
89 DocDef::MacroDef(it) => docs_from_ast(&it.source(db).value),
90 }
91}
92
93impl<T: Into<DocDef> + Copy> Docs for T {
94 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
95 db.documentation((*self).into())
96 }
97}
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 4aa427de4..b7bafe23d 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -1,151 +1,127 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{HasSource as _, Lookup}; 3use hir_def::{HasChildSource, HasSource as _, Lookup, VariantId};
4use hir_expand::either::Either;
4use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::ast::{self, AstNode};
5 6
6use crate::{ 7use crate::{
7 db::{AstDatabase, DefDatabase, HirDatabase}, 8 db::{DefDatabase, HirDatabase},
8 ids::AstItemDef, 9 ids::AstItemDef,
9 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, 10 Const, Enum, EnumVariant, FieldSource, Function, HasBody, Import, MacroDef, Module,
10 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, 11 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
11}; 12};
12 13
13pub use hir_expand::Source; 14pub use hir_expand::Source;
14 15
15pub trait HasSource { 16pub trait HasSource {
16 type Ast; 17 type Ast;
17 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<Self::Ast>; 18 fn source(self, db: &impl DefDatabase) -> Source<Self::Ast>;
18} 19}
19 20
20/// NB: Module is !HasSource, because it has two source nodes at the same time: 21/// NB: Module is !HasSource, because it has two source nodes at the same time:
21/// definition and declaration. 22/// definition and declaration.
22impl Module { 23impl Module {
23 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 24 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
24 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> { 25 pub fn definition_source(self, db: &impl DefDatabase) -> Source<ModuleSource> {
25 let def_map = db.crate_def_map(self.id.krate); 26 let def_map = db.crate_def_map(self.id.krate);
26 let decl_id = def_map[self.id.module_id].declaration; 27 let src = def_map[self.id.module_id].definition_source(db);
27 let file_id = def_map[self.id.module_id].definition; 28 src.map(|it| match it {
28 let value = ModuleSource::new(db, file_id, decl_id); 29 Either::A(it) => ModuleSource::SourceFile(it),
29 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id()); 30 Either::B(it) => ModuleSource::Module(it),
30 Source { file_id, value } 31 })
31 } 32 }
32 33
33 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. 34 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
34 /// `None` for the crate root. 35 /// `None` for the crate root.
35 pub fn declaration_source( 36 pub fn declaration_source(self, db: &impl DefDatabase) -> Option<Source<ast::Module>> {
36 self,
37 db: &(impl DefDatabase + AstDatabase),
38 ) -> Option<Source<ast::Module>> {
39 let def_map = db.crate_def_map(self.id.krate); 37 let def_map = db.crate_def_map(self.id.krate);
40 let decl = def_map[self.id.module_id].declaration?; 38 def_map[self.id.module_id].declaration_source(db)
41 let value = decl.to_node(db);
42 Some(Source { file_id: decl.file_id(), value })
43 } 39 }
44} 40}
45 41
46impl HasSource for StructField { 42impl HasSource for StructField {
47 type Ast = FieldSource; 43 type Ast = FieldSource;
48 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> { 44 fn source(self, db: &impl DefDatabase) -> Source<FieldSource> {
49 let var_data = self.parent.variant_data(db); 45 let var = VariantId::from(self.parent);
50 let fields = var_data.fields().unwrap(); 46 let src = var.child_source(db);
51 let ss; 47 src.map(|it| match it[self.id].clone() {
52 let es; 48 Either::A(it) => FieldSource::Pos(it),
53 let (file_id, struct_kind) = match self.parent { 49 Either::B(it) => FieldSource::Named(it),
54 VariantDef::Struct(s) => { 50 })
55 ss = s.source(db);
56 (ss.file_id, ss.value.kind())
57 }
58 VariantDef::EnumVariant(e) => {
59 es = e.source(db);
60 (es.file_id, es.value.kind())
61 }
62 };
63
64 let field_sources = match struct_kind {
65 ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
66 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
67 ast::StructKind::Unit => Vec::new(),
68 };
69 let value = field_sources
70 .into_iter()
71 .zip(fields.iter())
72 .find(|(_syntax, (id, _))| *id == self.id)
73 .unwrap()
74 .0;
75 Source { file_id, value }
76 } 51 }
77} 52}
78impl HasSource for Struct { 53impl HasSource for Struct {
79 type Ast = ast::StructDef; 54 type Ast = ast::StructDef;
80 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { 55 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
81 self.id.0.source(db) 56 self.id.0.source(db)
82 } 57 }
83} 58}
84impl HasSource for Union { 59impl HasSource for Union {
85 type Ast = ast::StructDef; 60 type Ast = ast::StructDef;
86 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { 61 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
87 self.id.0.source(db) 62 self.id.0.source(db)
88 } 63 }
89} 64}
90impl HasSource for Enum { 65impl HasSource for Enum {
91 type Ast = ast::EnumDef; 66 type Ast = ast::EnumDef;
92 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumDef> { 67 fn source(self, db: &impl DefDatabase) -> Source<ast::EnumDef> {
93 self.id.source(db) 68 self.id.source(db)
94 } 69 }
95} 70}
96impl HasSource for EnumVariant { 71impl HasSource for EnumVariant {
97 type Ast = ast::EnumVariant; 72 type Ast = ast::EnumVariant;
98 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> { 73 fn source(self, db: &impl DefDatabase) -> Source<ast::EnumVariant> {
99 let enum_data = db.enum_data(self.parent.id); 74 self.parent.id.child_source(db).map(|map| map[self.id].clone())
100 let src = self.parent.id.source(db);
101 let value = src
102 .value
103 .variant_list()
104 .into_iter()
105 .flat_map(|it| it.variants())
106 .zip(enum_data.variants.iter())
107 .find(|(_syntax, (id, _))| *id == self.id)
108 .unwrap()
109 .0;
110 Source { file_id: src.file_id, value }
111 } 75 }
112} 76}
113impl HasSource for Function { 77impl HasSource for Function {
114 type Ast = ast::FnDef; 78 type Ast = ast::FnDef;
115 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::FnDef> { 79 fn source(self, db: &impl DefDatabase) -> Source<ast::FnDef> {
116 self.id.lookup(db).source(db) 80 self.id.lookup(db).source(db)
117 } 81 }
118} 82}
119impl HasSource for Const { 83impl HasSource for Const {
120 type Ast = ast::ConstDef; 84 type Ast = ast::ConstDef;
121 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ConstDef> { 85 fn source(self, db: &impl DefDatabase) -> Source<ast::ConstDef> {
122 self.id.lookup(db).source(db) 86 self.id.lookup(db).source(db)
123 } 87 }
124} 88}
125impl HasSource for Static { 89impl HasSource for Static {
126 type Ast = ast::StaticDef; 90 type Ast = ast::StaticDef;
127 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StaticDef> { 91 fn source(self, db: &impl DefDatabase) -> Source<ast::StaticDef> {
128 self.id.source(db) 92 self.id.source(db)
129 } 93 }
130} 94}
131impl HasSource for Trait { 95impl HasSource for Trait {
132 type Ast = ast::TraitDef; 96 type Ast = ast::TraitDef;
133 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TraitDef> { 97 fn source(self, db: &impl DefDatabase) -> Source<ast::TraitDef> {
134 self.id.source(db) 98 self.id.source(db)
135 } 99 }
136} 100}
137impl HasSource for TypeAlias { 101impl HasSource for TypeAlias {
138 type Ast = ast::TypeAliasDef; 102 type Ast = ast::TypeAliasDef;
139 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TypeAliasDef> { 103 fn source(self, db: &impl DefDatabase) -> Source<ast::TypeAliasDef> {
140 self.id.lookup(db).source(db) 104 self.id.lookup(db).source(db)
141 } 105 }
142} 106}
143impl HasSource for MacroDef { 107impl HasSource for MacroDef {
144 type Ast = ast::MacroCall; 108 type Ast = ast::MacroCall;
145 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> { 109 fn source(self, db: &impl DefDatabase) -> Source<ast::MacroCall> {
146 Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) } 110 Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) }
147 } 111 }
148} 112}
113impl HasSource for Import {
114 type Ast = Either<ast::UseTree, ast::ExternCrateItem>;
115
116 /// Returns the syntax of the last path segment corresponding to this import
117 fn source(self, db: &impl DefDatabase) -> Source<Self::Ast> {
118 let src = self.parent.definition_source(db);
119 let (_, source_map) = db.raw_items_with_source_map(src.file_id);
120 let root = db.parse_or_expand(src.file_id).unwrap();
121 let ptr = source_map.get(self.id);
122 src.with_value(ptr.map(|it| it.to_node(&root), |it| it.to_node(&root)))
123 }
124}
149 125
150pub trait HasBodySource: HasBody + HasSource 126pub trait HasBodySource: HasBody + HasSource
151where 127where
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index ed0d68001..3ae5df8d5 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -2,71 +2,34 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::attr::Attr;
6use ra_db::salsa; 5use ra_db::salsa;
7use ra_syntax::SmolStr;
8 6
9use crate::{ 7use crate::{
10 debug::HirDebugDatabase,
11 ids, 8 ids,
12 lang_item::{LangItemTarget, LangItems},
13 ty::{ 9 ty::{
14 method_resolution::CrateImplBlocks, 10 method_resolution::CrateImplBlocks,
15 traits::{AssocTyValue, Impl}, 11 traits::{AssocTyValue, Impl},
16 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, 12 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef,
17 TypeCtor, 13 TypeCtor,
18 }, 14 },
19 type_alias::TypeAliasData, 15 Crate, DefWithBody, GenericDef, ImplBlock, StructField, Trait,
20 Const, ConstData, Crate, DefWithBody, FnData, Function, GenericDef, ImplBlock, Module, Static,
21 StructField, Trait, TypeAlias,
22}; 16};
23 17
24pub use hir_def::db::{ 18pub use hir_def::db::{
25 BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, 19 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery,
26 EnumDataQuery, ExprScopesQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, 20 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery,
27 InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, 21 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
28 TraitDataQuery, 22 LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery,
23 StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery,
29}; 24};
30pub use hir_expand::db::{ 25pub use hir_expand::db::{
31 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 26 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
32 ParseMacroQuery, 27 ParseMacroQuery,
33}; 28};
34 29
35// This database uses `AstDatabase` internally,
36#[salsa::query_group(DefDatabaseStorage)]
37#[salsa::requires(AstDatabase)]
38pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
39 #[salsa::invoke(FnData::fn_data_query)]
40 fn fn_data(&self, func: Function) -> Arc<FnData>;
41
42 #[salsa::invoke(TypeAliasData::type_alias_data_query)]
43 fn type_alias_data(&self, typ: TypeAlias) -> Arc<TypeAliasData>;
44
45 #[salsa::invoke(ConstData::const_data_query)]
46 fn const_data(&self, konst: Const) -> Arc<ConstData>;
47
48 #[salsa::invoke(ConstData::static_data_query)]
49 fn static_data(&self, konst: Static) -> Arc<ConstData>;
50
51 #[salsa::invoke(LangItems::module_lang_items_query)]
52 fn module_lang_items(&self, module: Module) -> Option<Arc<LangItems>>;
53
54 #[salsa::invoke(LangItems::crate_lang_items_query)]
55 fn crate_lang_items(&self, krate: Crate) -> Arc<LangItems>;
56
57 #[salsa::invoke(LangItems::lang_item_query)]
58 fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option<LangItemTarget>;
59
60 #[salsa::invoke(crate::code_model::docs::documentation_query)]
61 fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>;
62
63 #[salsa::invoke(crate::code_model::attrs::attributes_query)]
64 fn attrs(&self, def: crate::AttrDef) -> Option<Arc<[Attr]>>;
65}
66
67#[salsa::query_group(HirDatabaseStorage)] 30#[salsa::query_group(HirDatabaseStorage)]
68#[salsa::requires(salsa::Database)] 31#[salsa::requires(salsa::Database)]
69pub trait HirDatabase: DefDatabase + AstDatabase { 32pub trait HirDatabase: DefDatabase {
70 #[salsa::invoke(crate::ty::infer_query)] 33 #[salsa::invoke(crate::ty::infer_query)]
71 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>; 34 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
72 35
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs
index 4f3e922c3..8ec371f6e 100644
--- a/crates/ra_hir/src/debug.rs
+++ b/crates/ra_hir/src/debug.rs
@@ -1,3 +1,5 @@
1//! XXX: This does not work at the moment.
2//!
1//! printf debugging infrastructure for rust-analyzer. 3//! printf debugging infrastructure for rust-analyzer.
2//! 4//!
3//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`, 5//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`,
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
index e8ed04056..529ac8251 100644
--- a/crates/ra_hir/src/from_id.rs
+++ b/crates/ra_hir/src/from_id.rs
@@ -4,14 +4,14 @@
4//! are splitting the hir. 4//! are splitting the hir.
5 5
6use hir_def::{ 6use hir_def::{
7 AdtId, AssocItemId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, 7 AdtId, AssocItemId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
8 ModuleDefId, StaticId, StructId, TypeAliasId, UnionId, 8 GenericDefId, ModuleDefId, StaticId, StructFieldId, StructId, TypeAliasId, UnionId, VariantId,
9}; 9};
10 10
11use crate::{ 11use crate::{
12 ty::{CallableDef, TypableDef}, 12 ty::{CallableDef, TypableDef},
13 Adt, AssocItem, Const, Crate, DefWithBody, EnumVariant, Function, GenericDef, ModuleDef, 13 Adt, AssocItem, AttrDef, Const, Crate, DefWithBody, EnumVariant, Function, GenericDef,
14 Static, TypeAlias, 14 ModuleDef, Static, StructField, TypeAlias, VariantDef,
15}; 15};
16 16
17impl From<ra_db::CrateId> for Crate { 17impl From<ra_db::CrateId> for Crate {
@@ -70,6 +70,12 @@ impl From<EnumVariantId> for EnumVariant {
70 } 70 }
71} 71}
72 72
73impl From<EnumVariant> for EnumVariantId {
74 fn from(def: EnumVariant) -> Self {
75 EnumVariantId { parent: def.parent.id, local_id: def.id }
76 }
77}
78
73impl From<ModuleDefId> for ModuleDef { 79impl From<ModuleDefId> for ModuleDef {
74 fn from(id: ModuleDefId) -> Self { 80 fn from(id: ModuleDefId) -> Self {
75 match id { 81 match id {
@@ -219,3 +225,35 @@ impl From<CallableDef> for GenericDefId {
219 } 225 }
220 } 226 }
221} 227}
228
229impl From<VariantDef> for VariantId {
230 fn from(def: VariantDef) -> Self {
231 match def {
232 VariantDef::Struct(it) => VariantId::StructId(it.id),
233 VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()),
234 }
235 }
236}
237
238impl From<StructField> for StructFieldId {
239 fn from(def: StructField) -> Self {
240 StructFieldId { parent: def.parent.into(), local_id: def.id }
241 }
242}
243
244impl From<AttrDef> for AttrDefId {
245 fn from(def: AttrDef) -> Self {
246 match def {
247 AttrDef::Module(it) => AttrDefId::ModuleId(it.id),
248 AttrDef::StructField(it) => AttrDefId::StructFieldId(it.into()),
249 AttrDef::Adt(it) => AttrDefId::AdtId(it.into()),
250 AttrDef::Function(it) => AttrDefId::FunctionId(it.id),
251 AttrDef::EnumVariant(it) => AttrDefId::EnumVariantId(it.into()),
252 AttrDef::Static(it) => AttrDefId::StaticId(it.id),
253 AttrDef::Const(it) => AttrDefId::ConstId(it.id),
254 AttrDef::Trait(it) => AttrDefId::TraitId(it.id),
255 AttrDef::TypeAlias(it) => AttrDefId::TypeAliasId(it.id),
256 AttrDef::MacroDef(it) => AttrDefId::MacroDefId(it.id),
257 }
258 }
259}
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 774fa1d96..334eeebac 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -18,11 +18,11 @@ impl HasSource for ImplBlock {
18 18
19impl ImplBlock { 19impl ImplBlock {
20 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { 20 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
21 db.impl_data(self.id).target_trait().cloned() 21 db.impl_data(self.id).target_trait.clone()
22 } 22 }
23 23
24 pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef { 24 pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
25 db.impl_data(self.id).target_type().clone() 25 db.impl_data(self.id).target_type.clone()
26 } 26 }
27 27
28 pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { 28 pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
@@ -35,11 +35,11 @@ impl ImplBlock {
35 } 35 }
36 36
37 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { 37 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
38 db.impl_data(self.id).items().iter().map(|it| (*it).into()).collect() 38 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
39 } 39 }
40 40
41 pub fn is_negative(&self, db: &impl DefDatabase) -> bool { 41 pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
42 db.impl_data(self.id).is_negative() 42 db.impl_data(self.id).is_negative
43 } 43 }
44 44
45 pub fn module(&self, db: &impl DefDatabase) -> Module { 45 pub fn module(&self, db: &impl DefDatabase) -> Module {
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
deleted file mode 100644
index 89fd85f59..000000000
--- a/crates/ra_hir/src/lang_item.rs
+++ /dev/null
@@ -1,160 +0,0 @@
1//! FIXME: write short doc here
2
3use rustc_hash::FxHashMap;
4use std::sync::Arc;
5
6use ra_syntax::{ast::AttrsOwner, SmolStr};
7
8use crate::{
9 db::{AstDatabase, DefDatabase, HirDatabase},
10 Adt, Crate, Enum, Function, HasSource, ImplBlock, Module, ModuleDef, Static, Struct, Trait,
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum LangItemTarget {
15 Enum(Enum),
16 Function(Function),
17 ImplBlock(ImplBlock),
18 Static(Static),
19 Struct(Struct),
20 Trait(Trait),
21}
22
23impl LangItemTarget {
24 pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
25 Some(match self {
26 LangItemTarget::Enum(e) => e.module(db).krate(),
27 LangItemTarget::Function(f) => f.module(db).krate(),
28 LangItemTarget::ImplBlock(i) => i.krate(db),
29 LangItemTarget::Static(s) => s.module(db).krate(),
30 LangItemTarget::Struct(s) => s.module(db).krate(),
31 LangItemTarget::Trait(t) => t.module(db).krate(),
32 })
33 }
34}
35
36#[derive(Default, Debug, Clone, PartialEq, Eq)]
37pub struct LangItems {
38 items: FxHashMap<SmolStr, LangItemTarget>,
39}
40
41impl LangItems {
42 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> {
43 self.items.get(item)
44 }
45
46 /// Salsa query. This will look for lang items in a specific crate.
47 pub(crate) fn crate_lang_items_query(
48 db: &(impl DefDatabase + AstDatabase),
49 krate: Crate,
50 ) -> Arc<LangItems> {
51 let mut lang_items = LangItems::default();
52
53 if let Some(module) = krate.root_module(db) {
54 lang_items.collect_lang_items_recursive(db, module);
55 }
56
57 Arc::new(lang_items)
58 }
59
60 pub(crate) fn module_lang_items_query(
61 db: &(impl DefDatabase + AstDatabase),
62 module: Module,
63 ) -> Option<Arc<LangItems>> {
64 let mut lang_items = LangItems::default();
65 lang_items.collect_lang_items(db, module);
66 if lang_items.items.is_empty() {
67 None
68 } else {
69 Some(Arc::new(lang_items))
70 }
71 }
72
73 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
74 /// traversing its dependencies.
75 pub(crate) fn lang_item_query(
76 db: &impl DefDatabase,
77 start_crate: Crate,
78 item: SmolStr,
79 ) -> Option<LangItemTarget> {
80 let lang_items = db.crate_lang_items(start_crate);
81 let start_crate_target = lang_items.items.get(&item);
82 if let Some(target) = start_crate_target {
83 Some(*target)
84 } else {
85 for dep in start_crate.dependencies(db) {
86 let dep_crate = dep.krate;
87 let dep_target = db.lang_item(dep_crate, item.clone());
88 if dep_target.is_some() {
89 return dep_target;
90 }
91 }
92 None
93 }
94 }
95
96 fn collect_lang_items(&mut self, db: &(impl DefDatabase + AstDatabase), module: Module) {
97 // Look for impl targets
98 for impl_block in module.impl_blocks(db) {
99 let src = impl_block.source(db);
100 if let Some(lang_item_name) = lang_item_name(&src.value) {
101 self.items
102 .entry(lang_item_name)
103 .or_insert_with(|| LangItemTarget::ImplBlock(impl_block));
104 }
105 }
106
107 for def in module.declarations(db) {
108 match def {
109 ModuleDef::Trait(trait_) => {
110 self.collect_lang_item(db, trait_, LangItemTarget::Trait)
111 }
112 ModuleDef::Adt(Adt::Enum(e)) => self.collect_lang_item(db, e, LangItemTarget::Enum),
113 ModuleDef::Adt(Adt::Struct(s)) => {
114 self.collect_lang_item(db, s, LangItemTarget::Struct)
115 }
116 ModuleDef::Function(f) => self.collect_lang_item(db, f, LangItemTarget::Function),
117 ModuleDef::Static(s) => self.collect_lang_item(db, s, LangItemTarget::Static),
118 _ => {}
119 }
120 }
121 }
122
123 fn collect_lang_items_recursive(
124 &mut self,
125 db: &(impl DefDatabase + AstDatabase),
126 module: Module,
127 ) {
128 if let Some(module_lang_items) = db.module_lang_items(module) {
129 self.items.extend(module_lang_items.items.iter().map(|(k, v)| (k.clone(), *v)))
130 }
131
132 // Look for lang items in the children
133 for child in module.children(db) {
134 self.collect_lang_items_recursive(db, child);
135 }
136 }
137
138 fn collect_lang_item<T, N>(
139 &mut self,
140 db: &(impl DefDatabase + AstDatabase),
141 item: T,
142 constructor: fn(T) -> LangItemTarget,
143 ) where
144 T: Copy + HasSource<Ast = N>,
145 N: AttrsOwner,
146 {
147 let node = item.source(db).value;
148 if let Some(lang_item_name) = lang_item_name(&node) {
149 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
150 }
151 }
152}
153
154fn lang_item_name<T: AttrsOwner>(node: &T) -> Option<SmolStr> {
155 node.attrs()
156 .filter_map(|a| a.as_simple_key_value())
157 .filter(|(key, _)| key == "lang")
158 .map(|(_, val)| val)
159 .nth(0)
160}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 8c6834392..e51d4d063 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -32,11 +32,9 @@ pub mod db;
32pub mod source_binder; 32pub mod source_binder;
33 33
34mod ids; 34mod ids;
35mod type_alias;
36mod ty; 35mod ty;
37mod impl_block; 36mod impl_block;
38mod expr; 37mod expr;
39mod lang_item;
40pub mod diagnostics; 38pub mod diagnostics;
41mod util; 39mod util;
42 40
@@ -52,13 +50,11 @@ mod marks;
52 50
53pub use crate::{ 51pub use crate::{
54 code_model::{ 52 code_model::{
55 attrs::{AttrDef, Attrs},
56 docs::{DocDef, Docs, Documentation},
57 src::{HasBodySource, HasSource}, 53 src::{HasBodySource, HasSource},
58 Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, 54 Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum,
59 EnumVariant, FieldSource, FnData, Function, GenericDef, GenericParam, HasBody, ImplBlock, 55 EnumVariant, FieldSource, Function, GenericDef, GenericParam, HasAttrs, HasBody, ImplBlock,
60 Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField, 56 Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct,
61 Trait, TypeAlias, Union, VariantDef, 57 StructField, Trait, TypeAlias, Union, VariantDef,
62 }, 58 },
63 expr::ExprScopes, 59 expr::ExprScopes,
64 from_source::FromSource, 60 from_source::FromSource,
@@ -73,7 +69,7 @@ pub use crate::{
73 69
74pub use hir_def::{ 70pub use hir_def::{
75 builtin_type::BuiltinType, 71 builtin_type::BuiltinType,
76 nameres::{per_ns::PerNs, raw::ImportId}, 72 docs::Documentation,
77 path::{Path, PathKind}, 73 path::{Path, PathKind},
78 type_ref::Mutability, 74 type_ref::Mutability,
79}; 75};
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index c42ceabdf..797f90d50 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -131,6 +131,7 @@ pub struct ReferenceDescriptor {
131} 131}
132 132
133pub struct Expansion { 133pub struct Expansion {
134 macro_file_kind: MacroFileKind,
134 macro_call_id: MacroCallId, 135 macro_call_id: MacroCallId,
135} 136}
136 137
@@ -145,7 +146,7 @@ impl Expansion {
145 } 146 }
146 147
147 pub fn file_id(&self) -> HirFileId { 148 pub fn file_id(&self) -> HirFileId {
148 self.macro_call_id.as_file(MacroFileKind::Items) 149 self.macro_call_id.as_file(self.macro_file_kind)
149 } 150 }
150} 151}
151 152
@@ -439,7 +440,10 @@ impl SourceAnalyzer {
439 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), 440 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
440 ); 441 );
441 let macro_call_loc = MacroCallLoc { def, ast_id }; 442 let macro_call_loc = MacroCallLoc { def, ast_id };
442 Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) 443 Some(Expansion {
444 macro_call_id: db.intern_macro(macro_call_loc),
445 macro_file_kind: to_macro_file_kind(macro_call.value),
446 })
443 } 447 }
444 448
445 #[cfg(test)] 449 #[cfg(test)]
@@ -538,3 +542,35 @@ fn adjust(
538 }) 542 })
539 .map(|(_ptr, scope)| *scope) 543 .map(|(_ptr, scope)| *scope)
540} 544}
545
546/// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to.
547/// FIXME: Not completed
548fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind {
549 let syn = macro_call.syntax();
550 let parent = match syn.parent() {
551 Some(it) => it,
552 None => {
553 // FIXME:
554 // If it is root, which means the parent HirFile
555 // MacroKindFile must be non-items
556 // return expr now.
557 return MacroFileKind::Expr;
558 }
559 };
560
561 match parent.kind() {
562 MACRO_ITEMS | SOURCE_FILE => MacroFileKind::Items,
563 LET_STMT => {
564 // FIXME: Handle Pattern
565 MacroFileKind::Expr
566 }
567 EXPR_STMT => MacroFileKind::Statements,
568 BLOCK => MacroFileKind::Statements,
569 ARG_LIST => MacroFileKind::Expr,
570 TRY_EXPR => MacroFileKind::Expr,
571 _ => {
572 // Unknown , Just guess it is `Items`
573 MacroFileKind::Items
574 }
575 }
576}
diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs
index 1caa2e875..03c7ac155 100644
--- a/crates/ra_hir/src/test_db.rs
+++ b/crates/ra_hir/src/test_db.rs
@@ -2,7 +2,7 @@
2 2
3use std::{panic, sync::Arc}; 3use std::{panic, sync::Arc};
4 4
5use hir_def::{db::DefDatabase2, ModuleId}; 5use hir_def::{db::DefDatabase, ModuleId};
6use hir_expand::diagnostics::DiagnosticSink; 6use hir_expand::diagnostics::DiagnosticSink;
7use parking_lot::Mutex; 7use parking_lot::Mutex;
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase}; 8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase};
@@ -15,7 +15,6 @@ use crate::{db, debug::HirDebugHelper};
15 db::InternDatabaseStorage, 15 db::InternDatabaseStorage,
16 db::AstDatabaseStorage, 16 db::AstDatabaseStorage,
17 db::DefDatabaseStorage, 17 db::DefDatabaseStorage,
18 db::DefDatabase2Storage,
19 db::HirDatabaseStorage 18 db::HirDatabaseStorage
20)] 19)]
21#[derive(Debug, Default)] 20#[derive(Debug, Default)]
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index b60e4bb31..41c99d227 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -5,12 +5,13 @@
5 5
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::resolver::Resolver; 8use hir_def::{lang_item::LangItemTarget, resolver::Resolver};
9use hir_expand::name; 9use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11 11
12use crate::{db::HirDatabase, Trait};
13
12use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; 14use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
13use crate::db::HirDatabase;
14 15
15const AUTODEREF_RECURSION_LIMIT: usize = 10; 16const AUTODEREF_RECURSION_LIMIT: usize = 10;
16 17
@@ -41,7 +42,7 @@ fn deref_by_trait(
41) -> Option<Canonical<Ty>> { 42) -> Option<Canonical<Ty>> {
42 let krate = resolver.krate()?; 43 let krate = resolver.krate()?;
43 let deref_trait = match db.lang_item(krate.into(), "deref".into())? { 44 let deref_trait = match db.lang_item(krate.into(), "deref".into())? {
44 crate::lang_item::LangItemTarget::Trait(t) => t, 45 LangItemTarget::TraitId(t) => Trait::from(t),
45 _ => return None, 46 _ => return None,
46 }; 47 };
47 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; 48 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 69b13baef..471bdc387 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -22,6 +22,7 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
22use rustc_hash::FxHashMap; 22use rustc_hash::FxHashMap;
23 23
24use hir_def::{ 24use hir_def::{
25 data::{ConstData, FunctionData},
25 path::known, 26 path::known,
26 resolver::{HasResolver, Resolver, TypeNs}, 27 resolver::{HasResolver, Resolver, TypeNs},
27 type_ref::{Mutability, TypeRef}, 28 type_ref::{Mutability, TypeRef},
@@ -43,8 +44,8 @@ use crate::{
43 db::HirDatabase, 44 db::HirDatabase,
44 expr::{BindingAnnotation, Body, ExprId, PatId}, 45 expr::{BindingAnnotation, Body, ExprId, PatId},
45 ty::infer::diagnostics::InferenceDiagnostic, 46 ty::infer::diagnostics::InferenceDiagnostic,
46 Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, 47 Adt, AssocItem, DefWithBody, FloatTy, Function, HasBody, IntTy, Path, StructField, Trait,
47 StructField, Trait, VariantDef, 48 VariantDef,
48}; 49};
49 50
50macro_rules! ty_app { 51macro_rules! ty_app {
@@ -68,10 +69,10 @@ pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResu
68 let resolver = DefWithBodyId::from(def).resolver(db); 69 let resolver = DefWithBodyId::from(def).resolver(db);
69 let mut ctx = InferenceContext::new(db, def, resolver); 70 let mut ctx = InferenceContext::new(db, def, resolver);
70 71
71 match def { 72 match &def {
72 DefWithBody::Const(ref c) => ctx.collect_const(&c.data(db)), 73 DefWithBody::Const(c) => ctx.collect_const(&db.const_data(c.id)),
73 DefWithBody::Function(ref f) => ctx.collect_fn(&f.data(db)), 74 DefWithBody::Function(f) => ctx.collect_fn(&db.function_data(f.id)),
74 DefWithBody::Static(ref s) => ctx.collect_const(&s.data(db)), 75 DefWithBody::Static(s) => ctx.collect_const(&db.static_data(s.id)),
75 } 76 }
76 77
77 ctx.infer_body(); 78 ctx.infer_body();
@@ -559,17 +560,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
559 } 560 }
560 561
561 fn collect_const(&mut self, data: &ConstData) { 562 fn collect_const(&mut self, data: &ConstData) {
562 self.return_ty = self.make_ty(data.type_ref()); 563 self.return_ty = self.make_ty(&data.type_ref);
563 } 564 }
564 565
565 fn collect_fn(&mut self, data: &FnData) { 566 fn collect_fn(&mut self, data: &FunctionData) {
566 let body = Arc::clone(&self.body); // avoid borrow checker problem 567 let body = Arc::clone(&self.body); // avoid borrow checker problem
567 for (type_ref, pat) in data.params().iter().zip(body.params()) { 568 for (type_ref, pat) in data.params.iter().zip(body.params()) {
568 let ty = self.make_ty(type_ref); 569 let ty = self.make_ty(type_ref);
569 570
570 self.infer_pat(*pat, &ty, BindingMode::default()); 571 self.infer_pat(*pat, &ty, BindingMode::default());
571 } 572 }
572 self.return_ty = self.make_ty(data.ret_type()); 573 self.return_ty = self.make_ty(&data.ret_type);
573 } 574 }
574 575
575 fn infer_body(&mut self) { 576 fn infer_body(&mut self) {
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs
index 0772b9df5..4ea038d99 100644
--- a/crates/ra_hir/src/ty/infer/coerce.rs
+++ b/crates/ra_hir/src/ty/infer/coerce.rs
@@ -4,13 +4,12 @@
4//! 4//!
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use hir_def::resolver::Resolver; 7use hir_def::{lang_item::LangItemTarget, resolver::Resolver};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use test_utils::tested_by; 9use test_utils::tested_by;
10 10
11use crate::{ 11use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 lang_item::LangItemTarget,
14 ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, 13 ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk},
15 Adt, Mutability, 14 Adt, Mutability,
16}; 15};
@@ -50,7 +49,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
50 ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { 49 ) -> FxHashMap<(TypeCtor, TypeCtor), usize> {
51 let krate = resolver.krate().unwrap(); 50 let krate = resolver.krate().unwrap();
52 let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { 51 let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) {
53 Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate.into(), trait_), 52 Some(LangItemTarget::TraitId(trait_)) => {
53 db.impls_for_trait(krate.into(), trait_.into())
54 }
54 _ => return FxHashMap::default(), 55 _ => return FxHashMap::default(),
55 }; 56 };
56 57
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 75c552569..2272510e8 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -622,10 +622,10 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) ->
622} 622}
623 623
624fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { 624fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
625 let data = def.data(db); 625 let data = db.function_data(def.id);
626 let resolver = def.id.resolver(db); 626 let resolver = def.id.resolver(db);
627 let params = data.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); 627 let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
628 let ret = Ty::from_hir(db, &resolver, data.ret_type()); 628 let ret = Ty::from_hir(db, &resolver, &data.ret_type);
629 FnSig::from_params_and_return(params, ret) 629 FnSig::from_params_and_return(params, ret)
630} 630}
631 631
@@ -639,18 +639,18 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
639 639
640/// Build the declared type of a const. 640/// Build the declared type of a const.
641fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { 641fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty {
642 let data = def.data(db); 642 let data = db.const_data(def.id);
643 let resolver = def.id.resolver(db); 643 let resolver = def.id.resolver(db);
644 644
645 Ty::from_hir(db, &resolver, data.type_ref()) 645 Ty::from_hir(db, &resolver, &data.type_ref)
646} 646}
647 647
648/// Build the declared type of a static. 648/// Build the declared type of a static.
649fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { 649fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty {
650 let data = def.data(db); 650 let data = db.static_data(def.id);
651 let resolver = def.id.resolver(db); 651 let resolver = def.id.resolver(db);
652 652
653 Ty::from_hir(db, &resolver, data.type_ref()) 653 Ty::from_hir(db, &resolver, &data.type_ref)
654} 654}
655 655
656/// Build the declared type of a static. 656/// Build the declared type of a static.
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 64adb814d..caa5f5f74 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -5,7 +5,7 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::resolver::Resolver; 8use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef};
9use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
10 10
11use crate::{ 11use crate::{
@@ -91,34 +91,43 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV
91 // Types like slice can have inherent impls in several crates, (core and alloc). 91 // Types like slice can have inherent impls in several crates, (core and alloc).
92 // The corresponding impls are marked with lang items, so we can use them to find the required crates. 92 // The corresponding impls are marked with lang items, so we can use them to find the required crates.
93 macro_rules! lang_item_crate { 93 macro_rules! lang_item_crate {
94 ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ 94 ($($name:expr),+ $(,)?) => {{
95 let mut v = ArrayVec::<[Crate; 2]>::new(); 95 let mut v = ArrayVec::<[LangItemTarget; 2]>::new();
96 $( 96 $(
97 v.extend($db.lang_item($cur_crate, $name.into()).and_then(|item| item.krate($db))); 97 v.extend(db.lang_item(cur_crate.crate_id, $name.into()));
98 )+ 98 )+
99 Some(v) 99 v
100 }}; 100 }};
101 } 101 }
102 102
103 match ty { 103 let lang_item_targets = match ty {
104 Ty::Apply(a_ty) => match a_ty.ctor { 104 Ty::Apply(a_ty) => match a_ty.ctor {
105 TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), 105 TypeCtor::Adt(def_id) => return Some(std::iter::once(def_id.krate(db)?).collect()),
106 TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), 106 TypeCtor::Bool => lang_item_crate!("bool"),
107 TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), 107 TypeCtor::Char => lang_item_crate!("char"),
108 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { 108 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness {
109 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) 109 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
110 FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"), 110 FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"),
111 FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"), 111 FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"),
112 }, 112 },
113 TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(db, cur_crate, i.ty_to_string()), 113 TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()),
114 TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"), 114 TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
115 TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), 115 TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
116 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"), 116 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
117 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!(db, cur_crate, "mut_ptr"), 117 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
118 _ => None, 118 _ => return None,
119 }, 119 },
120 _ => None, 120 _ => return None,
121 } 121 };
122 let res = lang_item_targets
123 .into_iter()
124 .filter_map(|it| match it {
125 LangItemTarget::ImplBlockId(it) => Some(it),
126 _ => None,
127 })
128 .map(|it| it.module(db).krate.into())
129 .collect();
130 Some(res)
122} 131}
123 132
124/// Look up the method with the given name, returning the actual autoderefed 133/// Look up the method with the given name, returning the actual autoderefed
@@ -233,7 +242,7 @@ fn iterate_trait_method_candidates<T>(
233 .chain(traits_from_env) 242 .chain(traits_from_env)
234 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); 243 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from));
235 'traits: for t in traits { 244 'traits: for t in traits {
236 let data = t.trait_data(db); 245 let data = db.trait_data(t.id);
237 246
238 // we'll be lazy about checking whether the type implements the 247 // we'll be lazy about checking whether the type implements the
239 // trait, but if we find out it doesn't, we'll skip the rest of the 248 // trait, but if we find out it doesn't, we'll skip the rest of the
@@ -291,9 +300,9 @@ fn is_valid_candidate(
291) -> bool { 300) -> bool {
292 match item { 301 match item {
293 AssocItem::Function(m) => { 302 AssocItem::Function(m) => {
294 let data = m.data(db); 303 let data = db.function_data(m.id);
295 name.map_or(true, |name| data.name() == name) 304 name.map_or(true, |name| data.name == *name)
296 && (data.has_self_param() || mode == LookupMode::Path) 305 && (data.has_self_param || mode == LookupMode::Path)
297 } 306 }
298 AssocItem::Const(c) => { 307 AssocItem::Const(c) => {
299 name.map_or(true, |name| Some(name) == c.name(db).as_ref()) 308 name.map_or(true, |name| Some(name) == c.name(db).as_ref())
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 74c12a0a2..17a50cf74 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -4857,3 +4857,41 @@ fn main() {
4857 "### 4857 "###
4858 ); 4858 );
4859} 4859}
4860
4861#[test]
4862fn infer_builtin_macros_file() {
4863 assert_snapshot!(
4864 infer(r#"
4865#[rustc_builtin_macro]
4866macro_rules! file {() => {}}
4867
4868fn main() {
4869 let x = file!();
4870}
4871"#),
4872 @r###"
4873 ![0; 2) '""': &str
4874 [64; 88) '{ ...!(); }': ()
4875 [74; 75) 'x': &str
4876 "###
4877 );
4878}
4879
4880#[test]
4881fn infer_builtin_macros_column() {
4882 assert_snapshot!(
4883 infer(r#"
4884#[rustc_builtin_macro]
4885macro_rules! column {() => {}}
4886
4887fn main() {
4888 let x = column!();
4889}
4890"#),
4891 @r###"
4892 ![0; 2) '13': i32
4893 [66; 92) '{ ...!(); }': ()
4894 [76; 77) 'x': i32
4895 "###
4896 );
4897}
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 88785f305..53818a5e5 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -9,6 +9,7 @@ use chalk_ir::{
9}; 9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_def::lang_item::LangItemTarget;
12use hir_expand::name; 13use hir_expand::name;
13 14
14use ra_db::salsa::{InternId, InternKey}; 15use ra_db::salsa::{InternId, InternKey};
@@ -832,9 +833,9 @@ fn closure_fn_trait_output_assoc_ty_value(
832} 833}
833 834
834fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { 835fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> {
835 let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; 836 let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?;
836 match target { 837 match target {
837 crate::lang_item::LangItemTarget::Trait(t) => Some(t), 838 LangItemTarget::TraitId(t) => Some(t.into()),
838 _ => None, 839 _ => None,
839 } 840 }
840} 841}
diff --git a/crates/ra_hir/src/type_alias.rs b/crates/ra_hir/src/type_alias.rs
deleted file mode 100644
index 392f244cf..000000000
--- a/crates/ra_hir/src/type_alias.rs
+++ /dev/null
@@ -1,31 +0,0 @@
1//! HIR for type aliases (i.e. the `type` keyword).
2
3use std::sync::Arc;
4
5use hir_def::type_ref::TypeRef;
6use hir_expand::name::{AsName, Name};
7
8use ra_syntax::ast::NameOwner;
9
10use crate::{
11 db::{AstDatabase, DefDatabase},
12 HasSource, TypeAlias,
13};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct TypeAliasData {
17 pub(crate) name: Name,
18 pub(crate) type_ref: Option<TypeRef>,
19}
20
21impl TypeAliasData {
22 pub(crate) fn type_alias_data_query(
23 db: &(impl DefDatabase + AstDatabase),
24 typ: TypeAlias,
25 ) -> Arc<TypeAliasData> {
26 let node = typ.source(db).value;
27 let name = node.name().map_or_else(Name::missing, |n| n.as_name());
28 let type_ref = node.type_ref().map(TypeRef::from_ast);
29 Arc::new(TypeAliasData { name, type_ref })
30 }
31}
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index d04f54e15..20e9a1eb5 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -2,13 +2,17 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::name::{AsName, Name}; 5use hir_expand::{
6use ra_arena::Arena; 6 either::Either,
7 name::{AsName, Name},
8 Source,
9};
10use ra_arena::{map::ArenaMap, Arena};
7use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 11use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
8 12
9use crate::{ 13use crate::{
10 db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, 14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource,
11 LocalStructFieldId, StructOrUnionId, 15 LocalEnumVariantId, LocalStructFieldId, StructOrUnionId, VariantId,
12}; 16};
13 17
14/// Note that we use `StructData` for unions as well! 18/// Note that we use `StructData` for unions as well!
@@ -30,13 +34,9 @@ pub struct EnumVariantData {
30 pub variant_data: Arc<VariantData>, 34 pub variant_data: Arc<VariantData>,
31} 35}
32 36
33/// Fields of an enum variant or struct
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct VariantData(VariantDataInner);
36
37#[derive(Debug, Clone, PartialEq, Eq)] 37#[derive(Debug, Clone, PartialEq, Eq)]
38enum VariantDataInner { 38pub enum VariantData {
39 Struct(Arena<LocalStructFieldId, StructFieldData>), 39 Record(Arena<LocalStructFieldId, StructFieldData>),
40 Tuple(Arena<LocalStructFieldId, StructFieldData>), 40 Tuple(Arena<LocalStructFieldId, StructFieldData>),
41 Unit, 41 Unit,
42} 42}
@@ -49,10 +49,7 @@ pub struct StructFieldData {
49} 49}
50 50
51impl StructData { 51impl StructData {
52 pub(crate) fn struct_data_query( 52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructOrUnionId) -> Arc<StructData> {
53 db: &impl DefDatabase2,
54 id: StructOrUnionId,
55 ) -> Arc<StructData> {
56 let src = id.source(db); 53 let src = id.source(db);
57 let name = src.value.name().map(|n| n.as_name()); 54 let name = src.value.name().map(|n| n.as_name());
58 let variant_data = VariantData::new(src.value.kind()); 55 let variant_data = VariantData::new(src.value.kind());
@@ -62,20 +59,12 @@ impl StructData {
62} 59}
63 60
64impl EnumData { 61impl EnumData {
65 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> { 62 pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc<EnumData> {
66 let src = e.source(db); 63 let src = e.source(db);
67 let name = src.value.name().map(|n| n.as_name()); 64 let name = src.value.name().map(|n| n.as_name());
68 let variants = src 65 let mut trace = Trace::new_for_arena();
69 .value 66 lower_enum(&mut trace, &src.value);
70 .variant_list() 67 Arc::new(EnumData { name, variants: trace.into_arena() })
71 .into_iter()
72 .flat_map(|it| it.variants())
73 .map(|var| EnumVariantData {
74 name: var.name().map(|it| it.as_name()),
75 variant_data: Arc::new(VariantData::new(var.kind())),
76 })
77 .collect();
78 Arc::new(EnumData { name, variants })
79 } 68 }
80 69
81 pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { 70 pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
@@ -84,39 +73,109 @@ impl EnumData {
84 } 73 }
85} 74}
86 75
76impl HasChildSource for EnumId {
77 type ChildId = LocalEnumVariantId;
78 type Value = ast::EnumVariant;
79 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> {
80 let src = self.source(db);
81 let mut trace = Trace::new_for_map();
82 lower_enum(&mut trace, &src.value);
83 src.with_value(trace.into_map())
84 }
85}
86
87fn lower_enum(
88 trace: &mut Trace<LocalEnumVariantId, EnumVariantData, ast::EnumVariant>,
89 ast: &ast::EnumDef,
90) {
91 for var in ast.variant_list().into_iter().flat_map(|it| it.variants()) {
92 trace.alloc(
93 || var.clone(),
94 || EnumVariantData {
95 name: var.name().map(|it| it.as_name()),
96 variant_data: Arc::new(VariantData::new(var.kind())),
97 },
98 )
99 }
100}
101
87impl VariantData { 102impl VariantData {
88 fn new(flavor: ast::StructKind) -> Self { 103 fn new(flavor: ast::StructKind) -> Self {
89 let inner = match flavor { 104 let mut trace = Trace::new_for_arena();
90 ast::StructKind::Tuple(fl) => { 105 match lower_struct(&mut trace, &flavor) {
91 let fields = fl 106 StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
92 .fields() 107 StructKind::Record => VariantData::Record(trace.into_arena()),
93 .enumerate() 108 StructKind::Unit => VariantData::Unit,
94 .map(|(i, fd)| StructFieldData { 109 }
110 }
111
112 pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> {
113 match &self {
114 VariantData::Record(fields) | VariantData::Tuple(fields) => Some(fields),
115 _ => None,
116 }
117 }
118}
119
120impl HasChildSource for VariantId {
121 type ChildId = LocalStructFieldId;
122 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>;
123
124 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> {
125 let src = match self {
126 VariantId::EnumVariantId(it) => {
127 // I don't really like the fact that we call into parent source
128 // here, this might add to more queries then necessary.
129 let src = it.parent.child_source(db);
130 src.map(|map| map[it.local_id].kind())
131 }
132 VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()),
133 };
134 let mut trace = Trace::new_for_map();
135 lower_struct(&mut trace, &src.value);
136 src.with_value(trace.into_map())
137 }
138}
139
140enum StructKind {
141 Tuple,
142 Record,
143 Unit,
144}
145
146fn lower_struct(
147 trace: &mut Trace<
148 LocalStructFieldId,
149 StructFieldData,
150 Either<ast::TupleFieldDef, ast::RecordFieldDef>,
151 >,
152 ast: &ast::StructKind,
153) -> StructKind {
154 match ast {
155 ast::StructKind::Tuple(fl) => {
156 for (i, fd) in fl.fields().enumerate() {
157 trace.alloc(
158 || Either::A(fd.clone()),
159 || StructFieldData {
95 name: Name::new_tuple_field(i), 160 name: Name::new_tuple_field(i),
96 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 161 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
97 }) 162 },
98 .collect(); 163 )
99 VariantDataInner::Tuple(fields)
100 } 164 }
101 ast::StructKind::Named(fl) => { 165 StructKind::Tuple
102 let fields = fl 166 }
103 .fields() 167 ast::StructKind::Record(fl) => {
104 .map(|fd| StructFieldData { 168 for fd in fl.fields() {
169 trace.alloc(
170 || Either::B(fd.clone()),
171 || StructFieldData {
105 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 172 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
106 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 173 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
107 }) 174 },
108 .collect(); 175 )
109 VariantDataInner::Struct(fields)
110 } 176 }
111 ast::StructKind::Unit => VariantDataInner::Unit, 177 StructKind::Record
112 };
113 VariantData(inner)
114 }
115
116 pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> {
117 match &self.0 {
118 VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
119 _ => None,
120 } 178 }
179 ast::StructKind::Unit => StructKind::Unit,
121 } 180 }
122} 181}
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 0e961ca12..48ce8cd93 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -1,8 +1,8 @@
1//! A higher level attributes based on TokenTree, with also some shortcuts. 1//! A higher level attributes based on TokenTree, with also some shortcuts.
2 2
3use std::sync::Arc; 3use std::{ops, sync::Arc};
4 4
5use hir_expand::hygiene::Hygiene; 5use hir_expand::{either::Either, hygiene::Hygiene, AstId};
6use mbe::ast_to_token_tree; 6use mbe::ast_to_token_tree;
7use ra_cfg::CfgOptions; 7use ra_cfg::CfgOptions;
8use ra_syntax::{ 8use ra_syntax::{
@@ -11,7 +11,81 @@ use ra_syntax::{
11}; 11};
12use tt::Subtree; 12use tt::Subtree;
13 13
14use crate::path::Path; 14use crate::{
15 db::DefDatabase, path::Path, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup,
16};
17
18#[derive(Default, Debug, Clone, PartialEq, Eq)]
19pub struct Attrs {
20 entries: Option<Arc<[Attr]>>,
21}
22
23impl ops::Deref for Attrs {
24 type Target = [Attr];
25
26 fn deref(&self) -> &[Attr] {
27 match &self.entries {
28 Some(it) => &*it,
29 None => &[],
30 }
31 }
32}
33
34impl Attrs {
35 pub(crate) fn attrs_query(db: &impl DefDatabase, def: AttrDefId) -> Attrs {
36 match def {
37 AttrDefId::ModuleId(module) => {
38 let def_map = db.crate_def_map(module.krate);
39 let src = match def_map[module.module_id].declaration_source(db) {
40 Some(it) => it,
41 None => return Attrs::default(),
42 };
43 let hygiene = Hygiene::new(db, src.file_id);
44 Attr::from_attrs_owner(&src.value, &hygiene)
45 }
46 AttrDefId::StructFieldId(it) => {
47 let src = it.parent.child_source(db);
48 match &src.value[it.local_id] {
49 Either::A(_tuple) => Attrs::default(),
50 Either::B(record) => {
51 let hygiene = Hygiene::new(db, src.file_id);
52 Attr::from_attrs_owner(record, &hygiene)
53 }
54 }
55 }
56 AttrDefId::EnumVariantId(it) => {
57 let src = it.parent.child_source(db);
58 let hygiene = Hygiene::new(db, src.file_id);
59 Attr::from_attrs_owner(&src.value[it.local_id], &hygiene)
60 }
61 AttrDefId::AdtId(it) => match it {
62 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
63 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
64 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
65 },
66 AttrDefId::StaticId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
67 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
68 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
69 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
70 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db),
71 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db),
72 AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db),
73 }
74 }
75
76 pub fn has_atom(&self, atom: &str) -> bool {
77 self.iter().any(|it| it.is_simple_atom(atom))
78 }
79
80 pub fn find_string_value(&self, key: &str) -> Option<SmolStr> {
81 self.iter().filter(|attr| attr.is_simple_atom(key)).find_map(|attr| {
82 match attr.input.as_ref()? {
83 AttrInput::Literal(it) => Some(it.clone()),
84 _ => None,
85 }
86 })
87 }
88}
15 89
16#[derive(Debug, Clone, PartialEq, Eq)] 90#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct Attr { 91pub struct Attr {
@@ -43,13 +117,15 @@ impl Attr {
43 Some(Attr { path, input }) 117 Some(Attr { path, input })
44 } 118 }
45 119
46 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Option<Arc<[Attr]>> { 120 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
47 let mut attrs = owner.attrs().peekable(); 121 let mut attrs = owner.attrs().peekable();
48 if attrs.peek().is_none() { 122 let entries = if attrs.peek().is_none() {
49 // Avoid heap allocation 123 // Avoid heap allocation
50 return None; 124 None
51 } 125 } else {
52 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect()) 126 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
127 };
128 Attrs { entries }
53 } 129 }
54 130
55 pub fn is_simple_atom(&self, name: &str) -> bool { 131 pub fn is_simple_atom(&self, name: &str) -> bool {
@@ -82,3 +158,23 @@ impl Attr {
82 cfg_options.is_cfg_enabled(self.as_cfg()?) 158 cfg_options.is_cfg_enabled(self.as_cfg()?)
83 } 159 }
84} 160}
161
162fn attrs_from_ast<D, N>(src: AstId<N>, db: &D) -> Attrs
163where
164 N: ast::AttrsOwner,
165 D: DefDatabase,
166{
167 let hygiene = Hygiene::new(db, src.file_id());
168 Attr::from_attrs_owner(&src.to_node(db), &hygiene)
169}
170
171fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs
172where
173 T: HasSource,
174 T::Value: ast::AttrsOwner,
175 D: DefDatabase,
176{
177 let src = node.source(db);
178 let hygiene = Hygiene::new(db, src.file_id);
179 Attr::from_attrs_owner(&src.value, &hygiene)
180}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index dfb79a30a..225638b42 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -13,7 +13,7 @@ use ra_syntax::{ast, AstNode, AstPtr};
13use rustc_hash::FxHashMap; 13use rustc_hash::FxHashMap;
14 14
15use crate::{ 15use crate::{
16 db::DefDatabase2, 16 db::DefDatabase,
17 expr::{Expr, ExprId, Pat, PatId}, 17 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 18 nameres::CrateDefMap,
19 path::Path, 19 path::Path,
@@ -28,7 +28,7 @@ pub struct Expander {
28} 28}
29 29
30impl Expander { 30impl Expander {
31 pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander { 31 pub fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 32 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 33 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 34 Expander { crate_def_map, current_file_id, hygiene, module }
@@ -36,7 +36,7 @@ impl Expander {
36 36
37 fn enter_expand( 37 fn enter_expand(
38 &mut self, 38 &mut self,
39 db: &impl DefDatabase2, 39 db: &impl DefDatabase,
40 macro_call: ast::MacroCall, 40 macro_call: ast::MacroCall,
41 ) -> Option<(Mark, ast::Expr)> { 41 ) -> Option<(Mark, ast::Expr)> {
42 let ast_id = AstId::new( 42 let ast_id = AstId::new(
@@ -67,7 +67,7 @@ impl Expander {
67 None 67 None
68 } 68 }
69 69
70 fn exit(&mut self, db: &impl DefDatabase2, mark: Mark) { 70 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 71 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 72 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 73 std::mem::forget(mark);
@@ -81,7 +81,7 @@ impl Expander {
81 Path::from_src(path, &self.hygiene) 81 Path::from_src(path, &self.hygiene)
82 } 82 }
83 83
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> { 84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
85 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() 85 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros()
86 } 86 }
87} 87}
@@ -142,7 +142,7 @@ pub struct BodySourceMap {
142 142
143impl Body { 143impl Body {
144 pub(crate) fn body_with_source_map_query( 144 pub(crate) fn body_with_source_map_query(
145 db: &impl DefDatabase2, 145 db: &impl DefDatabase,
146 def: DefWithBodyId, 146 def: DefWithBodyId,
147 ) -> (Arc<Body>, Arc<BodySourceMap>) { 147 ) -> (Arc<Body>, Arc<BodySourceMap>) {
148 let mut params = None; 148 let mut params = None;
@@ -169,12 +169,12 @@ impl Body {
169 (Arc::new(body), Arc::new(source_map)) 169 (Arc::new(body), Arc::new(source_map))
170 } 170 }
171 171
172 pub(crate) fn body_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc<Body> { 172 pub(crate) fn body_query(db: &impl DefDatabase, def: DefWithBodyId) -> Arc<Body> {
173 db.body_with_source_map(def).0 173 db.body_with_source_map(def).0
174 } 174 }
175 175
176 fn new( 176 fn new(
177 db: &impl DefDatabase2, 177 db: &impl DefDatabase,
178 expander: Expander, 178 expander: Expander,
179 params: Option<ast::ParamList>, 179 params: Option<ast::ParamList>,
180 body: Option<ast::Expr>, 180 body: Option<ast::Expr>,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index d8e911aa5..f4640dfa4 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -17,7 +17,7 @@ use test_utils::tested_by;
17use crate::{ 17use crate::{
18 body::{Body, BodySourceMap, Expander, PatPtr}, 18 body::{Body, BodySourceMap, Expander, PatPtr},
19 builtin_type::{BuiltinFloat, BuiltinInt}, 19 builtin_type::{BuiltinFloat, BuiltinInt},
20 db::DefDatabase2, 20 db::DefDatabase,
21 expr::{ 21 expr::{
22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
@@ -28,7 +28,7 @@ use crate::{
28}; 28};
29 29
30pub(super) fn lower( 30pub(super) fn lower(
31 db: &impl DefDatabase2, 31 db: &impl DefDatabase,
32 expander: Expander, 32 expander: Expander,
33 params: Option<ast::ParamList>, 33 params: Option<ast::ParamList>,
34 body: Option<ast::Expr>, 34 body: Option<ast::Expr>,
@@ -57,7 +57,7 @@ struct ExprCollector<DB> {
57 57
58impl<'a, DB> ExprCollector<&'a DB> 58impl<'a, DB> ExprCollector<&'a DB>
59where 59where
60 DB: DefDatabase2, 60 DB: DefDatabase,
61{ 61{
62 fn collect( 62 fn collect(
63 mut self, 63 mut self,
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 58740b679..20d707bc4 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -7,7 +7,7 @@ use rustc_hash::FxHashMap;
7 7
8use crate::{ 8use crate::{
9 body::Body, 9 body::Body,
10 db::DefDatabase2, 10 db::DefDatabase,
11 expr::{Expr, ExprId, Pat, PatId, Statement}, 11 expr::{Expr, ExprId, Pat, PatId, Statement},
12 DefWithBodyId, 12 DefWithBodyId,
13}; 13};
@@ -45,7 +45,7 @@ pub struct ScopeData {
45} 45}
46 46
47impl ExprScopes { 47impl ExprScopes {
48 pub(crate) fn expr_scopes_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc<ExprScopes> { 48 pub(crate) fn expr_scopes_query(db: &impl DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
49 let body = db.body(def); 49 let body = db.body(def);
50 Arc::new(ExprScopes::new(&*body)) 50 Arc::new(ExprScopes::new(&*body))
51 } 51 }
@@ -176,7 +176,7 @@ mod tests {
176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
177 use test_utils::{assert_eq_text, covers, extract_offset}; 177 use test_utils::{assert_eq_text, covers, extract_offset};
178 178
179 use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId}; 179 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId};
180 180
181 fn find_function(db: &TestDB, file_id: FileId) -> FunctionId { 181 fn find_function(db: &TestDB, file_id: FileId) -> FunctionId {
182 let krate = db.test_crate(); 182 let krate = db.test_crate();
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
new file mode 100644
index 000000000..f0b3e198a
--- /dev/null
+++ b/crates/ra_hir_def/src/data.rs
@@ -0,0 +1,217 @@
1//! Contains basic data about various HIR declarations.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{self, AsName, Name},
7 AstId,
8};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
10
11use crate::{
12 db::DefDatabase,
13 type_ref::{Mutability, TypeRef},
14 AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource,
15 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
16};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct FunctionData {
20 pub name: Name,
21 pub params: Vec<TypeRef>,
22 pub ret_type: TypeRef,
23 /// True if the first param is `self`. This is relevant to decide whether this
24 /// can be called as a method.
25 pub has_self_param: bool,
26}
27
28impl FunctionData {
29 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
30 let src = func.lookup(db).source(db);
31 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
32 let mut params = Vec::new();
33 let mut has_self_param = false;
34 if let Some(param_list) = src.value.param_list() {
35 if let Some(self_param) = param_list.self_param() {
36 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
37 TypeRef::from_ast(type_ref)
38 } else {
39 let self_type = TypeRef::Path(name::SELF_TYPE.into());
40 match self_param.kind() {
41 ast::SelfParamKind::Owned => self_type,
42 ast::SelfParamKind::Ref => {
43 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
44 }
45 ast::SelfParamKind::MutRef => {
46 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
47 }
48 }
49 };
50 params.push(self_type);
51 has_self_param = true;
52 }
53 for param in param_list.params() {
54 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
55 params.push(type_ref);
56 }
57 }
58 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
59 TypeRef::from_ast(type_ref)
60 } else {
61 TypeRef::unit()
62 };
63
64 let sig = FunctionData { name, params, ret_type, has_self_param };
65 Arc::new(sig)
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct TypeAliasData {
71 pub name: Name,
72 pub type_ref: Option<TypeRef>,
73}
74
75impl TypeAliasData {
76 pub(crate) fn type_alias_data_query(
77 db: &impl DefDatabase,
78 typ: TypeAliasId,
79 ) -> Arc<TypeAliasData> {
80 let node = typ.lookup(db).source(db).value;
81 let name = node.name().map_or_else(Name::missing, |n| n.as_name());
82 let type_ref = node.type_ref().map(TypeRef::from_ast);
83 Arc::new(TypeAliasData { name, type_ref })
84 }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct TraitData {
89 pub name: Option<Name>,
90 pub items: Vec<AssocItemId>,
91 pub auto: bool,
92}
93
94impl TraitData {
95 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> {
96 let src = tr.source(db);
97 let name = src.value.name().map(|n| n.as_name());
98 let auto = src.value.is_auto();
99 let ast_id_map = db.ast_id_map(src.file_id);
100 let items = if let Some(item_list) = src.value.item_list() {
101 item_list
102 .impl_items()
103 .map(|item_node| match item_node {
104 ast::ImplItem::FnDef(it) => FunctionLoc {
105 container: ContainerId::TraitId(tr),
106 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
107 }
108 .intern(db)
109 .into(),
110 ast::ImplItem::ConstDef(it) => ConstLoc {
111 container: ContainerId::TraitId(tr),
112 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
113 }
114 .intern(db)
115 .into(),
116 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
117 container: ContainerId::TraitId(tr),
118 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
119 }
120 .intern(db)
121 .into(),
122 })
123 .collect()
124 } else {
125 Vec::new()
126 };
127 Arc::new(TraitData { name, items, auto })
128 }
129
130 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
131 self.items.iter().filter_map(|item| match item {
132 AssocItemId::TypeAliasId(t) => Some(*t),
133 _ => None,
134 })
135 }
136}
137
138#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct ImplData {
140 pub target_trait: Option<TypeRef>,
141 pub target_type: TypeRef,
142 pub items: Vec<AssocItemId>,
143 pub is_negative: bool,
144}
145
146impl ImplData {
147 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> {
148 let src = id.source(db);
149 let items = db.ast_id_map(src.file_id);
150
151 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
152 let target_type = TypeRef::from_ast_opt(src.value.target_type());
153 let is_negative = src.value.is_negative();
154
155 let items = if let Some(item_list) = src.value.item_list() {
156 item_list
157 .impl_items()
158 .map(|item_node| match item_node {
159 ast::ImplItem::FnDef(it) => {
160 let def = FunctionLoc {
161 container: ContainerId::ImplId(id),
162 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
163 }
164 .intern(db);
165 def.into()
166 }
167 ast::ImplItem::ConstDef(it) => {
168 let def = ConstLoc {
169 container: ContainerId::ImplId(id),
170 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
171 }
172 .intern(db);
173 def.into()
174 }
175 ast::ImplItem::TypeAliasDef(it) => {
176 let def = TypeAliasLoc {
177 container: ContainerId::ImplId(id),
178 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
179 }
180 .intern(db);
181 def.into()
182 }
183 })
184 .collect()
185 } else {
186 Vec::new()
187 };
188
189 let res = ImplData { target_trait, target_type, items, is_negative };
190 Arc::new(res)
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct ConstData {
196 pub name: Option<Name>,
197 pub type_ref: TypeRef,
198}
199
200impl ConstData {
201 pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> {
202 let node = konst.lookup(db).source(db).value;
203 const_data_for(&node)
204 }
205
206 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
207 let node = konst.source(db).value;
208 const_data_for(&node)
209 }
210}
211
212fn const_data_for<N: NameOwner + TypeAscriptionOwner>(node: &N) -> Arc<ConstData> {
213 let name = node.name().map(|n| n.as_name());
214 let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
215 let sig = ConstData { name, type_ref };
216 Arc::new(sig)
217}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 844f8bbe8..7fec2e8c0 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -3,43 +3,46 @@ use std::sync::Arc;
3 3
4use hir_expand::{db::AstDatabase, HirFileId}; 4use hir_expand::{db::AstDatabase, HirFileId};
5use ra_db::{salsa, CrateId, SourceDatabase}; 5use ra_db::{salsa, CrateId, SourceDatabase};
6use ra_syntax::ast; 6use ra_syntax::{ast, SmolStr};
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
10 attr::Attrs,
10 body::{scope::ExprScopes, Body, BodySourceMap}, 11 body::{scope::ExprScopes, Body, BodySourceMap},
12 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData},
13 docs::Documentation,
11 generics::GenericParams, 14 generics::GenericParams,
12 impls::ImplData, 15 lang_item::{LangItemTarget, LangItems},
13 nameres::{ 16 nameres::{
14 raw::{ImportSourceMap, RawItems}, 17 raw::{ImportSourceMap, RawItems},
15 CrateDefMap, 18 CrateDefMap,
16 }, 19 },
17 traits::TraitData, 20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
18 DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId, 21 ImplId, ItemLoc, ModuleId, StaticId, StructOrUnionId, TraitId, TypeAliasId, TypeAliasLoc,
19}; 22};
20 23
21#[salsa::query_group(InternDatabaseStorage)] 24#[salsa::query_group(InternDatabaseStorage)]
22pub trait InternDatabase: SourceDatabase { 25pub trait InternDatabase: SourceDatabase {
23 #[salsa::interned] 26 #[salsa::interned]
24 fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId; 27 fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
25 #[salsa::interned] 28 #[salsa::interned]
26 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId; 29 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> StructOrUnionId;
27 #[salsa::interned] 30 #[salsa::interned]
28 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId; 31 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId;
29 #[salsa::interned] 32 #[salsa::interned]
30 fn intern_const(&self, loc: crate::ConstLoc) -> crate::ConstId; 33 fn intern_const(&self, loc: ConstLoc) -> ConstId;
31 #[salsa::interned] 34 #[salsa::interned]
32 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId; 35 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> StaticId;
33 #[salsa::interned] 36 #[salsa::interned]
34 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId; 37 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId;
35 #[salsa::interned] 38 #[salsa::interned]
36 fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId; 39 fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
37 #[salsa::interned] 40 #[salsa::interned]
38 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId; 41 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> ImplId;
39} 42}
40 43
41#[salsa::query_group(DefDatabase2Storage)] 44#[salsa::query_group(DefDatabaseStorage)]
42pub trait DefDatabase2: InternDatabase + AstDatabase { 45pub trait DefDatabase: InternDatabase + AstDatabase {
43 #[salsa::invoke(RawItems::raw_items_with_source_map_query)] 46 #[salsa::invoke(RawItems::raw_items_with_source_map_query)]
44 fn raw_items_with_source_map( 47 fn raw_items_with_source_map(
45 &self, 48 &self,
@@ -64,6 +67,18 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
64 #[salsa::invoke(TraitData::trait_data_query)] 67 #[salsa::invoke(TraitData::trait_data_query)]
65 fn trait_data(&self, e: TraitId) -> Arc<TraitData>; 68 fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
66 69
70 #[salsa::invoke(TypeAliasData::type_alias_data_query)]
71 fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
72
73 #[salsa::invoke(FunctionData::fn_data_query)]
74 fn function_data(&self, func: FunctionId) -> Arc<FunctionData>;
75
76 #[salsa::invoke(ConstData::const_data_query)]
77 fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
78
79 #[salsa::invoke(ConstData::static_data_query)]
80 fn static_data(&self, konst: StaticId) -> Arc<ConstData>;
81
67 #[salsa::invoke(Body::body_with_source_map_query)] 82 #[salsa::invoke(Body::body_with_source_map_query)]
68 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 83 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
69 84
@@ -75,4 +90,21 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
75 90
76 #[salsa::invoke(GenericParams::generic_params_query)] 91 #[salsa::invoke(GenericParams::generic_params_query)]
77 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; 92 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
93
94 #[salsa::invoke(Attrs::attrs_query)]
95 fn attrs(&self, def: AttrDefId) -> Attrs;
96
97 #[salsa::invoke(LangItems::module_lang_items_query)]
98 fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>;
99
100 #[salsa::invoke(LangItems::crate_lang_items_query)]
101 fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
102
103 #[salsa::invoke(LangItems::lang_item_query)]
104 fn lang_item(&self, start_crate: CrateId, item: SmolStr) -> Option<LangItemTarget>;
105
106 // FIXME(https://github.com/rust-analyzer/rust-analyzer/issues/2148#issuecomment-550519102)
107 // Remove this query completely, in favor of `Attrs::docs` method
108 #[salsa::invoke(Documentation::documentation_query)]
109 fn documentation(&self, def: AttrDefId) -> Option<Documentation>;
78} 110}
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
new file mode 100644
index 000000000..69846fd1b
--- /dev/null
+++ b/crates/ra_hir_def/src/docs.rs
@@ -0,0 +1,68 @@
1//! FIXME: write short doc here
2
3use std::sync::Arc;
4
5use hir_expand::either::Either;
6use ra_syntax::ast;
7
8use crate::{db::DefDatabase, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup};
9
10/// Holds documentation
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Documentation(Arc<str>);
13
14impl Into<String> for Documentation {
15 fn into(self) -> String {
16 self.as_str().to_owned()
17 }
18}
19
20impl Documentation {
21 fn new(s: &str) -> Documentation {
22 Documentation(s.into())
23 }
24
25 pub fn as_str(&self) -> &str {
26 &*self.0
27 }
28
29 pub(crate) fn documentation_query(
30 db: &impl DefDatabase,
31 def: AttrDefId,
32 ) -> Option<Documentation> {
33 match def {
34 AttrDefId::ModuleId(module) => {
35 let def_map = db.crate_def_map(module.krate);
36 let src = def_map[module.module_id].declaration_source(db)?;
37 docs_from_ast(&src.value)
38 }
39 AttrDefId::StructFieldId(it) => {
40 let src = it.parent.child_source(db);
41 match &src.value[it.local_id] {
42 Either::A(_tuple) => None,
43 Either::B(record) => docs_from_ast(record),
44 }
45 }
46 AttrDefId::AdtId(it) => match it {
47 AdtId::StructId(it) => docs_from_ast(&it.0.source(db).value),
48 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value),
49 AdtId::UnionId(it) => docs_from_ast(&it.0.source(db).value),
50 },
51 AttrDefId::EnumVariantId(it) => {
52 let src = it.parent.child_source(db);
53 docs_from_ast(&src.value[it.local_id])
54 }
55 AttrDefId::StaticId(it) => docs_from_ast(&it.source(db).value),
56 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value),
57 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)),
58 AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value),
59 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value),
60 AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value),
61 AttrDefId::ImplId(_) => None,
62 }
63 }
64}
65
66pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
67 node.doc_comment_text().map(|it| Documentation::new(&it))
68}
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 9e2e4c3cc..015fe772e 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -8,7 +8,7 @@ use hir_expand::name::{self, AsName, Name};
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 9
10use crate::{ 10use crate::{
11 db::DefDatabase2, 11 db::DefDatabase,
12 type_ref::{TypeBound, TypeRef}, 12 type_ref::{TypeBound, TypeRef},
13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup, 13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup,
14}; 14};
@@ -42,7 +42,7 @@ pub struct WherePredicate {
42 42
43impl GenericParams { 43impl GenericParams {
44 pub(crate) fn generic_params_query( 44 pub(crate) fn generic_params_query(
45 db: &impl DefDatabase2, 45 db: &impl DefDatabase,
46 def: GenericDefId, 46 def: GenericDefId,
47 ) -> Arc<GenericParams> { 47 ) -> Arc<GenericParams> {
48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); 48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it));
@@ -50,7 +50,7 @@ impl GenericParams {
50 } 50 }
51 51
52 fn new( 52 fn new(
53 db: &impl DefDatabase2, 53 db: &impl DefDatabase,
54 def: GenericDefId, 54 def: GenericDefId,
55 parent_params: Option<Arc<GenericParams>>, 55 parent_params: Option<Arc<GenericParams>>,
56 ) -> GenericParams { 56 ) -> GenericParams {
@@ -168,7 +168,7 @@ impl GenericParams {
168 } 168 }
169} 169}
170 170
171fn parent_generic_def(db: &impl DefDatabase2, def: GenericDefId) -> Option<GenericDefId> { 171fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
172 let container = match def { 172 let container = match def {
173 GenericDefId::FunctionId(it) => it.lookup(db).container, 173 GenericDefId::FunctionId(it) => it.lookup(db).container,
174 GenericDefId::TypeAliasId(it) => it.lookup(db).container, 174 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs
deleted file mode 100644
index 750a869f2..000000000
--- a/crates/ra_hir_def/src/impls.rs
+++ /dev/null
@@ -1,86 +0,0 @@
1//! Defines hir-level representation of impls.
2//!
3//! The handling is similar, but is not quite the same as for other items,
4//! because `impl`s don't have names.
5
6use std::sync::Arc;
7
8use hir_expand::AstId;
9use ra_syntax::ast;
10
11use crate::{
12 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
13 FunctionLoc, ImplId, Intern, TypeAliasLoc,
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ImplData {
18 target_trait: Option<TypeRef>,
19 target_type: TypeRef,
20 items: Vec<AssocItemId>,
21 negative: bool,
22}
23
24impl ImplData {
25 pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
26 let src = id.source(db);
27 let items = db.ast_id_map(src.file_id);
28
29 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
30 let target_type = TypeRef::from_ast_opt(src.value.target_type());
31 let negative = src.value.is_negative();
32
33 let items = if let Some(item_list) = src.value.item_list() {
34 item_list
35 .impl_items()
36 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => {
38 let def = FunctionLoc {
39 container: ContainerId::ImplId(id),
40 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
41 }
42 .intern(db);
43 def.into()
44 }
45 ast::ImplItem::ConstDef(it) => {
46 let def = ConstLoc {
47 container: ContainerId::ImplId(id),
48 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
49 }
50 .intern(db);
51 def.into()
52 }
53 ast::ImplItem::TypeAliasDef(it) => {
54 let def = TypeAliasLoc {
55 container: ContainerId::ImplId(id),
56 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
57 }
58 .intern(db);
59 def.into()
60 }
61 })
62 .collect()
63 } else {
64 Vec::new()
65 };
66
67 let res = ImplData { target_trait, target_type, items, negative };
68 Arc::new(res)
69 }
70
71 pub fn target_trait(&self) -> Option<&TypeRef> {
72 self.target_trait.as_ref()