aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres/tests/macros.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres/tests/macros.rs')
-rw-r--r--crates/ra_hir_def/src/nameres/tests/macros.rs602
1 files changed, 602 insertions, 0 deletions
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
new file mode 100644
index 000000000..9bb3895ad
--- /dev/null
+++ b/crates/ra_hir_def/src/nameres/tests/macros.rs
@@ -0,0 +1,602 @@
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!(map, @r###"
21 ⋮crate
22 ⋮Foo: t v
23 ⋮nested: t
24
25 ⋮crate::nested
26 ⋮Bar: t v
27 ⋮Baz: 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 mod m {
42 m!(n3)
43 }
44
45 //- /n1.rs
46 m!(n2)
47 //- /n1/n2.rs
48 struct X;
49 //- /m/n3.rs
50 struct Y;
51 ",
52 );
53 assert_snapshot!(map, @r###"
54 crate
55 m: t
56 n1: t
57
58 crate::m
59 n3: t
60
61 crate::m::n3
62 Y: t v
63
64 crate::n1
65 n2: t
66
67 crate::n1::n2
68 X: t v
69 "###);
70}
71
72#[test]
73fn macro_rules_from_other_crates_are_visible() {
74 let map = def_map(
75 "
76 //- /main.rs crate:main deps:foo
77 foo::structs!(Foo, Bar)
78 mod bar;
79
80 //- /bar.rs
81 use crate::*;
82
83 //- /lib.rs crate:foo
84 #[macro_export]
85 macro_rules! structs {
86 ($($i:ident),*) => {
87 $(struct $i { field: u32 } )*
88 }
89 }
90 ",
91 );
92 assert_snapshot!(map, @r###"
93 ⋮crate
94 ⋮Bar: t v
95 ⋮Foo: t v
96 ⋮bar: t
97
98 ⋮crate::bar
99 ⋮Bar: t v
100 ⋮Foo: t v
101 ⋮bar: t
102 "###);
103}
104
105#[test]
106fn macro_rules_export_with_local_inner_macros_are_visible() {
107 let map = def_map(
108 "
109 //- /main.rs crate:main deps:foo
110 foo::structs!(Foo, Bar)
111 mod bar;
112
113 //- /bar.rs
114 use crate::*;
115
116 //- /lib.rs crate:foo
117 #[macro_export(local_inner_macros)]
118 macro_rules! structs {
119 ($($i:ident),*) => {
120 $(struct $i { field: u32 } )*
121 }
122 }
123 ",
124 );
125 assert_snapshot!(map, @r###"
126 ⋮crate
127 ⋮Bar: t v
128 ⋮Foo: t v
129 ⋮bar: t
130
131 ⋮crate::bar
132 ⋮Bar: t v
133 ⋮Foo: t v
134 ⋮bar: t
135 "###);
136}
137
138#[test]
139fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
140 let map = def_map(
141 "
142 //- /main.rs crate:main deps:foo
143 macro_rules! baz {
144 () => {
145 use foo::bar;
146 }
147 }
148
149 foo!();
150 bar!();
151 baz!();
152
153 //- /lib.rs crate:foo
154 #[macro_export]
155 macro_rules! foo {
156 () => {
157 struct Foo { field: u32 }
158 }
159 }
160 #[macro_export]
161 macro_rules! bar {
162 () => {
163 use foo::foo;
164 }
165 }
166 ",
167 );
168 assert_snapshot!(map, @r###"
169 ⋮crate
170 ⋮Foo: t v
171 ⋮bar: m
172 ⋮foo: m
173 "###);
174}
175
176#[test]
177fn macro_rules_from_other_crates_are_visible_with_macro_use() {
178 // covers!(macro_rules_from_other_crates_are_visible_with_macro_use);
179 let map = def_map(
180 "
181 //- /main.rs crate:main deps:foo
182 structs!(Foo);
183 structs_priv!(Bar);
184 structs_not_exported!(MacroNotResolved1);
185 crate::structs!(MacroNotResolved2);
186
187 mod bar;
188
189 #[macro_use]
190 extern crate foo;
191
192 //- /bar.rs
193 structs!(Baz);
194 crate::structs!(MacroNotResolved3);
195
196 //- /lib.rs crate:foo
197 #[macro_export]
198 macro_rules! structs {
199 ($i:ident) => { struct $i; }
200 }
201
202 macro_rules! structs_not_exported {
203 ($i:ident) => { struct $i; }
204 }
205
206 mod priv_mod {
207 #[macro_export]
208 macro_rules! structs_priv {
209 ($i:ident) => { struct $i; }
210 }
211 }
212 ",
213 );
214 assert_snapshot!(map, @r###"
215 ⋮crate
216 ⋮Bar: t v
217 ⋮Foo: t v
218 ⋮bar: t
219 ⋮foo: t
220
221 ⋮crate::bar
222 ⋮Baz: t v
223 "###);
224}
225
226#[test]
227fn prelude_is_macro_use() {
228 // covers!(prelude_is_macro_use);
229 let map = def_map(
230 "
231 //- /main.rs crate:main deps:foo
232 structs!(Foo);
233 structs_priv!(Bar);
234 structs_outside!(Out);
235 crate::structs!(MacroNotResolved2);
236
237 mod bar;
238
239 //- /bar.rs
240 structs!(Baz);
241 crate::structs!(MacroNotResolved3);
242
243 //- /lib.rs crate:foo
244 #[prelude_import]
245 use self::prelude::*;
246
247 mod prelude {
248 #[macro_export]
249 macro_rules! structs {
250 ($i:ident) => { struct $i; }
251 }
252
253 mod priv_mod {
254 #[macro_export]
255 macro_rules! structs_priv {
256 ($i:ident) => { struct $i; }
257 }
258 }
259 }
260
261 #[macro_export]
262 macro_rules! structs_outside {
263 ($i:ident) => { struct $i; }
264 }
265 ",
266 );
267 assert_snapshot!(map, @r###"
268 ⋮crate
269 ⋮Bar: t v
270 ⋮Foo: t v
271 ⋮Out: t v
272 ⋮bar: t
273
274 ⋮crate::bar
275 ⋮Baz: t v
276 "###);
277}
278
279#[test]
280fn prelude_cycle() {
281 let map = def_map(
282 "
283 //- /lib.rs
284 #[prelude_import]
285 use self::prelude::*;
286
287 declare_mod!();
288
289 mod prelude {
290 macro_rules! declare_mod {
291 () => (mod foo {})
292 }
293 }
294 ",
295 );
296 assert_snapshot!(map, @r###"
297 ⋮crate
298 ⋮prelude: t
299
300 ⋮crate::prelude
301 "###);
302}
303
304#[test]
305fn plain_macros_are_legacy_textual_scoped() {
306 let map = def_map(
307 r#"
308 //- /main.rs
309 mod m1;
310 bar!(NotFoundNotMacroUse);
311
312 mod m2 {
313 foo!(NotFoundBeforeInside2);
314 }
315
316 macro_rules! foo {
317 ($x:ident) => { struct $x; }
318 }
319 foo!(Ok);
320
321 mod m3;
322 foo!(OkShadowStop);
323 bar!(NotFoundMacroUseStop);
324
325 #[macro_use]
326 mod m5 {
327 #[macro_use]
328 mod m6 {
329 macro_rules! foo {
330 ($x:ident) => { fn $x() {} }
331 }
332 }
333 }
334 foo!(ok_double_macro_use_shadow);
335
336 baz!(NotFoundBefore);
337 #[macro_use]
338 mod m7 {
339 macro_rules! baz {
340 ($x:ident) => { struct $x; }
341 }
342 }
343 baz!(OkAfter);
344
345 //- /m1.rs
346 foo!(NotFoundBeforeInside1);
347 macro_rules! bar {
348 ($x:ident) => { struct $x; }
349 }
350
351 //- /m3/mod.rs
352 foo!(OkAfterInside);
353 macro_rules! foo {
354 ($x:ident) => { fn $x() {} }
355 }
356 foo!(ok_shadow);
357
358 #[macro_use]
359 mod m4;
360 bar!(OkMacroUse);
361
362 //- /m3/m4.rs
363 foo!(ok_shadow_deep);
364 macro_rules! bar {
365 ($x:ident) => { struct $x; }
366 }
367 "#,
368 );
369 assert_snapshot!(map, @r###"
370 ⋮crate
371 ⋮Ok: t v
372 ⋮OkAfter: t v
373 ⋮OkShadowStop: t v
374 ⋮m1: t
375 ⋮m2: t
376 ⋮m3: t
377 ⋮m5: t
378 ⋮m7: t
379 ⋮ok_double_macro_use_shadow: v
380
381 ⋮crate::m7
382
383 ⋮crate::m1
384
385 ⋮crate::m5
386 ⋮m6: t
387
388 ⋮crate::m5::m6
389
390 ⋮crate::m2
391
392 ⋮crate::m3
393 ⋮OkAfterInside: t v
394 ⋮OkMacroUse: t v
395 ⋮m4: t
396 ⋮ok_shadow: v
397
398 ⋮crate::m3::m4
399 ⋮ok_shadow_deep: v
400 "###);
401}
402
403#[test]
404fn type_value_macro_live_in_different_scopes() {
405 let map = def_map(
406 "
407 //- /main.rs
408 #[macro_export]
409 macro_rules! foo {
410 ($x:ident) => { type $x = (); }
411 }
412
413 foo!(foo);
414 use foo as bar;
415
416 use self::foo as baz;
417 fn baz() {}
418 ",
419 );
420 assert_snapshot!(map, @r###"
421 ⋮crate
422 ⋮bar: t m
423 ⋮baz: t v m
424 ⋮foo: t m
425 "###);
426}
427
428#[test]
429fn macro_use_can_be_aliased() {
430 let map = def_map(
431 "
432 //- /main.rs crate:main deps:foo
433 #[macro_use]
434 extern crate foo;
435
436 foo!(Direct);
437 bar!(Alias);
438
439 //- /lib.rs crate:foo
440 use crate::foo as bar;
441
442 mod m {
443 #[macro_export]
444 macro_rules! foo {
445 ($x:ident) => { struct $x; }
446 }
447 }
448 ",
449 );
450 assert_snapshot!(map, @r###"
451 ⋮crate
452 ⋮Alias: t v
453 ⋮Direct: t v
454 ⋮foo: t
455 "###);
456}
457
458#[test]
459fn path_qualified_macros() {
460 let map = def_map(
461 "
462 //- /main.rs
463 macro_rules! foo {
464 ($x:ident) => { struct $x; }
465 }
466
467 crate::foo!(NotResolved);
468
469 crate::bar!(OkCrate);
470 bar!(OkPlain);
471 alias1!(NotHere);
472 m::alias1!(OkAliasPlain);
473 m::alias2!(OkAliasSuper);
474 m::alias3!(OkAliasCrate);
475 not_found!(NotFound);
476
477 mod m {
478 #[macro_export]
479 macro_rules! bar {
480 ($x:ident) => { struct $x; }
481 }
482
483 pub use bar as alias1;
484 pub use super::bar as alias2;
485 pub use crate::bar as alias3;
486 pub use self::bar as not_found;
487 }
488 ",
489 );
490 assert_snapshot!(map, @r###"
491 ⋮crate
492 ⋮OkAliasCrate: t v
493 ⋮OkAliasPlain: t v
494 ⋮OkAliasSuper: t v
495 ⋮OkCrate: t v
496 ⋮OkPlain: t v
497 ⋮bar: m
498 ⋮m: t
499
500 ⋮crate::m
501 ⋮alias1: m
502 ⋮alias2: m
503 ⋮alias3: m
504 ⋮not_found: _
505 "###);
506}
507
508#[test]
509fn macro_dollar_crate_is_correct_in_item() {
510 // covers!(macro_dollar_crate_self);
511 // covers!(macro_dollar_crate_other);
512 let map = def_map(
513 "
514 //- /main.rs crate:main deps:foo
515 #[macro_use]
516 extern crate foo;
517
518 #[macro_use]
519 mod m {
520 macro_rules! current {
521 () => {
522 use $crate::Foo as FooSelf;
523 }
524 }
525 }
526
527 struct Foo;
528
529 current!();
530 not_current1!();
531 foo::not_current2!();
532
533 //- /lib.rs crate:foo
534 mod m {
535 #[macro_export]
536 macro_rules! not_current1 {
537 () => {
538 use $crate::Bar;
539 }
540 }
541 }
542
543 #[macro_export]
544 macro_rules! not_current2 {
545 () => {
546 use $crate::Baz;
547 }
548 }
549
550 struct Bar;
551 struct Baz;
552 ",
553 );
554 assert_snapshot!(map, @r###"
555 ⋮crate
556 ⋮Bar: t v
557 ⋮Baz: t v
558 ⋮Foo: t v
559 ⋮FooSelf: t v
560 ⋮foo: t
561 ⋮m: t
562
563 ⋮crate::m
564 "###);
565}
566
567#[test]
568fn macro_dollar_crate_is_correct_in_indirect_deps() {
569 // covers!(macro_dollar_crate_other);
570 // From std
571 let map = def_map(
572 r#"
573 //- /main.rs crate:main deps:std
574 foo!();
575
576 //- /std.rs crate:std deps:core
577 #[prelude_import]
578 use self::prelude::*;
579
580 pub use core::foo;
581
582 mod prelude {}
583
584 #[macro_use]
585 mod std_macros;
586
587 //- /core.rs crate:core
588 #[macro_export]
589 macro_rules! foo {
590 () => {
591 use $crate::bar;
592 }
593 }
594
595 pub struct bar;
596 "#,
597 );
598 assert_snapshot!(map, @r###"
599 ⋮crate
600 ⋮bar: t v
601 "###);
602}