aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/marks.rs2
-rw-r--r--crates/ra_hir/src/nameres.rs5
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map.rs2
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/collector.rs15
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/tests.rs411
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs118
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs123
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs94
-rw-r--r--crates/ra_hir/src/nameres/tests.rs769
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 @@
1test_utils::marks!( 1test_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)]
698mod 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 @@
1mod macros;
2mod globs;
3mod incremental;
4
1use std::sync::Arc; 5use std::sync::Arc;
2 6
3use ra_db::SourceDatabase; 7use 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###"
76crate 82crate
83V: t v
84E: t
85foo: t
77S: t v 86S: t v
78 87
79crate::foo 88crate::foo
89bar: t
80f: v 90f: v
81 91
82crate::foo::bar 92crate::foo::bar
@@ -87,91 +97,96 @@ E: t
87} 97}
88 98
89#[test] 99#[test]
90fn macro_rules_are_globally_visible() { 100fn 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###"
107crate 114crate
108Foo: t v 115Foo: t v
116foo: t
109 117
110crate::nested 118crate::foo
111Bar: t v
112Baz: t v 119Baz: t v
113"###); 120"###
121 );
114} 122}
115 123
116#[test] 124#[test]
117fn macro_rules_can_define_modules() { 125fn 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###"
133crate 143crate
144Quux: t
145Baz: t v
146foo: t
134 147
135crate::n1 148crate::foo
149bar: t
136 150
137crate::n1::n2 151crate::foo::bar
138X: t v 152Quux: t
139"###); 153Baz: t v
154"###
155 );
140} 156}
141 157
142#[test] 158#[test]
143fn macro_rules_from_other_crates_are_visible() { 159fn 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###"
167crate 178crate
168Foo: t v 179Baz: t v
169Bar: t v 180foo: t
170 181
171crate::bar 182crate::foo
172Foo: t v 183bar: t
173Bar: t v 184Baz: t v
174"###); 185
186crate::foo::bar
187Baz: 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]
206fn glob_across_crates() { 221fn 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###"
231crate
232V: t v
233E: t
234"###
235 );
236}
237
238#[test]
239fn 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###"
264crate
265bar: t
266foo: t
267
268crate::bar
269Bar: t v
270
271crate::foo
272FromLib: t v
273Bar: t v
274"###
275 );
276}
277
278#[test]
279fn 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###"
296crate
297Bar: t v
298foo: t
299
300crate::foo
301Bar: t v
302"###
303 );
304}
305
306#[test]
307fn 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###"
327crate
328Baz: _
329"###
330 );
331}
332
333#[test]
334fn 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###"
348crate
349Baz: t v
350foo: t
351
352crate::foo
353bar: t
354
355crate::foo::bar
356Baz: t v
357"###
358 );
359}
360
361#[test]
362fn 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###"
222crate 379crate
223Baz: t v 380Baz: t v
224"### 381"###
@@ -226,40 +383,146 @@ Baz: t v
226} 383}
227 384
228#[test] 385#[test]
229fn item_map_enum_importing() { 386fn 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###"
239crate 409crate
240V: t v 410Arc: t v
241E: t
242"### 411"###
243 ); 412 );
244} 413}
245 414
246#[test] 415#[test]
247fn glob_enum() { 416fn 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###"
439crate
440Arc: t v
441"###
442 );
443}
444
445#[test]
446fn 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###"
469crate
470C: t v
471"###
472 );
473}
474
475#[test]
476fn 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###"
259crate 498crate
260Foo: t
261Bar: t v
262Baz: t v 499Baz: t v
263"### 500"###
264 ); 501 );
265} 502}
503
504#[test]
505fn 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###"
523crate
524Bar: t v
525foo: 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 @@
1use super::*;
2
3#[test]
4fn 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###"
21crate
22bar: t
23Foo: t v
24Baz: t v
25foo: t
26
27crate::foo
28bar: t
29Foo: t v
30Baz: t v
31
32crate::foo::bar
33Baz: t v
34"###
35 );
36}
37
38#[test]
39fn 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###"
57crate
58bar: t
59Foo: t v
60Baz: t v
61foo: t
62
63crate::foo
64bar: t
65Foo: t v
66Baz: t v
67
68crate::foo::bar
69bar: t
70Foo: t v
71Baz: t v
72"###
73 );
74}
75
76#[test]
77fn 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###"
93crate
94Baz: t v
95"###
96 );
97}
98
99#[test]
100fn 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###"
112crate
113Foo: t
114Bar: t v
115Baz: 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 @@
1use super::*;
2
3use std::sync::Arc;
4
5use ra_db::SourceDatabase;
6
7fn 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]
28fn 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]
56fn 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]
96fn 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 @@
1use super::*;
2
3#[test]
4fn 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###"
21crate
22nested: t
23Foo: t v
24
25crate::nested
26Bar: t v
27Baz: t v
28"###);
29}
30
31#[test]
32fn 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###"
48crate
49n1: t
50
51crate::n1
52n2: t
53
54crate::n1::n2
55X: t v
56"###);
57}
58
59#[test]
60fn 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###"
84crate
85bar: t
86Foo: t v
87Bar: t v
88
89crate::bar
90bar: t
91Foo: t v
92Bar: 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 @@
1use std::sync::Arc;
2
3use ra_db::SourceDatabase;
4use test_utils::{assert_eq_text, covers};
5
6use crate::{
7 ItemMap,
8 PersistentHirDatabase,
9 mock::MockDatabase,
10 nameres::crate_def_map::ModuleId,
11};
12use super::Resolution;
13
14fn 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
22fn 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]
44fn 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]
71fn 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]
95fn 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]
124fn 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]
153fn 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]
183fn 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]
214fn 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]
238fn 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]
269fn 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]
308fn 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]
339fn 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]
377fn 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]
406fn 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]
430fn 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]
451fn 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]
481fn 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]
517fn 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]
553fn 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]
589fn 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]
624fn 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
655fn 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]
676fn 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]
704fn 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]
742fn 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}