diff options
Diffstat (limited to 'crates')
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; | |||
8 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | 8 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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 | ||
9 | use rustc_hash::FxHashMap; | 9 | use std::{fmt, str::FromStr}; |
10 | 10 | ||
11 | use ra_cfg::CfgOptions; | 11 | use ra_cfg::CfgOptions; |
12 | use ra_syntax::SmolStr; | 12 | use ra_syntax::SmolStr; |
13 | use rustc_hash::FxHashMap; | ||
13 | use rustc_hash::FxHashSet; | 14 | use rustc_hash::FxHashSet; |
14 | 15 | ||
15 | use crate::{RelativePath, RelativePathBuf}; | 16 | use crate::{RelativePath, RelativePathBuf}; |
16 | use 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)] | ||
84 | pub struct CyclicDependencies; | ||
85 | |||
86 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 83 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
87 | pub struct CrateId(pub u32); | 84 | pub struct CrateId(pub u32); |
88 | 85 | ||
89 | impl 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)] | ||
96 | pub enum Edition { | ||
97 | Edition2018, | ||
98 | Edition2015, | ||
99 | } | ||
100 | |||
101 | #[derive(Debug)] | ||
102 | pub struct ParseEditionError { | ||
103 | pub msg: String, | ||
104 | } | ||
105 | |||
106 | impl 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)] |
118 | struct CrateData { | 87 | struct 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 | ||
125 | impl CrateData { | 95 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
126 | fn new(file_id: FileId, edition: Edition, cfg_options: CfgOptions) -> CrateData { | 96 | pub 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 }) | 102 | pub 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 | ||
141 | impl Dependency { | ||
142 | pub fn crate_id(&self) -> CrateId { | ||
143 | self.crate_id | ||
144 | } | ||
145 | } | ||
146 | |||
147 | impl CrateGraph { | 112 | impl 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 | ||
209 | impl CrateId { | ||
210 | pub fn shift(self, amount: u32) -> CrateId { | ||
211 | CrateId(self.0 + amount) | ||
212 | } | ||
213 | } | ||
214 | |||
215 | impl 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 | |||
225 | impl 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 | |||
238 | impl Dependency { | ||
239 | pub fn crate_id(&self) -> CrateId { | ||
240 | self.crate_id | ||
241 | } | ||
242 | } | ||
243 | |||
244 | #[derive(Debug)] | ||
245 | pub struct ParseEditionError { | ||
246 | invalid_input: String, | ||
247 | } | ||
248 | |||
249 | impl 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 | |||
255 | impl std::error::Error for ParseEditionError {} | ||
256 | |||
257 | #[derive(Debug)] | ||
258 | pub struct CyclicDependenciesError; | ||
259 | |||
242 | #[cfg(test)] | 260 | #[cfg(test)] |
243 | mod tests { | 261 | mod 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 | ||
11 | pub use crate::{ | 11 | pub 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 | }; |
15 | pub use relative_path::{RelativePath, RelativePathBuf}; | 15 | pub use relative_path::{RelativePath, RelativePathBuf}; |
16 | pub use salsa; | 16 | pub 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 | ||
3 | pub(crate) mod src; | 3 | pub(crate) mod src; |
4 | pub(crate) mod docs; | ||
5 | pub(crate) mod attrs; | ||
6 | 4 | ||
7 | use std::sync::Arc; | 5 | use 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 | }; |
20 | use hir_expand::{ | 18 | use hir_expand::{ |
21 | diagnostics::DiagnosticSink, | 19 | diagnostics::DiagnosticSink, |
22 | name::{self, AsName}, | 20 | name::{self, AsName}, |
21 | AstId, | ||
23 | }; | 22 | }; |
24 | use ra_db::{CrateId, Edition}; | 23 | use ra_db::{CrateId, Edition, FileId, FilePosition}; |
25 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 24 | use ra_syntax::{ast, AstNode, SyntaxNode}; |
26 | 25 | ||
27 | use crate::{ | 26 | use 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 | ||
82 | pub enum ModuleSource { | ||
83 | SourceFile(ast::SourceFile), | ||
84 | Module(ast::Module), | ||
85 | } | ||
86 | |||
87 | impl 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)] |
84 | pub struct Module { | 141 | pub 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 | ||
114 | pub use hir_def::ModuleSource; | 171 | pub use hir_def::attr::Attrs; |
115 | 172 | ||
116 | impl Module { | 173 | impl 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 | ||
289 | pub 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)] |
242 | pub struct StructField { | 295 | pub 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)] | ||
565 | pub 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 | |||
574 | impl 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 | |||
635 | impl Function { | 617 | impl 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)] | ||
752 | pub struct ConstData { | ||
753 | pub(crate) name: Option<Name>, | ||
754 | pub(crate) type_ref: TypeRef, | ||
755 | } | ||
756 | |||
757 | impl 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 | |||
783 | fn 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)] |
791 | pub struct Static { | 734 | pub 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)] | ||
1050 | pub 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 | |||
1063 | impl_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 | |||
1076 | pub trait HasAttrs { | ||
1077 | fn attrs(self, db: &impl DefDatabase) -> Attrs; | ||
1078 | } | ||
1079 | |||
1080 | impl<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 | |||
1087 | pub trait Docs { | ||
1088 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>; | ||
1089 | } | ||
1090 | impl<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 | |||
3 | use crate::{ | ||
4 | db::{AstDatabase, DefDatabase, HirDatabase}, | ||
5 | Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static, | ||
6 | Struct, StructField, Trait, TypeAlias, Union, | ||
7 | }; | ||
8 | use hir_def::attr::Attr; | ||
9 | use hir_expand::hygiene::Hygiene; | ||
10 | use ra_syntax::ast; | ||
11 | use std::sync::Arc; | ||
12 | |||
13 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
14 | pub 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 | |||
27 | impl_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 | |||
40 | pub trait Attrs { | ||
41 | fn attrs(&self, db: &impl HirDatabase) -> Option<Arc<[Attr]>>; | ||
42 | } | ||
43 | |||
44 | pub(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 | |||
77 | fn attrs_from_ast<T, D>(node: T, db: &D) -> Option<Arc<[Attr]>> | ||
78 | where | ||
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 | |||
88 | impl<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 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use ra_syntax::ast; | ||
6 | |||
7 | use 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)] | ||
14 | pub 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 | |||
27 | impl_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)] | ||
42 | pub struct Documentation(Arc<str>); | ||
43 | |||
44 | impl 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 | |||
54 | impl Into<String> for Documentation { | ||
55 | fn into(self) -> String { | ||
56 | self.as_str().to_owned() | ||
57 | } | ||
58 | } | ||
59 | |||
60 | pub trait Docs { | ||
61 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>; | ||
62 | } | ||
63 | |||
64 | pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> { | ||
65 | node.doc_comment_text().map(|it| Documentation::new(&it)) | ||
66 | } | ||
67 | |||
68 | pub(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 | |||
93 | impl<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 | ||
3 | use hir_def::{HasSource as _, Lookup}; | 3 | use hir_def::{HasChildSource, HasSource as _, Lookup, VariantId}; |
4 | use hir_expand::either::Either; | ||
4 | use ra_syntax::ast::{self, AstNode}; | 5 | use ra_syntax::ast::{self, AstNode}; |
5 | 6 | ||
6 | use crate::{ | 7 | use 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 | ||
13 | pub use hir_expand::Source; | 14 | pub use hir_expand::Source; |
14 | 15 | ||
15 | pub trait HasSource { | 16 | pub 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. |
22 | impl Module { | 23 | impl 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 | ||
46 | impl HasSource for StructField { | 42 | impl 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 | } |
78 | impl HasSource for Struct { | 53 | impl 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 | } |
84 | impl HasSource for Union { | 59 | impl 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 | } |
90 | impl HasSource for Enum { | 65 | impl 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 | } |
96 | impl HasSource for EnumVariant { | 71 | impl 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 | } |
113 | impl HasSource for Function { | 77 | impl 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 | } |
119 | impl HasSource for Const { | 83 | impl 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 | } |
125 | impl HasSource for Static { | 89 | impl 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 | } |
131 | impl HasSource for Trait { | 95 | impl 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 | } |
137 | impl HasSource for TypeAlias { | 101 | impl 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 | } |
143 | impl HasSource for MacroDef { | 107 | impl 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 | } |
113 | impl 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 | ||
150 | pub trait HasBodySource: HasBody + HasSource | 126 | pub trait HasBodySource: HasBody + HasSource |
151 | where | 127 | where |
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 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_def::attr::Attr; | ||
6 | use ra_db::salsa; | 5 | use ra_db::salsa; |
7 | use ra_syntax::SmolStr; | ||
8 | 6 | ||
9 | use crate::{ | 7 | use 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 | ||
24 | pub use hir_def::db::{ | 18 | pub 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 | }; |
30 | pub use hir_expand::db::{ | 25 | pub 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)] | ||
38 | pub 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)] |
69 | pub trait HirDatabase: DefDatabase + AstDatabase { | 32 | pub 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 | ||
6 | use hir_def::{ | 6 | use 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 | ||
11 | use crate::{ | 11 | use 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 | ||
17 | impl From<ra_db::CrateId> for Crate { | 17 | impl From<ra_db::CrateId> for Crate { |
@@ -70,6 +70,12 @@ impl From<EnumVariantId> for EnumVariant { | |||
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | impl From<EnumVariant> for EnumVariantId { | ||
74 | fn from(def: EnumVariant) -> Self { | ||
75 | EnumVariantId { parent: def.parent.id, local_id: def.id } | ||
76 | } | ||
77 | } | ||
78 | |||
73 | impl From<ModuleDefId> for ModuleDef { | 79 | impl 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 | |||
229 | impl 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 | |||
238 | impl From<StructField> for StructFieldId { | ||
239 | fn from(def: StructField) -> Self { | ||
240 | StructFieldId { parent: def.parent.into(), local_id: def.id } | ||
241 | } | ||
242 | } | ||
243 | |||
244 | impl 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 | ||
19 | impl ImplBlock { | 19 | impl 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 | |||
3 | use rustc_hash::FxHashMap; | ||
4 | use std::sync::Arc; | ||
5 | |||
6 | use ra_syntax::{ast::AttrsOwner, SmolStr}; | ||
7 | |||
8 | use 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)] | ||
14 | pub enum LangItemTarget { | ||
15 | Enum(Enum), | ||
16 | Function(Function), | ||
17 | ImplBlock(ImplBlock), | ||
18 | Static(Static), | ||
19 | Struct(Struct), | ||
20 | Trait(Trait), | ||
21 | } | ||
22 | |||
23 | impl 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)] | ||
37 | pub struct LangItems { | ||
38 | items: FxHashMap<SmolStr, LangItemTarget>, | ||
39 | } | ||
40 | |||
41 | impl 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 | |||
154 | fn 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; | |||
32 | pub mod source_binder; | 32 | pub mod source_binder; |
33 | 33 | ||
34 | mod ids; | 34 | mod ids; |
35 | mod type_alias; | ||
36 | mod ty; | 35 | mod ty; |
37 | mod impl_block; | 36 | mod impl_block; |
38 | mod expr; | 37 | mod expr; |
39 | mod lang_item; | ||
40 | pub mod diagnostics; | 38 | pub mod diagnostics; |
41 | mod util; | 39 | mod util; |
42 | 40 | ||
@@ -52,13 +50,11 @@ mod marks; | |||
52 | 50 | ||
53 | pub use crate::{ | 51 | pub 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 | ||
74 | pub use hir_def::{ | 70 | pub 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 | ||
133 | pub struct Expansion { | 133 | pub 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 | ||
548 | fn 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 | ||
3 | use std::{panic, sync::Arc}; | 3 | use std::{panic, sync::Arc}; |
4 | 4 | ||
5 | use hir_def::{db::DefDatabase2, ModuleId}; | 5 | use hir_def::{db::DefDatabase, ModuleId}; |
6 | use hir_expand::diagnostics::DiagnosticSink; | 6 | use hir_expand::diagnostics::DiagnosticSink; |
7 | use parking_lot::Mutex; | 7 | use parking_lot::Mutex; |
8 | use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase}; | 8 | use 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 | ||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use hir_def::resolver::Resolver; | 8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; |
9 | use hir_expand::name; | 9 | use hir_expand::name; |
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | 11 | ||
12 | use crate::{db::HirDatabase, Trait}; | ||
13 | |||
12 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; | 14 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; |
13 | use crate::db::HirDatabase; | ||
14 | 15 | ||
15 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 16 | const 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}; | |||
22 | use rustc_hash::FxHashMap; | 22 | use rustc_hash::FxHashMap; |
23 | 23 | ||
24 | use hir_def::{ | 24 | use 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 | ||
50 | macro_rules! ty_app { | 51 | macro_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 | ||
7 | use hir_def::resolver::Resolver; | 7 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
10 | 10 | ||
11 | use crate::{ | 11 | use 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 | ||
624 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | 624 | fn 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. |
641 | fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { | 641 | fn 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. |
649 | fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { | 649 | fn 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 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::resolver::Resolver; | 8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef}; |
9 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
10 | 10 | ||
11 | use crate::{ | 11 | use 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] | ||
4862 | fn infer_builtin_macros_file() { | ||
4863 | assert_snapshot!( | ||
4864 | infer(r#" | ||
4865 | #[rustc_builtin_macro] | ||
4866 | macro_rules! file {() => {}} | ||
4867 | |||
4868 | fn 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] | ||
4881 | fn infer_builtin_macros_column() { | ||
4882 | assert_snapshot!( | ||
4883 | infer(r#" | ||
4884 | #[rustc_builtin_macro] | ||
4885 | macro_rules! column {() => {}} | ||
4886 | |||
4887 | fn 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 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use hir_def::lang_item::LangItemTarget; | ||
12 | use hir_expand::name; | 13 | use hir_expand::name; |
13 | 14 | ||
14 | use ra_db::salsa::{InternId, InternKey}; | 15 | use ra_db::salsa::{InternId, InternKey}; |
@@ -832,9 +833,9 @@ fn closure_fn_trait_output_assoc_ty_value( | |||
832 | } | 833 | } |
833 | 834 | ||
834 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 835 | fn 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 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_def::type_ref::TypeRef; | ||
6 | use hir_expand::name::{AsName, Name}; | ||
7 | |||
8 | use ra_syntax::ast::NameOwner; | ||
9 | |||
10 | use crate::{ | ||
11 | db::{AstDatabase, DefDatabase}, | ||
12 | HasSource, TypeAlias, | ||
13 | }; | ||
14 | |||
15 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
16 | pub struct TypeAliasData { | ||
17 | pub(crate) name: Name, | ||
18 | pub(crate) type_ref: Option<TypeRef>, | ||
19 | } | ||
20 | |||
21 | impl 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 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_expand::name::{AsName, Name}; | 5 | use hir_expand::{ |
6 | use ra_arena::Arena; | 6 | either::Either, |
7 | name::{AsName, Name}, | ||
8 | Source, | ||
9 | }; | ||
10 | use ra_arena::{map::ArenaMap, Arena}; | ||
7 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 11 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; |
8 | 12 | ||
9 | use crate::{ | 13 | use 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)] | ||
35 | pub struct VariantData(VariantDataInner); | ||
36 | |||
37 | #[derive(Debug, Clone, PartialEq, Eq)] | 37 | #[derive(Debug, Clone, PartialEq, Eq)] |
38 | enum VariantDataInner { | 38 | pub 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 | ||
51 | impl StructData { | 51 | impl 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 | ||
64 | impl EnumData { | 61 | impl 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 | ||
76 | impl 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 | |||
87 | fn 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 | |||
87 | impl VariantData { | 102 | impl 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 | |||
120 | impl 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 | |||
140 | enum StructKind { | ||
141 | Tuple, | ||
142 | Record, | ||
143 | Unit, | ||
144 | } | ||
145 | |||
146 | fn 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 | ||
3 | use std::sync::Arc; | 3 | use std::{ops, sync::Arc}; |
4 | 4 | ||
5 | use hir_expand::hygiene::Hygiene; | 5 | use hir_expand::{either::Either, hygiene::Hygiene, AstId}; |
6 | use mbe::ast_to_token_tree; | 6 | use mbe::ast_to_token_tree; |
7 | use ra_cfg::CfgOptions; | 7 | use ra_cfg::CfgOptions; |
8 | use ra_syntax::{ | 8 | use ra_syntax::{ |
@@ -11,7 +11,81 @@ use ra_syntax::{ | |||
11 | }; | 11 | }; |
12 | use tt::Subtree; | 12 | use tt::Subtree; |
13 | 13 | ||
14 | use crate::path::Path; | 14 | use crate::{ |
15 | db::DefDatabase, path::Path, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup, | ||
16 | }; | ||
17 | |||
18 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | ||
19 | pub struct Attrs { | ||
20 | entries: Option<Arc<[Attr]>>, | ||
21 | } | ||
22 | |||
23 | impl 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 | |||
34 | impl 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)] |
17 | pub struct Attr { | 91 | pub 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 | |||
162 | fn attrs_from_ast<D, N>(src: AstId<N>, db: &D) -> Attrs | ||
163 | where | ||
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 | |||
171 | fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs | ||
172 | where | ||
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}; | |||
13 | use rustc_hash::FxHashMap; | 13 | use rustc_hash::FxHashMap; |
14 | 14 | ||
15 | use crate::{ | 15 | use 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 | ||
30 | impl Expander { | 30 | impl 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 | ||
143 | impl Body { | 143 | impl 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; | |||
17 | use crate::{ | 17 | use 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 | ||
30 | pub(super) fn lower( | 30 | pub(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 | ||
58 | impl<'a, DB> ExprCollector<&'a DB> | 58 | impl<'a, DB> ExprCollector<&'a DB> |
59 | where | 59 | where |
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 | ||
8 | use crate::{ | 8 | use 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 | ||
47 | impl ExprScopes { | 47 | impl 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 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_expand::{ | ||
6 | name::{self, AsName, Name}, | ||
7 | AstId, | ||
8 | }; | ||
9 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | ||
10 | |||
11 | use 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)] | ||
19 | pub 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 | |||
28 | impl 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)] | ||
70 | pub struct TypeAliasData { | ||
71 | pub name: Name, | ||
72 | pub type_ref: Option<TypeRef>, | ||
73 | } | ||
74 | |||
75 | impl 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)] | ||
88 | pub struct TraitData { | ||
89 | pub name: Option<Name>, | ||
90 | pub items: Vec<AssocItemId>, | ||
91 | pub auto: bool, | ||
92 | } | ||
93 | |||
94 | impl 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)] | ||
139 | pub 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 | |||
146 | impl 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)] | ||
195 | pub struct ConstData { | ||
196 | pub name: Option<Name>, | ||
197 | pub type_ref: TypeRef, | ||
198 | } | ||
199 | |||
200 | impl 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 | |||
212 | fn 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 | ||
4 | use hir_expand::{db::AstDatabase, HirFileId}; | 4 | use hir_expand::{db::AstDatabase, HirFileId}; |
5 | use ra_db::{salsa, CrateId, SourceDatabase}; | 5 | use ra_db::{salsa, CrateId, SourceDatabase}; |
6 | use ra_syntax::ast; | 6 | use ra_syntax::{ast, SmolStr}; |
7 | 7 | ||
8 | use crate::{ | 8 | use 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)] |
22 | pub trait InternDatabase: SourceDatabase { | 25 | pub 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)] |
42 | pub trait DefDatabase2: InternDatabase + AstDatabase { | 45 | pub 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 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_expand::either::Either; | ||
6 | use ra_syntax::ast; | ||
7 | |||
8 | use crate::{db::DefDatabase, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup}; | ||
9 | |||
10 | /// Holds documentation | ||
11 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
12 | pub struct Documentation(Arc<str>); | ||
13 | |||
14 | impl Into<String> for Documentation { | ||
15 | fn into(self) -> String { | ||
16 | self.as_str().to_owned() | ||
17 | } | ||
18 | } | ||
19 | |||
20 | impl 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 | |||
66 | pub(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}; | |||
8 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | 8 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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 | ||
43 | impl GenericParams { | 43 | impl 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 | ||
171 | fn parent_generic_def(db: &impl DefDatabase2, def: GenericDefId) -> Option<GenericDefId> { | 171 | fn 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 | |||
6 | use std::sync::Arc; | ||
7 | |||
8 | use hir_expand::AstId; | ||
9 | use ra_syntax::ast; | ||
10 | |||
11 | use crate::{ | ||
12 | db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId, | ||
13 | FunctionLoc, ImplId, Intern, TypeAliasLoc, | ||
14 | }; | ||
15 | |||
16 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
17 | pub struct ImplData { | ||
18 | target_trait: Option<TypeRef>, | ||
19 | target_type: TypeRef, | ||
20 | items: Vec<AssocItemId>, | ||
21 | negative: bool, | ||
22 | } | ||
23 | |||
24 | impl 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. | ||
5 | use std::sync::Arc; | ||
6 | |||
7 | use ra_syntax::SmolStr; | ||
8 | use rustc_hash::FxHashMap; | ||
9 | |||
10 | use 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)] | ||
16 | pub 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)] | ||
26 | pub struct LangItems { | ||
27 | items: FxHashMap<SmolStr, LangItemTarget>, | ||
28 | } | ||
29 | |||
30 | impl 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; | |||
13 | pub mod type_ref; | 13 | pub mod type_ref; |
14 | pub mod builtin_type; | 14 | pub mod builtin_type; |
15 | pub mod adt; | 15 | pub mod adt; |
16 | pub mod impls; | ||
17 | pub mod diagnostics; | 16 | pub mod diagnostics; |
18 | pub mod expr; | 17 | pub mod expr; |
19 | pub mod body; | 18 | pub mod body; |
20 | pub mod generics; | 19 | pub mod generics; |
21 | pub mod traits; | ||
22 | pub mod resolver; | 20 | pub mod resolver; |
21 | pub mod data; | ||
22 | pub mod lang_item; | ||
23 | pub mod docs; | ||
24 | pub mod per_ns; | ||
25 | |||
26 | mod trace; | ||
27 | mod nameres; | ||
23 | 28 | ||
24 | #[cfg(test)] | 29 | #[cfg(test)] |
25 | mod test_db; | 30 | mod test_db; |
26 | #[cfg(test)] | 31 | #[cfg(test)] |
27 | mod marks; | 32 | mod marks; |
28 | 33 | ||
29 | // FIXME: this should be private | ||
30 | pub mod nameres; | ||
31 | |||
32 | use std::hash::{Hash, Hasher}; | 34 | use std::hash::{Hash, Hasher}; |
33 | 35 | ||
34 | use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, Source}; | 36 | use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; |
35 | use ra_arena::{impl_arena_id, RawId}; | 37 | use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; |
36 | use ra_db::{salsa, CrateId, FileId}; | 38 | use ra_db::{salsa, CrateId}; |
37 | use ra_syntax::{ast, AstNode, SyntaxNode}; | 39 | use ra_syntax::{ast, AstNode}; |
38 | 40 | ||
39 | use crate::{builtin_type::BuiltinType, db::InternDatabase}; | 41 | use crate::{builtin_type::BuiltinType, db::InternDatabase}; |
40 | 42 | ||
41 | pub enum ModuleSource { | 43 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
42 | SourceFile(ast::SourceFile), | 44 | pub struct LocalImportId(RawId); |
43 | Module(ast::Module), | 45 | impl_arena_id!(LocalImportId); |
44 | } | ||
45 | |||
46 | impl 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)] |
103 | pub struct ModuleId { | 48 | pub 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)] |
111 | pub struct CrateModuleId(RawId); | 56 | pub struct LocalModuleId(RawId); |
112 | impl_arena_id!(CrateModuleId); | 57 | impl_arena_id!(LocalModuleId); |
113 | 58 | ||
114 | macro_rules! impl_intern_key { | 59 | macro_rules! impl_intern_key { |
115 | ($name:ident) => { | 60 | ($name:ident) => { |
@@ -208,14 +153,14 @@ pub struct FunctionLoc { | |||
208 | 153 | ||
209 | impl Intern for FunctionLoc { | 154 | impl 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 | ||
216 | impl Lookup for FunctionId { | 161 | impl 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)] |
281 | pub struct StructFieldId { | 226 | pub 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 | ||
299 | impl Intern for ConstLoc { | 244 | impl 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 | ||
306 | impl Lookup for ConstId { | 251 | impl 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 | ||
347 | impl Intern for TypeAliasLoc { | 292 | impl 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 | ||
354 | impl Lookup for TypeAliasId { | 299 | impl 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)] | ||
425 | pub 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 | |||
439 | impl_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 | |||
479 | trait Intern { | 453 | trait 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 | ||
484 | pub trait Lookup { | 458 | pub 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 | ||
489 | pub trait HasModule { | 463 | pub trait HasModule { |
490 | fn module(&self, db: &impl db::DefDatabase2) -> ModuleId; | 464 | fn module(&self, db: &impl db::DefDatabase) -> ModuleId; |
491 | } | 465 | } |
492 | 466 | ||
493 | impl HasModule for FunctionLoc { | 467 | impl 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 | ||
503 | impl HasModule for TypeAliasLoc { | 477 | impl 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 | ||
513 | impl HasModule for ConstLoc { | 487 | impl 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 | ||
523 | pub trait HasSource { | 497 | pub 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 | ||
528 | impl HasSource for FunctionLoc { | 502 | impl 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 { | |||
537 | impl HasSource for TypeAliasLoc { | 511 | impl 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 { | |||
546 | impl HasSource for ConstLoc { | 520 | impl 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 | |||
529 | pub 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 | ||
50 | pub mod raw; | 50 | pub(crate) mod raw; |
51 | pub mod per_ns; | ||
52 | mod collector; | 51 | mod collector; |
53 | mod mod_resolution; | 52 | mod mod_resolution; |
54 | mod path_resolution; | 53 | mod path_resolution; |
@@ -58,7 +57,10 @@ mod tests; | |||
58 | 57 | ||
59 | use std::sync::Arc; | 58 | use std::sync::Arc; |
60 | 59 | ||
61 | use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; | 60 | use hir_expand::{ |
61 | ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId, | ||
62 | Source, | ||
63 | }; | ||
62 | use once_cell::sync::Lazy; | 64 | use once_cell::sync::Lazy; |
63 | use ra_arena::Arena; | 65 | use ra_arena::Arena; |
64 | use ra_db::{CrateId, Edition, FileId}; | 66 | use ra_db::{CrateId, Edition, FileId}; |
@@ -68,12 +70,11 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
68 | 70 | ||
69 | use crate::{ | 71 | use 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 | ||
107 | impl std::ops::Index<CrateModuleId> for CrateDefMap { | 108 | impl 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)] |
115 | pub struct ModuleData { | 116 | pub 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 | ||
213 | impl CrateDefMap { | 217 | impl 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 | ||
292 | impl 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 | |||
288 | mod diagnostics { | 315 | mod 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; | |||
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use crate::{ | 14 | use 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 | ||
27 | pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { | 28 | pub(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 { | |||
94 | struct DefCollector<'a, DB> { | 95 | struct 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 | ||
109 | impl<DB> DefCollector<'_, DB> | 110 | impl<DB> DefCollector<'_, DB> |
110 | where | 111 | where |
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 |
523 | struct ModCollector<'a, D> { | 524 | struct 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 | ||
531 | impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> | 532 | impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> |
532 | where | 533 | where |
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 | ||
795 | fn is_macro_rules(path: &Path) -> bool { | 792 | fn 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; | |||
3 | use ra_db::{FileId, RelativePathBuf}; | 3 | use ra_db::{FileId, RelativePathBuf}; |
4 | use ra_syntax::SmolStr; | 4 | use ra_syntax::SmolStr; |
5 | 5 | ||
6 | use crate::{db::DefDatabase2, HirFileId}; | 6 | use crate::{db::DefDatabase, HirFileId}; |
7 | 7 | ||
8 | #[derive(Clone, Debug)] | 8 | #[derive(Clone, Debug)] |
9 | pub(super) struct ModDir { | 9 | pub(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; | |||
15 | use test_utils::tested_by; | 15 | use test_utils::tested_by; |
16 | 16 | ||
17 | use crate::{ | 17 | use 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::{ | |||
12 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; | 12 | use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ |
14 | ast::{self, AttrsOwner, NameOwner}, | 14 | ast::{self, AttrsOwner, NameOwner}, |
15 | AstNode, AstPtr, SourceFile, | 15 | AstNode, AstPtr, |
16 | }; | 16 | }; |
17 | use test_utils::tested_by; | 17 | use test_utils::tested_by; |
18 | 18 | ||
19 | use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source}; | 19 | use 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)] |
26 | pub struct RawItems { | 31 | pub 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)] |
37 | pub struct ImportSourceMap { | 42 | pub struct ImportSourceMap { |
38 | map: ArenaMap<ImportId, ImportSourcePtr>, | 43 | map: ArenaMap<LocalImportId, ImportSourcePtr>, |
39 | } | 44 | } |
40 | 45 | ||
41 | type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; | 46 | type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; |
42 | type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>; | ||
43 | |||
44 | fn 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 | ||
48 | impl ImportSourceMap { | 48 | impl 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 | ||
63 | impl RawItems { | 58 | impl 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 | ||
104 | impl Index<ImportId> for RawItems { | 99 | impl 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. | ||
133 | type Attrs = Option<Arc<[Attr]>>; | ||
134 | |||
135 | #[derive(Debug, PartialEq, Eq, Clone)] | 127 | #[derive(Debug, PartialEq, Eq, Clone)] |
136 | pub(super) struct RawItem { | 128 | pub(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 | ||
141 | impl 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)] |
148 | pub(super) enum RawItemKind { | 134 | pub(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)] | ||
167 | pub struct ImportId(RawId); | ||
168 | impl_arena_id!(ImportId); | ||
169 | |||
170 | #[derive(Debug, Clone, PartialEq, Eq)] | 152 | #[derive(Debug, Clone, PartialEq, Eq)] |
171 | pub struct ImportData { | 153 | pub 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; | |||
10 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 10 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
11 | use test_utils::covers; | 11 | use test_utils::covers; |
12 | 12 | ||
13 | use crate::{db::DefDatabase2, nameres::*, test_db::TestDB, CrateModuleId}; | 13 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId}; |
14 | 14 | ||
15 | fn def_map(fixtute: &str) -> String { | 15 | fn 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; | |||
11 | use crate::{ | 11 | use 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)] |
31 | pub(crate) struct ModuleItemMap { | 32 | pub(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 | ||
88 | impl Resolver { | 89 | impl 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 | ||
380 | impl Scope { | 381 | impl 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? |
428 | pub fn resolver_for_expr( | 429 | pub 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 | ||
437 | pub fn resolver_for_scope( | 434 | pub 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 | ||
488 | pub trait HasResolver { | 485 | pub 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 | ||
493 | impl HasResolver for ModuleId { | 490 | impl 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 | ||
500 | impl HasResolver for TraitId { | 497 | impl 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 | ||
506 | impl<T: Into<AdtId>> HasResolver for T { | 503 | impl<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 | ||
522 | impl HasResolver for FunctionId { | 519 | impl 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 | ||
528 | impl HasResolver for DefWithBodyId { | 525 | impl 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 | ||
538 | impl HasResolver for ConstId { | 535 | impl 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 | ||
544 | impl HasResolver for StaticId { | 541 | impl 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 | ||
550 | impl HasResolver for TypeAliasId { | 547 | impl 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 | ||
556 | impl HasResolver for ContainerId { | 553 | impl 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 | ||
566 | impl HasResolver for GenericDefId { | 563 | impl 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 | ||
580 | impl HasResolver for ImplId { | 577 | impl 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)] |
18 | pub struct TestDB { | 18 | pub 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. | ||
12 | use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId}; | ||
13 | |||
14 | pub(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 | |||
21 | impl<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 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_expand::{ | ||
6 | name::{AsName, Name}, | ||
7 | AstId, | ||
8 | }; | ||
9 | |||
10 | use ra_syntax::ast::{self, NameOwner}; | ||
11 | |||
12 | use crate::{ | ||
13 | db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId, | ||
14 | TypeAliasId, TypeAliasLoc, | ||
15 | }; | ||
16 | |||
17 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
18 | pub struct TraitData { | ||
19 | pub name: Option<Name>, | ||
20 | pub items: Vec<AssocItemId>, | ||
21 | pub auto: bool, | ||
22 | } | ||
23 | |||
24 | impl 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 | ||
9 | use crate::quote; | 9 | use crate::quote; |
10 | 10 | ||
11 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 11 | macro_rules! register_builtin { |
12 | pub 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 | ||
16 | impl 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 | ||
29 | pub fn find_builtin_macro( | 47 | register_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 | ||
42 | fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { | 54 | fn 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 | |||
94 | fn 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 | |||
117 | fn 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 | |||
133 | fn 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 | |||
154 | fn 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)] | ||
176 | mod 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(¯o_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(¯o_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; | |||
9 | use ra_syntax::{AstNode, Parse, SyntaxNode}; | 9 | use ra_syntax::{AstNode, Parse, SyntaxNode}; |
10 | 10 | ||
11 | use crate::{ | 11 | use 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)] |
17 | pub enum TokenExpander { | 17 | pub enum TokenExpander { |
18 | MacroRules(mbe::MacroRules), | 18 | MacroRules(mbe::MacroRules), |
19 | Builtin(BuiltinExpander), | 19 | Builtin(BuiltinFnLikeExpander), |
20 | } | 20 | } |
21 | 21 | ||
22 | impl TokenExpander { | 22 | impl 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 | ||
26 | use crate::ast_id_map::FileAstId; | 26 | use crate::ast_id_map::FileAstId; |
27 | use crate::builtin_macro::BuiltinExpander; | 27 | use crate::builtin_macro::BuiltinFnLikeExpander; |
28 | |||
29 | #[cfg(test)] | ||
30 | mod 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 { | |||
109 | pub enum MacroFileKind { | 112 | pub 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)] |
135 | pub enum MacroDefKind { | 139 | pub 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"); | |||
142 | pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); | 142 | pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); |
143 | 143 | ||
144 | // Builtin Macros | 144 | // Builtin Macros |
145 | pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); | ||
146 | pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); | ||
145 | pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); | 147 | pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); |
148 | pub 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 | |||
3 | use std::{ | ||
4 | panic, | ||
5 | sync::{Arc, Mutex}, | ||
6 | }; | ||
7 | |||
8 | use 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)] | ||
16 | pub struct TestDB { | ||
17 | runtime: salsa::Runtime<TestDB>, | ||
18 | events: Mutex<Option<Vec<salsa::Event<TestDB>>>>, | ||
19 | } | ||
20 | |||
21 | impl 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 | |||
34 | impl panic::RefUnwindSafe for TestDB {} | ||
35 | |||
36 | impl 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) | |||
59 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { | 59 | fn 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 | ||
3 | use hir::{Adt, Either, PathResolution}; | 3 | use hir::{Adt, Either, HasSource, PathResolution}; |
4 | use ra_syntax::AstNode; | 4 | use ra_syntax::AstNode; |
5 | use test_utils::tested_by; | 5 | use 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 | ||
3 | use hir::{db::HirDatabase, Attrs, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; | 3 | use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; |
4 | use join_to_string::join; | 4 | use join_to_string::join; |
5 | use ra_syntax::ast::NameOwner; | 5 | use ra_syntax::ast::NameOwner; |
6 | use test_utils::tested_by; | 6 | use 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 | ||
288 | fn is_deprecated(node: impl Attrs, db: &impl HirDatabase) -> bool { | 290 | fn 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 | ||
295 | fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { | 294 | fn 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; | |||
54 | use ra_cfg::CfgOptions; | 54 | use ra_cfg::CfgOptions; |
55 | use ra_db::{ | 55 | use ra_db::{ |
56 | salsa::{self, ParallelDatabase}, | 56 | salsa::{self, ParallelDatabase}, |
57 | CheckCanceled, FileLoader, SourceDatabase, | 57 | CheckCanceled, Env, FileLoader, SourceDatabase, |
58 | }; | 58 | }; |
59 | use ra_syntax::{SourceFile, TextRange, TextUnit}; | 59 | use 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 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use ra_cfg::CfgOptions; | 5 | use ra_cfg::CfgOptions; |
6 | use ra_db::RelativePathBuf; | 6 | use ra_db::{Env, RelativePathBuf}; |
7 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; | 7 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; |
8 | 8 | ||
9 | use crate::{ | 9 | use 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)] |
36 | mod tests { | 36 | mod 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" | ||
256 | fn main() { | ||
257 | // Fix<|> me | ||
258 | let x = 1 + 1; | ||
259 | } | ||
260 | ", | ||
261 | r" | ||
262 | fn main() { | ||
263 | // Fix | ||
264 | // <|> me | ||
265 | let x = 1 + 1; | ||
266 | } | ||
267 | ", | ||
268 | ); | ||
269 | do_check_noop( | ||
270 | r" | ||
271 | fn 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)] | ||
11 | macro_rules! println { | ||
12 | ($($tt:tt)*) => { | ||
13 | compile_error!("stdout is locked, use eprintln") | ||
14 | }; | ||
15 | } | ||
16 | |||
17 | #[allow(unused)] | ||
18 | macro_rules! print { | ||
19 | ($($tt:tt)*) => { | ||
20 | compile_error!("stdout is locked, use eprint") | ||
21 | }; | ||
22 | } | ||
23 | |||
4 | mod caps; | 24 | mod caps; |
5 | mod cargo_target_spec; | 25 | mod cargo_target_spec; |
6 | mod conv; | 26 | mod 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 | ||
3 | use flexi_logger::{Duplicate, Logger}; | 3 | use flexi_logger::{Duplicate, Logger}; |
4 | use lsp_server::Connection; | 4 | use lsp_server::Connection; |
5 | |||
6 | use ra_lsp_server::{show_message, Result, ServerConfig}; | 5 | use ra_lsp_server::{show_message, Result, ServerConfig}; |
7 | use ra_prof; | 6 | use 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 | }; |
8 | use std::iter::successors; | ||
8 | use tt::buffer::{Cursor, TokenBuffer}; | 9 | use tt::buffer::{Cursor, TokenBuffer}; |
9 | 10 | ||
10 | use crate::subtree_source::SubtreeTokenSource; | 11 | use 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 | ||
3 | use std::path::{Path, PathBuf}; | 3 | use std::path::{Path, PathBuf}; |
4 | use std::str::FromStr; | ||
5 | 4 | ||
6 | use cargo_metadata::{CargoOpt, MetadataCommand}; | 5 | use cargo_metadata::{CargoOpt, MetadataCommand}; |
7 | use ra_arena::{impl_arena_id, Arena, RawId}; | 6 | use 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 | ||
15 | use ra_cfg::CfgOptions; | 15 | use ra_cfg::CfgOptions; |
16 | use ra_db::{CrateGraph, CrateId, Edition, FileId}; | 16 | use ra_db::{CrateGraph, CrateId, Edition, Env, FileId}; |
17 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::FxHashMap; |
18 | use serde_json::from_reader; | 18 | use 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)] |
180 | pub enum StructKind { | 180 | pub 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 | ||
186 | impl StructKind { | 186 | impl 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 { |