aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-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
73 files changed, 1995 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()
73 }
74
75 pub fn target_type(&self) -> &TypeRef {
76 &self.target_type
77 }
78
79 pub fn items(&self) -> &[AssocItemId] {
80 &self.items
81 }
82
83 pub fn is_negative(&self) -> bool {
84 self.negative
85 }
86}
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
new file mode 100644
index 000000000..df951c533
--- /dev/null
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -0,0 +1,120 @@
1//! Collects lang items: items marked with `#[lang = "..."]` attribute.
2//!
3//! This attribute to tell the compiler about semi built-in std library
4//! features, such as Fn family of traits.
5use std::sync::Arc;
6
7use ra_syntax::SmolStr;
8use rustc_hash::FxHashMap;
9
10use crate::{
11 db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, ModuleId,
12 StaticId, StructId, TraitId,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum LangItemTarget {
17 EnumId(EnumId),
18 FunctionId(FunctionId),
19 ImplBlockId(ImplId),
20 StaticId(StaticId),
21 StructId(StructId),
22 TraitId(TraitId),
23}
24
25#[derive(Default, Debug, Clone, PartialEq, Eq)]
26pub struct LangItems {
27 items: FxHashMap<SmolStr, LangItemTarget>,
28}
29
30impl LangItems {
31 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> {
32 self.items.get(item)
33 }
34
35 /// Salsa query. This will look for lang items in a specific crate.
36 pub(crate) fn crate_lang_items_query(db: &impl DefDatabase, krate: CrateId) -> Arc<LangItems> {
37 let mut lang_items = LangItems::default();
38
39 let crate_def_map = db.crate_def_map(krate);
40
41 crate_def_map
42 .modules()
43 .filter_map(|module_id| db.module_lang_items(ModuleId { krate, module_id }))
44 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v))));
45
46 Arc::new(lang_items)
47 }
48
49 pub(crate) fn module_lang_items_query(
50 db: &impl DefDatabase,
51 module: ModuleId,
52 ) -> Option<Arc<LangItems>> {
53 let mut lang_items = LangItems::default();
54 lang_items.collect_lang_items(db, module);
55 if lang_items.items.is_empty() {
56 None
57 } else {
58 Some(Arc::new(lang_items))
59 }
60 }
61
62 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
63 /// traversing its dependencies.
64 pub(crate) fn lang_item_query(
65 db: &impl DefDatabase,
66 start_crate: CrateId,
67 item: SmolStr,
68 ) -> Option<LangItemTarget> {
69 let lang_items = db.crate_lang_items(start_crate);
70 let start_crate_target = lang_items.items.get(&item);
71 if let Some(target) = start_crate_target {
72 return Some(*target);
73 }
74 db.crate_graph()
75 .dependencies(start_crate)
76 .find_map(|dep| db.lang_item(dep.crate_id, item.clone()))
77 }
78
79 fn collect_lang_items(&mut self, db: &impl DefDatabase, module: ModuleId) {
80 // Look for impl targets
81 let def_map = db.crate_def_map(module.krate);
82 let module_data = &def_map[module.module_id];
83 for &impl_block in module_data.impls.iter() {
84 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
85 }
86
87 for def in module_data.scope.declarations() {
88 match def {
89 ModuleDefId::TraitId(trait_) => {
90 self.collect_lang_item(db, trait_, LangItemTarget::TraitId)
91 }
92 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
93 self.collect_lang_item(db, e, LangItemTarget::EnumId)
94 }
95 ModuleDefId::AdtId(AdtId::StructId(s)) => {
96 self.collect_lang_item(db, s, LangItemTarget::StructId)
97 }
98 ModuleDefId::FunctionId(f) => {
99 self.collect_lang_item(db, f, LangItemTarget::FunctionId)
100 }
101 ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::StaticId),
102 _ => {}
103 }
104 }
105 }
106
107 fn collect_lang_item<T>(
108 &mut self,
109 db: &impl DefDatabase,
110 item: T,
111 constructor: fn(T) -> LangItemTarget,
112 ) where
113 T: Into<AttrDefId> + Copy,
114 {
115 let attrs = db.attrs(item.into());
116 if let Some(lang_item_name) = attrs.find_string_value("lang") {
117 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
118 }
119 }
120}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index d579f5c7e..1d195d65d 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,103 +13,48 @@ pub mod path;
13pub mod type_ref; 13pub mod type_ref;
14pub mod builtin_type; 14pub mod builtin_type;
15pub mod adt; 15pub mod adt;
16pub mod impls;
17pub mod diagnostics; 16pub mod diagnostics;
18pub mod expr; 17pub mod expr;
19pub mod body; 18pub mod body;
20pub mod generics; 19pub mod generics;
21pub mod traits;
22pub mod resolver; 20pub mod resolver;
21pub mod data;
22pub mod lang_item;
23pub mod docs;
24pub mod per_ns;
25
26mod trace;
27mod nameres;
23 28
24#[cfg(test)] 29#[cfg(test)]
25mod test_db; 30mod test_db;
26#[cfg(test)] 31#[cfg(test)]
27mod marks; 32mod marks;
28 33
29// FIXME: this should be private
30pub mod nameres;
31
32use std::hash::{Hash, Hasher}; 34use std::hash::{Hash, Hasher};
33 35
34use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, Source}; 36use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source};
35use ra_arena::{impl_arena_id, RawId}; 37use ra_arena::{impl_arena_id, map::ArenaMap, RawId};
36use ra_db::{salsa, CrateId, FileId}; 38use ra_db::{salsa, CrateId};
37use ra_syntax::{ast, AstNode, SyntaxNode}; 39use ra_syntax::{ast, AstNode};
38 40
39use crate::{builtin_type::BuiltinType, db::InternDatabase}; 41use crate::{builtin_type::BuiltinType, db::InternDatabase};
40 42
41pub enum ModuleSource { 43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
42 SourceFile(ast::SourceFile), 44pub struct LocalImportId(RawId);
43 Module(ast::Module), 45impl_arena_id!(LocalImportId);
44}
45
46impl ModuleSource {
47 pub fn new(
48 db: &impl db::DefDatabase2,
49 file_id: Option<FileId>,
50 decl_id: Option<AstId<ast::Module>>,
51 ) -> ModuleSource {
52 match (file_id, decl_id) {
53 (Some(file_id), _) => {
54 let source_file = db.parse(file_id).tree();
55 ModuleSource::SourceFile(source_file)
56 }
57 (None, Some(item_id)) => {
58 let module = item_id.to_node(db);
59 assert!(module.item_list().is_some(), "expected inline module");
60 ModuleSource::Module(module)
61 }
62 (None, None) => panic!(),
63 }
64 }
65
66 // FIXME: this methods do not belong here
67 pub fn from_position(
68 db: &impl db::DefDatabase2,
69 position: ra_db::FilePosition,
70 ) -> ModuleSource {
71 let parse = db.parse(position.file_id);
72 match &ra_syntax::algo::find_node_at_offset::<ast::Module>(
73 parse.tree().syntax(),
74 position.offset,
75 ) {
76 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
77 _ => {
78 let source_file = parse.tree();
79 ModuleSource::SourceFile(source_file)
80 }
81 }
82 }
83
84 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource {
85 if let Some(m) =
86 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
87 {
88 ModuleSource::Module(m)
89 } else {
90 let file_id = child.file_id.original_file(db);
91 let source_file = db.parse(file_id).tree();
92 ModuleSource::SourceFile(source_file)
93 }
94 }
95
96 pub fn from_file_id(db: &impl db::DefDatabase2, file_id: FileId) -> ModuleSource {
97 let source_file = db.parse(file_id).tree();
98 ModuleSource::SourceFile(source_file)
99 }
100}
101 46
102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
103pub struct ModuleId { 48pub struct ModuleId {
104 pub krate: CrateId, 49 pub krate: CrateId,
105 pub module_id: CrateModuleId, 50 pub module_id: LocalModuleId,
106} 51}
107 52
108/// An ID of a module, **local** to a specific crate 53/// An ID of a module, **local** to a specific crate
109// FIXME: rename to `LocalModuleId`. 54// FIXME: rename to `LocalModuleId`.
110#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 55#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
111pub struct CrateModuleId(RawId); 56pub struct LocalModuleId(RawId);
112impl_arena_id!(CrateModuleId); 57impl_arena_id!(LocalModuleId);
113 58
114macro_rules! impl_intern_key { 59macro_rules! impl_intern_key {
115 ($name:ident) => { 60 ($name:ident) => {
@@ -208,14 +153,14 @@ pub struct FunctionLoc {
208 153
209impl Intern for FunctionLoc { 154impl Intern for FunctionLoc {
210 type ID = FunctionId; 155 type ID = FunctionId;
211 fn intern(self, db: &impl db::DefDatabase2) -> FunctionId { 156 fn intern(self, db: &impl db::DefDatabase) -> FunctionId {
212 db.intern_function(self) 157 db.intern_function(self)
213 } 158 }
214} 159}
215 160
216impl Lookup for FunctionId { 161impl Lookup for FunctionId {
217 type Data = FunctionLoc; 162 type Data = FunctionLoc;
218 fn lookup(&self, db: &impl db::DefDatabase2) -> FunctionLoc { 163 fn lookup(&self, db: &impl db::DefDatabase) -> FunctionLoc {
219 db.lookup_intern_function(*self) 164 db.lookup_intern_function(*self)
220 } 165 }
221} 166}
@@ -279,8 +224,8 @@ pub enum VariantId {
279 224
280#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 225#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
281pub struct StructFieldId { 226pub struct StructFieldId {
282 parent: VariantId, 227 pub parent: VariantId,
283 local_id: LocalStructFieldId, 228 pub local_id: LocalStructFieldId,
284} 229}
285 230
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -298,14 +243,14 @@ pub struct ConstLoc {
298 243
299impl Intern for ConstLoc { 244impl Intern for ConstLoc {
300 type ID = ConstId; 245 type ID = ConstId;
301 fn intern(self, db: &impl db::DefDatabase2) -> ConstId { 246 fn intern(self, db: &impl db::DefDatabase) -> ConstId {
302 db.intern_const(self) 247 db.intern_const(self)
303 } 248 }
304} 249}
305 250
306impl Lookup for ConstId { 251impl Lookup for ConstId {
307 type Data = ConstLoc; 252 type Data = ConstLoc;
308 fn lookup(&self, db: &impl db::DefDatabase2) -> ConstLoc { 253 fn lookup(&self, db: &impl db::DefDatabase) -> ConstLoc {
309 db.lookup_intern_const(*self) 254 db.lookup_intern_const(*self)
310 } 255 }
311} 256}
@@ -346,14 +291,14 @@ pub struct TypeAliasLoc {
346 291
347impl Intern for TypeAliasLoc { 292impl Intern for TypeAliasLoc {
348 type ID = TypeAliasId; 293 type ID = TypeAliasId;
349 fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId { 294 fn intern(self, db: &impl db::DefDatabase) -> TypeAliasId {
350 db.intern_type_alias(self) 295 db.intern_type_alias(self)
351 } 296 }
352} 297}
353 298
354impl Lookup for TypeAliasId { 299impl Lookup for TypeAliasId {
355 type Data = TypeAliasLoc; 300 type Data = TypeAliasLoc;
356 fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc { 301 fn lookup(&self, db: &impl db::DefDatabase) -> TypeAliasLoc {
357 db.lookup_intern_type_alias(*self) 302 db.lookup_intern_type_alias(*self)
358 } 303 }
359} 304}
@@ -476,22 +421,51 @@ impl_froms!(
476 ConstId 421 ConstId
477); 422);
478 423
424#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
425pub enum AttrDefId {
426 ModuleId(ModuleId),
427 StructFieldId(StructFieldId),
428 AdtId(AdtId),
429 FunctionId(FunctionId),
430 EnumVariantId(EnumVariantId),
431 StaticId(StaticId),
432 ConstId(ConstId),
433 TraitId(TraitId),
434 TypeAliasId(TypeAliasId),
435 MacroDefId(MacroDefId),
436 ImplId(ImplId),
437}
438
439impl_froms!(
440 AttrDefId: ModuleId,
441 StructFieldId,
442 AdtId(StructId, EnumId, UnionId),
443 EnumVariantId,
444 StaticId,
445 ConstId,
446 FunctionId,
447 TraitId,
448 TypeAliasId,
449 MacroDefId,
450 ImplId
451);
452
479trait Intern { 453trait Intern {
480 type ID; 454 type ID;
481 fn intern(self, db: &impl db::DefDatabase2) -> Self::ID; 455 fn intern(self, db: &impl db::DefDatabase) -> Self::ID;
482} 456}
483 457
484pub trait Lookup { 458pub trait Lookup {
485 type Data; 459 type Data;
486 fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data; 460 fn lookup(&self, db: &impl db::DefDatabase) -> Self::Data;
487} 461}
488 462
489pub trait HasModule { 463pub trait HasModule {
490 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId; 464 fn module(&self, db: &impl db::DefDatabase) -> ModuleId;
491} 465}
492 466
493impl HasModule for FunctionLoc { 467impl HasModule for FunctionLoc {
494 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 468 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
495 match self.container { 469 match self.container {
496 ContainerId::ModuleId(it) => it, 470 ContainerId::ModuleId(it) => it,
497 ContainerId::ImplId(it) => it.module(db), 471 ContainerId::ImplId(it) => it.module(db),
@@ -501,7 +475,7 @@ impl HasModule for FunctionLoc {
501} 475}
502 476
503impl HasModule for TypeAliasLoc { 477impl HasModule for TypeAliasLoc {
504 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 478 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
505 match self.container { 479 match self.container {
506 ContainerId::ModuleId(it) => it, 480 ContainerId::ModuleId(it) => it,
507 ContainerId::ImplId(it) => it.module(db), 481 ContainerId::ImplId(it) => it.module(db),
@@ -511,7 +485,7 @@ impl HasModule for TypeAliasLoc {
511} 485}
512 486
513impl HasModule for ConstLoc { 487impl HasModule for ConstLoc {
514 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 488 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
515 match self.container { 489 match self.container {
516 ContainerId::ModuleId(it) => it, 490 ContainerId::ModuleId(it) => it,
517 ContainerId::ImplId(it) => it.module(db), 491 ContainerId::ImplId(it) => it.module(db),
@@ -522,13 +496,13 @@ impl HasModule for ConstLoc {
522 496
523pub trait HasSource { 497pub trait HasSource {
524 type Value; 498 type Value;
525 fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>; 499 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>;
526} 500}
527 501
528impl HasSource for FunctionLoc { 502impl HasSource for FunctionLoc {
529 type Value = ast::FnDef; 503 type Value = ast::FnDef;
530 504
531 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::FnDef> { 505 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::FnDef> {
532 let node = self.ast_id.to_node(db); 506 let node = self.ast_id.to_node(db);
533 Source::new(self.ast_id.file_id(), node) 507 Source::new(self.ast_id.file_id(), node)
534 } 508 }
@@ -537,7 +511,7 @@ impl HasSource for FunctionLoc {
537impl HasSource for TypeAliasLoc { 511impl HasSource for TypeAliasLoc {
538 type Value = ast::TypeAliasDef; 512 type Value = ast::TypeAliasDef;
539 513
540 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::TypeAliasDef> { 514 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::TypeAliasDef> {
541 let node = self.ast_id.to_node(db); 515 let node = self.ast_id.to_node(db);
542 Source::new(self.ast_id.file_id(), node) 516 Source::new(self.ast_id.file_id(), node)
543 } 517 }
@@ -546,8 +520,17 @@ impl HasSource for TypeAliasLoc {
546impl HasSource for ConstLoc { 520impl HasSource for ConstLoc {
547 type Value = ast::ConstDef; 521 type Value = ast::ConstDef;
548 522
549 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::ConstDef> { 523 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::ConstDef> {
550 let node = self.ast_id.to_node(db); 524 let node = self.ast_id.to_node(db);
551 Source::new(self.ast_id.file_id(), node) 525 Source::new(self.ast_id.file_id(), node)
552 } 526 }
553} 527}
528
529pub trait HasChildSource {
530 type ChildId;
531 type Value;
532 fn child_source(
533 &self,
534 db: &impl db::DefDatabase,
535 ) -> Source<ArenaMap<Self::ChildId, Self::Value>>;
536}
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index c01e020ef..3b2e99647 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -47,8 +47,7 @@
47//! path and, upon success, we run macro expansion and "collect module" phase on 47//! path and, upon success, we run macro expansion and "collect module" phase on
48//! the result 48//! the result
49 49
50pub mod raw; 50pub(crate) mod raw;
51pub mod per_ns;
52mod collector; 51mod collector;
53mod mod_resolution; 52mod mod_resolution;
54mod path_resolution; 53mod path_resolution;
@@ -58,7 +57,10 @@ mod tests;
58 57
59use std::sync::Arc; 58use std::sync::Arc;
60 59
61use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; 60use hir_expand::{
61 ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId,
62 Source,
63};
62use once_cell::sync::Lazy; 64use once_cell::sync::Lazy;
63use ra_arena::Arena; 65use ra_arena::Arena;
64use ra_db::{CrateId, Edition, FileId}; 66use ra_db::{CrateId, Edition, FileId};
@@ -68,12 +70,11 @@ use rustc_hash::{FxHashMap, FxHashSet};
68 70
69use crate::{ 71use crate::{
70 builtin_type::BuiltinType, 72 builtin_type::BuiltinType,
71 db::DefDatabase2, 73 db::DefDatabase,
72 nameres::{ 74 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
73 diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId,
74 },
75 path::Path, 75 path::Path,
76 AstId, CrateModuleId, FunctionId, ImplId, ModuleDefId, ModuleId, TraitId, 76 per_ns::PerNs,
77 AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
77}; 78};
78 79
79/// Contains all top-level defs from a macro-expanded crate 80/// Contains all top-level defs from a macro-expanded crate
@@ -86,8 +87,8 @@ pub struct CrateDefMap {
86 /// a dependency (`std` or `core`). 87 /// a dependency (`std` or `core`).
87 prelude: Option<ModuleId>, 88 prelude: Option<ModuleId>,
88 extern_prelude: FxHashMap<Name, ModuleDefId>, 89 extern_prelude: FxHashMap<Name, ModuleDefId>,
89 root: CrateModuleId, 90 root: LocalModuleId,
90 modules: Arena<CrateModuleId, ModuleData>, 91 modules: Arena<LocalModuleId, ModuleData>,
91 92
92 /// Some macros are not well-behavior, which leads to infinite loop 93 /// Some macros are not well-behavior, which leads to infinite loop
93 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } 94 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
@@ -104,24 +105,27 @@ pub struct CrateDefMap {
104 diagnostics: Vec<DefDiagnostic>, 105 diagnostics: Vec<DefDiagnostic>,
105} 106}
106 107
107impl std::ops::Index<CrateModuleId> for CrateDefMap { 108impl std::ops::Index<LocalModuleId> for CrateDefMap {
108 type Output = ModuleData; 109 type Output = ModuleData;
109 fn index(&self, id: CrateModuleId) -> &ModuleData { 110 fn index(&self, id: LocalModuleId) -> &ModuleData {
110 &self.modules[id] 111 &self.modules[id]
111 } 112 }
112} 113}
113 114
114#[derive(Default, Debug, PartialEq, Eq)] 115#[derive(Default, Debug, PartialEq, Eq)]
115pub struct ModuleData { 116pub struct ModuleData {
116 pub parent: Option<CrateModuleId>, 117 pub parent: Option<LocalModuleId>,
117 pub children: FxHashMap<Name, CrateModuleId>, 118 pub children: FxHashMap<Name, LocalModuleId>,
118 pub scope: ModuleScope, 119 pub scope: ModuleScope,
120
121 // FIXME: these can't be both null, we need a three-state enum here.
119 /// None for root 122 /// None for root
120 pub declaration: Option<AstId<ast::Module>>, 123 pub declaration: Option<AstId<ast::Module>>,
121 /// None for inline modules. 124 /// None for inline modules.
122 /// 125 ///
123 /// Note that non-inline modules, by definition, live inside non-macro file. 126 /// Note that non-inline modules, by definition, live inside non-macro file.
124 pub definition: Option<FileId>, 127 pub definition: Option<FileId>,
128
125 pub impls: Vec<ImplId>, 129 pub impls: Vec<ImplId>,
126} 130}
127 131
@@ -207,21 +211,21 @@ pub struct Resolution {
207 /// None for unresolved 211 /// None for unresolved
208 pub def: PerNs, 212 pub def: PerNs,
209 /// ident by which this is imported into local scope. 213 /// ident by which this is imported into local scope.
210 pub import: Option<ImportId>, 214 pub import: Option<LocalImportId>,
211} 215}
212 216
213impl CrateDefMap { 217impl CrateDefMap {
214 pub(crate) fn crate_def_map_query( 218 pub(crate) fn crate_def_map_query(
215 // Note that this doesn't have `+ AstDatabase`! 219 // Note that this doesn't have `+ AstDatabase`!
216 // This gurantess that `CrateDefMap` is stable across reparses. 220 // This gurantess that `CrateDefMap` is stable across reparses.
217 db: &impl DefDatabase2, 221 db: &impl DefDatabase,
218 krate: CrateId, 222 krate: CrateId,
219 ) -> Arc<CrateDefMap> { 223 ) -> Arc<CrateDefMap> {
220 let _p = profile("crate_def_map_query"); 224 let _p = profile("crate_def_map_query");
221 let def_map = { 225 let def_map = {
222 let crate_graph = db.crate_graph(); 226 let crate_graph = db.crate_graph();
223 let edition = crate_graph.edition(krate); 227 let edition = crate_graph.edition(krate);
224 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 228 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
225 let root = modules.alloc(ModuleData::default()); 229 let root = modules.alloc(ModuleData::default());
226 CrateDefMap { 230 CrateDefMap {
227 krate, 231 krate,
@@ -242,7 +246,7 @@ impl CrateDefMap {
242 self.krate 246 self.krate
243 } 247 }
244 248
245 pub fn root(&self) -> CrateModuleId { 249 pub fn root(&self) -> LocalModuleId {
246 self.root 250 self.root
247 } 251 }
248 252
@@ -256,8 +260,8 @@ impl CrateDefMap {
256 260
257 pub fn add_diagnostics( 261 pub fn add_diagnostics(
258 &self, 262 &self,
259 db: &impl DefDatabase2, 263 db: &impl DefDatabase,
260 module: CrateModuleId, 264 module: LocalModuleId,
261 sink: &mut DiagnosticSink, 265 sink: &mut DiagnosticSink,
262 ) { 266 ) {
263 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) 267 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
@@ -265,19 +269,19 @@ impl CrateDefMap {
265 269
266 pub fn resolve_path( 270 pub fn resolve_path(
267 &self, 271 &self,
268 db: &impl DefDatabase2, 272 db: &impl DefDatabase,
269 original_module: CrateModuleId, 273 original_module: LocalModuleId,
270 path: &Path, 274 path: &Path,
271 ) -> (PerNs, Option<usize>) { 275 ) -> (PerNs, Option<usize>) {
272 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); 276 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
273 (res.resolved_def, res.segment_index) 277 (res.resolved_def, res.segment_index)
274 } 278 }
275 279
276 pub fn modules(&self) -> impl Iterator<Item = CrateModuleId> + '_ { 280 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ {
277 self.modules.iter().map(|(id, _data)| id) 281 self.modules.iter().map(|(id, _data)| id)
278 } 282 }
279 283
280 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = CrateModuleId> + '_ { 284 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
281 self.modules 285 self.modules
282 .iter() 286 .iter()
283 .filter(move |(_id, data)| data.definition == Some(file_id)) 287 .filter(move |(_id, data)| data.definition == Some(file_id))
@@ -285,17 +289,40 @@ impl CrateDefMap {
285 } 289 }
286} 290}
287 291
292impl ModuleData {
293 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
294 pub fn definition_source(
295 &self,
296 db: &impl DefDatabase,
297 ) -> Source<Either<ast::SourceFile, ast::Module>> {
298 if let Some(file_id) = self.definition {
299 let sf = db.parse(file_id).tree();
300 return Source::new(file_id.into(), Either::A(sf));
301 }
302 let decl = self.declaration.unwrap();
303 Source::new(decl.file_id(), Either::B(decl.to_node(db)))
304 }
305
306 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
307 /// `None` for the crate root.
308 pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<Source<ast::Module>> {
309 let decl = self.declaration?;
310 let value = decl.to_node(db);
311 Some(Source { file_id: decl.file_id(), value })
312 }
313}
314
288mod diagnostics { 315mod diagnostics {
289 use hir_expand::diagnostics::DiagnosticSink; 316 use hir_expand::diagnostics::DiagnosticSink;
290 use ra_db::RelativePathBuf; 317 use ra_db::RelativePathBuf;
291 use ra_syntax::{ast, AstPtr}; 318 use ra_syntax::{ast, AstPtr};
292 319
293 use crate::{db::DefDatabase2, diagnostics::UnresolvedModule, nameres::CrateModuleId, AstId}; 320 use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};
294 321
295 #[derive(Debug, PartialEq, Eq)] 322 #[derive(Debug, PartialEq, Eq)]
296 pub(super) enum DefDiagnostic { 323 pub(super) enum DefDiagnostic {
297 UnresolvedModule { 324 UnresolvedModule {
298 module: CrateModuleId, 325 module: LocalModuleId,
299 declaration: AstId<ast::Module>, 326 declaration: AstId<ast::Module>,
300 candidate: RelativePathBuf, 327 candidate: RelativePathBuf,
301 }, 328 },
@@ -304,8 +331,8 @@ mod diagnostics {
304 impl DefDiagnostic { 331 impl DefDiagnostic {
305 pub(super) fn add_to( 332 pub(super) fn add_to(
306 &self, 333 &self,
307 db: &impl DefDatabase2, 334 db: &impl DefDatabase,
308 target_module: CrateModuleId, 335 target_module: LocalModuleId,
309 sink: &mut DiagnosticSink, 336 sink: &mut DiagnosticSink,
310 ) { 337 ) {
311 match self { 338 match self {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index aae3dcadf..b02364e86 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -12,19 +12,20 @@ use rustc_hash::FxHashMap;
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use crate::{ 14use crate::{
15 attr::Attr, 15 attr::Attrs,
16 db::DefDatabase2, 16 db::DefDatabase,
17 nameres::{ 17 nameres::{
18 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 18 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 19 raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 20 },
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId, 22 per_ns::PerNs,
23 FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, 23 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
24 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId,
24 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 25 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
25}; 26};
26 27
27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { 28pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
28 let crate_graph = db.crate_graph(); 29 let crate_graph = db.crate_graph();
29 30
30 // populate external prelude 31 // populate external prelude
@@ -94,10 +95,10 @@ impl MacroStackMonitor {
94struct DefCollector<'a, DB> { 95struct DefCollector<'a, DB> {
95 db: &'a DB, 96 db: &'a DB,
96 def_map: CrateDefMap, 97 def_map: CrateDefMap,
97 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 98 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
98 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 99 unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>,
99 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>, 100 unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>,
100 mod_dirs: FxHashMap<CrateModuleId, ModDir>, 101 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
101 102
102 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 103 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
103 /// To prevent stack overflow, we add a deep counter here for prevent that. 104 /// To prevent stack overflow, we add a deep counter here for prevent that.
@@ -108,7 +109,7 @@ struct DefCollector<'a, DB> {
108 109
109impl<DB> DefCollector<'_, DB> 110impl<DB> DefCollector<'_, DB>
110where 111where
111 DB: DefDatabase2, 112 DB: DefDatabase,
112{ 113{
113 fn collect(&mut self) { 114 fn collect(&mut self) {
114 let crate_graph = self.db.crate_graph(); 115 let crate_graph = self.db.crate_graph();
@@ -173,7 +174,7 @@ where
173 /// ``` 174 /// ```
174 fn define_macro( 175 fn define_macro(
175 &mut self, 176 &mut self,
176 module_id: CrateModuleId, 177 module_id: LocalModuleId,
177 name: Name, 178 name: Name,
178 macro_: MacroDefId, 179 macro_: MacroDefId,
179 export: bool, 180 export: bool,
@@ -200,7 +201,7 @@ where
200 /// the definition of current module. 201 /// the definition of current module.
201 /// And also, `macro_use` on a module will import all legacy macros visable inside to 202 /// And also, `macro_use` on a module will import all legacy macros visable inside to
202 /// current legacy scope, with possible shadowing. 203 /// current legacy scope, with possible shadowing.
203 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDefId) { 204 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) {
204 // Always shadowing 205 // Always shadowing
205 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_); 206 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
206 } 207 }
@@ -208,7 +209,7 @@ where
208 /// Import macros from `#[macro_use] extern crate`. 209 /// Import macros from `#[macro_use] extern crate`.
209 fn import_macros_from_extern_crate( 210 fn import_macros_from_extern_crate(
210 &mut self, 211 &mut self,
211 current_module_id: CrateModuleId, 212 current_module_id: LocalModuleId,
212 import: &raw::ImportData, 213 import: &raw::ImportData,
213 ) { 214 ) {
214 log::debug!( 215 log::debug!(
@@ -235,7 +236,7 @@ where
235 /// Exported macros are just all macros in the root module scope. 236 /// Exported macros are just all macros in the root module scope.
236 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases 237 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
237 /// created by `use` in the root module, ignoring the visibility of `use`. 238 /// created by `use` in the root module, ignoring the visibility of `use`.
238 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: CrateId) { 239 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
239 let def_map = self.db.crate_def_map(krate); 240 let def_map = self.db.crate_def_map(krate);
240 for (name, def) in def_map[def_map.root].scope.macros() { 241 for (name, def) in def_map[def_map.root].scope.macros() {
241 // `macro_use` only bring things into legacy scope. 242 // `macro_use` only bring things into legacy scope.
@@ -265,7 +266,7 @@ where
265 266
266 fn resolve_import( 267 fn resolve_import(
267 &self, 268 &self,
268 module_id: CrateModuleId, 269 module_id: LocalModuleId,
269 import: &raw::ImportData, 270 import: &raw::ImportData,
270 ) -> (PerNs, ReachedFixedPoint) { 271 ) -> (PerNs, ReachedFixedPoint) {
271 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 272 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
@@ -291,9 +292,9 @@ where
291 292
292 fn record_resolved_import( 293 fn record_resolved_import(
293 &mut self, 294 &mut self,
294 module_id: CrateModuleId, 295 module_id: LocalModuleId,
295 def: PerNs, 296 def: PerNs,
296 import_id: raw::ImportId, 297 import_id: LocalImportId,
297 import: &raw::ImportData, 298 import: &raw::ImportData,
298 ) { 299 ) {
299 if import.is_glob { 300 if import.is_glob {
@@ -387,8 +388,8 @@ where
387 388
388 fn update( 389 fn update(
389 &mut self, 390 &mut self,
390 module_id: CrateModuleId, 391 module_id: LocalModuleId,
391 import: Option<raw::ImportId>, 392 import: Option<LocalImportId>,
392 resolutions: &[(Name, Resolution)], 393 resolutions: &[(Name, Resolution)],
393 ) { 394 ) {
394 self.update_recursive(module_id, import, resolutions, 0) 395 self.update_recursive(module_id, import, resolutions, 0)
@@ -396,8 +397,8 @@ where
396 397
397 fn update_recursive( 398 fn update_recursive(
398 &mut self, 399 &mut self,
399 module_id: CrateModuleId, 400 module_id: LocalModuleId,
400 import: Option<raw::ImportId>, 401 import: Option<LocalImportId>,
401 resolutions: &[(Name, Resolution)], 402 resolutions: &[(Name, Resolution)],
402 depth: usize, 403 depth: usize,
403 ) { 404 ) {
@@ -484,7 +485,7 @@ where
484 485
485 fn collect_macro_expansion( 486 fn collect_macro_expansion(
486 &mut self, 487 &mut self,
487 module_id: CrateModuleId, 488 module_id: LocalModuleId,
488 macro_call_id: MacroCallId, 489 macro_call_id: MacroCallId,
489 macro_def_id: MacroDefId, 490 macro_def_id: MacroDefId,
490 ) { 491 ) {
@@ -522,7 +523,7 @@ where
522/// Walks a single module, populating defs, imports and macros 523/// Walks a single module, populating defs, imports and macros
523struct ModCollector<'a, D> { 524struct ModCollector<'a, D> {
524 def_collector: D, 525 def_collector: D,
525 module_id: CrateModuleId, 526 module_id: LocalModuleId,
526 file_id: HirFileId, 527 file_id: HirFileId,
527 raw_items: &'a raw::RawItems, 528 raw_items: &'a raw::RawItems,
528 mod_dir: ModDir, 529 mod_dir: ModDir,
@@ -530,7 +531,7 @@ struct ModCollector<'a, D> {
530 531
531impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> 532impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
532where 533where
533 DB: DefDatabase2, 534 DB: DefDatabase,
534{ 535{
535 fn collect(&mut self, items: &[raw::RawItem]) { 536 fn collect(&mut self, items: &[raw::RawItem]) {
536 // Note: don't assert that inserted value is fresh: it's simply not true 537 // Note: don't assert that inserted value is fresh: it's simply not true
@@ -549,7 +550,7 @@ where
549 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 550 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
550 // any other items. 551 // any other items.
551 for item in items { 552 for item in items {
552 if self.is_cfg_enabled(item.attrs()) { 553 if self.is_cfg_enabled(&item.attrs) {
553 if let raw::RawItemKind::Import(import_id) = item.kind { 554 if let raw::RawItemKind::Import(import_id) = item.kind {
554 let import = self.raw_items[import_id].clone(); 555 let import = self.raw_items[import_id].clone();
555 if import.is_extern_crate && import.is_macro_use { 556 if import.is_extern_crate && import.is_macro_use {
@@ -560,10 +561,10 @@ where
560 } 561 }
561 562
562 for item in items { 563 for item in items {
563 if self.is_cfg_enabled(item.attrs()) { 564 if self.is_cfg_enabled(&item.attrs) {
564 match item.kind { 565 match item.kind {
565 raw::RawItemKind::Module(m) => { 566 raw::RawItemKind::Module(m) => {
566 self.collect_module(&self.raw_items[m], item.attrs()) 567 self.collect_module(&self.raw_items[m], &item.attrs)
567 } 568 }
568 raw::RawItemKind::Import(import_id) => self 569 raw::RawItemKind::Import(import_id) => self
569 .def_collector 570 .def_collector
@@ -585,9 +586,9 @@ where
585 } 586 }
586 } 587 }
587 588
588 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &[Attr]) { 589 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
589 let path_attr = self.path_attr(attrs); 590 let path_attr = self.path_attr(attrs);
590 let is_macro_use = self.is_macro_use(attrs); 591 let is_macro_use = attrs.has_atom("macro_use");
591 match module { 592 match module {
592 // inline module, just recurse 593 // inline module, just recurse
593 raw::ModuleData::Definition { name, items, ast_id } => { 594 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -647,7 +648,7 @@ where
647 name: Name, 648 name: Name,
648 declaration: AstId<ast::Module>, 649 declaration: AstId<ast::Module>,
649 definition: Option<FileId>, 650 definition: Option<FileId>,
650 ) -> CrateModuleId { 651 ) -> LocalModuleId {
651 let modules = &mut self.def_collector.def_map.modules; 652 let modules = &mut self.def_collector.def_map.modules;
652 let res = modules.alloc(ModuleData::default()); 653 let res = modules.alloc(ModuleData::default());
653 modules[res].parent = Some(self.module_id); 654 modules[res].parent = Some(self.module_id);
@@ -772,24 +773,20 @@ where
772 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); 773 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path));
773 } 774 }
774 775
775 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) { 776 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
776 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); 777 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
777 for (name, macro_) in macros { 778 for (name, macro_) in macros {
778 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); 779 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
779 } 780 }
780 } 781 }
781 782
782 fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { 783 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
783 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 784 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false))
784 } 785 }
785 786
786 fn path_attr<'a>(&self, attrs: &'a [Attr]) -> Option<&'a SmolStr> { 787 fn path_attr<'a>(&self, attrs: &'a Attrs) -> Option<&'a SmolStr> {
787 attrs.iter().find_map(|attr| attr.as_path()) 788 attrs.iter().find_map(|attr| attr.as_path())
788 } 789 }
789
790 fn is_macro_use<'a>(&self, attrs: &'a [Attr]) -> bool {
791 attrs.iter().any(|attr| attr.is_simple_atom("macro_use"))
792 }
793} 790}
794 791
795fn is_macro_rules(path: &Path) -> bool { 792fn is_macro_rules(path: &Path) -> bool {
@@ -802,12 +799,12 @@ mod tests {
802 use ra_db::{fixture::WithFixture, SourceDatabase}; 799 use ra_db::{fixture::WithFixture, SourceDatabase};
803 use rustc_hash::FxHashSet; 800 use rustc_hash::FxHashSet;
804 801
805 use crate::{db::DefDatabase2, test_db::TestDB}; 802 use crate::{db::DefDatabase, test_db::TestDB};
806 803
807 use super::*; 804 use super::*;
808 805
809 fn do_collect_defs( 806 fn do_collect_defs(
810 db: &impl DefDatabase2, 807 db: &impl DefDatabase,
811 def_map: CrateDefMap, 808 def_map: CrateDefMap,
812 monitor: MacroStackMonitor, 809 monitor: MacroStackMonitor,
813 ) -> CrateDefMap { 810 ) -> CrateDefMap {
@@ -831,7 +828,7 @@ mod tests {
831 828
832 let def_map = { 829 let def_map = {
833 let edition = db.crate_graph().edition(krate); 830 let edition = db.crate_graph().edition(krate);
834 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 831 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
835 let root = modules.alloc(ModuleData::default()); 832 let root = modules.alloc(ModuleData::default());
836 CrateDefMap { 833 CrateDefMap {
837 krate, 834 krate,
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs
index b3b1379d0..14fb8ba3a 100644
--- a/crates/ra_hir_def/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs
@@ -3,7 +3,7 @@ use hir_expand::name::Name;
3use ra_db::{FileId, RelativePathBuf}; 3use ra_db::{FileId, RelativePathBuf};
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
5 5
6use crate::{db::DefDatabase2, HirFileId}; 6use crate::{db::DefDatabase, HirFileId};
7 7
8#[derive(Clone, Debug)] 8#[derive(Clone, Debug)]
9pub(super) struct ModDir { 9pub(super) struct ModDir {
@@ -40,7 +40,7 @@ impl ModDir {
40 40
41 pub(super) fn resolve_declaration( 41 pub(super) fn resolve_declaration(
42 &self, 42 &self,
43 db: &impl DefDatabase2, 43 db: &impl DefDatabase,
44 file_id: HirFileId, 44 file_id: HirFileId,
45 name: &Name, 45 name: &Name,
46 attr_path: Option<&SmolStr>, 46 attr_path: Option<&SmolStr>,
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 95692f826..9455f22bb 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -15,10 +15,11 @@ use ra_db::Edition;
15use test_utils::tested_by; 15use test_utils::tested_by;
16 16
17use crate::{ 17use crate::{
18 db::DefDatabase2, 18 db::DefDatabase,
19 nameres::{per_ns::PerNs, CrateDefMap}, 19 nameres::CrateDefMap,
20 path::{Path, PathKind}, 20 path::{Path, PathKind},
21 AdtId, CrateModuleId, EnumVariantId, ModuleDefId, ModuleId, 21 per_ns::PerNs,
22 AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
22}; 23};
23 24
24#[derive(Debug, Clone, Copy, PartialEq, Eq)] 25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -63,9 +64,9 @@ impl CrateDefMap {
63 // the result. 64 // the result.
64 pub(super) fn resolve_path_fp_with_macro( 65 pub(super) fn resolve_path_fp_with_macro(
65 &self, 66 &self,
66 db: &impl DefDatabase2, 67 db: &impl DefDatabase,
67 mode: ResolveMode, 68 mode: ResolveMode,
68 original_module: CrateModuleId, 69 original_module: LocalModuleId,
69 path: &Path, 70 path: &Path,
70 ) -> ResolvePathResult { 71 ) -> ResolvePathResult {
71 let mut segments = path.segments.iter().enumerate(); 72 let mut segments = path.segments.iter().enumerate();
@@ -216,8 +217,8 @@ impl CrateDefMap {
216 217
217 fn resolve_name_in_module( 218 fn resolve_name_in_module(
218 &self, 219 &self,
219 db: &impl DefDatabase2, 220 db: &impl DefDatabase,
220 module: CrateModuleId, 221 module: LocalModuleId,
221 name: &Name, 222 name: &Name,
222 ) -> PerNs { 223 ) -> PerNs {
223 // Resolve in: 224 // Resolve in:
@@ -243,7 +244,7 @@ impl CrateDefMap {
243 from_crate_root.or(from_extern_prelude) 244 from_crate_root.or(from_extern_prelude)
244 } 245 }
245 246
246 fn resolve_in_prelude(&self, db: &impl DefDatabase2, name: &Name) -> PerNs { 247 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
247 if let Some(prelude) = self.prelude { 248 if let Some(prelude) = self.prelude {
248 let keep; 249 let keep;
249 let def_map = if prelude.krate == self.krate { 250 let def_map = if prelude.krate == self.krate {
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 7c68fd638..552cbe544 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -12,11 +12,16 @@ use hir_expand::{
12use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 12use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
13use ra_syntax::{ 13use ra_syntax::{
14 ast::{self, AttrsOwner, NameOwner}, 14 ast::{self, AttrsOwner, NameOwner},
15 AstNode, AstPtr, SourceFile, 15 AstNode, AstPtr,
16}; 16};
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
19use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source}; 19use crate::{
20 attr::{Attr, Attrs},
21 db::DefDatabase,
22 path::Path,
23 FileAstId, HirFileId, LocalImportId, Source,
24};
20 25
21/// `RawItems` is a set of top-level items in a file (except for impls). 26/// `RawItems` is a set of top-level items in a file (except for impls).
22/// 27///
@@ -25,7 +30,7 @@ use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, Modu
25#[derive(Debug, Default, PartialEq, Eq)] 30#[derive(Debug, Default, PartialEq, Eq)]
26pub struct RawItems { 31pub struct RawItems {
27 modules: Arena<Module, ModuleData>, 32 modules: Arena<Module, ModuleData>,
28 imports: Arena<ImportId, ImportData>, 33 imports: Arena<LocalImportId, ImportData>,
29 defs: Arena<Def, DefData>, 34 defs: Arena<Def, DefData>,
30 macros: Arena<Macro, MacroData>, 35 macros: Arena<Macro, MacroData>,
31 impls: Arena<Impl, ImplData>, 36 impls: Arena<Impl, ImplData>,
@@ -35,41 +40,31 @@ pub struct RawItems {
35 40
36#[derive(Debug, Default, PartialEq, Eq)] 41#[derive(Debug, Default, PartialEq, Eq)]
37pub struct ImportSourceMap { 42pub struct ImportSourceMap {
38 map: ArenaMap<ImportId, ImportSourcePtr>, 43 map: ArenaMap<LocalImportId, ImportSourcePtr>,
39} 44}
40 45
41type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; 46type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
42type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
43
44fn to_node(ptr: ImportSourcePtr, file: &SourceFile) -> ImportSource {
45 ptr.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
46}
47 47
48impl ImportSourceMap { 48impl ImportSourceMap {
49 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { 49 fn insert(&mut self, import: LocalImportId, ptr: ImportSourcePtr) {
50 self.map.insert(import, ptr) 50 self.map.insert(import, ptr)
51 } 51 }
52 52
53 pub fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource { 53 pub fn get(&self, import: LocalImportId) -> ImportSourcePtr {
54 let file = match source { 54 self.map[import].clone()
55 ModuleSource::SourceFile(file) => file.clone(),
56 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
57 };
58
59 to_node(self.map[import], &file)
60 } 55 }
61} 56}
62 57
63impl RawItems { 58impl RawItems {
64 pub(crate) fn raw_items_query( 59 pub(crate) fn raw_items_query(
65 db: &(impl DefDatabase2 + AstDatabase), 60 db: &(impl DefDatabase + AstDatabase),
66 file_id: HirFileId, 61 file_id: HirFileId,
67 ) -> Arc<RawItems> { 62 ) -> Arc<RawItems> {
68 db.raw_items_with_source_map(file_id).0 63 db.raw_items_with_source_map(file_id).0
69 } 64 }
70 65
71 pub(crate) fn raw_items_with_source_map_query( 66 pub(crate) fn raw_items_with_source_map_query(
72 db: &(impl DefDatabase2 + AstDatabase), 67 db: &(impl DefDatabase + AstDatabase),
73 file_id: HirFileId, 68 file_id: HirFileId,
74 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { 69 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
75 let mut collector = RawItemsCollector { 70 let mut collector = RawItemsCollector {
@@ -101,9 +96,9 @@ impl Index<Module> for RawItems {
101 } 96 }
102} 97}
103 98
104impl Index<ImportId> for RawItems { 99impl Index<LocalImportId> for RawItems {
105 type Output = ImportData; 100 type Output = ImportData;
106 fn index(&self, idx: ImportId) -> &ImportData { 101 fn index(&self, idx: LocalImportId) -> &ImportData {
107 &self.imports[idx] 102 &self.imports[idx]
108 } 103 }
109} 104}
@@ -129,25 +124,16 @@ impl Index<Impl> for RawItems {
129 } 124 }
130} 125}
131 126
132// Avoid heap allocation on items without attributes.
133type Attrs = Option<Arc<[Attr]>>;
134
135#[derive(Debug, PartialEq, Eq, Clone)] 127#[derive(Debug, PartialEq, Eq, Clone)]
136pub(super) struct RawItem { 128pub(super) struct RawItem {
137 attrs: Attrs, 129 pub(super) attrs: Attrs,
138 pub(super) kind: RawItemKind, 130 pub(super) kind: RawItemKind,
139} 131}
140 132
141impl RawItem {
142 pub(super) fn attrs(&self) -> &[Attr] {
143 self.attrs.as_ref().map_or(&[], |it| &*it)
144 }
145}
146
147#[derive(Debug, PartialEq, Eq, Clone, Copy)] 133#[derive(Debug, PartialEq, Eq, Clone, Copy)]
148pub(super) enum RawItemKind { 134pub(super) enum RawItemKind {
149 Module(Module), 135 Module(Module),
150 Import(ImportId), 136 Import(LocalImportId),
151 Def(Def), 137 Def(Def),
152 Macro(Macro), 138 Macro(Macro),
153 Impl(Impl), 139 Impl(Impl),
@@ -163,10 +149,6 @@ pub(super) enum ModuleData {
163 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 149 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
164} 150}
165 151
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
167pub struct ImportId(RawId);
168impl_arena_id!(ImportId);
169
170#[derive(Debug, Clone, PartialEq, Eq)] 152#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct ImportData { 153pub struct ImportData {
172 pub(super) path: Path, 154 pub(super) path: Path,
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 256f7d4be..f0b86af7c 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -10,7 +10,7 @@ use insta::assert_snapshot;
10use ra_db::{fixture::WithFixture, SourceDatabase}; 10use ra_db::{fixture::WithFixture, SourceDatabase};
11use test_utils::covers; 11use test_utils::covers;
12 12
13use crate::{db::DefDatabase2, nameres::*, test_db::TestDB, CrateModuleId}; 13use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId};
14 14
15fn def_map(fixtute: &str) -> String { 15fn def_map(fixtute: &str) -> String {
16 let dm = compute_crate_def_map(fixtute); 16 let dm = compute_crate_def_map(fixtute);
@@ -28,7 +28,7 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
28 go(&mut buf, map, "\ncrate", map.root()); 28 go(&mut buf, map, "\ncrate", map.root());
29 return buf.trim().to_string(); 29 return buf.trim().to_string();
30 30
31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) { 31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) {
32 *buf += path; 32 *buf += path;
33 *buf += "\n"; 33 *buf += "\n";
34 34
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index eb7b85c07..e11530062 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -665,7 +665,7 @@ fn unresolved_module_diagnostics() {
665 @r###" 665 @r###"
666 [ 666 [
667 UnresolvedModule { 667 UnresolvedModule {
668 module: CrateModuleId( 668 module: LocalModuleId(
669 0, 669 0,
670 ), 670 ),
671 declaration: AstId { 671 declaration: AstId {
diff --git a/crates/ra_hir_def/src/nameres/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 717ed1ef9..717ed1ef9 100644
--- a/crates/ra_hir_def/src/nameres/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 7b5c3ec06..b56de44dd 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -11,14 +11,15 @@ use rustc_hash::FxHashSet;
11use crate::{ 11use crate::{
12 body::scope::{ExprScopes, ScopeId}, 12 body::scope::{ExprScopes, ScopeId},
13 builtin_type::BuiltinType, 13 builtin_type::BuiltinType,
14 db::DefDatabase2, 14 db::DefDatabase,
15 expr::{ExprId, PatId}, 15 expr::{ExprId, PatId},
16 generics::GenericParams, 16 generics::GenericParams,
17 nameres::{per_ns::PerNs, CrateDefMap}, 17 nameres::CrateDefMap,
18 path::{Path, PathKind}, 18 path::{Path, PathKind},
19 AdtId, AstItemDef, ConstId, ContainerId, CrateModuleId, DefWithBodyId, EnumId, EnumVariantId, 19 per_ns::PerNs,
20 FunctionId, GenericDefId, ImplId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, 20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
21 TypeAliasId, 21 GenericDefId, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId,
22 TraitId, TypeAliasId,
22}; 23};
23 24
24#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
@@ -30,7 +31,7 @@ pub struct Resolver {
30#[derive(Debug, Clone)] 31#[derive(Debug, Clone)]
31pub(crate) struct ModuleItemMap { 32pub(crate) struct ModuleItemMap {
32 crate_def_map: Arc<CrateDefMap>, 33 crate_def_map: Arc<CrateDefMap>,
33 module_id: CrateModuleId, 34 module_id: LocalModuleId,
34} 35}
35 36
36#[derive(Debug, Clone)] 37#[derive(Debug, Clone)]
@@ -87,7 +88,7 @@ pub enum ValueNs {
87 88
88impl Resolver { 89impl Resolver {
89 /// Resolve known trait from std, like `std::futures::Future` 90 /// Resolve known trait from std, like `std::futures::Future`
90 pub fn resolve_known_trait(&self, db: &impl DefDatabase2, path: &Path) -> Option<TraitId> { 91 pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> {
91 let res = self.resolve_module_path(db, path).take_types()?; 92 let res = self.resolve_module_path(db, path).take_types()?;
92 match res { 93 match res {
93 ModuleDefId::TraitId(it) => Some(it), 94 ModuleDefId::TraitId(it) => Some(it),
@@ -96,7 +97,7 @@ impl Resolver {
96 } 97 }
97 98
98 /// Resolve known struct from std, like `std::boxed::Box` 99 /// Resolve known struct from std, like `std::boxed::Box`
99 pub fn resolve_known_struct(&self, db: &impl DefDatabase2, path: &Path) -> Option<StructId> { 100 pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> {
100 let res = self.resolve_module_path(db, path).take_types()?; 101 let res = self.resolve_module_path(db, path).take_types()?;
101 match res { 102 match res {
102 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), 103 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
@@ -105,7 +106,7 @@ impl Resolver {
105 } 106 }
106 107
107 /// Resolve known enum from std, like `std::result::Result` 108 /// Resolve known enum from std, like `std::result::Result`
108 pub fn resolve_known_enum(&self, db: &impl DefDatabase2, path: &Path) -> Option<EnumId> { 109 pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> {
109 let res = self.resolve_module_path(db, path).take_types()?; 110 let res = self.resolve_module_path(db, path).take_types()?;
110 match res { 111 match res {
111 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), 112 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
@@ -114,7 +115,7 @@ impl Resolver {
114 } 115 }
115 116
116 /// pub only for source-binder 117 /// pub only for source-binder
117 pub fn resolve_module_path(&self, db: &impl DefDatabase2, path: &Path) -> PerNs { 118 pub fn resolve_module_path(&self, db: &impl DefDatabase, path: &Path) -> PerNs {
118 let (item_map, module) = match self.module() { 119 let (item_map, module) = match self.module() {
119 Some(it) => it, 120 Some(it) => it,
120 None => return PerNs::none(), 121 None => return PerNs::none(),
@@ -128,7 +129,7 @@ impl Resolver {
128 129
129 pub fn resolve_path_in_type_ns( 130 pub fn resolve_path_in_type_ns(
130 &self, 131 &self,
131 db: &impl DefDatabase2, 132 db: &impl DefDatabase,
132 path: &Path, 133 path: &Path,
133 ) -> Option<(TypeNs, Option<usize>)> { 134 ) -> Option<(TypeNs, Option<usize>)> {
134 if path.is_type_relative() { 135 if path.is_type_relative() {
@@ -184,7 +185,7 @@ impl Resolver {
184 185
185 pub fn resolve_path_in_type_ns_fully( 186 pub fn resolve_path_in_type_ns_fully(
186 &self, 187 &self,
187 db: &impl DefDatabase2, 188 db: &impl DefDatabase,
188 path: &Path, 189 path: &Path,
189 ) -> Option<TypeNs> { 190 ) -> Option<TypeNs> {
190 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; 191 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?;
@@ -196,7 +197,7 @@ impl Resolver {
196 197
197 pub fn resolve_path_in_value_ns<'p>( 198 pub fn resolve_path_in_value_ns<'p>(
198 &self, 199 &self,
199 db: &impl DefDatabase2, 200 db: &impl DefDatabase,
200 path: &'p Path, 201 path: &'p Path,
201 ) -> Option<ResolveValueResult> { 202 ) -> Option<ResolveValueResult> {
202 if path.is_type_relative() { 203 if path.is_type_relative() {
@@ -296,7 +297,7 @@ impl Resolver {
296 297
297 pub fn resolve_path_in_value_ns_fully( 298 pub fn resolve_path_in_value_ns_fully(
298 &self, 299 &self,
299 db: &impl DefDatabase2, 300 db: &impl DefDatabase,
300 path: &Path, 301 path: &Path,
301 ) -> Option<ValueNs> { 302 ) -> Option<ValueNs> {
302 match self.resolve_path_in_value_ns(db, path)? { 303 match self.resolve_path_in_value_ns(db, path)? {
@@ -305,18 +306,18 @@ impl Resolver {
305 } 306 }
306 } 307 }
307 308
308 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> { 309 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
309 let (item_map, module) = self.module()?; 310 let (item_map, module) = self.module()?;
310 item_map.resolve_path(db, module, path).0.get_macros() 311 item_map.resolve_path(db, module, path).0.get_macros()
311 } 312 }
312 313
313 pub fn process_all_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { 314 pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
314 for scope in self.scopes.iter().rev() { 315 for scope in self.scopes.iter().rev() {
315 scope.process_names(db, f); 316 scope.process_names(db, f);
316 } 317 }
317 } 318 }
318 319
319 pub fn traits_in_scope(&self, db: &impl DefDatabase2) -> FxHashSet<TraitId> { 320 pub fn traits_in_scope(&self, db: &impl DefDatabase) -> FxHashSet<TraitId> {
320 let mut traits = FxHashSet::default(); 321 let mut traits = FxHashSet::default();
321 for scope in &self.scopes { 322 for scope in &self.scopes {
322 if let Scope::ModuleScope(m) = scope { 323 if let Scope::ModuleScope(m) = scope {
@@ -330,7 +331,7 @@ impl Resolver {
330 traits 331 traits
331 } 332 }
332 333
333 fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { 334 fn module(&self) -> Option<(&CrateDefMap, LocalModuleId)> {
334 self.scopes.iter().rev().find_map(|scope| match scope { 335 self.scopes.iter().rev().find_map(|scope| match scope {
335 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), 336 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
336 337
@@ -378,7 +379,7 @@ pub enum ScopeDef {
378} 379}
379 380
380impl Scope { 381impl Scope {
381 fn process_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { 382 fn process_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
382 match self { 383 match self {
383 Scope::ModuleScope(m) => { 384 Scope::ModuleScope(m) => {
384 // FIXME: should we provide `self` here? 385 // FIXME: should we provide `self` here?
@@ -425,17 +426,13 @@ impl Scope {
425} 426}
426 427
427// needs arbitrary_self_types to be a method... or maybe move to the def? 428// needs arbitrary_self_types to be a method... or maybe move to the def?
428pub fn resolver_for_expr( 429pub fn resolver_for_expr(db: &impl DefDatabase, owner: DefWithBodyId, expr_id: ExprId) -> Resolver {
429 db: &impl DefDatabase2,
430 owner: DefWithBodyId,
431 expr_id: ExprId,
432) -> Resolver {
433 let scopes = db.expr_scopes(owner); 430 let scopes = db.expr_scopes(owner);
434 resolver_for_scope(db, owner, scopes.scope_for(expr_id)) 431 resolver_for_scope(db, owner, scopes.scope_for(expr_id))
435} 432}
436 433
437pub fn resolver_for_scope( 434pub fn resolver_for_scope(
438 db: &impl DefDatabase2, 435 db: &impl DefDatabase,
439 owner: DefWithBodyId, 436 owner: DefWithBodyId,
440 scope_id: Option<ScopeId>, 437 scope_id: Option<ScopeId>,
441) -> Resolver { 438) -> Resolver {
@@ -454,7 +451,7 @@ impl Resolver {
454 self 451 self
455 } 452 }
456 453
457 fn push_generic_params_scope(self, db: &impl DefDatabase2, def: GenericDefId) -> Resolver { 454 fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver {
458 let params = db.generic_params(def); 455 let params = db.generic_params(def);
459 if params.params.is_empty() { 456 if params.params.is_empty() {
460 self 457 self
@@ -470,7 +467,7 @@ impl Resolver {
470 fn push_module_scope( 467 fn push_module_scope(
471 self, 468 self,
472 crate_def_map: Arc<CrateDefMap>, 469 crate_def_map: Arc<CrateDefMap>,
473 module_id: CrateModuleId, 470 module_id: LocalModuleId,
474 ) -> Resolver { 471 ) -> Resolver {
475 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 472 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
476 } 473 }
@@ -487,24 +484,24 @@ impl Resolver {
487 484
488pub trait HasResolver { 485pub trait HasResolver {
489 /// Builds a resolver for type references inside this def. 486 /// Builds a resolver for type references inside this def.
490 fn resolver(self, db: &impl DefDatabase2) -> Resolver; 487 fn resolver(self, db: &impl DefDatabase) -> Resolver;
491} 488}
492 489
493impl HasResolver for ModuleId { 490impl HasResolver for ModuleId {
494 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 491 fn resolver(self, db: &impl DefDatabase) -> Resolver {
495 let def_map = db.crate_def_map(self.krate); 492 let def_map = db.crate_def_map(self.krate);
496 Resolver::default().push_module_scope(def_map, self.module_id) 493 Resolver::default().push_module_scope(def_map, self.module_id)
497 } 494 }
498} 495}
499 496
500impl HasResolver for TraitId { 497impl HasResolver for TraitId {
501 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 498 fn resolver(self, db: &impl DefDatabase) -> Resolver {
502 self.module(db).resolver(db).push_generic_params_scope(db, self.into()) 499 self.module(db).resolver(db).push_generic_params_scope(db, self.into())
503 } 500 }
504} 501}
505 502
506impl<T: Into<AdtId>> HasResolver for T { 503impl<T: Into<AdtId>> HasResolver for T {
507 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 504 fn resolver(self, db: &impl DefDatabase) -> Resolver {
508 let def = self.into(); 505 let def = self.into();
509 let module = match def { 506 let module = match def {
510 AdtId::StructId(it) => it.0.module(db), 507 AdtId::StructId(it) => it.0.module(db),
@@ -520,13 +517,13 @@ impl<T: Into<AdtId>> HasResolver for T {
520} 517}
521 518
522impl HasResolver for FunctionId { 519impl HasResolver for FunctionId {
523 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 520 fn resolver(self, db: &impl DefDatabase) -> Resolver {
524 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) 521 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
525 } 522 }
526} 523}
527 524
528impl HasResolver for DefWithBodyId { 525impl HasResolver for DefWithBodyId {
529 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 526 fn resolver(self, db: &impl DefDatabase) -> Resolver {
530 match self { 527 match self {
531 DefWithBodyId::ConstId(c) => c.resolver(db), 528 DefWithBodyId::ConstId(c) => c.resolver(db),
532 DefWithBodyId::FunctionId(f) => f.resolver(db), 529 DefWithBodyId::FunctionId(f) => f.resolver(db),
@@ -536,25 +533,25 @@ impl HasResolver for DefWithBodyId {
536} 533}
537 534
538impl HasResolver for ConstId { 535impl HasResolver for ConstId {
539 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 536 fn resolver(self, db: &impl DefDatabase) -> Resolver {
540 self.lookup(db).container.resolver(db) 537 self.lookup(db).container.resolver(db)
541 } 538 }
542} 539}
543 540
544impl HasResolver for StaticId { 541impl HasResolver for StaticId {
545 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 542 fn resolver(self, db: &impl DefDatabase) -> Resolver {
546 self.module(db).resolver(db) 543 self.module(db).resolver(db)
547 } 544 }
548} 545}
549 546
550impl HasResolver for TypeAliasId { 547impl HasResolver for TypeAliasId {
551 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 548 fn resolver(self, db: &impl DefDatabase) -> Resolver {
552 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) 549 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
553 } 550 }
554} 551}
555 552
556impl HasResolver for ContainerId { 553impl HasResolver for ContainerId {
557 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 554 fn resolver(self, db: &impl DefDatabase) -> Resolver {
558 match self { 555 match self {
559 ContainerId::TraitId(it) => it.resolver(db), 556 ContainerId::TraitId(it) => it.resolver(db),
560 ContainerId::ImplId(it) => it.resolver(db), 557 ContainerId::ImplId(it) => it.resolver(db),
@@ -564,7 +561,7 @@ impl HasResolver for ContainerId {
564} 561}
565 562
566impl HasResolver for GenericDefId { 563impl HasResolver for GenericDefId {
567 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 564 fn resolver(self, db: &impl DefDatabase) -> Resolver {
568 match self { 565 match self {
569 GenericDefId::FunctionId(inner) => inner.resolver(db), 566 GenericDefId::FunctionId(inner) => inner.resolver(db),
570 GenericDefId::AdtId(adt) => adt.resolver(db), 567 GenericDefId::AdtId(adt) => adt.resolver(db),
@@ -578,7 +575,7 @@ impl HasResolver for GenericDefId {
578} 575}
579 576
580impl HasResolver for ImplId { 577impl HasResolver for ImplId {
581 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 578 fn resolver(self, db: &impl DefDatabase) -> Resolver {
582 self.module(db) 579 self.module(db)
583 .resolver(db) 580 .resolver(db)
584 .push_generic_params_scope(db, self.into()) 581 .push_generic_params_scope(db, self.into())
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs
index 8ee8e40d0..439e8a412 100644
--- a/crates/ra_hir_def/src/test_db.rs
+++ b/crates/ra_hir_def/src/test_db.rs
@@ -12,7 +12,7 @@ use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath
12 ra_db::SourceDatabaseStorage, 12 ra_db::SourceDatabaseStorage,
13 hir_expand::db::AstDatabaseStorage, 13 hir_expand::db::AstDatabaseStorage,
14 crate::db::InternDatabaseStorage, 14 crate::db::InternDatabaseStorage,
15 crate::db::DefDatabase2Storage 15 crate::db::DefDatabaseStorage
16)] 16)]
17#[derive(Debug, Default)] 17#[derive(Debug, Default)]
18pub struct TestDB { 18pub struct TestDB {
diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs
new file mode 100644
index 000000000..fc26f5a48
--- /dev/null
+++ b/crates/ra_hir_def/src/trace.rs
@@ -0,0 +1,49 @@
1//! Trace is a pretty niche data structure which is used when lowering a CST
2//! into HIR.
3//!
4//! Lowering process calculates two bits of information:
5//! * the lowered syntax itself
6//! * a mapping between lowered syntax and original syntax
7//!
8//! Due to the way salsa works, the mapping is usually hot lava, as it contains
9//! absolute offsets. The `Trace` structure (inspired, at least in name, by
10//! Kotlin's `BindingTrace`) allows use the same code to compute both
11//! projections.
12use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId};
13
14pub(crate) struct Trace<ID: ArenaId, T, V> {
15 for_arena: bool,
16 arena: Arena<ID, T>,
17 map: ArenaMap<ID, V>,
18 len: u32,
19}
20
21impl<ID: ra_arena::ArenaId, T, V> Trace<ID, T, V> {
22 pub(crate) fn new_for_arena() -> Trace<ID, T, V> {
23 Trace { for_arena: true, arena: Arena::default(), map: ArenaMap::default(), len: 0 }
24 }
25
26 pub(crate) fn new_for_map() -> Trace<ID, T, V> {
27 Trace { for_arena: false, arena: Arena::default(), map: ArenaMap::default(), len: 0 }
28 }
29
30 pub(crate) fn alloc(&mut self, value: impl Fn() -> V, data: impl Fn() -> T) {
31 if self.for_arena {
32 self.arena.alloc(data());
33 } else {
34 let id = ID::from_raw(RawId::from(self.len));
35 self.len += 1;
36 self.map.insert(id, value());
37 }
38 }
39
40 pub(crate) fn into_arena(self) -> Arena<ID, T> {
41 assert!(self.for_arena);
42 self.arena
43 }
44
45 pub(crate) fn into_map(self) -> ArenaMap<ID, V> {
46 assert!(!self.for_arena);
47 self.map
48 }
49}
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
deleted file mode 100644
index 6c2d5b2a9..000000000
--- a/crates/ra_hir_def/src/traits.rs
+++ /dev/null
@@ -1,66 +0,0 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{AsName, Name},
7 AstId,
8};
9
10use ra_syntax::ast::{self, NameOwner};
11
12use crate::{
13 db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
14 TypeAliasId, TypeAliasLoc,
15};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct TraitData {
19 pub name: Option<Name>,
20 pub items: Vec<AssocItemId>,
21 pub auto: bool,
22}
23
24impl TraitData {
25 pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
26 let src = tr.source(db);
27 let name = src.value.name().map(|n| n.as_name());
28 let auto = src.value.is_auto();
29 let ast_id_map = db.ast_id_map(src.file_id);
30 let items = if let Some(item_list) = src.value.item_list() {
31 item_list
32 .impl_items()
33 .map(|item_node| match item_node {
34 ast::ImplItem::FnDef(it) => FunctionLoc {
35 container: ContainerId::TraitId(tr),
36 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
37 }
38 .intern(db)
39 .into(),
40 ast::ImplItem::ConstDef(it) => ConstLoc {
41 container: ContainerId::TraitId(tr),
42 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
43 }
44 .intern(db)
45 .into(),
46 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
47 container: ContainerId::TraitId(tr),
48 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
49 }
50 .intern(db)
51 .into(),
52 })
53 .collect()
54 } else {
55 Vec::new()
56 };
57 Arc::new(TraitData { name, items, auto })
58 }
59
60 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
61 self.items.iter().filter_map(|item| match item {
62 AssocItemId::TypeAliasId(t) => Some(*t),
63 _ => None,
64 })
65 }
66}
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index 97fb0cb55..c0e0436c0 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -8,35 +8,47 @@ use crate::{
8 8
9use crate::quote; 9use crate::quote;
10 10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 11macro_rules! register_builtin {
12pub enum BuiltinExpander { 12 ( $(($name:ident, $kind: ident) => $expand:ident),* ) => {
13 Line, 13 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14} 14 pub enum BuiltinFnLikeExpander {
15 $($kind),*
16 }
15 17
16impl BuiltinExpander { 18 impl BuiltinFnLikeExpander {
17 pub fn expand( 19 pub fn expand(
18 &self, 20 &self,
19 db: &dyn AstDatabase, 21 db: &dyn AstDatabase,
20 id: MacroCallId, 22 id: MacroCallId,
21 tt: &tt::Subtree, 23 tt: &tt::Subtree,
22 ) -> Result<tt::Subtree, mbe::ExpandError> { 24 ) -> Result<tt::Subtree, mbe::ExpandError> {
23 match self { 25 let expander = match *self {
24 BuiltinExpander::Line => line_expand(db, id, tt), 26 $( BuiltinFnLikeExpander::$kind => $expand, )*
27 };
28 expander(db, id, tt)
29 }
25 } 30 }
26 } 31
32 pub fn find_builtin_macro(
33 ident: &name::Name,
34 krate: CrateId,
35 ast_id: AstId<ast::MacroCall>,
36 ) -> Option<MacroDefId> {
37 let kind = match ident {
38 $( id if id == &name::$name => BuiltinFnLikeExpander::$kind, )*
39 _ => return None,
40 };
41
42 Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(kind) })
43 }
44 };
27} 45}
28 46
29pub fn find_builtin_macro( 47register_builtin! {
30 ident: &name::Name, 48 (COLUMN_MACRO, Column) => column_expand,
31 krate: CrateId, 49 (FILE_MACRO, File) => file_expand,
32 ast_id: AstId<ast::MacroCall>, 50 (LINE_MACRO, Line) => line_expand,
33) -> Option<MacroDefId> { 51 (STRINGIFY_MACRO, Stringify) => stringify_expand
34 // FIXME: Better registering method
35 if ident == &name::LINE_MACRO {
36 Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::Line) })
37 } else {
38 None
39 }
40} 52}
41 53
42fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { 54fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize {
@@ -78,3 +90,173 @@ fn line_expand(
78 90
79 Ok(expanded) 91 Ok(expanded)
80} 92}
93
94fn stringify_expand(
95 db: &dyn AstDatabase,
96 id: MacroCallId,
97 _tt: &tt::Subtree,
98) -> Result<tt::Subtree, mbe::ExpandError> {
99 let loc = db.lookup_intern_macro(id);
100 let macro_call = loc.ast_id.to_node(db);
101
102 let macro_content = {
103 let arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?;
104 let macro_args = arg.syntax().clone();
105 let text = macro_args.text();
106 let without_parens = TextUnit::of_char('(')..text.len() - TextUnit::of_char(')');
107 text.slice(without_parens).to_string()
108 };
109
110 let expanded = quote! {
111 #macro_content
112 };
113
114 Ok(expanded)
115}
116
117fn to_col_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize {
118 // FIXME: Use expansion info
119 let file_id = file.original_file(db);
120 let text = db.file_text(file_id);
121 let mut col_num = 1;
122
123 for c in text[..pos.to_usize()].chars().rev() {
124 if c == '\n' {
125 break;
126 }
127 col_num = col_num + 1;
128 }
129
130 col_num
131}
132
133fn column_expand(
134 db: &dyn AstDatabase,
135 id: MacroCallId,
136 _tt: &tt::Subtree,
137) -> Result<tt::Subtree, mbe::ExpandError> {
138 let loc = db.lookup_intern_macro(id);
139 let macro_call = loc.ast_id.to_node(db);
140
141 let _arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?;
142 let col_start = macro_call.syntax().text_range().start();
143
144 let file = id.as_file(MacroFileKind::Expr);
145 let col_num = to_col_number(db, file, col_start);
146
147 let expanded = quote! {
148 #col_num
149 };
150
151 Ok(expanded)
152}
153
154fn file_expand(
155 db: &dyn AstDatabase,
156 id: MacroCallId,
157 _tt: &tt::Subtree,
158) -> Result<tt::Subtree, mbe::ExpandError> {
159 let loc = db.lookup_intern_macro(id);
160 let macro_call = loc.ast_id.to_node(db);
161
162 let _ = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?;
163
164 // FIXME: RA purposefully lacks knowledge of absolute file names
165 // so just return "".
166 let file_name = "";
167
168 let expanded = quote! {
169 #file_name
170 };
171
172 Ok(expanded)
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178 use crate::{test_db::TestDB, MacroCallLoc};
179 use ra_db::{fixture::WithFixture, SourceDatabase};
180
181 fn expand_builtin_macro(s: &str, expander: BuiltinFnLikeExpander) -> String {
182 let (db, file_id) = TestDB::with_single_file(&s);
183 let parsed = db.parse(file_id);
184 let macro_calls: Vec<_> =
185 parsed.syntax_node().descendants().filter_map(|it| ast::MacroCall::cast(it)).collect();
186
187 let ast_id_map = db.ast_id_map(file_id.into());
188
189 // the first one should be a macro_rules
190 let def = MacroDefId {
191 krate: CrateId(0),
192 ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0])),
193 kind: MacroDefKind::BuiltIn(expander),
194 };
195
196 let loc = MacroCallLoc {
197 def,
198 ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[1])),
199 };
200
201 let id = db.intern_macro(loc);
202 let parsed = db.parse_or_expand(id.as_file(MacroFileKind::Expr)).unwrap();
203
204 parsed.text().to_string()
205 }
206
207 #[test]
208 fn test_column_expand() {
209 let expanded = expand_builtin_macro(
210 r#"
211 #[rustc_builtin_macro]
212 macro_rules! column {() => {}}
213 column!()
214"#,
215 BuiltinFnLikeExpander::Column,
216 );
217
218 assert_eq!(expanded, "9");
219 }
220
221 #[test]
222 fn test_line_expand() {
223 let expanded = expand_builtin_macro(
224 r#"
225 #[rustc_builtin_macro]
226 macro_rules! line {() => {}}
227 line!()
228"#,
229 BuiltinFnLikeExpander::Line,
230 );
231
232 assert_eq!(expanded, "4");
233 }
234
235 #[test]
236 fn test_stringify_expand() {
237 let expanded = expand_builtin_macro(
238 r#"
239 #[rustc_builtin_macro]
240 macro_rules! stringify {() => {}}
241 stringify!(a b c)
242"#,
243 BuiltinFnLikeExpander::Stringify,
244 );
245
246 assert_eq!(expanded, "\"a b c\"");
247 }
248
249 #[test]
250 fn test_file_expand() {
251 let expanded = expand_builtin_macro(
252 r#"
253 #[rustc_builtin_macro]
254 macro_rules! file {() => {}}
255 file!()
256"#,
257 BuiltinFnLikeExpander::File,
258 );
259
260 assert_eq!(expanded, "\"\"");
261 }
262}
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
index 3c11c8a22..8e46fa177 100644
--- a/crates/ra_hir_expand/src/db.rs
+++ b/crates/ra_hir_expand/src/db.rs
@@ -9,14 +9,14 @@ use ra_prof::profile;
9use ra_syntax::{AstNode, Parse, SyntaxNode}; 9use ra_syntax::{AstNode, Parse, SyntaxNode};
10 10
11use crate::{ 11use crate::{
12 ast_id_map::AstIdMap, BuiltinExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, 12 ast_id_map::AstIdMap, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId,
13 MacroDefId, MacroDefKind, MacroFile, MacroFileKind, 13 MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, MacroFileKind,
14}; 14};
15 15
16#[derive(Debug, Clone, Eq, PartialEq)] 16#[derive(Debug, Clone, Eq, PartialEq)]
17pub enum TokenExpander { 17pub enum TokenExpander {
18 MacroRules(mbe::MacroRules), 18 MacroRules(mbe::MacroRules),
19 Builtin(BuiltinExpander), 19 Builtin(BuiltinFnLikeExpander),
20} 20}
21 21
22impl TokenExpander { 22impl TokenExpander {
@@ -151,6 +151,7 @@ pub(crate) fn parse_macro(
151 let fragment_kind = match macro_file.macro_file_kind { 151 let fragment_kind = match macro_file.macro_file_kind {
152 MacroFileKind::Items => FragmentKind::Items, 152 MacroFileKind::Items => FragmentKind::Items,
153 MacroFileKind::Expr => FragmentKind::Expr, 153 MacroFileKind::Expr => FragmentKind::Expr,
154 MacroFileKind::Statements => FragmentKind::Statements,
154 }; 155 };
155 let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?; 156 let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?;
156 Some((parse, Arc::new(rev_token_map))) 157 Some((parse, Arc::new(rev_token_map)))
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index 1389f64ce..4f3ccf1d0 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -24,7 +24,10 @@ use ra_syntax::{
24}; 24};
25 25
26use crate::ast_id_map::FileAstId; 26use crate::ast_id_map::FileAstId;
27use crate::builtin_macro::BuiltinExpander; 27use crate::builtin_macro::BuiltinFnLikeExpander;
28
29#[cfg(test)]
30mod test_db;
28 31
29/// Input to the analyzer is a set of files, where each file is identified by 32/// Input to the analyzer is a set of files, where each file is identified by
30/// `FileId` and contains source code. However, another source of source code in 33/// `FileId` and contains source code. However, another source of source code in
@@ -109,6 +112,7 @@ pub struct MacroFile {
109pub enum MacroFileKind { 112pub enum MacroFileKind {
110 Items, 113 Items,
111 Expr, 114 Expr,
115 Statements,
112} 116}
113 117
114/// `MacroCallId` identifies a particular macro invocation, like 118/// `MacroCallId` identifies a particular macro invocation, like
@@ -134,7 +138,7 @@ pub struct MacroDefId {
134#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 138#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
135pub enum MacroDefKind { 139pub enum MacroDefKind {
136 Declarative, 140 Declarative,
137 BuiltIn(BuiltinExpander), 141 BuiltIn(BuiltinFnLikeExpander),
138} 142}
139 143
140#[derive(Debug, Clone, PartialEq, Eq, Hash)] 144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index 1bf17d12b..eaea7a6a8 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -142,4 +142,7 @@ pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
142pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); 142pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
143 143
144// Builtin Macros 144// Builtin Macros
145pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file");
146pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column");
145pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); 147pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line");
148pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify");
diff --git a/crates/ra_hir_expand/src/test_db.rs b/crates/ra_hir_expand/src/test_db.rs
new file mode 100644
index 000000000..d23e75d9e
--- /dev/null
+++ b/crates/ra_hir_expand/src/test_db.rs
@@ -0,0 +1,50 @@
1//! Database used for testing `hir_expand`.
2
3use std::{
4 panic,
5 sync::{Arc, Mutex},
6};
7
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath};
9
10#[salsa::database(
11 ra_db::SourceDatabaseExtStorage,
12 ra_db::SourceDatabaseStorage,
13 crate::db::AstDatabaseStorage
14)]
15#[derive(Debug, Default)]
16pub struct TestDB {
17 runtime: salsa::Runtime<TestDB>,
18 events: Mutex<Option<Vec<salsa::Event<TestDB>>>>,
19}
20
21impl salsa::Database for TestDB {
22 fn salsa_runtime(&self) -> &salsa::Runtime<Self> {
23 &self.runtime
24 }
25
26 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
27 let mut events = self.events.lock().unwrap();
28 if let Some(events) = &mut *events {
29 events.push(event());
30 }
31 }
32}
33
34impl panic::RefUnwindSafe for TestDB {}
35
36impl FileLoader for TestDB {
37 fn file_text(&self, file_id: FileId) -> Arc<String> {
38 FileLoaderDelegate(self).file_text(file_id)
39 }
40 fn resolve_relative_path(
41 &self,
42 anchor: FileId,
43 relative_path: &RelativePath,
44 ) -> Option<FileId> {
45 FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
46 }
47 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
48 FileLoaderDelegate(self).relevant_crates(file_id)
49 }
50}
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index 41ee81511..7c367230e 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -30,7 +30,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
30 let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; 30 let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
31 match callable_def { 31 match callable_def {
32 hir::CallableDef::Function(it) => { 32 hir::CallableDef::Function(it) => {
33 (CallInfo::with_fn(db, it), it.data(db).has_self_param()) 33 (CallInfo::with_fn(db, it), it.has_self_param(db))
34 } 34 }
35 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false), 35 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false),
36 hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false), 36 hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false),
@@ -38,7 +38,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
38 } 38 }
39 FnCallNode::MethodCallExpr(expr) => { 39 FnCallNode::MethodCallExpr(expr) => {
40 let function = analyzer.resolve_method_call(&expr)?; 40 let function = analyzer.resolve_method_call(&expr)?;
41 (CallInfo::with_fn(db, function), function.data(db).has_self_param()) 41 (CallInfo::with_fn(db, function), function.has_self_param(db))
42 } 42 }
43 FnCallNode::MacroCallExpr(expr) => { 43 FnCallNode::MacroCallExpr(expr) => {
44 let macro_def = analyzer.resolve_macro_call(db, &expr)?; 44 let macro_def = analyzer.resolve_macro_call(db, &expr)?;
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 3c607d5b5..8a05b287f 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -313,7 +313,7 @@ impl RootDatabase {
313 hir::db::RawItemsQuery 313 hir::db::RawItemsQuery
314 hir::db::CrateDefMapQuery 314 hir::db::CrateDefMapQuery
315 hir::db::GenericParamsQuery 315 hir::db::GenericParamsQuery
316 hir::db::FnDataQuery 316 hir::db::FunctionDataQuery
317 hir::db::TypeAliasDataQuery 317 hir::db::TypeAliasDataQuery
318 hir::db::ConstDataQuery 318 hir::db::ConstDataQuery
319 hir::db::StaticDataQuery 319 hir::db::StaticDataQuery
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 4e2c497e1..5a3f9b5f6 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -59,8 +59,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
59fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 59fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
60 let mut seen_methods = FxHashSet::default(); 60 let mut seen_methods = FxHashSet::default();
61 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { 61 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
62 let data = func.data(ctx.db); 62 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
63 if data.has_self_param() && seen_methods.insert(data.name().clone()) {
64 acc.add_function(ctx, func); 63 acc.add_function(ctx, func);
65 } 64 }
66 None::<()> 65 None::<()>
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 5d974cf6d..63e25e0bf 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Adt, Either, PathResolution}; 3use hir::{Adt, Either, HasSource, PathResolution};
4use ra_syntax::AstNode; 4use ra_syntax::AstNode;
5use test_utils::tested_by; 5use test_utils::tested_by;
6 6
@@ -27,7 +27,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
27 } 27 }
28 if Some(module) == ctx.module { 28 if Some(module) == ctx.module {
29 if let Some(import) = import { 29 if let Some(import) = import {
30 if let Either::A(use_tree) = module.import_source(ctx.db, import) { 30 if let Either::A(use_tree) = import.source(ctx.db).value {
31 if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { 31 if use_tree.syntax().text_range().contains_inclusive(ctx.offset) {
32 // for `use self::foo<|>`, don't suggest `foo` as a completion 32 // for `use self::foo<|>`, don't suggest `foo` as a completion
33 tested_by!(dont_complete_current_use); 33 tested_by!(dont_complete_current_use);
@@ -53,8 +53,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
53 ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| { 53 ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| {
54 match item { 54 match item {
55 hir::AssocItem::Function(func) => { 55 hir::AssocItem::Function(func) => {
56 let data = func.data(ctx.db); 56 if !func.has_self_param(ctx.db) {
57 if !data.has_self_param() {
58 acc.add_function(ctx, func); 57 acc.add_function(ctx, func);
59 } 58 }
60 } 59 }
@@ -80,8 +79,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
80 for item in t.items(ctx.db) { 79 for item in t.items(ctx.db) {
81 match item { 80 match item {
82 hir::AssocItem::Function(func) => { 81 hir::AssocItem::Function(func) => {
83 let data = func.data(ctx.db); 82 if !func.has_self_param(ctx.db) {
84 if !data.has_self_param() {
85 acc.add_function(ctx, func); 83 acc.add_function(ctx, func);
86 } 84 }
87 } 85 }
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index b20329459..896ad1517 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -1,6 +1,6 @@
1//! This modules takes care of rendering various definitions as completion items. 1//! This modules takes care of rendering various definitions as completion items.
2 2
3use hir::{db::HirDatabase, Attrs, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; 3use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
4use join_to_string::join; 4use join_to_string::join;
5use ra_syntax::ast::NameOwner; 5use ra_syntax::ast::NameOwner;
6use test_utils::tested_by; 6use test_utils::tested_by;
@@ -199,14 +199,17 @@ impl Completions {
199 name: Option<String>, 199 name: Option<String>,
200 func: hir::Function, 200 func: hir::Function,
201 ) { 201 ) {
202 let data = func.data(ctx.db); 202 let func_name = func.name(ctx.db);
203 let name = name.unwrap_or_else(|| data.name().to_string()); 203 let has_self_param = func.has_self_param(ctx.db);
204 let params = func.params(ctx.db);
205
206 let name = name.unwrap_or_else(|| func_name.to_string());
204 let ast_node = func.source(ctx.db).value; 207 let ast_node = func.source(ctx.db).value;
205 let detail = function_label(&ast_node); 208 let detail = function_label(&ast_node);
206 209
207 let mut builder = 210 let mut builder =
208 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) 211 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
209 .kind(if data.has_self_param() { 212 .kind(if has_self_param {
210 CompletionItemKind::Method 213 CompletionItemKind::Method
211 } else { 214 } else {
212 CompletionItemKind::Function 215 CompletionItemKind::Function
@@ -221,12 +224,11 @@ impl Completions {
221 && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") 224 && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
222 { 225 {
223 tested_by!(inserts_parens_for_function_calls); 226 tested_by!(inserts_parens_for_function_calls);
224 let (snippet, label) = 227 let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 {
225 if data.params().is_empty() || data.has_self_param() && data.params().len() == 1 { 228 (format!("{}()$0", func_name), format!("{}()", name))
226 (format!("{}()$0", data.name()), format!("{}()", name)) 229 } else {
227 } else { 230 (format!("{}($0)", func_name), format!("{}(…)", name))
228 (format!("{}($0)", data.name()), format!("{}(…)", name)) 231 };
229 };
230 builder = builder.lookup_by(name).label(label).insert_snippet(snippet); 232 builder = builder.lookup_by(name).label(label).insert_snippet(snippet);
231 } 233 }
232 234
@@ -285,11 +287,8 @@ impl Completions {
285 } 287 }
286} 288}
287 289
288fn is_deprecated(node: impl Attrs, db: &impl HirDatabase) -> bool { 290fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool {
289 match node.attrs(db) { 291 node.attrs(db).has_atom("deprecated")
290 None => false,
291 Some(attrs) => attrs.iter().any(|x| x.is_simple_atom("deprecated")),
292 }
293} 292}
294 293
295fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { 294fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index c96465b6a..c2a9dcdd1 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -22,7 +22,6 @@ use crate::{
22 hir::db::InternDatabaseStorage, 22 hir::db::InternDatabaseStorage,
23 hir::db::AstDatabaseStorage, 23 hir::db::AstDatabaseStorage,
24 hir::db::DefDatabaseStorage, 24 hir::db::DefDatabaseStorage,
25 hir::db::DefDatabase2Storage,
26 hir::db::HirDatabaseStorage 25 hir::db::HirDatabaseStorage
27)] 26)]
28#[derive(Debug)] 27#[derive(Debug)]
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index f42dffc87..d96de4e4c 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide_api/src/display/function_signature.rs
@@ -55,7 +55,7 @@ impl FunctionSignature {
55 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option<Self> { 55 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option<Self> {
56 let node: ast::StructDef = st.source(db).value; 56 let node: ast::StructDef = st.source(db).value;
57 match node.kind() { 57 match node.kind() {
58 ast::StructKind::Named(_) => return None, 58 ast::StructKind::Record(_) => return None,
59 _ => (), 59 _ => (),
60 }; 60 };
61 61
@@ -89,7 +89,7 @@ impl FunctionSignature {
89 ) -> Option<Self> { 89 ) -> Option<Self> {
90 let node: ast::EnumVariant = variant.source(db).value; 90 let node: ast::EnumVariant = variant.source(db).value;
91 match node.kind() { 91 match node.kind() {
92 ast::StructKind::Named(_) | ast::StructKind::Unit => return None, 92 ast::StructKind::Record(_) | ast::StructKind::Unit => return None,
93 _ => (), 93 _ => (),
94 }; 94 };
95 95
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs
index 7f39262dc..673301b10 100644
--- a/crates/ra_ide_api/src/expand_macro.rs
+++ b/crates/ra_ide_api/src/expand_macro.rs
@@ -40,7 +40,7 @@ fn expand_macro_recur(
40 let analyzer = hir::SourceAnalyzer::new(db, source, None); 40 let analyzer = hir::SourceAnalyzer::new(db, source, None);
41 let expansion = analyzer.expand(db, macro_call)?; 41 let expansion = analyzer.expand(db, macro_call)?;
42 let macro_file_id = expansion.file_id(); 42 let macro_file_id = expansion.file_id();
43 let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?; 43 let mut expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?;
44 44
45 let children = expanded.descendants().filter_map(ast::MacroCall::cast); 45 let children = expanded.descendants().filter_map(ast::MacroCall::cast);
46 let mut replaces = FxHashMap::default(); 46 let mut replaces = FxHashMap::default();
@@ -49,7 +49,14 @@ fn expand_macro_recur(
49 let node = hir::Source::new(macro_file_id, &child); 49 let node = hir::Source::new(macro_file_id, &child);
50 let new_node = expand_macro_recur(db, source, node)?; 50 let new_node = expand_macro_recur(db, source, node)?;
51 51
52 replaces.insert(child.syntax().clone().into(), new_node.into()); 52 // Replace the whole node if it is root
53 // `replace_descendants` will not replace the parent node
54 // but `SyntaxNode::descendants include itself
55 if expanded == *child.syntax() {
56 expanded = new_node;
57 } else {
58 replaces.insert(child.syntax().clone().into(), new_node.into());
59 }
53 } 60 }
54 61
55 Some(replace_descendants(&expanded, &replaces)) 62 Some(replace_descendants(&expanded, &replaces))
@@ -84,24 +91,19 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
84 }; 91 };
85 92
86 res += &match token.kind() { 93 res += &match token.kind() {
87 k @ _ 94 k @ _ if is_text(k) && is_next(|it| !it.is_punct(), true) => {
88 if (k.is_keyword() || k.is_literal() || k == IDENT)
89 && is_next(|it| !it.is_punct(), true) =>
90 {
91 token.text().to_string() + " " 95 token.text().to_string() + " "
92 } 96 }
93 L_CURLY if is_next(|it| it != R_CURLY, true) => { 97 L_CURLY if is_next(|it| it != R_CURLY, true) => {
94 indent += 1; 98 indent += 1;
95 format!(" {{\n{}", " ".repeat(indent)) 99 let leading_space = if is_last(|it| is_text(it), false) { " " } else { "" };
100 format!("{}{{\n{}", leading_space, " ".repeat(indent))
96 } 101 }
97 R_CURLY if is_last(|it| it != L_CURLY, true) => { 102 R_CURLY if is_last(|it| it != L_CURLY, true) => {
98 indent = indent.checked_sub(1).unwrap_or(0); 103 indent = indent.checked_sub(1).unwrap_or(0);
99 format!("\n}}{}", " ".repeat(indent)) 104 format!("\n{}}}", " ".repeat(indent))
100 }
101 R_CURLY => {
102 indent = indent.checked_sub(1).unwrap_or(0);
103 format!("}}\n{}", " ".repeat(indent))
104 } 105 }
106 R_CURLY => format!("}}\n{}", " ".repeat(indent)),
105 T![;] => format!(";\n{}", " ".repeat(indent)), 107 T![;] => format!(";\n{}", " ".repeat(indent)),
106 T![->] => " -> ".to_string(), 108 T![->] => " -> ".to_string(),
107 T![=] => " = ".to_string(), 109 T![=] => " = ".to_string(),
@@ -112,7 +114,11 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
112 last = Some(token.kind()); 114 last = Some(token.kind());
113 } 115 }
114 116
115 res 117 return res;
118
119 fn is_text(k: SyntaxKind) -> bool {
120 k.is_keyword() || k.is_literal() || k == IDENT
121 }
116} 122}
117 123
118#[cfg(test)] 124#[cfg(test)]
@@ -175,4 +181,70 @@ fn some_thing() -> u32 {
175} 181}
176"###); 182"###);
177 } 183 }
184
185 #[test]
186 fn macro_expand_match_ast() {
187 let res = check_expand_macro(
188 r#"
189 //- /lib.rs
190 macro_rules! match_ast {
191 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
192
193 (match ($node:expr) {
194 $( ast::$ast:ident($it:ident) => $res:block, )*
195 _ => $catch_all:expr $(,)?
196 }) => {{
197 $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )*
198 { $catch_all }
199 }};
200 }
201
202 fn main() {
203 mat<|>ch_ast! {
204 match container {
205 ast::TraitDef(it) => {},
206 ast::ImplBlock(it) => {},
207 _ => { continue },
208 }
209 }
210 }
211 "#,
212 );
213
214 assert_eq!(res.name, "match_ast");
215 assert_snapshot!(res.expansion, @r###"
216{
217 if let Some(it) = ast::TraitDef::cast(container.clone()){}
218 else if let Some(it) = ast::ImplBlock::cast(container.clone()){}
219 else {
220 {
221 continue
222 }
223 }
224}
225"###);
226 }
227
228 #[test]
229 fn macro_expand_match_ast_inside_let_statement() {
230 let res = check_expand_macro(
231 r#"
232 //- /lib.rs
233 macro_rules! match_ast {
234 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
235 (match ($node:expr) {}) => {{}};
236 }
237
238 fn main() {
239 let p = f(|it| {
240 let res = mat<|>ch_ast! { match c {}};
241 Some(res)
242 })?;
243 }
244 "#,
245 );
246
247 assert_eq!(res.name, "match_ast");
248 assert_snapshot!(res.expansion, @r###"{}"###);
249 }
178} 250}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 62ad996bc..cb6c24eaa 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -54,7 +54,7 @@ use std::sync::Arc;
54use ra_cfg::CfgOptions; 54use ra_cfg::CfgOptions;
55use ra_db::{ 55use ra_db::{
56 salsa::{self, ParallelDatabase}, 56 salsa::{self, ParallelDatabase},
57 CheckCanceled, FileLoader, SourceDatabase, 57 CheckCanceled, Env, FileLoader, SourceDatabase,
58}; 58};
59use ra_syntax::{SourceFile, TextRange, TextUnit}; 59use ra_syntax::{SourceFile, TextRange, TextUnit};
60 60
@@ -240,7 +240,7 @@ impl Analysis {
240 // Default to enable test for single file. 240 // Default to enable test for single file.
241 let mut cfg_options = CfgOptions::default(); 241 let mut cfg_options = CfgOptions::default();
242 cfg_options.insert_atom("test".into()); 242 cfg_options.insert_atom("test".into());
243 crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options); 243 crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options, Env::default());
244 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); 244 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text));
245 change.set_crate_graph(crate_graph); 245 change.set_crate_graph(crate_graph);
246 host.apply_change(change); 246 host.apply_change(change);
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs
index 2b1c96dbf..bf8a54932 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide_api/src/mock_analysis.rs
@@ -3,7 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_cfg::CfgOptions; 5use ra_cfg::CfgOptions;
6use ra_db::RelativePathBuf; 6use ra_db::{Env, RelativePathBuf};
7use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; 7use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
8 8
9use crate::{ 9use crate::{
@@ -96,9 +96,15 @@ impl MockAnalysis {
96 let file_id = FileId(i as u32 + 1); 96 let file_id = FileId(i as u32 + 1);
97 let cfg_options = CfgOptions::default(); 97 let cfg_options = CfgOptions::default();
98 if path == "/lib.rs" || path == "/main.rs" { 98 if path == "/lib.rs" || path == "/main.rs" {
99 root_crate = Some(crate_graph.add_crate_root(file_id, Edition2018, cfg_options)); 99 root_crate = Some(crate_graph.add_crate_root(
100 file_id,
101 Edition2018,
102 cfg_options,
103 Env::default(),
104 ));
100 } else if path.ends_with("/lib.rs") { 105 } else if path.ends_with("/lib.rs") {
101 let other_crate = crate_graph.add_crate_root(file_id, Edition2018, cfg_options); 106 let other_crate =
107 crate_graph.add_crate_root(file_id, Edition2018, cfg_options, Env::default());
102 let crate_name = path.parent().unwrap().file_name().unwrap(); 108 let crate_name = path.parent().unwrap().file_name().unwrap();
103 if let Some(root_crate) = root_crate { 109 if let Some(root_crate) = root_crate {
104 crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap(); 110 crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap();
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs
index fa232a379..6027e7d54 100644
--- a/crates/ra_ide_api/src/parent_module.rs
+++ b/crates/ra_ide_api/src/parent_module.rs
@@ -34,12 +34,14 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
34 34
35#[cfg(test)] 35#[cfg(test)]
36mod tests { 36mod tests {
37 use ra_cfg::CfgOptions;
38 use ra_db::Env;
39
37 use crate::{ 40 use crate::{
38 mock_analysis::{analysis_and_position, MockAnalysis}, 41 mock_analysis::{analysis_and_position, MockAnalysis},
39 AnalysisChange, CrateGraph, 42 AnalysisChange, CrateGraph,
40 Edition::Edition2018, 43 Edition::Edition2018,
41 }; 44 };
42 use ra_cfg::CfgOptions;
43 45
44 #[test] 46 #[test]
45 fn test_resolve_parent_module() { 47 fn test_resolve_parent_module() {
@@ -87,7 +89,12 @@ mod tests {
87 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); 89 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
88 90
89 let mut crate_graph = CrateGraph::default(); 91 let mut crate_graph = CrateGraph::default();
90 let crate_id = crate_graph.add_crate_root(root_file, Edition2018, CfgOptions::default()); 92 let crate_id = crate_graph.add_crate_root(
93 root_file,
94 Edition2018,
95 CfgOptions::default(),
96 Env::default(),
97 );
91 let mut change = AnalysisChange::new(); 98 let mut change = AnalysisChange::new();
92 change.set_crate_graph(crate_graph); 99 change.set_crate_graph(crate_graph);
93 host.apply_change(change); 100 host.apply_change(change);
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs
index d51132f73..21e5be9b3 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide_api/src/typing.rs
@@ -40,9 +40,13 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
40 } 40 }
41 41
42 let prefix = comment.prefix(); 42 let prefix = comment.prefix();
43 if position.offset 43 let comment_range = comment.syntax().text_range();
44 < comment.syntax().text_range().start() + TextUnit::of_str(prefix) + TextUnit::from(1) 44 if position.offset < comment_range.start() + TextUnit::of_str(prefix) + TextUnit::from(1) {
45 { 45 return None;
46 }
47
48 // Continuing non-doc line comments (like this one :) ) is annoying
49 if prefix == "//" && comment_range.end() == position.offset {
46 return None; 50 return None;
47 } 51 }
48 52
@@ -247,6 +251,30 @@ impl S {
247} 251}
248", 252",
249 ); 253 );
254 do_check(
255 r"
256fn main() {
257 // Fix<|> me
258 let x = 1 + 1;
259}
260",
261 r"
262fn main() {
263 // Fix
264 // <|> me
265 let x = 1 + 1;
266}
267",
268 );
269 do_check_noop(
270 r"
271fn main() {
272 // Fix me<|>
273 let x = 1 + 1;
274}
275",
276 );
277
250 do_check_noop(r"<|>//! docz"); 278 do_check_noop(r"<|>//! docz");
251 } 279 }
252 280
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index 0e5dbbbd5..9c36402b0 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -1,6 +1,26 @@
1//! FIXME: write short doc here 1//! Implementation of the LSP for rust-analyzer.
2 2//!
3//! This crate takes Rust-specific analysis results from ra_ide_api and
4//! translates into LSP types.
5//!
6//! It also is the root of all state. `world` module defines the bulk of the
7//! state, and `main_loop` module defines the rules for modifying it.
3#![recursion_limit = "512"] 8#![recursion_limit = "512"]
9
10#[allow(unused)]
11macro_rules! println {
12 ($($tt:tt)*) => {
13 compile_error!("stdout is locked, use eprintln")
14 };
15}
16
17#[allow(unused)]
18macro_rules! print {
19 ($($tt:tt)*) => {
20 compile_error!("stdout is locked, use eprint")
21 };
22}
23
4mod caps; 24mod caps;
5mod cargo_target_spec; 25mod cargo_target_spec;
6mod conv; 26mod conv;
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index 7d9a1d054..e13c8ca14 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -1,8 +1,7 @@
1//! FIXME: write short doc here 1//! `ra_lsp_server` binary
2 2
3use flexi_logger::{Duplicate, Logger}; 3use flexi_logger::{Duplicate, Logger};
4use lsp_server::Connection; 4use lsp_server::Connection;
5
6use ra_lsp_server::{show_message, Result, ServerConfig}; 5use ra_lsp_server::{show_message, Result, ServerConfig};
7use ra_prof; 6use ra_prof;
8 7
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index d1c49c0b3..1de399fee 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -5,6 +5,7 @@ use ra_syntax::{
5 ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, 5 ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode,
6 SyntaxTreeBuilder, TextRange, TextUnit, T, 6 SyntaxTreeBuilder, TextRange, TextUnit, T,
7}; 7};
8use std::iter::successors;
8use tt::buffer::{Cursor, TokenBuffer}; 9use tt::buffer::{Cursor, TokenBuffer};
9 10
10use crate::subtree_source::SubtreeTokenSource; 11use crate::subtree_source::SubtreeTokenSource;
@@ -160,6 +161,31 @@ impl Convertor {
160 161
161 let first_child = tt.first_child_or_token()?; 162 let first_child = tt.first_child_or_token()?;
162 let last_child = tt.last_child_or_token()?; 163 let last_child = tt.last_child_or_token()?;
164
165 // ignore trivial first_child and last_child
166 let first_child = successors(Some(first_child), |it| {
167 if it.kind().is_trivia() {
168 it.next_sibling_or_token()
169 } else {
170 None
171 }
172 })
173 .last()
174 .unwrap();
175 if first_child.kind().is_trivia() {
176 return Some(tt::Subtree { token_trees: vec![], delimiter: tt::Delimiter::None });
177 }
178
179 let last_child = successors(Some(last_child), |it| {
180 if it.kind().is_trivia() {
181 it.prev_sibling_or_token()
182 } else {
183 None
184 }
185 })
186 .last()
187 .unwrap();
188
163 let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) { 189 let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) {
164 (T!['('], T![')']) => (tt::Delimiter::Parenthesis, true), 190 (T!['('], T![')']) => (tt::Delimiter::Parenthesis, true),
165 (T!['{'], T!['}']) => (tt::Delimiter::Brace, true), 191 (T!['{'], T!['}']) => (tt::Delimiter::Brace, true),
@@ -363,6 +389,7 @@ mod tests {
363 use super::*; 389 use super::*;
364 use crate::tests::{create_rules, expand}; 390 use crate::tests::{create_rules, expand};
365 use ra_parser::TokenSource; 391 use ra_parser::TokenSource;
392 use ra_syntax::algo::{insert_children, InsertPosition};
366 393
367 #[test] 394 #[test]
368 fn convert_tt_token_source() { 395 fn convert_tt_token_source() {
@@ -423,4 +450,45 @@ mod tests {
423 let expansion = expand(&rules, "stmts!();"); 450 let expansion = expand(&rules, "stmts!();");
424 assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); 451 assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err());
425 } 452 }
453
454 #[test]
455 fn test_token_tree_last_child_is_white_space() {
456 let source_file = ast::SourceFile::parse("f!({} );").ok().unwrap();
457 let macro_call = source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
458 let token_tree = macro_call.token_tree().unwrap();
459
460 // Token Tree now is :
461 // TokenTree
462 // - T!['(']
463 // - TokenTree
464 // - T!['{']
465 // - T!['}']
466 // - WHITE_SPACE
467 // - T![')']
468
469 let rbrace =
470 token_tree.syntax().descendants_with_tokens().find(|it| it.kind() == T!['}']).unwrap();
471 let space = token_tree
472 .syntax()
473 .descendants_with_tokens()
474 .find(|it| it.kind() == SyntaxKind::WHITESPACE)
475 .unwrap();
476
477 // reorder th white space, such that the white is inside the inner token-tree.
478 let token_tree = insert_children(
479 &rbrace.parent().unwrap(),
480 InsertPosition::Last,
481 &mut std::iter::once(space),
482 );
483
484 // Token Tree now is :
485 // TokenTree
486 // - T!['{']
487 // - T!['}']
488 // - WHITE_SPACE
489 let token_tree = ast::TokenTree::cast(token_tree).unwrap();
490 let tt = ast_to_token_tree(&token_tree).unwrap().0;
491
492 assert_eq!(tt.delimiter, tt::Delimiter::Brace);
493 }
426} 494}
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index cf88911b7..c128e608d 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -1,7 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::path::{Path, PathBuf}; 3use std::path::{Path, PathBuf};
4use std::str::FromStr;
5 4
6use cargo_metadata::{CargoOpt, MetadataCommand}; 5use cargo_metadata::{CargoOpt, MetadataCommand};
7use ra_arena::{impl_arena_id, Arena, RawId}; 6use ra_arena::{impl_arena_id, Arena, RawId};
@@ -143,8 +142,7 @@ impl CargoWorkspace {
143 for meta_pkg in meta.packages { 142 for meta_pkg in meta.packages {
144 let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg; 143 let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg;
145 let is_member = ws_members.contains(&id); 144 let is_member = ws_members.contains(&id);
146 let edition = Edition::from_str(&edition) 145 let edition = edition.parse::<Edition>()?;
147 .map_err(|e| (format!("metadata for package {} failed: {}", &name, e.msg)))?;
148 let pkg = packages.alloc(PackageData { 146 let pkg = packages.alloc(PackageData {
149 name, 147 name,
150 manifest: manifest_path, 148 manifest: manifest_path,
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 0e14f1b70..d04a8cbe2 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -13,7 +13,7 @@ use std::{
13}; 13};
14 14
15use ra_cfg::CfgOptions; 15use ra_cfg::CfgOptions;
16use ra_db::{CrateGraph, CrateId, Edition, FileId}; 16use ra_db::{CrateGraph, CrateId, Edition, Env, FileId};
17use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
18use serde_json::from_reader; 18use serde_json::from_reader;
19 19
@@ -146,7 +146,12 @@ impl ProjectWorkspace {
146 }; 146 };
147 crates.insert( 147 crates.insert(
148 crate_id, 148 crate_id,
149 crate_graph.add_crate_root(file_id, edition, cfg_options), 149 crate_graph.add_crate_root(
150 file_id,
151 edition,
152 cfg_options,
153 Env::default(),
154 ),
150 ); 155 );
151 } 156 }
152 } 157 }
@@ -180,8 +185,12 @@ impl ProjectWorkspace {
180 opts 185 opts
181 }; 186 };
182 187
183 let crate_id = 188 let crate_id = crate_graph.add_crate_root(
184 crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options); 189 file_id,
190 Edition::Edition2018,
191 cfg_options,
192 Env::default(),
193 );
185 sysroot_crates.insert(krate, crate_id); 194 sysroot_crates.insert(krate, crate_id);
186 names.insert(crate_id, krate.name(&sysroot).to_string()); 195 names.insert(crate_id, krate.name(&sysroot).to_string());
187 } 196 }
@@ -216,8 +225,12 @@ impl ProjectWorkspace {
216 opts.insert_features(pkg.features(&cargo).iter().map(Into::into)); 225 opts.insert_features(pkg.features(&cargo).iter().map(Into::into));
217 opts 226 opts
218 }; 227 };
219 let crate_id = 228 let crate_id = crate_graph.add_crate_root(
220 crate_graph.add_crate_root(file_id, edition, cfg_options); 229 file_id,
230 edition,
231 cfg_options,
232 Env::default(),
233 );
221 names.insert(crate_id, pkg.name(&cargo).to_string()); 234 names.insert(crate_id, pkg.name(&cargo).to_string());
222 if tgt.kind(&cargo) == TargetKind::Lib { 235 if tgt.kind(&cargo) == TargetKind::Lib {
223 lib_tgt = Some(crate_id); 236 lib_tgt = Some(crate_id);
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 4851dacb2..513ed7920 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -178,15 +178,15 @@ impl ast::ImplBlock {
178 178
179#[derive(Debug, Clone, PartialEq, Eq)] 179#[derive(Debug, Clone, PartialEq, Eq)]
180pub enum StructKind { 180pub enum StructKind {
181 Record(ast::RecordFieldDefList),
181 Tuple(ast::TupleFieldDefList), 182 Tuple(ast::TupleFieldDefList),
182 Named(ast::RecordFieldDefList),
183 Unit, 183 Unit,
184} 184}
185 185
186impl StructKind { 186impl StructKind {
187 fn from_node<N: AstNode>(node: &N) -> StructKind { 187 fn from_node<N: AstNode>(node: &N) -> StructKind {
188 if let Some(nfdl) = child_opt::<_, ast::RecordFieldDefList>(node) { 188 if let Some(nfdl) = child_opt::<_, ast::RecordFieldDefList>(node) {
189 StructKind::Named(nfdl) 189 StructKind::Record(nfdl)
190 } else if let Some(pfl) = child_opt::<_, ast::TupleFieldDefList>(node) { 190 } else if let Some(pfl) = child_opt::<_, ast::TupleFieldDefList>(node) {
191 StructKind::Tuple(pfl) 191 StructKind::Tuple(pfl)
192 } else { 192 } else {