diff options
-rw-r--r-- | crates/ra_hir/src/marks.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/collector.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/tests.rs | 411 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs | 118 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs | 123 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs | 94 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 769 |
9 files changed, 689 insertions, 850 deletions
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index 16852a6a1..e8f3005f1 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | test_utils::marks!( | 1 | test_utils::marks!( |
2 | name_res_works_for_broken_modules | 2 | name_res_works_for_broken_modules |
3 | item_map_enum_importing | 3 | can_import_enum_variant |
4 | type_var_cycles_resolve_completely | 4 | type_var_cycles_resolve_completely |
5 | type_var_cycles_resolve_as_possible | 5 | type_var_cycles_resolve_as_possible |
6 | type_var_resolves_to_int_var | 6 | type_var_resolves_to_int_var |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index baffbce6f..59297425e 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -661,7 +661,7 @@ impl ItemMap { | |||
661 | } | 661 | } |
662 | ModuleDef::Enum(e) => { | 662 | ModuleDef::Enum(e) => { |
663 | // enum variant | 663 | // enum variant |
664 | tested_by!(item_map_enum_importing); | 664 | tested_by!(can_import_enum_variant); |
665 | match e.variant(db, &segment.name) { | 665 | match e.variant(db, &segment.name) { |
666 | Some(variant) => PerNs::both(variant.into(), variant.into()), | 666 | Some(variant) => PerNs::both(variant.into(), variant.into()), |
667 | None => { | 667 | None => { |
@@ -693,6 +693,3 @@ impl ItemMap { | |||
693 | ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) | 693 | ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) |
694 | } | 694 | } |
695 | } | 695 | } |
696 | |||
697 | #[cfg(test)] | ||
698 | mod tests; | ||
diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs index d7ccb6584..37b36719f 100644 --- a/crates/ra_hir/src/nameres/crate_def_map.rs +++ b/crates/ra_hir/src/nameres/crate_def_map.rs | |||
@@ -273,7 +273,7 @@ impl CrateDefMap { | |||
273 | } | 273 | } |
274 | ModuleDef::Enum(e) => { | 274 | ModuleDef::Enum(e) => { |
275 | // enum variant | 275 | // enum variant |
276 | tested_by!(item_map_enum_importing); | 276 | tested_by!(can_import_enum_variant); |
277 | match e.variant(db, &segment.name) { | 277 | match e.variant(db, &segment.name) { |
278 | Some(variant) => PerNs::both(variant.into(), variant.into()), | 278 | Some(variant) => PerNs::both(variant.into(), variant.into()), |
279 | None => { | 279 | None => { |
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/crate_def_map/collector.rs index 2fbfa9e34..68f74b866 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/collector.rs | |||
@@ -85,6 +85,12 @@ where | |||
85 | break; | 85 | break; |
86 | } | 86 | } |
87 | } | 87 | } |
88 | |||
89 | let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); | ||
90 | // show unresolved imports in completion, etc | ||
91 | for (module_id, import, import_data) in unresolved_imports { | ||
92 | self.record_resolved_import(module_id, PerNs::none(), import, &import_data) | ||
93 | } | ||
88 | } | 94 | } |
89 | 95 | ||
90 | fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { | 96 | fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { |
@@ -415,7 +421,14 @@ where | |||
415 | modules[res].parent = Some(self.module_id); | 421 | modules[res].parent = Some(self.module_id); |
416 | modules[res].declaration = Some(declaration); | 422 | modules[res].declaration = Some(declaration); |
417 | modules[res].definition = definition; | 423 | modules[res].definition = definition; |
418 | modules[self.module_id].children.insert(name, res); | 424 | modules[self.module_id].children.insert(name.clone(), res); |
425 | let resolution = Resolution { | ||
426 | def: PerNs::types( | ||
427 | Module { krate: self.def_collector.def_map.krate, module_id: res }.into(), | ||
428 | ), | ||
429 | import: None, | ||
430 | }; | ||
431 | self.def_collector.update(self.module_id, None, &[(name, resolution)]); | ||
419 | res | 432 | res |
420 | } | 433 | } |
421 | 434 | ||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/crate_def_map/tests.rs index 742a19e5c..36c1d74ce 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/tests.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/tests.rs | |||
@@ -1,3 +1,7 @@ | |||
1 | mod macros; | ||
2 | mod globs; | ||
3 | mod incremental; | ||
4 | |||
1 | use std::sync::Arc; | 5 | use std::sync::Arc; |
2 | 6 | ||
3 | use ra_db::SourceDatabase; | 7 | use ra_db::SourceDatabase; |
@@ -62,6 +66,8 @@ fn crate_def_map_smoke_test() { | |||
62 | //- /lib.rs | 66 | //- /lib.rs |
63 | mod foo; | 67 | mod foo; |
64 | struct S; | 68 | struct S; |
69 | use crate::foo::bar::E; | ||
70 | use self::E::V; | ||
65 | 71 | ||
66 | //- /foo/mod.rs | 72 | //- /foo/mod.rs |
67 | pub mod bar; | 73 | pub mod bar; |
@@ -74,9 +80,13 @@ fn crate_def_map_smoke_test() { | |||
74 | ); | 80 | ); |
75 | assert_snapshot_matches!(map, @r###" | 81 | assert_snapshot_matches!(map, @r###" |
76 | crate | 82 | crate |
83 | V: t v | ||
84 | E: t | ||
85 | foo: t | ||
77 | S: t v | 86 | S: t v |
78 | 87 | ||
79 | crate::foo | 88 | crate::foo |
89 | bar: t | ||
80 | f: v | 90 | f: v |
81 | 91 | ||
82 | crate::foo::bar | 92 | crate::foo::bar |
@@ -87,91 +97,96 @@ E: t | |||
87 | } | 97 | } |
88 | 98 | ||
89 | #[test] | 99 | #[test] |
90 | fn macro_rules_are_globally_visible() { | 100 | fn use_as() { |
91 | let map = def_map( | 101 | let map = def_map( |
92 | " | 102 | " |
93 | //- /lib.rs | 103 | //- /lib.rs |
94 | macro_rules! structs { | 104 | mod foo; |
95 | ($($i:ident),*) => { | 105 | |
96 | $(struct $i { field: u32 } )* | 106 | use crate::foo::Baz as Foo; |
97 | } | ||
98 | } | ||
99 | structs!(Foo); | ||
100 | mod nested; | ||
101 | 107 | ||
102 | //- /nested.rs | 108 | //- /foo/mod.rs |
103 | structs!(Bar, Baz); | 109 | pub struct Baz; |
104 | ", | 110 | ", |
105 | ); | 111 | ); |
106 | assert_snapshot_matches!(map, @r###" | 112 | assert_snapshot_matches!(map, |
113 | @r###" | ||
107 | crate | 114 | crate |
108 | Foo: t v | 115 | Foo: t v |
116 | foo: t | ||
109 | 117 | ||
110 | crate::nested | 118 | crate::foo |
111 | Bar: t v | ||
112 | Baz: t v | 119 | Baz: t v |
113 | "###); | 120 | "### |
121 | ); | ||
114 | } | 122 | } |
115 | 123 | ||
116 | #[test] | 124 | #[test] |
117 | fn macro_rules_can_define_modules() { | 125 | fn use_trees() { |
118 | let map = def_map( | 126 | let map = def_map( |
119 | " | 127 | " |
120 | //- /lib.rs | 128 | //- /lib.rs |
121 | macro_rules! m { | 129 | mod foo; |
122 | ($name:ident) => { mod $name; } | 130 | |
123 | } | 131 | use crate::foo::bar::{Baz, Quux}; |
124 | m!(n1); | 132 | |
133 | //- /foo/mod.rs | ||
134 | pub mod bar; | ||
125 | 135 | ||
126 | //- /n1.rs | 136 | //- /foo/bar.rs |
127 | m!(n2) | 137 | pub struct Baz; |
128 | //- /n1/n2.rs | 138 | pub enum Quux {}; |
129 | struct X; | ||
130 | ", | 139 | ", |
131 | ); | 140 | ); |
132 | assert_snapshot_matches!(map, @r###" | 141 | assert_snapshot_matches!(map, |
142 | @r###" | ||
133 | crate | 143 | crate |
144 | Quux: t | ||
145 | Baz: t v | ||
146 | foo: t | ||
134 | 147 | ||
135 | crate::n1 | 148 | crate::foo |
149 | bar: t | ||
136 | 150 | ||
137 | crate::n1::n2 | 151 | crate::foo::bar |
138 | X: t v | 152 | Quux: t |
139 | "###); | 153 | Baz: t v |
154 | "### | ||
155 | ); | ||
140 | } | 156 | } |
141 | 157 | ||
142 | #[test] | 158 | #[test] |
143 | fn macro_rules_from_other_crates_are_visible() { | 159 | fn re_exports() { |
144 | let map = def_map_with_crate_graph( | 160 | let map = def_map( |
145 | " | 161 | " |
146 | //- /main.rs | 162 | //- /lib.rs |
147 | foo::structs!(Foo, Bar) | 163 | mod foo; |
148 | mod bar; | ||
149 | 164 | ||
150 | //- /bar.rs | 165 | use self::foo::Baz; |
151 | use crate::*; | ||
152 | 166 | ||
153 | //- /lib.rs | 167 | //- /foo/mod.rs |
154 | #[macro_export] | 168 | pub mod bar; |
155 | macro_rules! structs { | 169 | |
156 | ($($i:ident),*) => { | 170 | pub use self::bar::Baz; |
157 | $(struct $i { field: u32 } )* | 171 | |
158 | } | 172 | //- /foo/bar.rs |
159 | } | 173 | pub struct Baz; |
160 | ", | 174 | ", |
161 | crate_graph! { | ||
162 | "main": ("/main.rs", ["foo"]), | ||
163 | "foo": ("/lib.rs", []), | ||
164 | }, | ||
165 | ); | 175 | ); |
166 | assert_snapshot_matches!(map, @r###" | 176 | assert_snapshot_matches!(map, |
177 | @r###" | ||
167 | crate | 178 | crate |
168 | Foo: t v | 179 | Baz: t v |
169 | Bar: t v | 180 | foo: t |
170 | 181 | ||
171 | crate::bar | 182 | crate::foo |
172 | Foo: t v | 183 | bar: t |
173 | Bar: t v | 184 | Baz: t v |
174 | "###); | 185 | |
186 | crate::foo::bar | ||
187 | Baz: t v | ||
188 | "### | ||
189 | ); | ||
175 | } | 190 | } |
176 | 191 | ||
177 | #[test] | 192 | #[test] |
@@ -203,12 +218,152 @@ Baz: t v | |||
203 | } | 218 | } |
204 | 219 | ||
205 | #[test] | 220 | #[test] |
206 | fn glob_across_crates() { | 221 | fn can_import_enum_variant() { |
207 | covers!(glob_across_crates); | 222 | covers!(can_import_enum_variant); |
223 | let map = def_map( | ||
224 | " | ||
225 | //- /lib.rs | ||
226 | enum E { V } | ||
227 | use self::E::V; | ||
228 | ", | ||
229 | ); | ||
230 | assert_snapshot_matches!(map, @r###" | ||
231 | crate | ||
232 | V: t v | ||
233 | E: t | ||
234 | "### | ||
235 | ); | ||
236 | } | ||
237 | |||
238 | #[test] | ||
239 | fn edition_2015_imports() { | ||
240 | let map = def_map_with_crate_graph( | ||
241 | " | ||
242 | //- /main.rs | ||
243 | mod foo; | ||
244 | mod bar; | ||
245 | |||
246 | //- /bar.rs | ||
247 | struct Bar; | ||
248 | |||
249 | //- /foo.rs | ||
250 | use bar::Bar; | ||
251 | use other_crate::FromLib; | ||
252 | |||
253 | //- /lib.rs | ||
254 | struct FromLib; | ||
255 | ", | ||
256 | crate_graph! { | ||
257 | "main": ("/main.rs", "2015", ["other_crate"]), | ||
258 | "other_crate": ("/lib.rs", "2018", []), | ||
259 | }, | ||
260 | ); | ||
261 | |||
262 | assert_snapshot_matches!(map, | ||
263 | @r###" | ||
264 | crate | ||
265 | bar: t | ||
266 | foo: t | ||
267 | |||
268 | crate::bar | ||
269 | Bar: t v | ||
270 | |||
271 | crate::foo | ||
272 | FromLib: t v | ||
273 | Bar: t v | ||
274 | "### | ||
275 | ); | ||
276 | } | ||
277 | |||
278 | #[test] | ||
279 | fn module_resolution_works_for_non_standard_filenames() { | ||
280 | let map = def_map_with_crate_graph( | ||
281 | " | ||
282 | //- /my_library.rs | ||
283 | mod foo; | ||
284 | use self::foo::Bar; | ||
285 | |||
286 | //- /foo/mod.rs | ||
287 | pub struct Bar; | ||
288 | ", | ||
289 | crate_graph! { | ||
290 | "my_library": ("/my_library.rs", []), | ||
291 | }, | ||
292 | ); | ||
293 | |||
294 | assert_snapshot_matches!(map, | ||
295 | @r###" | ||
296 | crate | ||
297 | Bar: t v | ||
298 | foo: t | ||
299 | |||
300 | crate::foo | ||
301 | Bar: t v | ||
302 | "### | ||
303 | ); | ||
304 | } | ||
305 | |||
306 | #[test] | ||
307 | fn name_res_works_for_broken_modules() { | ||
308 | covers!(name_res_works_for_broken_modules); | ||
309 | let map = def_map( | ||
310 | " | ||
311 | //- /lib.rs | ||
312 | mod foo // no `;`, no body | ||
313 | |||
314 | use self::foo::Baz; | ||
315 | |||
316 | //- /foo/mod.rs | ||
317 | pub mod bar; | ||
318 | |||
319 | pub use self::bar::Baz; | ||
320 | |||
321 | //- /foo/bar.rs | ||
322 | pub struct Baz; | ||
323 | ", | ||
324 | ); | ||
325 | assert_snapshot_matches!(map, | ||
326 | @r###" | ||
327 | crate | ||
328 | Baz: _ | ||
329 | "### | ||
330 | ); | ||
331 | } | ||
332 | |||
333 | #[test] | ||
334 | fn item_map_using_self() { | ||
335 | let map = def_map( | ||
336 | " | ||
337 | //- /lib.rs | ||
338 | mod foo; | ||
339 | use crate::foo::bar::Baz::{self}; | ||
340 | //- /foo/mod.rs | ||
341 | pub mod bar; | ||
342 | //- /foo/bar.rs | ||
343 | pub struct Baz; | ||
344 | ", | ||
345 | ); | ||
346 | assert_snapshot_matches!(map, | ||
347 | @r###" | ||
348 | crate | ||
349 | Baz: t v | ||
350 | foo: t | ||
351 | |||
352 | crate::foo | ||
353 | bar: t | ||
354 | |||
355 | crate::foo::bar | ||
356 | Baz: t v | ||
357 | "### | ||
358 | ); | ||
359 | } | ||
360 | |||
361 | #[test] | ||
362 | fn item_map_across_crates() { | ||
208 | let map = def_map_with_crate_graph( | 363 | let map = def_map_with_crate_graph( |
209 | " | 364 | " |
210 | //- /main.rs | 365 | //- /main.rs |
211 | use test_crate::*; | 366 | use test_crate::Baz; |
212 | 367 | ||
213 | //- /lib.rs | 368 | //- /lib.rs |
214 | pub struct Baz; | 369 | pub struct Baz; |
@@ -218,7 +373,9 @@ fn glob_across_crates() { | |||
218 | "test_crate": ("/lib.rs", []), | 373 | "test_crate": ("/lib.rs", []), |
219 | }, | 374 | }, |
220 | ); | 375 | ); |
221 | assert_snapshot_matches!(map, @r###" | 376 | |
377 | assert_snapshot_matches!(map, | ||
378 | @r###" | ||
222 | crate | 379 | crate |
223 | Baz: t v | 380 | Baz: t v |
224 | "### | 381 | "### |
@@ -226,40 +383,146 @@ Baz: t v | |||
226 | } | 383 | } |
227 | 384 | ||
228 | #[test] | 385 | #[test] |
229 | fn item_map_enum_importing() { | 386 | fn extern_crate_rename() { |
230 | covers!(item_map_enum_importing); | 387 | let map = def_map_with_crate_graph( |
231 | let map = def_map( | ||
232 | " | 388 | " |
389 | //- /main.rs | ||
390 | extern crate alloc as alloc_crate; | ||
391 | |||
392 | mod alloc; | ||
393 | mod sync; | ||
394 | |||
395 | //- /sync.rs | ||
396 | use alloc_crate::Arc; | ||
397 | |||
233 | //- /lib.rs | 398 | //- /lib.rs |
234 | enum E { V } | 399 | struct Arc; |
235 | use self::E::V; | ||
236 | ", | 400 | ", |
401 | crate_graph! { | ||
402 | "main": ("/main.rs", ["alloc"]), | ||
403 | "alloc": ("/lib.rs", []), | ||
404 | }, | ||
237 | ); | 405 | ); |
238 | assert_snapshot_matches!(map, @r###" | 406 | |
407 | assert_snapshot_matches!(map, | ||
408 | @r###" | ||
239 | crate | 409 | crate |
240 | V: t v | 410 | Arc: t v |
241 | E: t | ||
242 | "### | 411 | "### |
243 | ); | 412 | ); |
244 | } | 413 | } |
245 | 414 | ||
246 | #[test] | 415 | #[test] |
247 | fn glob_enum() { | 416 | fn extern_crate_rename_2015_edition() { |
248 | covers!(glob_enum); | 417 | let map = def_map_with_crate_graph( |
249 | let map = def_map( | 418 | " |
419 | //- /main.rs | ||
420 | extern crate alloc as alloc_crate; | ||
421 | |||
422 | mod alloc; | ||
423 | mod sync; | ||
424 | |||
425 | //- /sync.rs | ||
426 | use alloc_crate::Arc; | ||
427 | |||
428 | //- /lib.rs | ||
429 | struct Arc; | ||
430 | ", | ||
431 | crate_graph! { | ||
432 | "main": ("/main.rs", "2015", ["alloc"]), | ||
433 | "alloc": ("/lib.rs", []), | ||
434 | }, | ||
435 | ); | ||
436 | |||
437 | assert_snapshot_matches!(map, | ||
438 | @r###" | ||
439 | crate | ||
440 | Arc: t v | ||
441 | "### | ||
442 | ); | ||
443 | } | ||
444 | |||
445 | #[test] | ||
446 | fn import_across_source_roots() { | ||
447 | let map = def_map_with_crate_graph( | ||
250 | " | 448 | " |
251 | //- /lib.rs | 449 | //- /lib.rs |
252 | enum Foo { | 450 | pub mod a { |
253 | Bar, Baz | 451 | pub mod b { |
452 | pub struct C; | ||
453 | } | ||
254 | } | 454 | } |
255 | use self::Foo::*; | 455 | |
456 | //- root /main/ | ||
457 | |||
458 | //- /main/main.rs | ||
459 | use test_crate::a::b::C; | ||
256 | ", | 460 | ", |
461 | crate_graph! { | ||
462 | "main": ("/main/main.rs", ["test_crate"]), | ||
463 | "test_crate": ("/lib.rs", []), | ||
464 | }, | ||
257 | ); | 465 | ); |
258 | assert_snapshot_matches!(map, @r###" | 466 | |
467 | assert_snapshot_matches!(map, | ||
468 | @r###" | ||
469 | crate | ||
470 | C: t v | ||
471 | "### | ||
472 | ); | ||
473 | } | ||
474 | |||
475 | #[test] | ||
476 | fn reexport_across_crates() { | ||
477 | let map = def_map_with_crate_graph( | ||
478 | " | ||
479 | //- /main.rs | ||
480 | use test_crate::Baz; | ||
481 | |||
482 | //- /lib.rs | ||
483 | pub use foo::Baz; | ||
484 | |||
485 | mod foo; | ||
486 | |||
487 | //- /foo.rs | ||
488 | pub struct Baz; | ||
489 | ", | ||
490 | crate_graph! { | ||
491 | "main": ("/main.rs", ["test_crate"]), | ||
492 | "test_crate": ("/lib.rs", []), | ||
493 | }, | ||
494 | ); | ||
495 | |||
496 | assert_snapshot_matches!(map, | ||
497 | @r###" | ||
259 | crate | 498 | crate |
260 | Foo: t | ||
261 | Bar: t v | ||
262 | Baz: t v | 499 | Baz: t v |
263 | "### | 500 | "### |
264 | ); | 501 | ); |
265 | } | 502 | } |
503 | |||
504 | #[test] | ||
505 | fn values_dont_shadow_extern_crates() { | ||
506 | let map = def_map_with_crate_graph( | ||
507 | " | ||
508 | //- /main.rs | ||
509 | fn foo() {} | ||
510 | use foo::Bar; | ||
511 | |||
512 | //- /foo/lib.rs | ||
513 | pub struct Bar; | ||
514 | ", | ||
515 | crate_graph! { | ||
516 | "main": ("/main.rs", ["foo"]), | ||
517 | "foo": ("/foo/lib.rs", []), | ||
518 | }, | ||
519 | ); | ||
520 | |||
521 | assert_snapshot_matches!(map, | ||
522 | @r###" | ||
523 | crate | ||
524 | Bar: t v | ||
525 | foo: v | ||
526 | "### | ||
527 | ); | ||
528 | } | ||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs b/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs new file mode 100644 index 000000000..6e50c7ff6 --- /dev/null +++ b/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs | |||
@@ -0,0 +1,118 @@ | |||
1 | use super::*; | ||
2 | |||
3 | #[test] | ||
4 | fn glob_1() { | ||
5 | let map = def_map( | ||
6 | " | ||
7 | //- /lib.rs | ||
8 | mod foo; | ||
9 | use foo::*; | ||
10 | |||
11 | //- /foo/mod.rs | ||
12 | pub mod bar; | ||
13 | pub use self::bar::Baz; | ||
14 | pub struct Foo; | ||
15 | |||
16 | //- /foo/bar.rs | ||
17 | pub struct Baz; | ||
18 | ", | ||
19 | ); | ||
20 | assert_snapshot_matches!(map, @r###" | ||
21 | crate | ||
22 | bar: t | ||
23 | Foo: t v | ||
24 | Baz: t v | ||
25 | foo: t | ||
26 | |||
27 | crate::foo | ||
28 | bar: t | ||
29 | Foo: t v | ||
30 | Baz: t v | ||
31 | |||
32 | crate::foo::bar | ||
33 | Baz: t v | ||
34 | "### | ||
35 | ); | ||
36 | } | ||
37 | |||
38 | #[test] | ||
39 | fn glob_2() { | ||
40 | let map = def_map( | ||
41 | " | ||
42 | //- /lib.rs | ||
43 | mod foo; | ||
44 | use foo::*; | ||
45 | |||
46 | //- /foo/mod.rs | ||
47 | pub mod bar; | ||
48 | pub use self::bar::*; | ||
49 | pub struct Foo; | ||
50 | |||
51 | //- /foo/bar.rs | ||
52 | pub struct Baz; | ||
53 | pub use super::*; | ||
54 | ", | ||
55 | ); | ||
56 | assert_snapshot_matches!(map, @r###" | ||
57 | crate | ||
58 | bar: t | ||
59 | Foo: t v | ||
60 | Baz: t v | ||
61 | foo: t | ||
62 | |||
63 | crate::foo | ||
64 | bar: t | ||
65 | Foo: t v | ||
66 | Baz: t v | ||
67 | |||
68 | crate::foo::bar | ||
69 | bar: t | ||
70 | Foo: t v | ||
71 | Baz: t v | ||
72 | "### | ||
73 | ); | ||
74 | } | ||
75 | |||
76 | #[test] | ||
77 | fn glob_across_crates() { | ||
78 | covers!(glob_across_crates); | ||
79 | let map = def_map_with_crate_graph( | ||
80 | " | ||
81 | //- /main.rs | ||
82 | use test_crate::*; | ||
83 | |||
84 | //- /lib.rs | ||
85 | pub struct Baz; | ||
86 | ", | ||
87 | crate_graph! { | ||
88 | "main": ("/main.rs", ["test_crate"]), | ||
89 | "test_crate": ("/lib.rs", []), | ||
90 | }, | ||
91 | ); | ||
92 | assert_snapshot_matches!(map, @r###" | ||
93 | crate | ||
94 | Baz: t v | ||
95 | "### | ||
96 | ); | ||
97 | } | ||
98 | |||
99 | #[test] | ||
100 | fn glob_enum() { | ||
101 | covers!(glob_enum); | ||
102 | let map = def_map( | ||
103 | " | ||
104 | //- /lib.rs | ||
105 | enum Foo { | ||
106 | Bar, Baz | ||
107 | } | ||
108 | use self::Foo::*; | ||
109 | ", | ||
110 | ); | ||
111 | assert_snapshot_matches!(map, @r###" | ||
112 | crate | ||
113 | Foo: t | ||
114 | Bar: t v | ||
115 | Baz: t v | ||
116 | "### | ||
117 | ); | ||
118 | } | ||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs b/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs new file mode 100644 index 000000000..698781923 --- /dev/null +++ b/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs | |||
@@ -0,0 +1,123 @@ | |||
1 | use super::*; | ||
2 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use ra_db::SourceDatabase; | ||
6 | |||
7 | fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { | ||
8 | let (mut db, pos) = MockDatabase::with_position(initial); | ||
9 | let crate_id = db.crate_graph().iter().next().unwrap(); | ||
10 | let krate = Crate { crate_id }; | ||
11 | { | ||
12 | let events = db.log_executed(|| { | ||
13 | db.crate_def_map(krate); | ||
14 | }); | ||
15 | assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) | ||
16 | } | ||
17 | db.set_file_text(pos.file_id, Arc::new(file_change.to_string())); | ||
18 | |||
19 | { | ||
20 | let events = db.log_executed(|| { | ||
21 | db.crate_def_map(krate); | ||
22 | }); | ||
23 | assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) | ||
24 | } | ||
25 | } | ||
26 | |||
27 | #[test] | ||
28 | fn typing_inside_a_function_should_not_invalidate_def_map() { | ||
29 | check_def_map_is_not_recomputed( | ||
30 | " | ||
31 | //- /lib.rs | ||
32 | mod foo;<|> | ||
33 | |||
34 | use crate::foo::bar::Baz; | ||
35 | |||
36 | fn foo() -> i32 { | ||
37 | 1 + 1 | ||
38 | } | ||
39 | //- /foo/mod.rs | ||
40 | pub mod bar; | ||
41 | |||
42 | //- /foo/bar.rs | ||
43 | pub struct Baz; | ||
44 | ", | ||
45 | " | ||
46 | mod foo; | ||
47 | |||
48 | use crate::foo::bar::Baz; | ||
49 | |||
50 | fn foo() -> i32 { 92 } | ||
51 | ", | ||
52 | ); | ||
53 | } | ||
54 | |||
55 | #[test] | ||
56 | fn adding_inner_items_should_not_invalidate_def_map() { | ||
57 | check_def_map_is_not_recomputed( | ||
58 | " | ||
59 | //- /lib.rs | ||
60 | struct S { a: i32} | ||
61 | enum E { A } | ||
62 | trait T { | ||
63 | fn a() {} | ||
64 | } | ||
65 | mod foo;<|> | ||
66 | impl S { | ||
67 | fn a() {} | ||
68 | } | ||
69 | use crate::foo::bar::Baz; | ||
70 | //- /foo/mod.rs | ||
71 | pub mod bar; | ||
72 | |||
73 | //- /foo/bar.rs | ||
74 | pub struct Baz; | ||
75 | ", | ||
76 | " | ||
77 | struct S { a: i32, b: () } | ||
78 | enum E { A, B } | ||
79 | trait T { | ||
80 | fn a() {} | ||
81 | fn b() {} | ||
82 | } | ||
83 | mod foo;<|> | ||
84 | impl S { | ||
85 | fn a() {} | ||
86 | fn b() {} | ||
87 | } | ||
88 | use crate::foo::bar::Baz; | ||
89 | ", | ||
90 | ); | ||
91 | } | ||
92 | |||
93 | // It would be awesome to make this work, but it's unclear how | ||
94 | #[test] | ||
95 | #[ignore] | ||
96 | fn typing_inside_a_function_inside_a_macro_should_not_invalidate_def_map() { | ||
97 | check_def_map_is_not_recomputed( | ||
98 | " | ||
99 | //- /lib.rs | ||
100 | mod foo; | ||
101 | |||
102 | use crate::foo::bar::Baz; | ||
103 | |||
104 | //- /foo/mod.rs | ||
105 | pub mod bar; | ||
106 | |||
107 | //- /foo/bar.rs | ||
108 | <|> | ||
109 | salsa::query_group! { | ||
110 | trait Baz { | ||
111 | fn foo() -> i32 { 1 + 1 } | ||
112 | } | ||
113 | } | ||
114 | ", | ||
115 | " | ||
116 | salsa::query_group! { | ||
117 | trait Baz { | ||
118 | fn foo() -> i32 { 92 } | ||
119 | } | ||
120 | } | ||
121 | ", | ||
122 | ); | ||
123 | } | ||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs b/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs new file mode 100644 index 000000000..8781b026b --- /dev/null +++ b/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs | |||
@@ -0,0 +1,94 @@ | |||
1 | use super::*; | ||
2 | |||
3 | #[test] | ||
4 | fn macro_rules_are_globally_visible() { | ||
5 | let map = def_map( | ||
6 | " | ||
7 | //- /lib.rs | ||
8 | macro_rules! structs { | ||
9 | ($($i:ident),*) => { | ||
10 | $(struct $i { field: u32 } )* | ||
11 | } | ||
12 | } | ||
13 | structs!(Foo); | ||
14 | mod nested; | ||
15 | |||
16 | //- /nested.rs | ||
17 | structs!(Bar, Baz); | ||
18 | ", | ||
19 | ); | ||
20 | assert_snapshot_matches!(map, @r###" | ||
21 | crate | ||
22 | nested: t | ||
23 | Foo: t v | ||
24 | |||
25 | crate::nested | ||
26 | Bar: t v | ||
27 | Baz: t v | ||
28 | "###); | ||
29 | } | ||
30 | |||
31 | #[test] | ||
32 | fn macro_rules_can_define_modules() { | ||
33 | let map = def_map( | ||
34 | " | ||
35 | //- /lib.rs | ||
36 | macro_rules! m { | ||
37 | ($name:ident) => { mod $name; } | ||
38 | } | ||
39 | m!(n1); | ||
40 | |||
41 | //- /n1.rs | ||
42 | m!(n2) | ||
43 | //- /n1/n2.rs | ||
44 | struct X; | ||
45 | ", | ||
46 | ); | ||
47 | assert_snapshot_matches!(map, @r###" | ||
48 | crate | ||
49 | n1: t | ||
50 | |||
51 | crate::n1 | ||
52 | n2: t | ||
53 | |||
54 | crate::n1::n2 | ||
55 | X: t v | ||
56 | "###); | ||
57 | } | ||
58 | |||
59 | #[test] | ||
60 | fn macro_rules_from_other_crates_are_visible() { | ||
61 | let map = def_map_with_crate_graph( | ||
62 | " | ||
63 | //- /main.rs | ||
64 | foo::structs!(Foo, Bar) | ||
65 | mod bar; | ||
66 | |||
67 | //- /bar.rs | ||
68 | use crate::*; | ||
69 | |||
70 | //- /lib.rs | ||
71 | #[macro_export] | ||
72 | macro_rules! structs { | ||
73 | ($($i:ident),*) => { | ||
74 | $(struct $i { field: u32 } )* | ||
75 | } | ||
76 | } | ||
77 | ", | ||
78 | crate_graph! { | ||
79 | "main": ("/main.rs", ["foo"]), | ||
80 | "foo": ("/lib.rs", []), | ||
81 | }, | ||
82 | ); | ||
83 | assert_snapshot_matches!(map, @r###" | ||
84 | crate | ||
85 | bar: t | ||
86 | Foo: t v | ||
87 | Bar: t v | ||
88 | |||
89 | crate::bar | ||
90 | bar: t | ||
91 | Foo: t v | ||
92 | Bar: t v | ||
93 | "###); | ||
94 | } | ||
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs deleted file mode 100644 index 961e442a9..000000000 --- a/crates/ra_hir/src/nameres/tests.rs +++ /dev/null | |||
@@ -1,769 +0,0 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_db::SourceDatabase; | ||
4 | use test_utils::{assert_eq_text, covers}; | ||
5 | |||
6 | use crate::{ | ||
7 | ItemMap, | ||
8 | PersistentHirDatabase, | ||
9 | mock::MockDatabase, | ||
10 | nameres::crate_def_map::ModuleId, | ||
11 | }; | ||
12 | use super::Resolution; | ||
13 | |||
14 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { | ||
15 | let (db, pos) = MockDatabase::with_position(fixture); | ||
16 | let module = crate::source_binder::module_from_position(&db, pos).unwrap(); | ||
17 | let krate = module.krate(&db).unwrap(); | ||
18 | let module_id = module.module_id; | ||
19 | (db.item_map(krate), module_id) | ||
20 | } | ||
21 | |||
22 | fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { | ||
23 | let mut lines = map[module_id] | ||
24 | .items | ||
25 | .iter() | ||
26 | .map(|(name, res)| format!("{}: {}", name, dump_resolution(res))) | ||
27 | .collect::<Vec<_>>(); | ||
28 | lines.sort(); | ||
29 | let actual = lines.join("\n"); | ||
30 | let expected = expected.trim().lines().map(|it| it.trim()).collect::<Vec<_>>().join("\n"); | ||
31 | assert_eq_text!(&expected, &actual); | ||
32 | |||
33 | fn dump_resolution(resolution: &Resolution) -> &'static str { | ||
34 | match (resolution.def.types.is_some(), resolution.def.values.is_some()) { | ||
35 | (true, true) => "t v", | ||
36 | (true, false) => "t", | ||
37 | (false, true) => "v", | ||
38 | (false, false) => "_", | ||
39 | } | ||
40 | } | ||
41 | } | ||
42 | |||
43 | #[test] | ||
44 | fn item_map_smoke_test() { | ||
45 | let (item_map, module_id) = item_map( | ||
46 | " | ||
47 | //- /lib.rs | ||
48 | mod foo; | ||
49 | |||
50 | use crate::foo::bar::Baz; | ||
51 | <|> | ||
52 | |||
53 | //- /foo/mod.rs | ||
54 | pub mod bar; | ||
55 | |||
56 | //- /foo/bar.rs | ||
57 | pub struct Baz; | ||
58 | ", | ||
59 | ); | ||
60 | check_module_item_map( | ||
61 | &item_map, | ||
62 | module_id, | ||
63 | " | ||
64 | Baz: t v | ||
65 | foo: t | ||
66 | ", | ||
67 | ); | ||
68 | } | ||
69 | |||
70 | #[test] | ||
71 | fn use_as() { | ||
72 | let (item_map, module_id) = item_map( | ||
73 | " | ||
74 | //- /lib.rs | ||
75 | mod foo; | ||
76 | |||
77 | use crate::foo::Baz as Foo; | ||
78 | <|> | ||
79 | |||
80 | //- /foo/mod.rs | ||
81 | pub struct Baz; | ||
82 | ", | ||
83 | ); | ||
84 | check_module_item_map( | ||
85 | &item_map, | ||
86 | module_id, | ||
87 | " | ||
88 | Foo: t v | ||
89 | foo: t | ||
90 | ", | ||
91 | ); | ||
92 | } | ||
93 | |||
94 | #[test] | ||
95 | fn use_trees() { | ||
96 | let (item_map, module_id) = item_map( | ||
97 | " | ||
98 | //- /lib.rs | ||
99 | mod foo; | ||
100 | |||
101 | use crate::foo::bar::{Baz, Quux}; | ||
102 | <|> | ||
103 | |||
104 | //- /foo/mod.rs | ||
105 | pub mod bar; | ||
106 | |||
107 | //- /foo/bar.rs | ||
108 | pub struct Baz; | ||
109 | pub enum Quux {}; | ||
110 | ", | ||
111 | ); | ||
112 | check_module_item_map( | ||
113 | &item_map, | ||
114 | module_id, | ||
115 | " | ||
116 | Baz: t v | ||
117 | Quux: t | ||
118 | foo: t | ||
119 | ", | ||
120 | ); | ||
121 | } | ||
122 | |||
123 | #[test] | ||
124 | fn re_exports() { | ||
125 | let (item_map, module_id) = item_map( | ||
126 | " | ||
127 | //- /lib.rs | ||
128 | mod foo; | ||
129 | |||
130 | use self::foo::Baz; | ||
131 | <|> | ||
132 | |||
133 | //- /foo/mod.rs | ||
134 | pub mod bar; | ||
135 | |||
136 | pub use self::bar::Baz; | ||
137 | |||
138 | //- /foo/bar.rs | ||
139 | pub struct Baz; | ||
140 | ", | ||
141 | ); | ||
142 | check_module_item_map( | ||
143 | &item_map, | ||
144 | module_id, | ||
145 | " | ||
146 | Baz: t v | ||
147 | foo: t | ||
148 | ", | ||
149 | ); | ||
150 | } | ||
151 | |||
152 | #[test] | ||
153 | fn glob_1() { | ||
154 | let (item_map, module_id) = item_map( | ||
155 | " | ||
156 | //- /lib.rs | ||
157 | mod foo; | ||
158 | use foo::*; | ||
159 | <|> | ||
160 | |||
161 | //- /foo/mod.rs | ||
162 | pub mod bar; | ||
163 | pub use self::bar::Baz; | ||
164 | pub struct Foo; | ||
165 | |||
166 | //- /foo/bar.rs | ||
167 | pub struct Baz; | ||
168 | ", | ||
169 | ); | ||
170 | check_module_item_map( | ||
171 | &item_map, | ||
172 | module_id, | ||
173 | " | ||
174 | Baz: t v | ||
175 | Foo: t v | ||
176 | bar: t | ||
177 | foo: t | ||
178 | ", | ||
179 | ); | ||
180 | } | ||
181 | |||
182 | #[test] | ||
183 | fn glob_2() { | ||
184 | let (item_map, module_id) = item_map( | ||
185 | " | ||
186 | //- /lib.rs | ||
187 | mod foo; | ||
188 | use foo::*; | ||
189 | <|> | ||
190 | |||
191 | //- /foo/mod.rs | ||
192 | pub mod bar; | ||
193 | pub use self::bar::*; | ||
194 | pub struct Foo; | ||
195 | |||
196 | //- /foo/bar.rs | ||
197 | pub struct Baz; | ||
198 | pub use super::*; | ||
199 | ", | ||
200 | ); | ||
201 | check_module_item_map( | ||
202 | &item_map, | ||
203 | module_id, | ||
204 | " | ||
205 | Baz: t v | ||
206 | Foo: t v | ||
207 | bar: t | ||
208 | foo: t | ||
209 | ", | ||
210 | ); | ||
211 | } | ||
212 | |||
213 | #[test] | ||
214 | fn glob_enum() { | ||
215 | covers!(glob_enum); | ||
216 | let (item_map, module_id) = item_map( | ||
217 | " | ||
218 | //- /lib.rs | ||
219 | enum Foo { | ||
220 | Bar, Baz | ||
221 | } | ||
222 | use self::Foo::*; | ||
223 | <|> | ||
224 | ", | ||
225 | ); | ||
226 | check_module_item_map( | ||
227 | &item_map, | ||
228 | module_id, | ||
229 | " | ||
230 | Bar: t v | ||
231 | Baz: t v | ||
232 | Foo: t | ||
233 | ", | ||
234 | ); | ||
235 | } | ||
236 | |||
237 | #[test] | ||
238 | fn glob_across_crates() { | ||
239 | covers!(glob_across_crates); | ||
240 | let mut db = MockDatabase::with_files( | ||
241 | " | ||
242 | //- /main.rs | ||
243 | use test_crate::*; | ||
244 | |||
245 | //- /lib.rs | ||
246 | pub struct Baz; | ||
247 | ", | ||
248 | ); | ||
249 | db.set_crate_graph_from_fixture(crate_graph! { | ||
250 | "main": ("/main.rs", ["test_crate"]), | ||
251 | "test_crate": ("/lib.rs", []), | ||
252 | }); | ||
253 | let main_id = db.file_id_of("/main.rs"); | ||
254 | |||
255 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | ||
256 | let krate = module.krate(&db).unwrap(); | ||
257 | let item_map = db.item_map(krate); | ||
258 | |||
259 | check_module_item_map( | ||
260 | &item_map, | ||
261 | module.module_id, | ||
262 | " | ||
263 | Baz: t v | ||
264 | ", | ||
265 | ); | ||
266 | } | ||
267 | |||
268 | #[test] | ||
269 | fn edition_2015_imports() { | ||
270 | let mut db = MockDatabase::with_files( | ||
271 | " | ||
272 | //- /main.rs | ||
273 | mod foo; | ||
274 | mod bar; | ||
275 | |||
276 | //- /bar.rs | ||
277 | struct Bar; | ||
278 | |||
279 | //- /foo.rs | ||
280 | use bar::Bar; | ||
281 | use other_crate::FromLib; | ||
282 | |||
283 | //- /lib.rs | ||
284 | struct FromLib; | ||
285 | ", | ||
286 | ); | ||
287 | db.set_crate_graph_from_fixture(crate_graph! { | ||
288 | "main": ("/main.rs", "2015", ["other_crate"]), | ||
289 | "other_crate": ("/lib.rs", "2018", []), | ||
290 | }); | ||
291 | let foo_id = db.file_id_of("/foo.rs"); | ||
292 | |||
293 | let module = crate::source_binder::module_from_file_id(&db, foo_id).unwrap(); | ||
294 | let krate = module.krate(&db).unwrap(); | ||
295 | let item_map = db.item_map(krate); | ||
296 | |||
297 | check_module_item_map( | ||
298 | &item_map, | ||
299 | module.module_id, | ||
300 | " | ||
301 | Bar: t v | ||
302 | FromLib: t v | ||
303 | ", | ||
304 | ); | ||
305 | } | ||
306 | |||
307 | #[test] | ||
308 | fn module_resolution_works_for_non_standard_filenames() { | ||
309 | let mut db = MockDatabase::with_files( | ||
310 | " | ||
311 | //- /my_library.rs | ||
312 | mod foo; | ||
313 | use self::foo::Bar; | ||
314 | |||
315 | //- /foo/mod.rs | ||
316 | pub struct Bar; | ||
317 | ", | ||
318 | ); | ||
319 | db.set_crate_graph_from_fixture(crate_graph! { | ||
320 | "my_library": ("/my_library.rs", []), | ||
321 | }); | ||
322 | let file_id = db.file_id_of("/my_library.rs"); | ||
323 | |||
324 | let module = crate::source_binder::module_from_file_id(&db, file_id).unwrap(); | ||
325 | let krate = module.krate(&db).unwrap(); | ||
326 | let module_id = module.module_id; | ||
327 | let item_map = db.item_map(krate); | ||
328 | check_module_item_map( | ||
329 | &item_map, | ||
330 | module_id, | ||
331 | " | ||
332 | Bar: t v | ||
333 | foo: t | ||
334 | ", | ||
335 | ); | ||
336 | } | ||
337 | |||
338 | #[test] | ||
339 | fn std_prelude() { | ||
340 | covers!(std_prelude); | ||
341 | let mut db = MockDatabase::with_files( | ||
342 | " | ||
343 | //- /main.rs | ||
344 | use Foo::*; | ||
345 | |||
346 | //- /lib.rs | ||
347 | mod prelude; | ||
348 | #[prelude_import] | ||
349 | use prelude::*; | ||
350 | |||
351 | //- /prelude.rs | ||
352 | pub enum Foo { Bar, Baz }; | ||
353 | ", | ||
354 | ); | ||
355 | db.set_crate_graph_from_fixture(crate_graph! { | ||
356 | "main": ("/main.rs", ["test_crate"]), | ||
357 | "test_crate": ("/lib.rs", []), | ||
358 | }); | ||
359 | let main_id = db.file_id_of("/main.rs"); | ||
360 | |||
361 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | ||
362 | eprintln!("module = {:?}", module); | ||
363 | let krate = module.krate(&db).unwrap(); | ||
364 | let item_map = db.item_map(krate); | ||
365 | |||
366 | check_module_item_map( | ||
367 | &item_map, | ||
368 | module.module_id, | ||
369 | " | ||
370 | Bar: t v | ||
371 | Baz: t v | ||
372 | ", | ||
373 | ); | ||
374 | } | ||
375 | |||
376 | #[test] | ||
377 | fn name_res_works_for_broken_modules() { | ||
378 | covers!(name_res_works_for_broken_modules); | ||
379 | let (item_map, module_id) = item_map( | ||
380 | " | ||
381 | //- /lib.rs | ||
382 | mod foo // no `;`, no body | ||
383 | |||
384 | use self::foo::Baz; | ||
385 | <|> | ||
386 | |||
387 | //- /foo/mod.rs | ||
388 | pub mod bar; | ||
389 | |||
390 | pub use self::bar::Baz; | ||
391 | |||
392 | //- /foo/bar.rs | ||
393 | pub struct Baz; | ||
394 | ", | ||
395 | ); | ||
396 | check_module_item_map( | ||
397 | &item_map, | ||
398 | module_id, | ||
399 | " | ||
400 | Baz: _ | ||
401 | ", | ||
402 | ); | ||
403 | } | ||
404 | |||
405 | #[test] | ||
406 | fn item_map_using_self() { | ||
407 | let (item_map, module_id) = item_map( | ||
408 | " | ||
409 | //- /lib.rs | ||
410 | mod foo; | ||
411 | use crate::foo::bar::Baz::{self}; | ||
412 | <|> | ||
413 | //- /foo/mod.rs | ||
414 | pub mod bar; | ||
415 | //- /foo/bar.rs | ||
416 | pub struct Baz; | ||
417 | ", | ||
418 | ); | ||
419 | check_module_item_map( | ||
420 | &item_map, | ||
421 | module_id, | ||
422 | " | ||
423 | Baz: t v | ||
424 | foo: t | ||
425 | ", | ||
426 | ); | ||
427 | } | ||
428 | |||
429 | #[test] | ||
430 | fn item_map_enum_importing() { | ||
431 | covers!(item_map_enum_importing); | ||
432 | let (item_map, module_id) = item_map( | ||
433 | " | ||
434 | //- /lib.rs | ||
435 | enum E { V } | ||
436 | use self::E::V; | ||
437 | <|> | ||
438 | ", | ||
439 | ); | ||
440 | check_module_item_map( | ||
441 | &item_map, | ||
442 | module_id, | ||
443 | " | ||
444 | E: t | ||
445 | V: t v | ||
446 | ", | ||
447 | ); | ||
448 | } | ||
449 | |||
450 | #[test] | ||
451 | fn item_map_across_crates() { | ||
452 | let mut db = MockDatabase::with_files( | ||
453 | " | ||
454 | //- /main.rs | ||
455 | use test_crate::Baz; | ||
456 | |||
457 | //- /lib.rs | ||
458 | pub struct Baz; | ||
459 | ", | ||
460 | ); | ||
461 | db.set_crate_graph_from_fixture(crate_graph! { | ||
462 | "main": ("/main.rs", ["test_crate"]), | ||
463 | "test_crate": ("/lib.rs", []), | ||
464 | }); | ||
465 | let main_id = db.file_id_of("/main.rs"); | ||
466 | |||
467 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | ||
468 | let krate = module.krate(&db).unwrap(); | ||
469 | let item_map = db.item_map(krate); | ||
470 | |||
471 | check_module_item_map( | ||
472 | &item_map, | ||
473 | module.module_id, | ||
474 | " | ||
475 | Baz: t v | ||
476 | ", | ||
477 | ); | ||
478 | } | ||
479 | |||
480 | #[test] | ||
481 | fn extern_crate_rename() { | ||
482 | let mut db = MockDatabase::with_files( | ||
483 | " | ||
484 | //- /main.rs | ||
485 | extern crate alloc as alloc_crate; | ||
486 | |||
487 | mod alloc; | ||
488 | mod sync; | ||
489 | |||
490 | //- /sync.rs | ||
491 | use alloc_crate::Arc; | ||
492 | |||
493 | //- /lib.rs | ||
494 | struct Arc; | ||
495 | ", | ||
496 | ); | ||
497 | db.set_crate_graph_from_fixture(crate_graph! { | ||
498 | "main": ("/main.rs", ["alloc"]), | ||
499 | "alloc": ("/lib.rs", []), | ||
500 | }); | ||
501 | let sync_id = db.file_id_of("/sync.rs"); | ||
502 | |||
503 | let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap(); | ||
504 | let krate = module.krate(&db).unwrap(); | ||
505 | let item_map = db.item_map(krate); | ||
506 | |||
507 | check_module_item_map( | ||
508 | &item_map, | ||
509 | module.module_id, | ||
510 | " | ||
511 | Arc: t v | ||
512 | ", | ||
513 | ); | ||
514 | } | ||
515 | |||
516 | #[test] | ||
517 | fn extern_crate_rename_2015_edition() { | ||
518 | let mut db = MockDatabase::with_files( | ||
519 | " | ||
520 | //- /main.rs | ||
521 | extern crate alloc as alloc_crate; | ||
522 | |||
523 | mod alloc; | ||
524 | mod sync; | ||
525 | |||
526 | //- /sync.rs | ||
527 | use alloc_crate::Arc; | ||
528 | |||
529 | //- /lib.rs | ||
530 | struct Arc; | ||
531 | ", | ||
532 | ); | ||
533 | db.set_crate_graph_from_fixture(crate_graph! { | ||
534 | "main": ("/main.rs", "2015", ["alloc"]), | ||
535 | "alloc": ("/lib.rs", []), | ||
536 | }); | ||
537 | let sync_id = db.file_id_of("/sync.rs"); | ||
538 | |||
539 | let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap(); | ||
540 | let krate = module.krate(&db).unwrap(); | ||
541 | let item_map = db.item_map(krate); | ||
542 | |||
543 | check_module_item_map( | ||
544 | &item_map, | ||
545 | module.module_id, | ||
546 | " | ||
547 | Arc: t v | ||
548 | ", | ||
549 | ); | ||
550 | } | ||
551 | |||
552 | #[test] | ||
553 | fn import_across_source_roots() { | ||
554 | let mut db = MockDatabase::with_files( | ||
555 | " | ||
556 | //- /lib.rs | ||
557 | pub mod a { | ||
558 | pub mod b { | ||
559 | pub struct C; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | //- root /main/ | ||
564 | |||
565 | //- /main/main.rs | ||
566 | use test_crate::a::b::C; | ||
567 | ", | ||
568 | ); | ||
569 | db.set_crate_graph_from_fixture(crate_graph! { | ||
570 | "main": ("/main/main.rs", ["test_crate"]), | ||
571 | "test_crate": ("/lib.rs", []), | ||
572 | }); | ||
573 | let main_id = db.file_id_of("/main/main.rs"); | ||
574 | |||
575 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | ||
576 | let krate = module.krate(&db).unwrap(); | ||
577 | let item_map = db.item_map(krate); | ||
578 | |||
579 | check_module_item_map( | ||
580 | &item_map, | ||
581 | module.module_id, | ||
582 | " | ||
583 | C: t v | ||
584 | ", | ||
585 | ); | ||
586 | } | ||
587 | |||
588 | #[test] | ||
589 | fn reexport_across_crates() { | ||
590 | let mut db = MockDatabase::with_files( | ||
591 | " | ||
592 | //- /main.rs | ||
593 | use test_crate::Baz; | ||
594 | |||
595 | //- /lib.rs | ||
596 | pub use foo::Baz; | ||
597 | |||
598 | mod foo; | ||
599 | |||
600 | //- /foo.rs | ||
601 | pub struct Baz; | ||
602 | ", | ||
603 | ); | ||
604 | db.set_crate_graph_from_fixture(crate_graph! { | ||
605 | "main": ("/main.rs", ["test_crate"]), | ||
606 | "test_crate": ("/lib.rs", []), | ||
607 | }); | ||
608 | let main_id = db.file_id_of("/main.rs"); | ||
609 | |||
610 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | ||
611 | let krate = module.krate(&db).unwrap(); | ||
612 | let item_map = db.item_map(krate); | ||
613 | |||
614 | check_module_item_map( | ||
615 | &item_map, | ||
616 | module.module_id, | ||
617 | " | ||
618 | Baz: t v | ||
619 | ", | ||
620 | ); | ||
621 | } | ||
622 | |||
623 | #[test] | ||
624 | fn values_dont_shadow_extern_crates() { | ||
625 | let mut db = MockDatabase::with_files( | ||
626 | " | ||
627 | //- /main.rs | ||
628 | fn foo() {} | ||
629 | use foo::Bar; | ||
630 | |||
631 | //- /foo/lib.rs | ||
632 | pub struct Bar; | ||
633 | ", | ||
634 | ); | ||
635 | db.set_crate_graph_from_fixture(crate_graph! { | ||
636 | "main": ("/main.rs", ["foo"]), | ||
637 | "foo": ("/foo/lib.rs", []), | ||
638 | }); | ||
639 | let main_id = db.file_id_of("/main.rs"); | ||
640 | |||
641 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | ||
642 | let krate = module.krate(&db).unwrap(); | ||
643 | let item_map = db.item_map(krate); | ||
644 | |||
645 | check_module_item_map( | ||
646 | &item_map, | ||
647 | module.module_id, | ||
648 | " | ||
649 | Bar: t v | ||
650 | foo: v | ||
651 | ", | ||
652 | ); | ||
653 | } | ||
654 | |||
655 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { | ||
656 | let (mut db, pos) = MockDatabase::with_position(initial); | ||
657 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); | ||
658 | let krate = module.krate(&db).unwrap(); | ||
659 | { | ||
660 | let events = db.log_executed(|| { | ||
661 | db.item_map(krate); | ||
662 | }); | ||
663 | assert!(format!("{:?}", events).contains("item_map")) | ||
664 | } | ||
665 | db.set_file_text(pos.file_id, Arc::new(file_change.to_string())); | ||
666 | |||
667 | { | ||
668 | let events = db.log_executed(|| { | ||
669 | db.item_map(krate); | ||
670 | }); | ||
671 | assert!(!format!("{:?}", events).contains("item_map"), "{:#?}", events) | ||
672 | } | ||
673 | } | ||
674 | |||
675 | #[test] | ||
676 | fn typing_inside_a_function_should_not_invalidate_item_map() { | ||
677 | check_item_map_is_not_recomputed( | ||
678 | " | ||
679 | //- /lib.rs | ||
680 | mod foo;<|> | ||
681 | |||
682 | use crate::foo::bar::Baz; | ||
683 | |||
684 | fn foo() -> i32 { | ||
685 | 1 + 1 | ||
686 | } | ||
687 | //- /foo/mod.rs | ||
688 | pub mod bar; | ||
689 | |||
690 | //- /foo/bar.rs | ||
691 | pub struct Baz; | ||
692 | ", | ||
693 | " | ||
694 | mod foo; | ||
695 | |||
696 | use crate::foo::bar::Baz; | ||
697 | |||
698 | fn foo() -> i32 { 92 } | ||
699 | ", | ||
700 | ); | ||
701 | } | ||
702 | |||
703 | #[test] | ||
704 | fn adding_inner_items_should_not_invalidate_item_map() { | ||
705 | check_item_map_is_not_recomputed( | ||
706 | " | ||
707 | //- /lib.rs | ||
708 | struct S { a: i32} | ||
709 | enum E { A } | ||
710 | trait T { | ||
711 | fn a() {} | ||
712 | } | ||
713 | mod foo;<|> | ||
714 | impl S { | ||
715 | fn a() {} | ||
716 | } | ||
717 | use crate::foo::bar::Baz; | ||
718 | //- /foo/mod.rs | ||
719 | pub mod bar; | ||
720 | |||
721 | //- /foo/bar.rs | ||
722 | pub struct Baz; | ||
723 | ", | ||
724 | " | ||
725 | struct S { a: i32, b: () } | ||
726 | enum E { A, B } | ||
727 | trait T { | ||
728 | fn a() {} | ||
729 | fn b() {} | ||
730 | } | ||
731 | mod foo;<|> | ||
732 | impl S { | ||
733 | fn a() {} | ||
734 | fn b() {} | ||
735 | } | ||
736 | use crate::foo::bar::Baz; | ||
737 | ", | ||
738 | ); | ||
739 | } | ||
740 | |||
741 | #[test] | ||
742 | fn typing_inside_a_function_inside_a_macro_should_not_invalidate_item_map() { | ||
743 | check_item_map_is_not_recomputed( | ||
744 | " | ||
745 | //- /lib.rs | ||
746 | mod foo; | ||
747 | |||
748 | use crate::foo::bar::Baz; | ||
749 | |||
750 | //- /foo/mod.rs | ||
751 | pub mod bar; | ||
752 | |||
753 | //- /foo/bar.rs | ||
754 | <|> | ||
755 | salsa::query_group! { | ||
756 | trait Baz { | ||
757 | fn foo() -> i32 { 1 + 1 } | ||
758 | } | ||
759 | } | ||
760 | ", | ||
761 | " | ||
762 | salsa::query_group! { | ||
763 | trait Baz { | ||
764 | fn foo() -> i32 { 92 } | ||
765 | } | ||
766 | } | ||
767 | ", | ||
768 | ); | ||
769 | } | ||