diff options
Diffstat (limited to 'crates')
27 files changed, 339 insertions, 183 deletions
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs index 62bf2a4b2..54baa3a63 100644 --- a/crates/base_db/src/lib.rs +++ b/crates/base_db/src/lib.rs | |||
@@ -120,6 +120,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> { | |||
120 | } | 120 | } |
121 | 121 | ||
122 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { | 122 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { |
123 | let _p = profile::span("relevant_crates"); | ||
123 | let source_root = self.0.file_source_root(file_id); | 124 | let source_root = self.0.file_source_root(file_id); |
124 | self.0.source_root_crates(source_root) | 125 | self.0.source_root_crates(source_root) |
125 | } | 126 | } |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index debc3ee62..b9c1dc44d 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -191,6 +191,7 @@ impl Crate { | |||
191 | db: &dyn DefDatabase, | 191 | db: &dyn DefDatabase, |
192 | query: import_map::Query, | 192 | query: import_map::Query, |
193 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { | 193 | ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { |
194 | let _p = profile::span("query_external_importables"); | ||
194 | import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { | 195 | import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { |
195 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), | 196 | ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), |
196 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), | 197 | ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), |
@@ -2185,6 +2186,7 @@ impl Type { | |||
2185 | name: Option<&Name>, | 2186 | name: Option<&Name>, |
2186 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 2187 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
2187 | ) -> Option<T> { | 2188 | ) -> Option<T> { |
2189 | let _p = profile::span("iterate_method_candidates"); | ||
2188 | // There should be no inference vars in types passed here | 2190 | // There should be no inference vars in types passed here |
2189 | // FIXME check that? | 2191 | // FIXME check that? |
2190 | // FIXME replace Unknown by bound vars here | 2192 | // FIXME replace Unknown by bound vars here |
@@ -2218,6 +2220,7 @@ impl Type { | |||
2218 | name: Option<&Name>, | 2220 | name: Option<&Name>, |
2219 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 2221 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
2220 | ) -> Option<T> { | 2222 | ) -> Option<T> { |
2223 | let _p = profile::span("iterate_path_candidates"); | ||
2221 | let canonical = hir_ty::replace_errors_with_variables(&self.ty); | 2224 | let canonical = hir_ty::replace_errors_with_variables(&self.ty); |
2222 | 2225 | ||
2223 | let env = self.env.clone(); | 2226 | let env = self.env.clone(); |
@@ -2255,6 +2258,7 @@ impl Type { | |||
2255 | &'a self, | 2258 | &'a self, |
2256 | db: &'a dyn HirDatabase, | 2259 | db: &'a dyn HirDatabase, |
2257 | ) -> impl Iterator<Item = Trait> + 'a { | 2260 | ) -> impl Iterator<Item = Trait> + 'a { |
2261 | let _p = profile::span("applicable_inherent_traits"); | ||
2258 | self.autoderef(db) | 2262 | self.autoderef(db) |
2259 | .filter_map(|derefed_type| derefed_type.ty.dyn_trait()) | 2263 | .filter_map(|derefed_type| derefed_type.ty.dyn_trait()) |
2260 | .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) | 2264 | .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) |
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs index 960cabb5f..404e3e153 100644 --- a/crates/hir_def/src/import_map.rs +++ b/crates/hir_def/src/import_map.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! A map of all publicly exported items in a crate. | 1 | //! A map of all publicly exported items in a crate. |
2 | 2 | ||
3 | use std::{cmp::Ordering, fmt, hash::BuildHasherDefault, sync::Arc}; | 3 | use std::{fmt, hash::BuildHasherDefault, sync::Arc}; |
4 | 4 | ||
5 | use base_db::CrateId; | 5 | use base_db::CrateId; |
6 | use fst::{self, Streamer}; | 6 | use fst::{self, Streamer}; |
@@ -69,81 +69,11 @@ pub struct ImportMap { | |||
69 | impl ImportMap { | 69 | impl ImportMap { |
70 | pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { | 70 | pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { |
71 | let _p = profile::span("import_map_query"); | 71 | let _p = profile::span("import_map_query"); |
72 | let def_map = db.crate_def_map(krate); | ||
73 | let mut import_map = Self::default(); | ||
74 | |||
75 | // We look only into modules that are public(ly reexported), starting with the crate root. | ||
76 | let empty = ImportPath { segments: vec![] }; | ||
77 | let root = def_map.module_id(def_map.root()); | ||
78 | let mut worklist = vec![(root, empty)]; | ||
79 | while let Some((module, mod_path)) = worklist.pop() { | ||
80 | let ext_def_map; | ||
81 | let mod_data = if module.krate == krate { | ||
82 | &def_map[module.local_id] | ||
83 | } else { | ||
84 | // The crate might reexport a module defined in another crate. | ||
85 | ext_def_map = module.def_map(db); | ||
86 | &ext_def_map[module.local_id] | ||
87 | }; | ||
88 | |||
89 | let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { | ||
90 | let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); | ||
91 | if per_ns.is_none() { | ||
92 | None | ||
93 | } else { | ||
94 | Some((name, per_ns)) | ||
95 | } | ||
96 | }); | ||
97 | |||
98 | for (name, per_ns) in visible_items { | ||
99 | let mk_path = || { | ||
100 | let mut path = mod_path.clone(); | ||
101 | path.segments.push(name.clone()); | ||
102 | path | ||
103 | }; | ||
104 | |||
105 | for item in per_ns.iter_items() { | ||
106 | let path = mk_path(); | ||
107 | let path_len = path.len(); | ||
108 | let import_info = | ||
109 | ImportInfo { path, container: module, is_trait_assoc_item: false }; | ||
110 | |||
111 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
112 | import_map.collect_trait_assoc_items( | ||
113 | db, | ||
114 | tr, | ||
115 | matches!(item, ItemInNs::Types(_)), | ||
116 | &import_info, | ||
117 | ); | ||
118 | } | ||
119 | 72 | ||
120 | match import_map.map.entry(item) { | 73 | let mut import_map = collect_import_map(db, krate); |
121 | Entry::Vacant(entry) => { | ||
122 | entry.insert(import_info); | ||
123 | } | ||
124 | Entry::Occupied(mut entry) => { | ||
125 | // If the new path is shorter, prefer that one. | ||
126 | if path_len < entry.get().path.len() { | ||
127 | *entry.get_mut() = import_info; | ||
128 | } else { | ||
129 | continue; | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | // If we've just added a path to a module, descend into it. We might traverse | ||
135 | // modules multiple times, but only if the new path to it is shorter than the | ||
136 | // first (else we `continue` above). | ||
137 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | ||
138 | worklist.push((mod_id, mk_path())); | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | 74 | ||
144 | let mut importables = import_map.map.iter().collect::<Vec<_>>(); | 75 | let mut importables = import_map.map.iter().collect::<Vec<_>>(); |
145 | 76 | importables.sort_by_cached_key(|(_, import_info)| fst_path(&import_info.path)); | |
146 | importables.sort_by(cmp); | ||
147 | 77 | ||
148 | // Build the FST, taking care not to insert duplicate values. | 78 | // Build the FST, taking care not to insert duplicate values. |
149 | 79 | ||
@@ -151,13 +81,13 @@ impl ImportMap { | |||
151 | let mut last_batch_start = 0; | 81 | let mut last_batch_start = 0; |
152 | 82 | ||
153 | for idx in 0..importables.len() { | 83 | for idx in 0..importables.len() { |
154 | if let Some(next_item) = importables.get(idx + 1) { | 84 | let key = fst_path(&importables[last_batch_start].1.path); |
155 | if cmp(&importables[last_batch_start], next_item) == Ordering::Equal { | 85 | if let Some((_, next_import_info)) = importables.get(idx + 1) { |
86 | if key == fst_path(&next_import_info.path) { | ||
156 | continue; | 87 | continue; |
157 | } | 88 | } |
158 | } | 89 | } |
159 | 90 | ||
160 | let key = fst_path(&importables[last_batch_start].1.path); | ||
161 | builder.insert(key, last_batch_start as u64).unwrap(); | 91 | builder.insert(key, last_batch_start as u64).unwrap(); |
162 | 92 | ||
163 | last_batch_start = idx + 1; | 93 | last_batch_start = idx + 1; |
@@ -185,6 +115,7 @@ impl ImportMap { | |||
185 | is_type_in_ns: bool, | 115 | is_type_in_ns: bool, |
186 | original_import_info: &ImportInfo, | 116 | original_import_info: &ImportInfo, |
187 | ) { | 117 | ) { |
118 | let _p = profile::span("collect_trait_assoc_items"); | ||
188 | for (assoc_item_name, item) in &db.trait_data(tr).items { | 119 | for (assoc_item_name, item) in &db.trait_data(tr).items { |
189 | let module_def_id = match item { | 120 | let module_def_id = match item { |
190 | AssocItemId::FunctionId(f) => ModuleDefId::from(*f), | 121 | AssocItemId::FunctionId(f) => ModuleDefId::from(*f), |
@@ -210,6 +141,84 @@ impl ImportMap { | |||
210 | } | 141 | } |
211 | } | 142 | } |
212 | 143 | ||
144 | fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap { | ||
145 | let _p = profile::span("collect_import_map"); | ||
146 | |||
147 | let def_map = db.crate_def_map(krate); | ||
148 | let mut import_map = ImportMap::default(); | ||
149 | |||
150 | // We look only into modules that are public(ly reexported), starting with the crate root. | ||
151 | let empty = ImportPath { segments: vec![] }; | ||
152 | let root = def_map.module_id(def_map.root()); | ||
153 | let mut worklist = vec![(root, empty)]; | ||
154 | while let Some((module, mod_path)) = worklist.pop() { | ||
155 | let ext_def_map; | ||
156 | let mod_data = if module.krate == krate { | ||
157 | &def_map[module.local_id] | ||
158 | } else { | ||
159 | // The crate might reexport a module defined in another crate. | ||
160 | ext_def_map = module.def_map(db); | ||
161 | &ext_def_map[module.local_id] | ||
162 | }; | ||
163 | |||
164 | let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| { | ||
165 | let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public); | ||
166 | if per_ns.is_none() { | ||
167 | None | ||
168 | } else { | ||
169 | Some((name, per_ns)) | ||
170 | } | ||
171 | }); | ||
172 | |||
173 | for (name, per_ns) in visible_items { | ||
174 | let mk_path = || { | ||
175 | let mut path = mod_path.clone(); | ||
176 | path.segments.push(name.clone()); | ||
177 | path | ||
178 | }; | ||
179 | |||
180 | for item in per_ns.iter_items() { | ||
181 | let path = mk_path(); | ||
182 | let path_len = path.len(); | ||
183 | let import_info = | ||
184 | ImportInfo { path, container: module, is_trait_assoc_item: false }; | ||
185 | |||
186 | if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { | ||
187 | import_map.collect_trait_assoc_items( | ||
188 | db, | ||
189 | tr, | ||
190 | matches!(item, ItemInNs::Types(_)), | ||
191 | &import_info, | ||
192 | ); | ||
193 | } | ||
194 | |||
195 | match import_map.map.entry(item) { | ||
196 | Entry::Vacant(entry) => { | ||
197 | entry.insert(import_info); | ||
198 | } | ||
199 | Entry::Occupied(mut entry) => { | ||
200 | // If the new path is shorter, prefer that one. | ||
201 | if path_len < entry.get().path.len() { | ||
202 | *entry.get_mut() = import_info; | ||
203 | } else { | ||
204 | continue; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | // If we've just added a path to a module, descend into it. We might traverse | ||
210 | // modules multiple times, but only if the new path to it is shorter than the | ||
211 | // first (else we `continue` above). | ||
212 | if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() { | ||
213 | worklist.push((mod_id, mk_path())); | ||
214 | } | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | import_map | ||
220 | } | ||
221 | |||
213 | impl PartialEq for ImportMap { | 222 | impl PartialEq for ImportMap { |
214 | fn eq(&self, other: &Self) -> bool { | 223 | fn eq(&self, other: &Self) -> bool { |
215 | // `fst` and `importables` are built from `map`, so we don't need to compare them. | 224 | // `fst` and `importables` are built from `map`, so we don't need to compare them. |
@@ -240,17 +249,12 @@ impl fmt::Debug for ImportMap { | |||
240 | } | 249 | } |
241 | 250 | ||
242 | fn fst_path(path: &ImportPath) -> String { | 251 | fn fst_path(path: &ImportPath) -> String { |
252 | let _p = profile::span("fst_path"); | ||
243 | let mut s = path.to_string(); | 253 | let mut s = path.to_string(); |
244 | s.make_ascii_lowercase(); | 254 | s.make_ascii_lowercase(); |
245 | s | 255 | s |
246 | } | 256 | } |
247 | 257 | ||
248 | fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo)) -> Ordering { | ||
249 | let lhs_str = fst_path(&lhs.path); | ||
250 | let rhs_str = fst_path(&rhs.path); | ||
251 | lhs_str.cmp(&rhs_str) | ||
252 | } | ||
253 | |||
254 | #[derive(Debug, Eq, PartialEq, Hash)] | 258 | #[derive(Debug, Eq, PartialEq, Hash)] |
255 | pub enum ImportKind { | 259 | pub enum ImportKind { |
256 | Module, | 260 | Module, |
@@ -338,6 +342,7 @@ impl Query { | |||
338 | } | 342 | } |
339 | 343 | ||
340 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { | 344 | fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { |
345 | let _p = profile::span("import_map::Query::import_matches"); | ||
341 | if import.is_trait_assoc_item { | 346 | if import.is_trait_assoc_item { |
342 | if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) { | 347 | if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) { |
343 | return false; | 348 | return false; |
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs index 9e90f745c..3a45cbfa1 100644 --- a/crates/hir_def/src/lang_item.rs +++ b/crates/hir_def/src/lang_item.rs | |||
@@ -141,6 +141,7 @@ impl LangItems { | |||
141 | ) where | 141 | ) where |
142 | T: Into<AttrDefId> + Copy, | 142 | T: Into<AttrDefId> + Copy, |
143 | { | 143 | { |
144 | let _p = profile::span("collect_lang_item"); | ||
144 | if let Some(lang_item_name) = lang_attr(db, item) { | 145 | if let Some(lang_item_name) = lang_attr(db, item) { |
145 | self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); | 146 | self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); |
146 | } | 147 | } |
diff --git a/crates/hir_def/src/per_ns.rs b/crates/hir_def/src/per_ns.rs index a594afce6..a9f13cb82 100644 --- a/crates/hir_def/src/per_ns.rs +++ b/crates/hir_def/src/per_ns.rs | |||
@@ -62,6 +62,7 @@ impl PerNs { | |||
62 | } | 62 | } |
63 | 63 | ||
64 | pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { | 64 | pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { |
65 | let _p = profile::span("PerNs::filter_visibility"); | ||
65 | PerNs { | 66 | PerNs { |
66 | types: self.types.filter(|(_, v)| f(*v)), | 67 | types: self.types.filter(|(_, v)| f(*v)), |
67 | values: self.values.filter(|(_, v)| f(*v)), | 68 | values: self.values.filter(|(_, v)| f(*v)), |
@@ -86,6 +87,7 @@ impl PerNs { | |||
86 | } | 87 | } |
87 | 88 | ||
88 | pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> { | 89 | pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> { |
90 | let _p = profile::span("PerNs::iter_items"); | ||
89 | self.types | 91 | self.types |
90 | .map(|it| ItemInNs::Types(it.0)) | 92 | .map(|it| ItemInNs::Types(it.0)) |
91 | .into_iter() | 93 | .into_iter() |
diff --git a/crates/ide/src/prime_caches.rs b/crates/ide/src/prime_caches.rs index d912a01b8..36801c964 100644 --- a/crates/ide/src/prime_caches.rs +++ b/crates/ide/src/prime_caches.rs | |||
@@ -33,14 +33,15 @@ pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress) | |||
33 | // FIXME: This would be easy to parallelize, since it's in the ideal ordering for that. | 33 | // FIXME: This would be easy to parallelize, since it's in the ideal ordering for that. |
34 | // Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks | 34 | // Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks |
35 | // cancellation, so we cannot use rayon. | 35 | // cancellation, so we cannot use rayon. |
36 | for (i, krate) in topo.iter().enumerate() { | 36 | for (i, &crate_id) in topo.iter().enumerate() { |
37 | let crate_name = graph[*krate].display_name.as_deref().unwrap_or_default().to_string(); | 37 | let crate_name = graph[crate_id].display_name.as_deref().unwrap_or_default().to_string(); |
38 | 38 | ||
39 | cb(PrimeCachesProgress::StartedOnCrate { | 39 | cb(PrimeCachesProgress::StartedOnCrate { |
40 | on_crate: crate_name, | 40 | on_crate: crate_name, |
41 | n_done: i, | 41 | n_done: i, |
42 | n_total: topo.len(), | 42 | n_total: topo.len(), |
43 | }); | 43 | }); |
44 | db.crate_def_map(*krate); | 44 | db.crate_def_map(crate_id); |
45 | db.import_map(crate_id); | ||
45 | } | 46 | } |
46 | } | 47 | } |
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index ae492a264..f8b64a669 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -1380,4 +1380,24 @@ lib::foo!(); | |||
1380 | "#]], | 1380 | "#]], |
1381 | ); | 1381 | ); |
1382 | } | 1382 | } |
1383 | |||
1384 | #[test] | ||
1385 | fn macro_doesnt_reference_attribute_on_call() { | ||
1386 | check( | ||
1387 | r#" | ||
1388 | macro_rules! m { | ||
1389 | () => {}; | ||
1390 | } | ||
1391 | |||
1392 | #[proc_macro_test::attr_noop] | ||
1393 | m$0!(); | ||
1394 | |||
1395 | "#, | ||
1396 | expect![[r#" | ||
1397 | m Macro FileId(0) 0..32 13..14 | ||
1398 | |||
1399 | FileId(0) 64..65 | ||
1400 | "#]], | ||
1401 | ); | ||
1402 | } | ||
1383 | } | 1403 | } |
diff --git a/crates/ide_assists/src/handlers/change_visibility.rs b/crates/ide_assists/src/handlers/change_visibility.rs index d7e39b2ae..ed936667f 100644 --- a/crates/ide_assists/src/handlers/change_visibility.rs +++ b/crates/ide_assists/src/handlers/change_visibility.rs | |||
@@ -1,7 +1,9 @@ | |||
1 | use syntax::{ | 1 | use syntax::{ |
2 | ast::{self, NameOwner, VisibilityOwner}, | 2 | ast::{self, NameOwner, VisibilityOwner}, |
3 | AstNode, | 3 | AstNode, |
4 | SyntaxKind::{CONST, ENUM, FN, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, VISIBILITY}, | 4 | SyntaxKind::{ |
5 | CONST, ENUM, FN, MACRO_DEF, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, USE, VISIBILITY, | ||
6 | }, | ||
5 | T, | 7 | T, |
6 | }; | 8 | }; |
7 | 9 | ||
@@ -37,12 +39,15 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
37 | | T![enum] | 39 | | T![enum] |
38 | | T![trait] | 40 | | T![trait] |
39 | | T![type] | 41 | | T![type] |
42 | | T![use] | ||
43 | | T![macro] | ||
40 | ) | 44 | ) |
41 | }); | 45 | }); |
42 | 46 | ||
43 | let (offset, target) = if let Some(keyword) = item_keyword { | 47 | let (offset, target) = if let Some(keyword) = item_keyword { |
44 | let parent = keyword.parent()?; | 48 | let parent = keyword.parent()?; |
45 | let def_kws = vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT]; | 49 | let def_kws = |
50 | vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF]; | ||
46 | // Parent is not a definition, can't add visibility | 51 | // Parent is not a definition, can't add visibility |
47 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { | 52 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { |
48 | return None; | 53 | return None; |
@@ -122,6 +127,8 @@ mod tests { | |||
122 | check_assist(change_visibility, "$0trait Foo {}", "pub(crate) trait Foo {}"); | 127 | check_assist(change_visibility, "$0trait Foo {}", "pub(crate) trait Foo {}"); |
123 | check_assist(change_visibility, "m$0od {}", "pub(crate) mod {}"); | 128 | check_assist(change_visibility, "m$0od {}", "pub(crate) mod {}"); |
124 | check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}"); | 129 | check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}"); |
130 | check_assist(change_visibility, "$0macro foo() {}", "pub(crate) macro foo() {}"); | ||
131 | check_assist(change_visibility, "$0use foo;", "pub(crate) use foo;"); | ||
125 | } | 132 | } |
126 | 133 | ||
127 | #[test] | 134 | #[test] |
diff --git a/crates/ide_assists/src/handlers/remove_unused_param.rs b/crates/ide_assists/src/handlers/remove_unused_param.rs index 2699d2861..fabfe7e93 100644 --- a/crates/ide_assists/src/handlers/remove_unused_param.rs +++ b/crates/ide_assists/src/handlers/remove_unused_param.rs | |||
@@ -37,8 +37,20 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt | |||
37 | _ => return None, | 37 | _ => return None, |
38 | }; | 38 | }; |
39 | let func = param.syntax().ancestors().find_map(ast::Fn::cast)?; | 39 | let func = param.syntax().ancestors().find_map(ast::Fn::cast)?; |
40 | let param_position = func.param_list()?.params().position(|it| it == param)?; | ||
41 | 40 | ||
41 | // check if fn is in impl Trait for .. | ||
42 | if func | ||
43 | .syntax() | ||
44 | .parent() // AssocItemList | ||
45 | .and_then(|x| x.parent()) | ||
46 | .and_then(ast::Impl::cast) | ||
47 | .map_or(false, |imp| imp.trait_().is_some()) | ||
48 | { | ||
49 | cov_mark::hit!(trait_impl); | ||
50 | return None; | ||
51 | } | ||
52 | |||
53 | let param_position = func.param_list()?.params().position(|it| it == param)?; | ||
42 | let fn_def = { | 54 | let fn_def = { |
43 | let func = ctx.sema.to_def(&func)?; | 55 | let func = ctx.sema.to_def(&func)?; |
44 | Definition::ModuleDef(func.into()) | 56 | Definition::ModuleDef(func.into()) |
@@ -254,6 +266,22 @@ fn main() { foo(9, 2) } | |||
254 | } | 266 | } |
255 | 267 | ||
256 | #[test] | 268 | #[test] |
269 | fn trait_impl() { | ||
270 | cov_mark::check!(trait_impl); | ||
271 | check_assist_not_applicable( | ||
272 | remove_unused_param, | ||
273 | r#" | ||
274 | trait Trait { | ||
275 | fn foo(x: i32); | ||
276 | } | ||
277 | impl Trait for () { | ||
278 | fn foo($0x: i32) {} | ||
279 | } | ||
280 | "#, | ||
281 | ); | ||
282 | } | ||
283 | |||
284 | #[test] | ||
257 | fn remove_across_files() { | 285 | fn remove_across_files() { |
258 | check_assist( | 286 | check_assist( |
259 | remove_unused_param, | 287 | remove_unused_param, |
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index 1dcccbb8b..1b69d72f9 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs | |||
@@ -357,9 +357,9 @@ impl NameRefClass { | |||
357 | } | 357 | } |
358 | } | 358 | } |
359 | 359 | ||
360 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 360 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { |
361 | if let Some(path) = macro_call.path() { | 361 | if path.qualifier().is_none() { |
362 | if path.qualifier().is_none() { | 362 | if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { |
363 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment | 363 | // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment |
364 | // paths are handled below (allowing `log$0::info!` to resolve to the log crate). | 364 | // paths are handled below (allowing `log$0::info!` to resolve to the log crate). |
365 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 365 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
@@ -367,9 +367,7 @@ impl NameRefClass { | |||
367 | } | 367 | } |
368 | } | 368 | } |
369 | } | 369 | } |
370 | } | ||
371 | 370 | ||
372 | if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) { | ||
373 | if let Some(resolved) = sema.resolve_path(&path) { | 371 | if let Some(resolved) = sema.resolve_path(&path) { |
374 | if path.syntax().parent().and_then(ast::Attr::cast).is_some() { | 372 | if path.syntax().parent().and_then(ast::Attr::cast).is_some() { |
375 | if let PathResolution::Def(ModuleDef::Function(func)) = resolved { | 373 | if let PathResolution::Def(ModuleDef::Function(func)) = resolved { |
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs index 5c372a7e5..000f87a85 100644 --- a/crates/ide_db/src/symbol_index.rs +++ b/crates/ide_db/src/symbol_index.rs | |||
@@ -197,6 +197,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { | |||
197 | } | 197 | } |
198 | 198 | ||
199 | pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> { | 199 | pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> { |
200 | let _p = profile::span("crate_symbols").detail(|| format!("{:?}", query)); | ||
200 | // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from | 201 | // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from |
201 | // that instead? | 202 | // that instead? |
202 | 203 | ||
@@ -321,6 +322,7 @@ impl SymbolIndex { | |||
321 | 322 | ||
322 | impl Query { | 323 | impl Query { |
323 | pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> { | 324 | pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> { |
325 | let _p = profile::span("symbol_index::Query::search"); | ||
324 | let mut op = fst::map::OpBuilder::new(); | 326 | let mut op = fst::map::OpBuilder::new(); |
325 | for file_symbols in indices.iter() { | 327 | for file_symbols in indices.iter() { |
326 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); | 328 | let automaton = fst::automaton::Subsequence::new(&self.lowercased); |
diff --git a/crates/proc_macro_srv/src/dylib.rs b/crates/proc_macro_srv/src/dylib.rs index cccc53220..5133e7c50 100644 --- a/crates/proc_macro_srv/src/dylib.rs +++ b/crates/proc_macro_srv/src/dylib.rs | |||
@@ -188,7 +188,9 @@ impl Expander { | |||
188 | /// Copy the dylib to temp directory to prevent locking in Windows | 188 | /// Copy the dylib to temp directory to prevent locking in Windows |
189 | #[cfg(windows)] | 189 | #[cfg(windows)] |
190 | fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> { | 190 | fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> { |
191 | use std::{ffi::OsString, time::SystemTime}; | 191 | use std::collections::hash_map::RandomState; |
192 | use std::ffi::OsString; | ||
193 | use std::hash::{BuildHasher, Hasher}; | ||
192 | 194 | ||
193 | let mut to = std::env::temp_dir(); | 195 | let mut to = std::env::temp_dir(); |
194 | 196 | ||
@@ -199,10 +201,11 @@ fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> { | |||
199 | ) | 201 | ) |
200 | })?; | 202 | })?; |
201 | 203 | ||
202 | // generate a time deps unique number | 204 | // Generate a unique number by abusing `HashMap`'s hasher. |
203 | let t = SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("Time went backwards"); | 205 | // Maybe this will also "inspire" a libs team member to finally put `rand` in libstd. |
206 | let t = RandomState::new().build_hasher().finish(); | ||
204 | 207 | ||
205 | let mut unique_name = OsString::from(t.as_millis().to_string()); | 208 | let mut unique_name = OsString::from(t.to_string()); |
206 | unique_name.push(file_name); | 209 | unique_name.push(file_name); |
207 | 210 | ||
208 | to.push(unique_name); | 211 | to.push(unique_name); |
diff --git a/crates/proc_macro_srv/src/tests/utils.rs b/crates/proc_macro_srv/src/tests/utils.rs index 2e950c113..2c093aa0a 100644 --- a/crates/proc_macro_srv/src/tests/utils.rs +++ b/crates/proc_macro_srv/src/tests/utils.rs | |||
@@ -7,35 +7,8 @@ use proc_macro_api::ListMacrosTask; | |||
7 | use std::str::FromStr; | 7 | use std::str::FromStr; |
8 | 8 | ||
9 | pub mod fixtures { | 9 | pub mod fixtures { |
10 | use cargo_metadata::Message; | ||
11 | use std::path::PathBuf; | ||
12 | use std::process::Command; | ||
13 | |||
14 | // Use current project metadata to get the proc-macro dylib path | ||
15 | pub fn proc_macro_test_dylib_path() -> std::path::PathBuf { | 10 | pub fn proc_macro_test_dylib_path() -> std::path::PathBuf { |
16 | let name = "proc_macro_test"; | 11 | proc_macro_test::PROC_MACRO_TEST_LOCATION.into() |
17 | let version = "0.0.0"; | ||
18 | let command = Command::new(toolchain::cargo()) | ||
19 | .args(&["check", "--tests", "--message-format", "json"]) | ||
20 | .output() | ||
21 | .unwrap() | ||
22 | .stdout; | ||
23 | |||
24 | for message in Message::parse_stream(command.as_slice()) { | ||
25 | match message.unwrap() { | ||
26 | Message::CompilerArtifact(artifact) => { | ||
27 | if artifact.target.kind.contains(&"proc-macro".to_string()) { | ||
28 | let repr = format!("{} {}", name, version); | ||
29 | if artifact.package_id.repr.starts_with(&repr) { | ||
30 | return PathBuf::from(&artifact.filenames[0]); | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | _ => (), // Unknown message | ||
35 | } | ||
36 | } | ||
37 | |||
38 | panic!("No proc-macro dylib for {} found!", name); | ||
39 | } | 12 | } |
40 | } | 13 | } |
41 | 14 | ||
diff --git a/crates/proc_macro_test/Cargo.toml b/crates/proc_macro_test/Cargo.toml index 753443be2..1a88e361e 100644 --- a/crates/proc_macro_test/Cargo.toml +++ b/crates/proc_macro_test/Cargo.toml | |||
@@ -8,4 +8,8 @@ publish = false | |||
8 | 8 | ||
9 | [lib] | 9 | [lib] |
10 | doctest = false | 10 | doctest = false |
11 | proc-macro = true | 11 | |
12 | [build-dependencies] | ||
13 | proc_macro_test_impl = { path = "imp", version = "0.0.0" } | ||
14 | toolchain = { path = "../toolchain", version = "0.0.0" } | ||
15 | cargo_metadata = "0.13" | ||
diff --git a/crates/proc_macro_test/build.rs b/crates/proc_macro_test/build.rs new file mode 100644 index 000000000..4653a93dd --- /dev/null +++ b/crates/proc_macro_test/build.rs | |||
@@ -0,0 +1,48 @@ | |||
1 | //! This will build the proc macro in `imp`, and copy the resulting dylib artifact into the | ||
2 | //! `OUT_DIR`. | ||
3 | //! | ||
4 | //! `proc_macro_test` itself contains only a path to that artifact. | ||
5 | |||
6 | use std::{ | ||
7 | env, fs, | ||
8 | path::{Path, PathBuf}, | ||
9 | process::Command, | ||
10 | }; | ||
11 | |||
12 | use cargo_metadata::Message; | ||
13 | |||
14 | fn main() { | ||
15 | let out_dir = env::var_os("OUT_DIR").unwrap(); | ||
16 | let out_dir = Path::new(&out_dir); | ||
17 | |||
18 | let name = "proc_macro_test_impl"; | ||
19 | let version = "0.0.0"; | ||
20 | let output = Command::new(toolchain::cargo()) | ||
21 | .current_dir("imp") | ||
22 | .args(&["build", "-p", "proc_macro_test_impl", "--message-format", "json"]) | ||
23 | .output() | ||
24 | .unwrap(); | ||
25 | assert!(output.status.success()); | ||
26 | |||
27 | let mut artifact_path = None; | ||
28 | for message in Message::parse_stream(output.stdout.as_slice()) { | ||
29 | match message.unwrap() { | ||
30 | Message::CompilerArtifact(artifact) => { | ||
31 | if artifact.target.kind.contains(&"proc-macro".to_string()) { | ||
32 | let repr = format!("{} {}", name, version); | ||
33 | if artifact.package_id.repr.starts_with(&repr) { | ||
34 | artifact_path = Some(PathBuf::from(&artifact.filenames[0])); | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | _ => (), // Unknown message | ||
39 | } | ||
40 | } | ||
41 | |||
42 | let src_path = artifact_path.expect("no dylib for proc_macro_test_impl found"); | ||
43 | let dest_path = out_dir.join(src_path.file_name().unwrap()); | ||
44 | fs::copy(src_path, &dest_path).unwrap(); | ||
45 | |||
46 | let info_path = out_dir.join("proc_macro_test_location.txt"); | ||
47 | fs::write(info_path, dest_path.to_str().unwrap()).unwrap(); | ||
48 | } | ||
diff --git a/crates/proc_macro_test/imp/.gitignore b/crates/proc_macro_test/imp/.gitignore new file mode 100644 index 000000000..2c96eb1b6 --- /dev/null +++ b/crates/proc_macro_test/imp/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | target/ | ||
2 | Cargo.lock | ||
diff --git a/crates/proc_macro_test/imp/Cargo.toml b/crates/proc_macro_test/imp/Cargo.toml new file mode 100644 index 000000000..1c2e75401 --- /dev/null +++ b/crates/proc_macro_test/imp/Cargo.toml | |||
@@ -0,0 +1,17 @@ | |||
1 | [package] | ||
2 | name = "proc_macro_test_impl" | ||
3 | version = "0.0.0" | ||
4 | license = "MIT OR Apache-2.0" | ||
5 | authors = ["rust-analyzer developers"] | ||
6 | edition = "2018" | ||
7 | publish = false | ||
8 | |||
9 | [lib] | ||
10 | doctest = false | ||
11 | proc-macro = true | ||
12 | |||
13 | [workspace] | ||
14 | |||
15 | [dependencies] | ||
16 | # this crate should not have any dependencies, since it uses its own workspace, | ||
17 | # and its own `Cargo.lock` | ||
diff --git a/crates/proc_macro_test/imp/src/lib.rs b/crates/proc_macro_test/imp/src/lib.rs new file mode 100644 index 000000000..4b26d2472 --- /dev/null +++ b/crates/proc_macro_test/imp/src/lib.rs | |||
@@ -0,0 +1,48 @@ | |||
1 | //! Exports a few trivial procedural macros for testing. | ||
2 | |||
3 | use proc_macro::TokenStream; | ||
4 | |||
5 | #[proc_macro] | ||
6 | pub fn fn_like_noop(args: TokenStream) -> TokenStream { | ||
7 | args | ||
8 | } | ||
9 | |||
10 | #[proc_macro] | ||
11 | pub fn fn_like_panic(args: TokenStream) -> TokenStream { | ||
12 | panic!("fn_like_panic!({})", args); | ||
13 | } | ||
14 | |||
15 | #[proc_macro] | ||
16 | pub fn fn_like_error(args: TokenStream) -> TokenStream { | ||
17 | format!("compile_error!(\"fn_like_error!({})\");", args).parse().unwrap() | ||
18 | } | ||
19 | |||
20 | #[proc_macro_attribute] | ||
21 | pub fn attr_noop(_args: TokenStream, item: TokenStream) -> TokenStream { | ||
22 | item | ||
23 | } | ||
24 | |||
25 | #[proc_macro_attribute] | ||
26 | pub fn attr_panic(args: TokenStream, item: TokenStream) -> TokenStream { | ||
27 | panic!("#[attr_panic {}] {}", args, item); | ||
28 | } | ||
29 | |||
30 | #[proc_macro_attribute] | ||
31 | pub fn attr_error(args: TokenStream, item: TokenStream) -> TokenStream { | ||
32 | format!("compile_error!(\"#[attr_error({})] {}\");", args, item).parse().unwrap() | ||
33 | } | ||
34 | |||
35 | #[proc_macro_derive(DeriveEmpty)] | ||
36 | pub fn derive_empty(_item: TokenStream) -> TokenStream { | ||
37 | TokenStream::new() | ||
38 | } | ||
39 | |||
40 | #[proc_macro_derive(DerivePanic)] | ||
41 | pub fn derive_panic(item: TokenStream) -> TokenStream { | ||
42 | panic!("#[derive(DerivePanic)] {}", item); | ||
43 | } | ||
44 | |||
45 | #[proc_macro_derive(DeriveError)] | ||
46 | pub fn derive_error(item: TokenStream) -> TokenStream { | ||
47 | format!("compile_error!(\"#[derive(DeriveError)] {}\");", item).parse().unwrap() | ||
48 | } | ||
diff --git a/crates/proc_macro_test/src/lib.rs b/crates/proc_macro_test/src/lib.rs index 4b26d2472..2edf23a63 100644 --- a/crates/proc_macro_test/src/lib.rs +++ b/crates/proc_macro_test/src/lib.rs | |||
@@ -1,48 +1,4 @@ | |||
1 | //! Exports a few trivial procedural macros for testing. | 1 | //! Exports a few trivial procedural macros for testing. |
2 | 2 | ||
3 | use proc_macro::TokenStream; | 3 | pub static PROC_MACRO_TEST_LOCATION: &str = |
4 | 4 | include_str!(concat!(env!("OUT_DIR"), "/proc_macro_test_location.txt")); | |
5 | #[proc_macro] | ||
6 | pub fn fn_like_noop(args: TokenStream) -> TokenStream { | ||
7 | args | ||
8 | } | ||
9 | |||
10 | #[proc_macro] | ||
11 | pub fn fn_like_panic(args: TokenStream) -> TokenStream { | ||
12 | panic!("fn_like_panic!({})", args); | ||
13 | } | ||
14 | |||
15 | #[proc_macro] | ||
16 | pub fn fn_like_error(args: TokenStream) -> TokenStream { | ||
17 | format!("compile_error!(\"fn_like_error!({})\");", args).parse().unwrap() | ||
18 | } | ||
19 | |||
20 | #[proc_macro_attribute] | ||
21 | pub fn attr_noop(_args: TokenStream, item: TokenStream) -> TokenStream { | ||
22 | item | ||
23 | } | ||
24 | |||
25 | #[proc_macro_attribute] | ||
26 | pub fn attr_panic(args: TokenStream, item: TokenStream) -> TokenStream { | ||
27 | panic!("#[attr_panic {}] {}", args, item); | ||
28 | } | ||
29 | |||
30 | #[proc_macro_attribute] | ||
31 | pub fn attr_error(args: TokenStream, item: TokenStream) -> TokenStream { | ||
32 | format!("compile_error!(\"#[attr_error({})] {}\");", args, item).parse().unwrap() | ||
33 | } | ||
34 | |||
35 | #[proc_macro_derive(DeriveEmpty)] | ||
36 | pub fn derive_empty(_item: TokenStream) -> TokenStream { | ||
37 | TokenStream::new() | ||
38 | } | ||
39 | |||
40 | #[proc_macro_derive(DerivePanic)] | ||
41 | pub fn derive_panic(item: TokenStream) -> TokenStream { | ||
42 | panic!("#[derive(DerivePanic)] {}", item); | ||
43 | } | ||
44 | |||
45 | #[proc_macro_derive(DeriveError)] | ||
46 | pub fn derive_error(item: TokenStream) -> TokenStream { | ||
47 | format!("compile_error!(\"#[derive(DeriveError)] {}\");", item).parse().unwrap() | ||
48 | } | ||
diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml index 1a8c8f862..653d3d983 100644 --- a/crates/profile/Cargo.toml +++ b/crates/profile/Cargo.toml | |||
@@ -20,6 +20,9 @@ jemalloc-ctl = { version = "0.4.1", package = "tikv-jemalloc-ctl", optional = tr | |||
20 | [target.'cfg(target_os = "linux")'.dependencies] | 20 | [target.'cfg(target_os = "linux")'.dependencies] |
21 | perf-event = "0.4" | 21 | perf-event = "0.4" |
22 | 22 | ||
23 | [target.'cfg(windows)'.dependencies] | ||
24 | winapi = { version = "0.3.8", features = ["psapi"] } | ||
25 | |||
23 | [features] | 26 | [features] |
24 | cpu_profiler = [] | 27 | cpu_profiler = [] |
25 | jemalloc = ["jemalloc-ctl"] | 28 | jemalloc = ["jemalloc-ctl"] |
diff --git a/crates/profile/src/memory_usage.rs b/crates/profile/src/memory_usage.rs index 2917ded60..6ef58c9c1 100644 --- a/crates/profile/src/memory_usage.rs +++ b/crates/profile/src/memory_usage.rs | |||
@@ -35,6 +35,22 @@ impl MemoryUsage { | |||
35 | // Note: This is incredibly slow. | 35 | // Note: This is incredibly slow. |
36 | let alloc = unsafe { libc::mallinfo() }.uordblks as isize; | 36 | let alloc = unsafe { libc::mallinfo() }.uordblks as isize; |
37 | MemoryUsage { allocated: Bytes(alloc) } | 37 | MemoryUsage { allocated: Bytes(alloc) } |
38 | } else if #[cfg(windows)] { | ||
39 | // There doesn't seem to be an API for determining heap usage, so we try to | ||
40 | // approximate that by using the Commit Charge value. | ||
41 | |||
42 | use winapi::um::processthreadsapi::*; | ||
43 | use winapi::um::psapi::*; | ||
44 | use std::mem::{MaybeUninit, size_of}; | ||
45 | |||
46 | let proc = unsafe { GetCurrentProcess() }; | ||
47 | let mut mem_counters = MaybeUninit::uninit(); | ||
48 | let cb = size_of::<PROCESS_MEMORY_COUNTERS>(); | ||
49 | let ret = unsafe { GetProcessMemoryInfo(proc, mem_counters.as_mut_ptr(), cb as u32) }; | ||
50 | assert!(ret != 0); | ||
51 | |||
52 | let usage = unsafe { mem_counters.assume_init().PagefileUsage }; | ||
53 | MemoryUsage { allocated: Bytes(usage as isize) } | ||
38 | } else { | 54 | } else { |
39 | MemoryUsage { allocated: Bytes(0) } | 55 | MemoryUsage { allocated: Bytes(0) } |
40 | } | 56 | } |
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs index 76b666dc2..25ebcc0ec 100644 --- a/crates/rust-analyzer/src/cli.rs +++ b/crates/rust-analyzer/src/cli.rs | |||
@@ -16,7 +16,6 @@ use vfs::Vfs; | |||
16 | pub use self::{ | 16 | pub use self::{ |
17 | analysis_stats::AnalysisStatsCmd, | 17 | analysis_stats::AnalysisStatsCmd, |
18 | diagnostics::diagnostics, | 18 | diagnostics::diagnostics, |
19 | load_cargo::{load_workspace, load_workspace_at, LoadCargoConfig}, | ||
20 | ssr::{apply_ssr_rules, search_for_patterns}, | 19 | ssr::{apply_ssr_rules, search_for_patterns}, |
21 | }; | 20 | }; |
22 | 21 | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 5364e907c..843c0ca37 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -70,6 +70,7 @@ impl AnalysisStatsCmd { | |||
70 | load_out_dirs_from_check: self.enable_build_scripts, | 70 | load_out_dirs_from_check: self.enable_build_scripts, |
71 | wrap_rustc: false, | 71 | wrap_rustc: false, |
72 | with_proc_macro: self.enable_proc_macros, | 72 | with_proc_macro: self.enable_proc_macros, |
73 | prefill_caches: false, | ||
73 | }; | 74 | }; |
74 | let (host, vfs, _proc_macro) = | 75 | let (host, vfs, _proc_macro) = |
75 | load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; | 76 | load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; |
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index c33c8179c..dc9a390fe 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs | |||
@@ -34,8 +34,12 @@ pub fn diagnostics( | |||
34 | with_proc_macro: bool, | 34 | with_proc_macro: bool, |
35 | ) -> Result<()> { | 35 | ) -> Result<()> { |
36 | let cargo_config = Default::default(); | 36 | let cargo_config = Default::default(); |
37 | let load_cargo_config = | 37 | let load_cargo_config = LoadCargoConfig { |
38 | LoadCargoConfig { load_out_dirs_from_check, with_proc_macro, wrap_rustc: false }; | 38 | load_out_dirs_from_check, |
39 | with_proc_macro, | ||
40 | wrap_rustc: false, | ||
41 | prefill_caches: false, | ||
42 | }; | ||
39 | let (host, _vfs, _proc_macro) = | 43 | let (host, _vfs, _proc_macro) = |
40 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | 44 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; |
41 | let db = host.raw_database(); | 45 | let db = host.raw_database(); |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 8cee65478..19cb1c046 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -14,13 +14,14 @@ use vfs::{loader::Handle, AbsPath, AbsPathBuf}; | |||
14 | 14 | ||
15 | use crate::reload::{ProjectFolders, SourceRootConfig}; | 15 | use crate::reload::{ProjectFolders, SourceRootConfig}; |
16 | 16 | ||
17 | pub struct LoadCargoConfig { | 17 | pub(crate) struct LoadCargoConfig { |
18 | pub load_out_dirs_from_check: bool, | 18 | pub(crate) load_out_dirs_from_check: bool, |
19 | pub wrap_rustc: bool, | 19 | pub(crate) wrap_rustc: bool, |
20 | pub with_proc_macro: bool, | 20 | pub(crate) with_proc_macro: bool, |
21 | pub(crate) prefill_caches: bool, | ||
21 | } | 22 | } |
22 | 23 | ||
23 | pub fn load_workspace_at( | 24 | pub(crate) fn load_workspace_at( |
24 | root: &Path, | 25 | root: &Path, |
25 | cargo_config: &CargoConfig, | 26 | cargo_config: &CargoConfig, |
26 | load_config: &LoadCargoConfig, | 27 | load_config: &LoadCargoConfig, |
@@ -33,7 +34,7 @@ pub fn load_workspace_at( | |||
33 | load_workspace(workspace, load_config, progress) | 34 | load_workspace(workspace, load_config, progress) |
34 | } | 35 | } |
35 | 36 | ||
36 | pub fn load_workspace( | 37 | fn load_workspace( |
37 | ws: ProjectWorkspace, | 38 | ws: ProjectWorkspace, |
38 | config: &LoadCargoConfig, | 39 | config: &LoadCargoConfig, |
39 | progress: &dyn Fn(String), | 40 | progress: &dyn Fn(String), |
@@ -82,6 +83,10 @@ pub fn load_workspace( | |||
82 | log::debug!("crate graph: {:?}", crate_graph); | 83 | log::debug!("crate graph: {:?}", crate_graph); |
83 | let host = | 84 | let host = |
84 | load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver); | 85 | load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver); |
86 | |||
87 | if config.prefill_caches { | ||
88 | host.analysis().prime_caches(|_| {})?; | ||
89 | } | ||
85 | Ok((host, vfs, proc_macro_client)) | 90 | Ok((host, vfs, proc_macro_client)) |
86 | } | 91 | } |
87 | 92 | ||
@@ -144,6 +149,7 @@ mod tests { | |||
144 | load_out_dirs_from_check: false, | 149 | load_out_dirs_from_check: false, |
145 | wrap_rustc: false, | 150 | wrap_rustc: false, |
146 | with_proc_macro: false, | 151 | with_proc_macro: false, |
152 | prefill_caches: false, | ||
147 | }; | 153 | }; |
148 | let (host, _vfs, _proc_macro) = | 154 | let (host, _vfs, _proc_macro) = |
149 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | 155 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; |
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs index 1fd9b5a9b..0b3475e09 100644 --- a/crates/rust-analyzer/src/cli/ssr.rs +++ b/crates/rust-analyzer/src/cli/ssr.rs | |||
@@ -13,6 +13,7 @@ pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { | |||
13 | load_out_dirs_from_check: true, | 13 | load_out_dirs_from_check: true, |
14 | wrap_rustc: false, | 14 | wrap_rustc: false, |
15 | with_proc_macro: true, | 15 | with_proc_macro: true, |
16 | prefill_caches: false, | ||
16 | }; | 17 | }; |
17 | let (host, vfs, _proc_macro) = | 18 | let (host, vfs, _proc_macro) = |
18 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; | 19 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; |
@@ -39,8 +40,12 @@ pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<Stri | |||
39 | use ide_db::base_db::SourceDatabaseExt; | 40 | use ide_db::base_db::SourceDatabaseExt; |
40 | use ide_db::symbol_index::SymbolsDatabase; | 41 | use ide_db::symbol_index::SymbolsDatabase; |
41 | let cargo_config = Default::default(); | 42 | let cargo_config = Default::default(); |
42 | let load_cargo_config = | 43 | let load_cargo_config = LoadCargoConfig { |
43 | LoadCargoConfig { load_out_dirs_from_check: true, wrap_rustc: true, with_proc_macro: true }; | 44 | load_out_dirs_from_check: true, |
45 | wrap_rustc: true, | ||
46 | with_proc_macro: true, | ||
47 | prefill_caches: false, | ||
48 | }; | ||
44 | let (host, _vfs, _proc_macro) = | 49 | let (host, _vfs, _proc_macro) = |
45 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; | 50 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; |
46 | let db = host.raw_database(); | 51 | let db = host.raw_database(); |
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index ec36a5f5c..8ddeb59f7 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs | |||
@@ -37,6 +37,7 @@ fn integrated_highlighting_benchmark() { | |||
37 | load_out_dirs_from_check: true, | 37 | load_out_dirs_from_check: true, |
38 | wrap_rustc: false, | 38 | wrap_rustc: false, |
39 | with_proc_macro: false, | 39 | with_proc_macro: false, |
40 | prefill_caches: false, | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | let (mut host, vfs, _proc_macro) = { | 43 | let (mut host, vfs, _proc_macro) = { |
@@ -91,6 +92,7 @@ fn integrated_completion_benchmark() { | |||
91 | load_out_dirs_from_check: true, | 92 | load_out_dirs_from_check: true, |
92 | wrap_rustc: false, | 93 | wrap_rustc: false, |
93 | with_proc_macro: false, | 94 | with_proc_macro: false, |
95 | prefill_caches: true, | ||
94 | }; | 96 | }; |
95 | 97 | ||
96 | let (mut host, vfs, _proc_macro) = { | 98 | let (mut host, vfs, _proc_macro) = { |