diff options
-rw-r--r-- | Cargo.lock | 4 | ||||
-rw-r--r-- | crates/ra_db/src/lib.rs | 30 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_def/src/db.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir_def/src/find_path.rs | 202 | ||||
-rw-r--r-- | crates/ra_hir_def/src/import_map.rs | 331 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/mod_resolution.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_def/src/per_ns.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_def/src/test_db.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/test_db.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/test_db.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide_db/src/change.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_db/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/heavy_tests/main.rs | 83 |
19 files changed, 556 insertions, 211 deletions
diff --git a/Cargo.lock b/Cargo.lock index 5f88ad0c4..15c6a4c11 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -471,9 +471,9 @@ dependencies = [ | |||
471 | 471 | ||
472 | [[package]] | 472 | [[package]] |
473 | name = "inotify" | 473 | name = "inotify" |
474 | version = "0.7.0" | 474 | version = "0.7.1" |
475 | source = "registry+https://github.com/rust-lang/crates.io-index" | 475 | source = "registry+https://github.com/rust-lang/crates.io-index" |
476 | checksum = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" | 476 | checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" |
477 | dependencies = [ | 477 | dependencies = [ |
478 | "bitflags", | 478 | "bitflags", |
479 | "inotify-sys", | 479 | "inotify-sys", |
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index fd4280de2..fcfa2788c 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs | |||
@@ -11,8 +11,8 @@ use ra_syntax::{ast, Parse, SourceFile, TextRange, TextSize}; | |||
11 | pub use crate::{ | 11 | pub use crate::{ |
12 | cancellation::Canceled, | 12 | cancellation::Canceled, |
13 | input::{ | 13 | input::{ |
14 | CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, | 14 | CrateData, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, |
15 | FileId, ProcMacroId, SourceRoot, SourceRootId, | 15 | ExternSourceId, FileId, ProcMacroId, SourceRoot, SourceRootId, |
16 | }, | 16 | }, |
17 | }; | 17 | }; |
18 | pub use relative_path::{RelativePath, RelativePathBuf}; | 18 | pub use relative_path::{RelativePath, RelativePathBuf}; |
@@ -89,8 +89,7 @@ pub const DEFAULT_LRU_CAP: usize = 128; | |||
89 | pub trait FileLoader { | 89 | pub trait FileLoader { |
90 | /// Text of the file. | 90 | /// Text of the file. |
91 | fn file_text(&self, file_id: FileId) -> Arc<String>; | 91 | fn file_text(&self, file_id: FileId) -> Arc<String>; |
92 | fn resolve_relative_path(&self, anchor: FileId, relative_path: &RelativePath) | 92 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId>; |
93 | -> Option<FileId>; | ||
94 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>; | 93 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>; |
95 | 94 | ||
96 | fn resolve_extern_path( | 95 | fn resolve_extern_path( |
@@ -155,20 +154,21 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> { | |||
155 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 154 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
156 | SourceDatabaseExt::file_text(self.0, file_id) | 155 | SourceDatabaseExt::file_text(self.0, file_id) |
157 | } | 156 | } |
158 | fn resolve_relative_path( | 157 | /// Note that we intentionally accept a `&str` and not a `&Path` here. This |
159 | &self, | 158 | /// method exists to handle `#[path = "/some/path.rs"] mod foo;` and such, |
160 | anchor: FileId, | 159 | /// so the input is guaranteed to be utf-8 string. We might introduce |
161 | relative_path: &RelativePath, | 160 | /// `struct StrPath(str)` for clarity some day, but it's a bit messy, so we |
162 | ) -> Option<FileId> { | 161 | /// get by with a `&str` for the time being. |
163 | let path = { | 162 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { |
164 | let mut path = self.0.file_relative_path(anchor); | 163 | let rel_path = { |
165 | assert!(path.pop()); | 164 | let mut rel_path = self.0.file_relative_path(anchor); |
166 | path.push(relative_path); | 165 | assert!(rel_path.pop()); |
167 | path.normalize() | 166 | rel_path.push(path); |
167 | rel_path.normalize() | ||
168 | }; | 168 | }; |
169 | let source_root = self.0.file_source_root(anchor); | 169 | let source_root = self.0.file_source_root(anchor); |
170 | let source_root = self.0.source_root(source_root); | 170 | let source_root = self.0.source_root(source_root); |
171 | source_root.file_by_relative_path(&path) | 171 | source_root.file_by_relative_path(&rel_path) |
172 | } | 172 | } |
173 | 173 | ||
174 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | 174 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index ec931b34f..098b66529 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -3,11 +3,11 @@ | |||
3 | pub use hir_def::db::{ | 3 | pub use hir_def::db::{ |
4 | AttrsQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQueryQuery, | 4 | AttrsQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQueryQuery, |
5 | CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, | 5 | CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, |
6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternConstQuery, | 6 | ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, ImportMapQuery, |
7 | InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, InternImplQuery, | 7 | InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, InternFunctionQuery, |
8 | InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery, | 8 | InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, InternTypeAliasQuery, |
9 | LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, StructDataQuery, | 9 | InternUnionQuery, LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, |
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | 10 | StructDataQuery, TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, |
11 | }; | 11 | }; |
12 | pub use hir_expand::db::{ | 12 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, | 13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, |
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 945a0025e..10cc26480 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Defines database & queries for name resolution. | 1 | //! Defines database & queries for name resolution. |
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use hir_expand::{db::AstDatabase, name::Name, HirFileId}; | 4 | use hir_expand::{db::AstDatabase, HirFileId}; |
5 | use ra_db::{salsa, CrateId, SourceDatabase, Upcast}; | 5 | use ra_db::{salsa, CrateId, SourceDatabase, Upcast}; |
6 | use ra_prof::profile; | 6 | use ra_prof::profile; |
7 | use ra_syntax::SmolStr; | 7 | use ra_syntax::SmolStr; |
@@ -12,13 +12,10 @@ use crate::{ | |||
12 | body::{scope::ExprScopes, Body, BodySourceMap}, | 12 | body::{scope::ExprScopes, Body, BodySourceMap}, |
13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, | 13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | docs::Documentation, | 14 | docs::Documentation, |
15 | find_path, | ||
16 | generics::GenericParams, | 15 | generics::GenericParams, |
17 | item_scope::ItemInNs, | 16 | import_map::ImportMap, |
18 | lang_item::{LangItemTarget, LangItems}, | 17 | lang_item::{LangItemTarget, LangItems}, |
19 | nameres::{raw::RawItems, CrateDefMap}, | 18 | nameres::{raw::RawItems, CrateDefMap}, |
20 | path::ModPath, | ||
21 | visibility::Visibility, | ||
22 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 19 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, |
23 | GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, | 20 | GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, |
24 | TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, | 21 | TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, |
@@ -113,15 +110,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
113 | #[salsa::invoke(Documentation::documentation_query)] | 110 | #[salsa::invoke(Documentation::documentation_query)] |
114 | fn documentation(&self, def: AttrDefId) -> Option<Documentation>; | 111 | fn documentation(&self, def: AttrDefId) -> Option<Documentation>; |
115 | 112 | ||
116 | #[salsa::invoke(find_path::importable_locations_of_query)] | 113 | #[salsa::invoke(ImportMap::import_map_query)] |
117 | fn importable_locations_of( | 114 | fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; |
118 | &self, | ||
119 | item: ItemInNs, | ||
120 | krate: CrateId, | ||
121 | ) -> Arc<[(ModuleId, Name, Visibility)]>; | ||
122 | |||
123 | #[salsa::invoke(find_path::find_path_inner_query)] | ||
124 | fn find_path_inner(&self, item: ItemInNs, from: ModuleId, max_len: usize) -> Option<ModPath>; | ||
125 | } | 115 | } |
126 | 116 | ||
127 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { | 117 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { |
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs index 4db798473..a7f59e028 100644 --- a/crates/ra_hir_def/src/find_path.rs +++ b/crates/ra_hir_def/src/find_path.rs | |||
@@ -1,9 +1,8 @@ | |||
1 | //! An algorithm to find a path to refer to a certain item. | 1 | //! An algorithm to find a path to refer to a certain item. |
2 | 2 | ||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_expand::name::{known, AsName, Name}; | 3 | use hir_expand::name::{known, AsName, Name}; |
6 | use ra_prof::profile; | 4 | use ra_prof::profile; |
5 | use rustc_hash::FxHashSet; | ||
7 | use test_utils::mark; | 6 | use test_utils::mark; |
8 | 7 | ||
9 | use crate::{ | 8 | use crate::{ |
@@ -11,7 +10,7 @@ use crate::{ | |||
11 | item_scope::ItemInNs, | 10 | item_scope::ItemInNs, |
12 | path::{ModPath, PathKind}, | 11 | path::{ModPath, PathKind}, |
13 | visibility::Visibility, | 12 | visibility::Visibility, |
14 | CrateId, ModuleDefId, ModuleId, | 13 | ModuleDefId, ModuleId, |
15 | }; | 14 | }; |
16 | 15 | ||
17 | // FIXME: handle local items | 16 | // FIXME: handle local items |
@@ -20,7 +19,7 @@ use crate::{ | |||
20 | /// *from where* you're referring to the item, hence the `from` parameter. | 19 | /// *from where* you're referring to the item, hence the `from` parameter. |
21 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | 20 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { |
22 | let _p = profile("find_path"); | 21 | let _p = profile("find_path"); |
23 | db.find_path_inner(item, from, MAX_PATH_LEN) | 22 | find_path_inner(db, item, from, MAX_PATH_LEN) |
24 | } | 23 | } |
25 | 24 | ||
26 | const MAX_PATH_LEN: usize = 15; | 25 | const MAX_PATH_LEN: usize = 15; |
@@ -36,20 +35,9 @@ impl ModPath { | |||
36 | let first_segment = self.segments.first(); | 35 | let first_segment = self.segments.first(); |
37 | first_segment == Some(&known::alloc) || first_segment == Some(&known::core) | 36 | first_segment == Some(&known::alloc) || first_segment == Some(&known::core) |
38 | } | 37 | } |
39 | |||
40 | fn len(&self) -> usize { | ||
41 | self.segments.len() | ||
42 | + match self.kind { | ||
43 | PathKind::Plain => 0, | ||
44 | PathKind::Super(i) => i as usize, | ||
45 | PathKind::Crate => 1, | ||
46 | PathKind::Abs => 0, | ||
47 | PathKind::DollarCrate(_) => 1, | ||
48 | } | ||
49 | } | ||
50 | } | 38 | } |
51 | 39 | ||
52 | pub(crate) fn find_path_inner_query( | 40 | fn find_path_inner( |
53 | db: &dyn DefDatabase, | 41 | db: &dyn DefDatabase, |
54 | item: ItemInNs, | 42 | item: ItemInNs, |
55 | from: ModuleId, | 43 | from: ModuleId, |
@@ -133,31 +121,61 @@ pub(crate) fn find_path_inner_query( | |||
133 | } | 121 | } |
134 | 122 | ||
135 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 123 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
124 | |||
136 | let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; | 125 | let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; |
137 | let crate_attrs = db.attrs(crate_root.into()); | 126 | let crate_attrs = db.attrs(crate_root.into()); |
138 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 127 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
139 | let importable_locations = find_importable_locations(db, item, from); | ||
140 | let mut best_path = None; | 128 | let mut best_path = None; |
141 | let mut best_path_len = max_len; | 129 | let mut best_path_len = max_len; |
142 | for (module_id, name) in importable_locations { | ||
143 | let mut path = match db.find_path_inner( | ||
144 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), | ||
145 | from, | ||
146 | best_path_len - 1, | ||
147 | ) { | ||
148 | None => continue, | ||
149 | Some(path) => path, | ||
150 | }; | ||
151 | path.segments.push(name); | ||
152 | 130 | ||
153 | let new_path = if let Some(best_path) = best_path { | 131 | if item.krate(db) == Some(from.krate) { |
154 | select_best_path(best_path, path, prefer_no_std) | 132 | // Item was defined in the same crate that wants to import it. It cannot be found in any |
155 | } else { | 133 | // dependency in this case. |
156 | path | 134 | |
157 | }; | 135 | let local_imports = find_local_import_locations(db, item, from); |
158 | best_path_len = new_path.len(); | 136 | for (module_id, name) in local_imports { |
159 | best_path = Some(new_path); | 137 | if let Some(mut path) = find_path_inner( |
138 | db, | ||
139 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), | ||
140 | from, | ||
141 | best_path_len - 1, | ||
142 | ) { | ||
143 | path.segments.push(name); | ||
144 | |||
145 | let new_path = if let Some(best_path) = best_path { | ||
146 | select_best_path(best_path, path, prefer_no_std) | ||
147 | } else { | ||
148 | path | ||
149 | }; | ||
150 | best_path_len = new_path.len(); | ||
151 | best_path = Some(new_path); | ||
152 | } | ||
153 | } | ||
154 | } else { | ||
155 | // Item was defined in some upstream crate. This means that it must be exported from one, | ||
156 | // too (unless we can't name it at all). It could *also* be (re)exported by the same crate | ||
157 | // that wants to import it here, but we always prefer to use the external path here. | ||
158 | |||
159 | let crate_graph = db.crate_graph(); | ||
160 | let extern_paths = crate_graph[from.krate].dependencies.iter().filter_map(|dep| { | ||
161 | let import_map = db.import_map(dep.crate_id); | ||
162 | import_map.path_of(item).map(|modpath| { | ||
163 | let mut modpath = modpath.clone(); | ||
164 | modpath.segments.insert(0, dep.as_name()); | ||
165 | modpath | ||
166 | }) | ||
167 | }); | ||
168 | |||
169 | for path in extern_paths { | ||
170 | let new_path = if let Some(best_path) = best_path { | ||
171 | select_best_path(best_path, path, prefer_no_std) | ||
172 | } else { | ||
173 | path | ||
174 | }; | ||
175 | best_path = Some(new_path); | ||
176 | } | ||
160 | } | 177 | } |
178 | |||
161 | best_path | 179 | best_path |
162 | } | 180 | } |
163 | 181 | ||
@@ -185,69 +203,86 @@ fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) - | |||
185 | } | 203 | } |
186 | } | 204 | } |
187 | 205 | ||
188 | fn find_importable_locations( | 206 | /// Finds locations in `from.krate` from which `item` can be imported by `from`. |
207 | fn find_local_import_locations( | ||
189 | db: &dyn DefDatabase, | 208 | db: &dyn DefDatabase, |
190 | item: ItemInNs, | 209 | item: ItemInNs, |
191 | from: ModuleId, | 210 | from: ModuleId, |
192 | ) -> Vec<(ModuleId, Name)> { | 211 | ) -> Vec<(ModuleId, Name)> { |
193 | let crate_graph = db.crate_graph(); | 212 | let _p = profile("find_local_import_locations"); |
194 | let mut result = Vec::new(); | 213 | |
195 | // We only look in the crate from which we are importing, and the direct | 214 | // `from` can import anything below `from` with visibility of at least `from`, and anything |
196 | // dependencies. We cannot refer to names from transitive dependencies | 215 | // above `from` with any visibility. That means we do not need to descend into private siblings |
197 | // directly (only through reexports in direct dependencies). | 216 | // of `from` (and similar). |
198 | for krate in Some(from.krate) | 217 | |
199 | .into_iter() | 218 | let def_map = db.crate_def_map(from.krate); |
200 | .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id)) | 219 | |
201 | { | 220 | // Compute the initial worklist. We start with all direct child modules of `from` as well as all |
202 | result.extend( | 221 | // of its (recursive) parent modules. |
203 | db.importable_locations_of(item, krate) | 222 | let data = &def_map.modules[from.local_id]; |
204 | .iter() | 223 | let mut worklist = data |
205 | .filter(|(_, _, vis)| vis.is_visible_from(db, from)) | 224 | .children |
206 | .map(|(m, n, _)| (*m, n.clone())), | 225 | .values() |
207 | ); | 226 | .map(|child| ModuleId { krate: from.krate, local_id: *child }) |
208 | } | 227 | .collect::<Vec<_>>(); |
209 | result | 228 | let mut parent = data.parent; |
210 | } | 229 | while let Some(p) = parent { |
230 | worklist.push(ModuleId { krate: from.krate, local_id: p }); | ||
231 | parent = def_map.modules[p].parent; | ||
232 | } | ||
233 | |||
234 | let mut seen: FxHashSet<_> = FxHashSet::default(); | ||
235 | |||
236 | let mut locations = Vec::new(); | ||
237 | while let Some(module) = worklist.pop() { | ||
238 | if !seen.insert(module) { | ||
239 | continue; // already processed this module | ||
240 | } | ||
241 | |||
242 | let ext_def_map; | ||
243 | let data = if module.krate == from.krate { | ||
244 | &def_map[module.local_id] | ||
245 | } else { | ||
246 | // The crate might reexport a module defined in another crate. | ||
247 | ext_def_map = db.crate_def_map(module.krate); | ||
248 | &ext_def_map[module.local_id] | ||
249 | }; | ||
211 | 250 | ||
212 | /// Collects all locations from which we might import the item in a particular | ||
213 | /// crate. These include the original definition of the item, and any | ||
214 | /// non-private `use`s. | ||
215 | /// | ||
216 | /// Note that the crate doesn't need to be the one in which the item is defined; | ||
217 | /// it might be re-exported in other crates. | ||
218 | pub(crate) fn importable_locations_of_query( | ||
219 | db: &dyn DefDatabase, | ||
220 | item: ItemInNs, | ||
221 | krate: CrateId, | ||
222 | ) -> Arc<[(ModuleId, Name, Visibility)]> { | ||
223 | let _p = profile("importable_locations_of_query"); | ||
224 | let def_map = db.crate_def_map(krate); | ||
225 | let mut result = Vec::new(); | ||
226 | for (local_id, data) in def_map.modules.iter() { | ||
227 | if let Some((name, vis)) = data.scope.name_of(item) { | 251 | if let Some((name, vis)) = data.scope.name_of(item) { |
228 | let is_private = if let Visibility::Module(private_to) = vis { | 252 | if vis.is_visible_from(db, from) { |
229 | private_to.local_id == local_id | 253 | let is_private = if let Visibility::Module(private_to) = vis { |
230 | } else { | 254 | private_to.local_id == module.local_id |
231 | false | 255 | } else { |
232 | }; | 256 | false |
233 | let is_original_def = if let Some(module_def_id) = item.as_module_def_id() { | 257 | }; |
234 | data.scope.declarations().any(|it| it == module_def_id) | 258 | let is_original_def = if let Some(module_def_id) = item.as_module_def_id() { |
235 | } else { | 259 | data.scope.declarations().any(|it| it == module_def_id) |
236 | false | 260 | } else { |
237 | }; | 261 | false |
238 | if is_private && !is_original_def { | 262 | }; |
263 | |||
239 | // Ignore private imports. these could be used if we are | 264 | // Ignore private imports. these could be used if we are |
240 | // in a submodule of this module, but that's usually not | 265 | // in a submodule of this module, but that's usually not |
241 | // what the user wants; and if this module can import | 266 | // what the user wants; and if this module can import |
242 | // the item and we're a submodule of it, so can we. | 267 | // the item and we're a submodule of it, so can we. |
243 | // Also this keeps the cached data smaller. | 268 | // Also this keeps the cached data smaller. |
244 | continue; | 269 | if !is_private || is_original_def { |
270 | locations.push((module, name.clone())); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | // Descend into all modules visible from `from`. | ||
276 | for (_, per_ns) in data.scope.entries() { | ||
277 | if let Some((ModuleDefId::ModuleId(module), vis)) = per_ns.take_types_vis() { | ||
278 | if vis.is_visible_from(db, from) { | ||
279 | worklist.push(module); | ||
280 | } | ||
245 | } | 281 | } |
246 | result.push((ModuleId { krate, local_id }, name.clone(), vis)); | ||
247 | } | 282 | } |
248 | } | 283 | } |
249 | 284 | ||
250 | Arc::from(result) | 285 | locations |
251 | } | 286 | } |
252 | 287 | ||
253 | #[cfg(test)] | 288 | #[cfg(test)] |
@@ -385,6 +420,7 @@ mod tests { | |||
385 | 420 | ||
386 | #[test] | 421 | #[test] |
387 | fn different_crate_renamed() { | 422 | fn different_crate_renamed() { |
423 | // Even if a local path exists, if the item is defined externally, prefer an external path. | ||
388 | let code = r#" | 424 | let code = r#" |
389 | //- /main.rs crate:main deps:std | 425 | //- /main.rs crate:main deps:std |
390 | extern crate std as std_renamed; | 426 | extern crate std as std_renamed; |
@@ -392,7 +428,7 @@ mod tests { | |||
392 | //- /std.rs crate:std | 428 | //- /std.rs crate:std |
393 | pub struct S; | 429 | pub struct S; |
394 | "#; | 430 | "#; |
395 | check_found_path(code, "std_renamed::S"); | 431 | check_found_path(code, "std::S"); |
396 | } | 432 | } |
397 | 433 | ||
398 | #[test] | 434 | #[test] |
diff --git a/crates/ra_hir_def/src/import_map.rs b/crates/ra_hir_def/src/import_map.rs new file mode 100644 index 000000000..4284a0a91 --- /dev/null +++ b/crates/ra_hir_def/src/import_map.rs | |||
@@ -0,0 +1,331 @@ | |||
1 | //! A map of all publicly exported items in a crate. | ||
2 | |||
3 | use std::{collections::hash_map::Entry, fmt, sync::Arc}; | ||
4 | |||
5 | use ra_db::CrateId; | ||
6 | use rustc_hash::FxHashMap; | ||
7 | |||
8 | use crate::{ | ||
9 | db::DefDatabase, | ||
10 | item_scope::ItemInNs, | ||
11 | path::{ModPath, PathKind}, | ||
12 | visibility::Visibility, | ||
13 | ModuleDefId, ModuleId, | ||
14 | }; | ||
15 | |||
16 | /// A map from publicly exported items to the path needed to import/name them from a downstream | ||
17 | /// crate. | ||
18 | /// | ||
19 | /// Reexports of items are taken into account, ie. if something is exported under multiple | ||
20 | /// names, the one with the shortest import path will be used. | ||
21 | /// | ||
22 | /// Note that all paths are relative to the containing crate's root, so the crate name still needs | ||
23 | /// to be prepended to the `ModPath` before the path is valid. | ||
24 | #[derive(Eq, PartialEq)] | ||
25 | pub struct ImportMap { | ||
26 | map: FxHashMap<ItemInNs, ModPath>, | ||
27 | } | ||
28 | |||
29 | impl ImportMap { | ||
30 | pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { | ||
31 | let _p = ra_prof::profile("import_map_query"); | ||
32 | let def_map = db.crate_def_map(krate); | ||
33 | let mut import_map = FxHashMap::with_capacity_and_hasher(64, Default::default()); | ||
34 | |||
35 | // We look only into modules that are public(ly reexported), starting with the crate root. | ||
36 | let empty = ModPath { kind: PathKind::Plain, segments: vec![] }; | ||
37 | let root = ModuleId { krate, local_id: def_map.root }; | ||
38 | let mut worklist = vec![(root, empty)]; | ||
39 | while let Some((module, mod_path)) = worklist.pop() { | ||
40 | let ext_def_map; | ||
41 | let mod_data = if module.krate == krate { | ||
42 | &def_map[module.local_id] | ||
43 | } else { | ||
44 | // The crate might reexport a module defined in another crate. | ||
45 | ext_def_map = db.crate_def_map(module.krate); | ||
46 | &ext_def_map[module.local_id] | ||
47 | }; | ||
48 | |||
49 | let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { | ||
50 | let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); | ||
51 | if per_ns.is_none() { | ||
52 | None | ||
53 | } else { | ||
54 | Some((name, per_ns)) | ||
55 | } | ||
56 | }); | ||
57 | |||
58 | for (name, per_ns) in visible_items { | ||
59 | let mk_path = || { | ||
60 | let mut path = mod_path.clone(); | ||
61 | path.segments.push(name.clone()); | ||
62 | path | ||
63 | }; | ||
64 | |||
65 | for item in per_ns.iter_items() { | ||
66 | let path = mk_path(); | ||
67 | match import_map.entry(item) { | ||
68 | Entry::Vacant(entry) => { | ||
69 | entry.insert(path); | ||
70 | } | ||
71 | Entry::Occupied(mut entry) => { | ||
72 | // If the new path is shorter, prefer that one. | ||
73 | if path.len() < entry.get().len() { | ||
74 | *entry.get_mut() = path; | ||
75 | } else { | ||
76 | continue; | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | // If we've just added a path to a module, descend into it. We might traverse | ||
82 | // modules multiple times, but only if the new path to it is shorter than the | ||
83 | // first (else we `continue` above). | ||
84 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | ||
85 | worklist.push((mod_id, mk_path())); | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | Arc::new(Self { map: import_map }) | ||
92 | } | ||
93 | |||
94 | /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root. | ||
95 | pub fn path_of(&self, item: ItemInNs) -> Option<&ModPath> { | ||
96 | self.map.get(&item) | ||
97 | } | ||
98 | } | ||
99 | |||
100 | impl fmt::Debug for ImportMap { | ||
101 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
102 | let mut importable_paths: Vec<_> = self | ||
103 | .map | ||
104 | .iter() | ||
105 | .map(|(item, modpath)| { | ||
106 | let ns = match item { | ||
107 | ItemInNs::Types(_) => "t", | ||
108 | ItemInNs::Values(_) => "v", | ||
109 | ItemInNs::Macros(_) => "m", | ||
110 | }; | ||
111 | format!("- {} ({})", modpath, ns) | ||
112 | }) | ||
113 | .collect(); | ||
114 | |||
115 | importable_paths.sort(); | ||
116 | f.write_str(&importable_paths.join("\n")) | ||
117 | } | ||
118 | } | ||
119 | |||
120 | #[cfg(test)] | ||
121 | mod tests { | ||
122 | use super::*; | ||
123 | use crate::test_db::TestDB; | ||
124 | use insta::assert_snapshot; | ||
125 | use ra_db::fixture::WithFixture; | ||
126 | use ra_db::SourceDatabase; | ||
127 | |||
128 | fn import_map(ra_fixture: &str) -> String { | ||
129 | let db = TestDB::with_files(ra_fixture); | ||
130 | let crate_graph = db.crate_graph(); | ||
131 | |||
132 | let import_maps: Vec<_> = crate_graph | ||
133 | .iter() | ||
134 | .filter_map(|krate| { | ||
135 | let cdata = &crate_graph[krate]; | ||
136 | let name = cdata.display_name.as_ref()?; | ||
137 | |||
138 | let map = db.import_map(krate); | ||
139 | |||
140 | Some(format!("{}:\n{:?}", name, map)) | ||
141 | }) | ||
142 | .collect(); | ||
143 | |||
144 | import_maps.join("\n") | ||
145 | } | ||
146 | |||
147 | #[test] | ||
148 | fn smoke() { | ||
149 | let map = import_map( | ||
150 | r" | ||
151 | //- /main.rs crate:main deps:lib | ||
152 | |||
153 | mod private { | ||
154 | pub use lib::Pub; | ||
155 | pub struct InPrivateModule; | ||
156 | } | ||
157 | |||
158 | pub mod publ1 { | ||
159 | use lib::Pub; | ||
160 | } | ||
161 | |||
162 | pub mod real_pub { | ||
163 | pub use lib::Pub; | ||
164 | } | ||
165 | pub mod real_pu2 { // same path length as above | ||
166 | pub use lib::Pub; | ||
167 | } | ||
168 | |||
169 | //- /lib.rs crate:lib | ||
170 | pub struct Pub {} | ||
171 | pub struct Pub2; // t + v | ||
172 | struct Priv; | ||
173 | ", | ||
174 | ); | ||
175 | |||
176 | assert_snapshot!(map, @r###" | ||
177 | main: | ||
178 | - publ1 (t) | ||
179 | - real_pu2 (t) | ||
180 | - real_pub (t) | ||
181 | - real_pub::Pub (t) | ||
182 | lib: | ||
183 | - Pub (t) | ||
184 | - Pub2 (t) | ||
185 | - Pub2 (v) | ||
186 | "###); | ||
187 | } | ||
188 | |||
189 | #[test] | ||
190 | fn prefers_shortest_path() { | ||
191 | let map = import_map( | ||
192 | r" | ||
193 | //- /main.rs crate:main | ||
194 | |||
195 | pub mod sub { | ||
196 | pub mod subsub { | ||
197 | pub struct Def {} | ||
198 | } | ||
199 | |||
200 | pub use super::sub::subsub::Def; | ||
201 | } | ||
202 | ", | ||
203 | ); | ||
204 | |||
205 | assert_snapshot!(map, @r###" | ||
206 | main: | ||
207 | - sub (t) | ||
208 | - sub::Def (t) | ||
209 | - sub::subsub (t) | ||
210 | "###); | ||
211 | } | ||
212 | |||
213 | #[test] | ||
214 | fn type_reexport_cross_crate() { | ||
215 | // Reexports need to be visible from a crate, even if the original crate exports the item | ||
216 | // at a shorter path. | ||
217 | let map = import_map( | ||
218 | r" | ||
219 | //- /main.rs crate:main deps:lib | ||
220 | pub mod m { | ||
221 | pub use lib::S; | ||
222 | } | ||
223 | //- /lib.rs crate:lib | ||
224 | pub struct S; | ||
225 | ", | ||
226 | ); | ||
227 | |||
228 | assert_snapshot!(map, @r###" | ||
229 | main: | ||
230 | - m (t) | ||
231 | - m::S (t) | ||
232 | - m::S (v) | ||
233 | lib: | ||
234 | - S (t) | ||
235 | - S (v) | ||
236 | "###); | ||
237 | } | ||
238 | |||
239 | #[test] | ||
240 | fn macro_reexport() { | ||
241 | let map = import_map( | ||
242 | r" | ||
243 | //- /main.rs crate:main deps:lib | ||
244 | pub mod m { | ||
245 | pub use lib::pub_macro; | ||
246 | } | ||
247 | //- /lib.rs crate:lib | ||
248 | #[macro_export] | ||
249 | macro_rules! pub_macro { | ||
250 | () => {}; | ||
251 | } | ||
252 | ", | ||
253 | ); | ||
254 | |||
255 | assert_snapshot!(map, @r###" | ||
256 | main: | ||
257 | - m (t) | ||
258 | - m::pub_macro (m) | ||
259 | lib: | ||
260 | - pub_macro (m) | ||
261 | "###); | ||
262 | } | ||
263 | |||
264 | #[test] | ||
265 | fn module_reexport() { | ||
266 | // Reexporting modules from a dependency adds all contents to the import map. | ||
267 | let map = import_map( | ||
268 | r" | ||
269 | //- /main.rs crate:main deps:lib | ||
270 | pub use lib::module as reexported_module; | ||
271 | //- /lib.rs crate:lib | ||
272 | pub mod module { | ||
273 | pub struct S; | ||
274 | } | ||
275 | ", | ||
276 | ); | ||
277 | |||
278 | assert_snapshot!(map, @r###" | ||
279 | main: | ||
280 | - reexported_module (t) | ||
281 | - reexported_module::S (t) | ||
282 | - reexported_module::S (v) | ||
283 | lib: | ||
284 | - module (t) | ||
285 | - module::S (t) | ||
286 | - module::S (v) | ||
287 | "###); | ||
288 | } | ||
289 | |||
290 | #[test] | ||
291 | fn cyclic_module_reexport() { | ||
292 | // A cyclic reexport does not hang. | ||
293 | let map = import_map( | ||
294 | r" | ||
295 | //- /lib.rs crate:lib | ||
296 | pub mod module { | ||
297 | pub struct S; | ||
298 | pub use super::sub::*; | ||
299 | } | ||
300 | |||
301 | pub mod sub { | ||
302 | pub use super::module; | ||
303 | } | ||
304 | ", | ||
305 | ); | ||
306 | |||
307 | assert_snapshot!(map, @r###" | ||
308 | lib: | ||
309 | - module (t) | ||
310 | - module::S (t) | ||
311 | - module::S (v) | ||
312 | - sub (t) | ||
313 | "###); | ||
314 | } | ||
315 | |||
316 | #[test] | ||
317 | fn private_macro() { | ||
318 | let map = import_map( | ||
319 | r" | ||
320 | //- /lib.rs crate:lib | ||
321 | macro_rules! private_macro { | ||
322 | () => {}; | ||
323 | } | ||
324 | ", | ||
325 | ); | ||
326 | |||
327 | assert_snapshot!(map, @r###" | ||
328 | lib: | ||
329 | "###); | ||
330 | } | ||
331 | } | ||
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index fc15948ad..b03ba939a 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -3,11 +3,12 @@ | |||
3 | 3 | ||
4 | use hir_expand::name::Name; | 4 | use hir_expand::name::Name; |
5 | use once_cell::sync::Lazy; | 5 | use once_cell::sync::Lazy; |
6 | use ra_db::CrateId; | ||
6 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
7 | 8 | ||
8 | use crate::{ | 9 | use crate::{ |
9 | per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, | 10 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, |
10 | TraitId, | 11 | Lookup, MacroDefId, ModuleDefId, TraitId, |
11 | }; | 12 | }; |
12 | 13 | ||
13 | #[derive(Debug, Default, PartialEq, Eq)] | 14 | #[derive(Debug, Default, PartialEq, Eq)] |
@@ -203,4 +204,22 @@ impl ItemInNs { | |||
203 | ItemInNs::Macros(_) => None, | 204 | ItemInNs::Macros(_) => None, |
204 | } | 205 | } |
205 | } | 206 | } |
207 | |||
208 | /// Returns the crate defining this item (or `None` if `self` is built-in). | ||
209 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { | ||
210 | Some(match self { | ||
211 | ItemInNs::Types(did) | ItemInNs::Values(did) => match did { | ||
212 | ModuleDefId::ModuleId(id) => id.krate, | ||
213 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate, | ||
214 | ModuleDefId::AdtId(id) => id.module(db).krate, | ||
215 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate, | ||
216 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate, | ||
217 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate, | ||
218 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate, | ||
219 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | ||
220 | ModuleDefId::BuiltinType(_) => return None, | ||
221 | }, | ||
222 | ItemInNs::Macros(id) => return id.krate, | ||
223 | }) | ||
224 | } | ||
206 | } | 225 | } |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 5325a2760..de490fcc5 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -43,6 +43,7 @@ pub mod child_by_source; | |||
43 | 43 | ||
44 | pub mod visibility; | 44 | pub mod visibility; |
45 | pub mod find_path; | 45 | pub mod find_path; |
46 | pub mod import_map; | ||
46 | 47 | ||
47 | #[cfg(test)] | 48 | #[cfg(test)] |
48 | mod test_db; | 49 | mod test_db; |
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs index 386c5cade..cede4a6fc 100644 --- a/crates/ra_hir_def/src/nameres/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs | |||
@@ -61,7 +61,7 @@ impl ModDir { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | for candidate in candidate_files.iter() { | 63 | for candidate in candidate_files.iter() { |
64 | if let Some(file_id) = db.resolve_relative_path(file_id, candidate) { | 64 | if let Some(file_id) = db.resolve_path(file_id, candidate.as_str()) { |
65 | let mut root_non_dir_owner = false; | 65 | let mut root_non_dir_owner = false; |
66 | let mut mod_path = RelativePathBuf::new(); | 66 | let mut mod_path = RelativePathBuf::new(); |
67 | if !(candidate.ends_with("mod.rs") || attr_path.is_some()) { | 67 | if !(candidate.ends_with("mod.rs") || attr_path.is_some()) { |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 4512448e0..bfa921de2 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -76,6 +76,19 @@ impl ModPath { | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | /// Returns the number of segments in the path (counting special segments like `$crate` and | ||
80 | /// `super`). | ||
81 | pub fn len(&self) -> usize { | ||
82 | self.segments.len() | ||
83 | + match self.kind { | ||
84 | PathKind::Plain => 0, | ||
85 | PathKind::Super(i) => i as usize, | ||
86 | PathKind::Crate => 1, | ||
87 | PathKind::Abs => 0, | ||
88 | PathKind::DollarCrate(_) => 1, | ||
89 | } | ||
90 | } | ||
91 | |||
79 | pub fn is_ident(&self) -> bool { | 92 | pub fn is_ident(&self) -> bool { |
80 | self.kind == PathKind::Plain && self.segments.len() == 1 | 93 | self.kind == PathKind::Plain && self.segments.len() == 1 |
81 | } | 94 | } |
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs index 6e435c8c1..74665c588 100644 --- a/crates/ra_hir_def/src/per_ns.rs +++ b/crates/ra_hir_def/src/per_ns.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | use hir_expand::MacroDefId; | 6 | use hir_expand::MacroDefId; |
7 | 7 | ||
8 | use crate::{visibility::Visibility, ModuleDefId}; | 8 | use crate::{item_scope::ItemInNs, visibility::Visibility, ModuleDefId}; |
9 | 9 | ||
10 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 10 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
11 | pub struct PerNs { | 11 | pub struct PerNs { |
@@ -84,4 +84,12 @@ impl PerNs { | |||
84 | macros: self.macros.or(other.macros), | 84 | macros: self.macros.or(other.macros), |
85 | } | 85 | } |
86 | } | 86 | } |
87 | |||
88 | pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> { | ||
89 | self.types | ||
90 | .map(|it| ItemInNs::Types(it.0)) | ||
91 | .into_iter() | ||
92 | .chain(self.values.map(|it| ItemInNs::Values(it.0)).into_iter()) | ||
93 | .chain(self.macros.map(|it| ItemInNs::Macros(it.0)).into_iter()) | ||
94 | } | ||
87 | } | 95 | } |
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs index eb83dee79..e7a5182f0 100644 --- a/crates/ra_hir_def/src/test_db.rs +++ b/crates/ra_hir_def/src/test_db.rs | |||
@@ -58,12 +58,8 @@ impl FileLoader for TestDB { | |||
58 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 58 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
59 | FileLoaderDelegate(self).file_text(file_id) | 59 | FileLoaderDelegate(self).file_text(file_id) |
60 | } | 60 | } |
61 | fn resolve_relative_path( | 61 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { |
62 | &self, | 62 | FileLoaderDelegate(self).resolve_path(anchor, path) |
63 | anchor: FileId, | ||
64 | relative_path: &RelativePath, | ||
65 | ) -> Option<FileId> { | ||
66 | FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) | ||
67 | } | 63 | } |
68 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | 64 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { |
69 | FileLoaderDelegate(self).relevant_crates(file_id) | 65 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 3bce8f673..eec5fb8eb 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -8,7 +8,7 @@ use crate::{ | |||
8 | use crate::{quote, EagerMacroId, LazyMacroId, MacroCallId}; | 8 | use crate::{quote, EagerMacroId, LazyMacroId, MacroCallId}; |
9 | use either::Either; | 9 | use either::Either; |
10 | use mbe::parse_to_token_tree; | 10 | use mbe::parse_to_token_tree; |
11 | use ra_db::{FileId, RelativePath}; | 11 | use ra_db::FileId; |
12 | use ra_parser::FragmentKind; | 12 | use ra_parser::FragmentKind; |
13 | 13 | ||
14 | macro_rules! register_builtin { | 14 | macro_rules! register_builtin { |
@@ -297,7 +297,7 @@ fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Opti | |||
297 | let call_site = call_id.as_file().original_file(db); | 297 | let call_site = call_id.as_file().original_file(db); |
298 | 298 | ||
299 | // Handle trivial case | 299 | // Handle trivial case |
300 | if let Some(res) = db.resolve_relative_path(call_site, &RelativePath::new(&path)) { | 300 | if let Some(res) = db.resolve_path(call_site, path) { |
301 | // Prevent include itself | 301 | // Prevent include itself |
302 | return if res == call_site { None } else { Some(res) }; | 302 | return if res == call_site { None } else { Some(res) }; |
303 | } | 303 | } |
diff --git a/crates/ra_hir_expand/src/test_db.rs b/crates/ra_hir_expand/src/test_db.rs index c1fb762de..765a2f6d1 100644 --- a/crates/ra_hir_expand/src/test_db.rs +++ b/crates/ra_hir_expand/src/test_db.rs | |||
@@ -41,12 +41,8 @@ impl FileLoader for TestDB { | |||
41 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 41 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
42 | FileLoaderDelegate(self).file_text(file_id) | 42 | FileLoaderDelegate(self).file_text(file_id) |
43 | } | 43 | } |
44 | fn resolve_relative_path( | 44 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { |
45 | &self, | 45 | FileLoaderDelegate(self).resolve_path(anchor, path) |
46 | anchor: FileId, | ||
47 | relative_path: &RelativePath, | ||
48 | ) -> Option<FileId> { | ||
49 | FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) | ||
50 | } | 46 | } |
51 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | 47 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { |
52 | FileLoaderDelegate(self).relevant_crates(file_id) | 48 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 8498d3d96..21a3bdfd1 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs | |||
@@ -72,12 +72,8 @@ impl FileLoader for TestDB { | |||
72 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 72 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
73 | FileLoaderDelegate(self).file_text(file_id) | 73 | FileLoaderDelegate(self).file_text(file_id) |
74 | } | 74 | } |
75 | fn resolve_relative_path( | 75 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { |
76 | &self, | 76 | FileLoaderDelegate(self).resolve_path(anchor, path) |
77 | anchor: FileId, | ||
78 | relative_path: &RelativePath, | ||
79 | ) -> Option<FileId> { | ||
80 | FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) | ||
81 | } | 77 | } |
82 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | 78 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { |
83 | FileLoaderDelegate(self).relevant_crates(file_id) | 79 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 75bd3c96b..49366de98 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -149,11 +149,10 @@ fn get_param_name_hints( | |||
149 | ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(), | 149 | ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(), |
150 | _ => return None, | 150 | _ => return None, |
151 | }; | 151 | }; |
152 | let args_count = args.clone().count(); | ||
153 | 152 | ||
154 | let fn_signature = get_fn_signature(sema, &expr)?; | 153 | let fn_signature = get_fn_signature(sema, &expr)?; |
155 | let n_params_to_skip = | 154 | let n_params_to_skip = |
156 | if fn_signature.has_self_param && fn_signature.parameter_names.len() > args_count { | 155 | if fn_signature.has_self_param && matches!(&expr, ast::Expr::MethodCallExpr(_)) { |
157 | 1 | 156 | 1 |
158 | } else { | 157 | } else { |
159 | 0 | 158 | 0 |
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs index 8446ef88e..ea78e49e0 100644 --- a/crates/ra_ide_db/src/change.rs +++ b/crates/ra_ide_db/src/change.rs | |||
@@ -334,6 +334,7 @@ impl RootDatabase { | |||
334 | hir::db::CrateLangItemsQuery | 334 | hir::db::CrateLangItemsQuery |
335 | hir::db::LangItemQuery | 335 | hir::db::LangItemQuery |
336 | hir::db::DocumentationQuery | 336 | hir::db::DocumentationQuery |
337 | hir::db::ImportMapQuery | ||
337 | 338 | ||
338 | // InternDatabase | 339 | // InternDatabase |
339 | hir::db::InternFunctionQuery | 340 | hir::db::InternFunctionQuery |
diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs index 1b74e6558..93d5891a0 100644 --- a/crates/ra_ide_db/src/lib.rs +++ b/crates/ra_ide_db/src/lib.rs | |||
@@ -57,12 +57,8 @@ impl FileLoader for RootDatabase { | |||
57 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 57 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
58 | FileLoaderDelegate(self).file_text(file_id) | 58 | FileLoaderDelegate(self).file_text(file_id) |
59 | } | 59 | } |
60 | fn resolve_relative_path( | 60 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { |
61 | &self, | 61 | FileLoaderDelegate(self).resolve_path(anchor, path) |
62 | anchor: FileId, | ||
63 | relative_path: &RelativePath, | ||
64 | ) -> Option<FileId> { | ||
65 | FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path) | ||
66 | } | 62 | } |
67 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { | 63 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { |
68 | FileLoaderDelegate(self).relevant_crates(file_id) | 64 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index ad3476310..0e2a83c6a 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs | |||
@@ -4,9 +4,7 @@ use std::{collections::HashMap, path::PathBuf, time::Instant}; | |||
4 | 4 | ||
5 | use lsp_types::{ | 5 | use lsp_types::{ |
6 | notification::DidOpenTextDocument, | 6 | notification::DidOpenTextDocument, |
7 | request::{ | 7 | request::{CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest}, |
8 | CodeActionRequest, Completion, Formatting, GotoDefinition, GotoTypeDefinition, HoverRequest, | ||
9 | }, | ||
10 | CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams, | 8 | CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams, |
11 | DocumentFormattingParams, FormattingOptions, GotoDefinitionParams, HoverParams, | 9 | DocumentFormattingParams, FormattingOptions, GotoDefinitionParams, HoverParams, |
12 | PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, | 10 | PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, |
@@ -507,6 +505,10 @@ fn main() { | |||
507 | println!("cargo:rerun-if-changed=build.rs"); | 505 | println!("cargo:rerun-if-changed=build.rs"); |
508 | } | 506 | } |
509 | //- src/main.rs | 507 | //- src/main.rs |
508 | #[rustc_builtin_macro] macro_rules! include {} | ||
509 | #[rustc_builtin_macro] macro_rules! concat {} | ||
510 | #[rustc_builtin_macro] macro_rules! env {} | ||
511 | |||
510 | include!(concat!(env!("OUT_DIR"), "/hello.rs")); | 512 | include!(concat!(env!("OUT_DIR"), "/hello.rs")); |
511 | 513 | ||
512 | #[cfg(atom_cfg)] | 514 | #[cfg(atom_cfg)] |
@@ -521,10 +523,8 @@ struct B; | |||
521 | fn main() { | 523 | fn main() { |
522 | let va = A; | 524 | let va = A; |
523 | let vb = B; | 525 | let vb = B; |
524 | message(); | 526 | let should_be_str = message(); |
525 | } | 527 | } |
526 | |||
527 | fn main() { message(); } | ||
528 | "###, | 528 | "###, |
529 | ) | 529 | ) |
530 | .with_config(|config| { | 530 | .with_config(|config| { |
@@ -532,54 +532,35 @@ fn main() { message(); } | |||
532 | }) | 532 | }) |
533 | .server(); | 533 | .server(); |
534 | server.wait_until_workspace_is_loaded(); | 534 | server.wait_until_workspace_is_loaded(); |
535 | let res = server.send_request::<GotoDefinition>(GotoDefinitionParams { | 535 | let res = server.send_request::<HoverRequest>(HoverParams { |
536 | text_document_position_params: TextDocumentPositionParams::new( | 536 | text_document_position_params: TextDocumentPositionParams::new( |
537 | server.doc_id("src/main.rs"), | 537 | server.doc_id("src/main.rs"), |
538 | Position::new(14, 8), | 538 | Position::new(18, 10), |
539 | ), | 539 | ), |
540 | work_done_progress_params: Default::default(), | 540 | work_done_progress_params: Default::default(), |
541 | partial_result_params: Default::default(), | ||
542 | }); | 541 | }); |
543 | assert!(format!("{}", res).contains("hello.rs")); | 542 | assert!(res.to_string().contains("&str")); |
544 | server.request::<GotoTypeDefinition>( | 543 | server.request::<GotoTypeDefinition>( |
545 | GotoDefinitionParams { | 544 | GotoDefinitionParams { |
546 | text_document_position_params: TextDocumentPositionParams::new( | 545 | text_document_position_params: TextDocumentPositionParams::new( |
547 | server.doc_id("src/main.rs"), | 546 | server.doc_id("src/main.rs"), |
548 | Position::new(12, 9), | 547 | Position::new(16, 9), |
549 | ), | 548 | ), |
550 | work_done_progress_params: Default::default(), | 549 | work_done_progress_params: Default::default(), |
551 | partial_result_params: Default::default(), | 550 | partial_result_params: Default::default(), |
552 | }, | 551 | }, |
553 | json!([{ | 552 | json!([{ |
554 | "originSelectionRange": { | 553 | "originSelectionRange": { |
555 | "end": { | 554 | "end": { "character": 10, "line": 16 }, |
556 | "character": 10, | 555 | "start": { "character": 8, "line": 16 } |
557 | "line": 12 | ||
558 | }, | ||
559 | "start": { | ||
560 | "character": 8, | ||
561 | "line": 12 | ||
562 | } | ||
563 | }, | 556 | }, |
564 | "targetRange": { | 557 | "targetRange": { |
565 | "end": { | 558 | "end": { "character": 9, "line": 7 }, |
566 | "character": 9, | 559 | "start": { "character": 0, "line": 6 } |
567 | "line": 3 | ||
568 | }, | ||
569 | "start": { | ||
570 | "character": 0, | ||
571 | "line": 2 | ||
572 | } | ||
573 | }, | 560 | }, |
574 | "targetSelectionRange": { | 561 | "targetSelectionRange": { |
575 | "end": { | 562 | "end": { "character": 8, "line": 7 }, |
576 | "character": 8, | 563 | "start": { "character": 7, "line": 7 } |
577 | "line": 3 | ||
578 | }, | ||
579 | "start": { | ||
580 | "character": 7, | ||
581 | "line": 3 | ||
582 | } | ||
583 | }, | 564 | }, |
584 | "targetUri": "file:///[..]src/main.rs" | 565 | "targetUri": "file:///[..]src/main.rs" |
585 | }]), | 566 | }]), |
@@ -588,41 +569,23 @@ fn main() { message(); } | |||
588 | GotoDefinitionParams { | 569 | GotoDefinitionParams { |
589 | text_document_position_params: TextDocumentPositionParams::new( | 570 | text_document_position_params: TextDocumentPositionParams::new( |
590 | server.doc_id("src/main.rs"), | 571 | server.doc_id("src/main.rs"), |
591 | Position::new(13, 9), | 572 | Position::new(17, 9), |
592 | ), | 573 | ), |
593 | work_done_progress_params: Default::default(), | 574 | work_done_progress_params: Default::default(), |
594 | partial_result_params: Default::default(), | 575 | partial_result_params: Default::default(), |
595 | }, | 576 | }, |
596 | json!([{ | 577 | json!([{ |
597 | "originSelectionRange": { | 578 | "originSelectionRange": { |
598 | "end": { | 579 | "end": { "character": 10, "line": 17 }, |
599 | "character": 10, | 580 | "start": { "character": 8, "line": 17 } |
600 | "line": 13 | ||
601 | }, | ||
602 | "start": { | ||
603 | "character": 8, | ||
604 | "line":13 | ||
605 | } | ||
606 | }, | 581 | }, |
607 | "targetRange": { | 582 | "targetRange": { |
608 | "end": { | 583 | "end": { "character": 9, "line": 11 }, |
609 | "character": 9, | 584 | "start": { "character": 0, "line":10 } |
610 | "line": 7 | ||
611 | }, | ||
612 | "start": { | ||
613 | "character": 0, | ||
614 | "line":6 | ||
615 | } | ||
616 | }, | 585 | }, |
617 | "targetSelectionRange": { | 586 | "targetSelectionRange": { |
618 | "end": { | 587 | "end": { "character": 8, "line": 11 }, |
619 | "character": 8, | 588 | "start": { "character": 7, "line": 11 } |
620 | "line": 7 | ||
621 | }, | ||
622 | "start": { | ||
623 | "character": 7, | ||
624 | "line": 7 | ||
625 | } | ||
626 | }, | 589 | }, |
627 | "targetUri": "file:///[..]src/main.rs" | 590 | "targetUri": "file:///[..]src/main.rs" |
628 | }]), | 591 | }]), |