]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/references.rs
Rename fails on renaming definitions created by macros
[rust.git] / crates / ide / src / references.rs
1 //! This module implements a reference search.
2 //! First, the element at the cursor position must be either an `ast::Name`
3 //! or `ast::NameRef`. If it's a `ast::NameRef`, at the classification step we
4 //! try to resolve the direct tree parent of this element, otherwise we
5 //! already have a definition and just need to get its HIR together with
6 //! some information that is needed for further steps of searching.
7 //! After that, we collect files that might contain references and look
8 //! for text occurrences of the identifier. If there's an `ast::NameRef`
9 //! at the index that the match starts at and its tree parent is
10 //! resolved to the search element definition, we get a reference.
11
12 use hir::{PathResolution, Semantics};
13 use ide_db::{
14     base_db::FileId,
15     defs::{Definition, NameClass, NameRefClass},
16     search::{ReferenceAccess, SearchScope, UsageSearchResult},
17     RootDatabase,
18 };
19 use rustc_hash::FxHashMap;
20 use syntax::{
21     algo::find_node_at_offset,
22     ast::{self, NameOwner},
23     match_ast, AstNode, SyntaxNode, TextRange, TextSize, T,
24 };
25
26 use crate::{display::TryToNav, FilePosition, NavigationTarget};
27
28 #[derive(Debug, Clone)]
29 pub struct ReferenceSearchResult {
30     pub declaration: Option<Declaration>,
31     pub references: FxHashMap<FileId, Vec<(TextRange, Option<ReferenceAccess>)>>,
32 }
33
34 #[derive(Debug, Clone)]
35 pub struct Declaration {
36     pub nav: NavigationTarget,
37     pub access: Option<ReferenceAccess>,
38 }
39
40 // Feature: Find All References
41 //
42 // Shows all references of the item at the cursor location
43 //
44 // |===
45 // | Editor  | Shortcut
46 //
47 // | VS Code | kbd:[Shift+Alt+F12]
48 // |===
49 //
50 // image::https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif[]
51 pub(crate) fn find_all_refs(
52     sema: &Semantics<RootDatabase>,
53     position: FilePosition,
54     search_scope: Option<SearchScope>,
55 ) -> Option<ReferenceSearchResult> {
56     let _p = profile::span("find_all_refs");
57     let syntax = sema.parse(position.file_id).syntax().clone();
58
59     let mut is_literal_search = false;
60     let def = if let Some(name) = name_for_constructor_search(&syntax, position) {
61         is_literal_search = true;
62         match NameClass::classify(sema, &name)? {
63             NameClass::Definition(it) | NameClass::ConstReference(it) => it,
64             NameClass::PatFieldShorthand { local_def: _, field_ref } => {
65                 Definition::Field(field_ref)
66             }
67         }
68     } else {
69         find_def(sema, &syntax, position.offset)?
70     };
71
72     let mut usages = def.usages(sema).set_scope(search_scope).include_self_refs().all();
73     let declaration = match def {
74         Definition::ModuleDef(hir::ModuleDef::Module(module)) => {
75             Some(NavigationTarget::from_module_to_decl(sema.db, module))
76         }
77         def => def.try_to_nav(sema.db),
78     }
79     .map(|nav| {
80         let decl_range = nav.focus_or_full_range();
81         Declaration { nav, access: decl_access(&def, &syntax, decl_range) }
82     });
83     if is_literal_search {
84         retain_adt_literal_usages(&mut usages, def, sema);
85     }
86
87     let references = usages
88         .into_iter()
89         .map(|(file_id, refs)| {
90             (file_id, refs.into_iter().map(|file_ref| (file_ref.range, file_ref.access)).collect())
91         })
92         .collect();
93
94     Some(ReferenceSearchResult { declaration, references })
95 }
96
97 pub(crate) fn find_def(
98     sema: &Semantics<RootDatabase>,
99     syntax: &SyntaxNode,
100     offset: TextSize,
101 ) -> Option<Definition> {
102     let def = match sema.find_node_at_offset_with_descend(syntax, offset)? {
103         ast::NameLike::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? {
104             NameRefClass::Definition(def) => def,
105             NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
106                 Definition::Local(local_ref)
107             }
108         },
109         ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
110             NameClass::Definition(it) | NameClass::ConstReference(it) => it,
111             NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
112                 Definition::Local(local_def)
113             }
114         },
115         ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
116             .and_then(|class| match class {
117                 NameRefClass::Definition(it) => Some(it),
118                 _ => None,
119             })
120             .or_else(|| {
121                 NameClass::classify_lifetime(sema, &lifetime).and_then(|class| match class {
122                     NameClass::Definition(it) => Some(it),
123                     _ => None,
124                 })
125             })?,
126     };
127     Some(def)
128 }
129
130 pub(crate) fn decl_access(
131     def: &Definition,
132     syntax: &SyntaxNode,
133     range: TextRange,
134 ) -> Option<ReferenceAccess> {
135     match def {
136         Definition::Local(_) | Definition::Field(_) => {}
137         _ => return None,
138     };
139
140     let stmt = find_node_at_offset::<ast::LetStmt>(syntax, range.start())?;
141     if stmt.initializer().is_some() {
142         let pat = stmt.pat()?;
143         if let ast::Pat::IdentPat(it) = pat {
144             if it.mut_token().is_some() {
145                 return Some(ReferenceAccess::Write);
146             }
147         }
148     }
149
150     None
151 }
152
153 /// Filter out all non-literal usages for adt-defs
154 fn retain_adt_literal_usages(
155     usages: &mut UsageSearchResult,
156     def: Definition,
157     sema: &Semantics<RootDatabase>,
158 ) {
159     let refs = usages.references.values_mut();
160     match def {
161         Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(enum_))) => {
162             refs.for_each(|it| {
163                 it.retain(|reference| {
164                     reference
165                         .name
166                         .as_name_ref()
167                         .map_or(false, |name_ref| is_enum_lit_name_ref(sema, enum_, name_ref))
168                 })
169             });
170             usages.references.retain(|_, it| !it.is_empty());
171         }
172         Definition::ModuleDef(hir::ModuleDef::Adt(_) | hir::ModuleDef::Variant(_)) => {
173             refs.for_each(|it| {
174                 it.retain(|reference| reference.name.as_name_ref().map_or(false, is_lit_name_ref))
175             });
176             usages.references.retain(|_, it| !it.is_empty());
177         }
178         _ => {}
179     }
180 }
181
182 /// Returns `Some` if the cursor is at a position for an item to search for all its constructor/literal usages
183 fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {
184     let token = syntax.token_at_offset(position.offset).right_biased()?;
185     let token_parent = token.parent()?;
186     let kind = token.kind();
187     if kind == T![;] {
188         ast::Struct::cast(token_parent)
189             .filter(|struct_| struct_.field_list().is_none())
190             .and_then(|struct_| struct_.name())
191     } else if kind == T!['{'] {
192         match_ast! {
193             match token_parent {
194                 ast::RecordFieldList(rfl) => match_ast! {
195                     match (rfl.syntax().parent()?) {
196                         ast::Variant(it) => it.name(),
197                         ast::Struct(it) => it.name(),
198                         ast::Union(it) => it.name(),
199                         _ => None,
200                     }
201                 },
202                 ast::VariantList(vl) => ast::Enum::cast(vl.syntax().parent()?)?.name(),
203                 _ => None,
204             }
205         }
206     } else if kind == T!['('] {
207         let tfl = ast::TupleFieldList::cast(token_parent)?;
208         match_ast! {
209             match (tfl.syntax().parent()?) {
210                 ast::Variant(it) => it.name(),
211                 ast::Struct(it) => it.name(),
212                 _ => None,
213             }
214         }
215     } else {
216         None
217     }
218 }
219
220 fn is_enum_lit_name_ref(
221     sema: &Semantics<RootDatabase>,
222     enum_: hir::Enum,
223     name_ref: &ast::NameRef,
224 ) -> bool {
225     let path_is_variant_of_enum = |path: ast::Path| {
226         matches!(
227             sema.resolve_path(&path),
228             Some(PathResolution::Def(hir::ModuleDef::Variant(variant)))
229                 if variant.parent_enum(sema.db) == enum_
230         )
231     };
232     name_ref
233         .syntax()
234         .ancestors()
235         .find_map(|ancestor| {
236             match_ast! {
237                 match ancestor {
238                     ast::PathExpr(path_expr) => path_expr.path().map(path_is_variant_of_enum),
239                     ast::RecordExpr(record_expr) => record_expr.path().map(path_is_variant_of_enum),
240                     _ => None,
241                 }
242             }
243         })
244         .unwrap_or(false)
245 }
246
247 fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {
248     path.and_then(|path| path.segment())
249         .and_then(|segment| segment.name_ref())
250         .map_or(false, |segment| segment == *name_ref)
251 }
252
253 fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
254     name_ref.syntax().ancestors().find_map(|ancestor| {
255         match_ast! {
256             match ancestor {
257                 ast::PathExpr(path_expr) => Some(path_ends_with(path_expr.path(), name_ref)),
258                 ast::RecordExpr(record_expr) => Some(path_ends_with(record_expr.path(), name_ref)),
259                 _ => None,
260             }
261         }
262     }).unwrap_or(false)
263 }
264
265 #[cfg(test)]
266 mod tests {
267     use expect_test::{expect, Expect};
268     use ide_db::base_db::FileId;
269     use stdx::format_to;
270
271     use crate::{fixture, SearchScope};
272
273     #[test]
274     fn test_struct_literal_after_space() {
275         check(
276             r#"
277 struct Foo $0{
278     a: i32,
279 }
280 impl Foo {
281     fn f() -> i32 { 42 }
282 }
283 fn main() {
284     let f: Foo;
285     f = Foo {a: Foo::f()};
286 }
287 "#,
288             expect![[r#"
289                 Foo Struct FileId(0) 0..26 7..10
290
291                 FileId(0) 101..104
292             "#]],
293         );
294     }
295
296     #[test]
297     fn test_struct_literal_before_space() {
298         check(
299             r#"
300 struct Foo$0 {}
301     fn main() {
302     let f: Foo;
303     f = Foo {};
304 }
305 "#,
306             expect![[r#"
307                 Foo Struct FileId(0) 0..13 7..10
308
309                 FileId(0) 41..44
310                 FileId(0) 54..57
311             "#]],
312         );
313     }
314
315     #[test]
316     fn test_struct_literal_with_generic_type() {
317         check(
318             r#"
319 struct Foo<T> $0{}
320     fn main() {
321     let f: Foo::<i32>;
322     f = Foo {};
323 }
324 "#,
325             expect![[r#"
326                 Foo Struct FileId(0) 0..16 7..10
327
328                 FileId(0) 64..67
329             "#]],
330         );
331     }
332
333     #[test]
334     fn test_struct_literal_for_tuple() {
335         check(
336             r#"
337 struct Foo$0(i32);
338
339 fn main() {
340     let f: Foo;
341     f = Foo(1);
342 }
343 "#,
344             expect![[r#"
345                 Foo Struct FileId(0) 0..16 7..10
346
347                 FileId(0) 54..57
348             "#]],
349         );
350     }
351
352     #[test]
353     fn test_struct_literal_for_union() {
354         check(
355             r#"
356 union Foo $0{
357     x: u32
358 }
359
360 fn main() {
361     let f: Foo;
362     f = Foo { x: 1 };
363 }
364 "#,
365             expect![[r#"
366                 Foo Union FileId(0) 0..24 6..9
367
368                 FileId(0) 62..65
369             "#]],
370         );
371     }
372
373     #[test]
374     fn test_enum_after_space() {
375         check(
376             r#"
377 enum Foo $0{
378     A,
379     B(),
380     C{},
381 }
382 fn main() {
383     let f: Foo;
384     f = Foo::A;
385     f = Foo::B();
386     f = Foo::C{};
387 }
388 "#,
389             expect![[r#"
390                 Foo Enum FileId(0) 0..37 5..8
391
392                 FileId(0) 74..77
393                 FileId(0) 90..93
394                 FileId(0) 108..111
395             "#]],
396         );
397     }
398
399     #[test]
400     fn test_variant_record_after_space() {
401         check(
402             r#"
403 enum Foo {
404     A $0{ n: i32 },
405     B,
406 }
407 fn main() {
408     let f: Foo;
409     f = Foo::B;
410     f = Foo::A { n: 92 };
411 }
412 "#,
413             expect![[r#"
414                 A Variant FileId(0) 15..27 15..16
415
416                 FileId(0) 95..96
417             "#]],
418         );
419     }
420     #[test]
421     fn test_variant_tuple_before_paren() {
422         check(
423             r#"
424 enum Foo {
425     A$0(i32),
426     B,
427 }
428 fn main() {
429     let f: Foo;
430     f = Foo::B;
431     f = Foo::A(92);
432 }
433 "#,
434             expect![[r#"
435                 A Variant FileId(0) 15..21 15..16
436
437                 FileId(0) 89..90
438             "#]],
439         );
440     }
441
442     #[test]
443     fn test_enum_before_space() {
444         check(
445             r#"
446 enum Foo$0 {
447     A,
448     B,
449 }
450 fn main() {
451     let f: Foo;
452     f = Foo::A;
453 }
454 "#,
455             expect![[r#"
456                 Foo Enum FileId(0) 0..26 5..8
457
458                 FileId(0) 50..53
459                 FileId(0) 63..66
460             "#]],
461         );
462     }
463
464     #[test]
465     fn test_enum_with_generic_type() {
466         check(
467             r#"
468 enum Foo<T> $0{
469     A(T),
470     B,
471 }
472 fn main() {
473     let f: Foo<i8>;
474     f = Foo::A(1);
475 }
476 "#,
477             expect![[r#"
478                 Foo Enum FileId(0) 0..32 5..8
479
480                 FileId(0) 73..76
481             "#]],
482         );
483     }
484
485     #[test]
486     fn test_enum_for_tuple() {
487         check(
488             r#"
489 enum Foo$0{
490     A(i8),
491     B(i8),
492 }
493 fn main() {
494     let f: Foo;
495     f = Foo::A(1);
496 }
497 "#,
498             expect![[r#"
499                 Foo Enum FileId(0) 0..33 5..8
500
501                 FileId(0) 70..73
502             "#]],
503         );
504     }
505
506     #[test]
507     fn test_find_all_refs_for_local() {
508         check(
509             r#"
510 fn main() {
511     let mut i = 1;
512     let j = 1;
513     i = i$0 + j;
514
515     {
516         i = 0;
517     }
518
519     i = 5;
520 }"#,
521             expect![[r#"
522                 i Local FileId(0) 20..25 24..25 Write
523
524                 FileId(0) 50..51 Write
525                 FileId(0) 54..55 Read
526                 FileId(0) 76..77 Write
527                 FileId(0) 94..95 Write
528             "#]],
529         );
530     }
531
532     #[test]
533     fn search_filters_by_range() {
534         check(
535             r#"
536 fn foo() {
537     let spam$0 = 92;
538     spam + spam
539 }
540 fn bar() {
541     let spam = 92;
542     spam + spam
543 }
544 "#,
545             expect![[r#"
546                 spam Local FileId(0) 19..23 19..23
547
548                 FileId(0) 34..38 Read
549                 FileId(0) 41..45 Read
550             "#]],
551         );
552     }
553
554     #[test]
555     fn test_find_all_refs_for_param_inside() {
556         check(
557             r#"
558 fn foo(i : u32) -> u32 { i$0 }
559 "#,
560             expect![[r#"
561                 i ValueParam FileId(0) 7..8 7..8
562
563                 FileId(0) 25..26 Read
564             "#]],
565         );
566     }
567
568     #[test]
569     fn test_find_all_refs_for_fn_param() {
570         check(
571             r#"
572 fn foo(i$0 : u32) -> u32 { i }
573 "#,
574             expect![[r#"
575                 i ValueParam FileId(0) 7..8 7..8
576
577                 FileId(0) 25..26 Read
578             "#]],
579         );
580     }
581
582     #[test]
583     fn test_find_all_refs_field_name() {
584         check(
585             r#"
586 //- /lib.rs
587 struct Foo {
588     pub spam$0: u32,
589 }
590
591 fn main(s: Foo) {
592     let f = s.spam;
593 }
594 "#,
595             expect![[r#"
596                 spam Field FileId(0) 17..30 21..25
597
598                 FileId(0) 67..71 Read
599             "#]],
600         );
601     }
602
603     #[test]
604     fn test_find_all_refs_impl_item_name() {
605         check(
606             r#"
607 struct Foo;
608 impl Foo {
609     fn f$0(&self) {  }
610 }
611 "#,
612             expect![[r#"
613                 f Function FileId(0) 27..43 30..31
614
615             "#]],
616         );
617     }
618
619     #[test]
620     fn test_find_all_refs_enum_var_name() {
621         check(
622             r#"
623 enum Foo {
624     A,
625     B$0,
626     C,
627 }
628 "#,
629             expect![[r#"
630                 B Variant FileId(0) 22..23 22..23
631
632             "#]],
633         );
634     }
635
636     #[test]
637     fn test_find_all_refs_enum_var_field() {
638         check(
639             r#"
640 enum Foo {
641     A,
642     B { field$0: u8 },
643     C,
644 }
645 "#,
646             expect![[r#"
647                 field Field FileId(0) 26..35 26..31
648
649             "#]],
650         );
651     }
652
653     #[test]
654     fn test_find_all_refs_two_modules() {
655         check(
656             r#"
657 //- /lib.rs
658 pub mod foo;
659 pub mod bar;
660
661 fn f() {
662     let i = foo::Foo { n: 5 };
663 }
664
665 //- /foo.rs
666 use crate::bar;
667
668 pub struct Foo {
669     pub n: u32,
670 }
671
672 fn f() {
673     let i = bar::Bar { n: 5 };
674 }
675
676 //- /bar.rs
677 use crate::foo;
678
679 pub struct Bar {
680     pub n: u32,
681 }
682
683 fn f() {
684     let i = foo::Foo$0 { n: 5 };
685 }
686 "#,
687             expect![[r#"
688                 Foo Struct FileId(1) 17..51 28..31
689
690                 FileId(0) 53..56
691                 FileId(2) 79..82
692             "#]],
693         );
694     }
695
696     #[test]
697     fn test_find_all_refs_decl_module() {
698         check(
699             r#"
700 //- /lib.rs
701 mod foo$0;
702
703 use foo::Foo;
704
705 fn f() {
706     let i = Foo { n: 5 };
707 }
708
709 //- /foo.rs
710 pub struct Foo {
711     pub n: u32,
712 }
713 "#,
714             expect![[r#"
715                 foo Module FileId(0) 0..8 4..7
716
717                 FileId(0) 14..17
718             "#]],
719         );
720     }
721
722     #[test]
723     fn test_find_all_refs_decl_module_on_self() {
724         check(
725             r#"
726 //- /lib.rs
727 mod foo;
728
729 //- /foo.rs
730 use self$0;
731 "#,
732             expect![[r#"
733                 foo Module FileId(0) 0..8 4..7
734
735                 FileId(1) 4..8
736             "#]],
737         );
738     }
739
740     #[test]
741     fn test_find_all_refs_decl_module_on_self_crate_root() {
742         check(
743             r#"
744 //- /lib.rs
745 use self$0;
746 "#,
747             expect![[r#"
748                 Module FileId(0) 0..10
749
750             "#]],
751         );
752     }
753
754     #[test]
755     fn test_find_all_refs_super_mod_vis() {
756         check(
757             r#"
758 //- /lib.rs
759 mod foo;
760
761 //- /foo.rs
762 mod some;
763 use some::Foo;
764
765 fn f() {
766     let i = Foo { n: 5 };
767 }
768
769 //- /foo/some.rs
770 pub(super) struct Foo$0 {
771     pub n: u32,
772 }
773 "#,
774             expect![[r#"
775                 Foo Struct FileId(2) 0..41 18..21
776
777                 FileId(1) 20..23
778                 FileId(1) 47..50
779             "#]],
780         );
781     }
782
783     #[test]
784     fn test_find_all_refs_with_scope() {
785         let code = r#"
786             //- /lib.rs
787             mod foo;
788             mod bar;
789
790             pub fn quux$0() {}
791
792             //- /foo.rs
793             fn f() { super::quux(); }
794
795             //- /bar.rs
796             fn f() { super::quux(); }
797         "#;
798
799         check_with_scope(
800             code,
801             None,
802             expect![[r#"
803                 quux Function FileId(0) 19..35 26..30
804
805                 FileId(1) 16..20
806                 FileId(2) 16..20
807             "#]],
808         );
809
810         check_with_scope(
811             code,
812             Some(SearchScope::single_file(FileId(2))),
813             expect![[r#"
814                 quux Function FileId(0) 19..35 26..30
815
816                 FileId(2) 16..20
817             "#]],
818         );
819     }
820
821     #[test]
822     fn test_find_all_refs_macro_def() {
823         check(
824             r#"
825 #[macro_export]
826 macro_rules! m1$0 { () => (()) }
827
828 fn foo() {
829     m1();
830     m1();
831 }
832 "#,
833             expect![[r#"
834                 m1 Macro FileId(0) 0..46 29..31
835
836                 FileId(0) 63..65
837                 FileId(0) 73..75
838             "#]],
839         );
840     }
841
842     #[test]
843     fn test_basic_highlight_read_write() {
844         check(
845             r#"
846 fn foo() {
847     let mut i$0 = 0;
848     i = i + 1;
849 }
850 "#,
851             expect![[r#"
852                 i Local FileId(0) 19..24 23..24 Write
853
854                 FileId(0) 34..35 Write
855                 FileId(0) 38..39 Read
856             "#]],
857         );
858     }
859
860     #[test]
861     fn test_basic_highlight_field_read_write() {
862         check(
863             r#"
864 struct S {
865     f: u32,
866 }
867
868 fn foo() {
869     let mut s = S{f: 0};
870     s.f$0 = 0;
871 }
872 "#,
873             expect![[r#"
874                 f Field FileId(0) 15..21 15..16
875
876                 FileId(0) 55..56 Read
877                 FileId(0) 68..69 Write
878             "#]],
879         );
880     }
881
882     #[test]
883     fn test_basic_highlight_decl_no_write() {
884         check(
885             r#"
886 fn foo() {
887     let i$0;
888     i = 1;
889 }
890 "#,
891             expect![[r#"
892                 i Local FileId(0) 19..20 19..20
893
894                 FileId(0) 26..27 Write
895             "#]],
896         );
897     }
898
899     #[test]
900     fn test_find_struct_function_refs_outside_module() {
901         check(
902             r#"
903 mod foo {
904     pub struct Foo;
905
906     impl Foo {
907         pub fn new$0() -> Foo { Foo }
908     }
909 }
910
911 fn main() {
912     let _f = foo::Foo::new();
913 }
914 "#,
915             expect![[r#"
916                 new Function FileId(0) 54..81 61..64
917
918                 FileId(0) 126..129
919             "#]],
920         );
921     }
922
923     #[test]
924     fn test_find_all_refs_nested_module() {
925         check(
926             r#"
927 //- /lib.rs
928 mod foo { mod bar; }
929
930 fn f$0() {}
931
932 //- /foo/bar.rs
933 use crate::f;
934
935 fn g() { f(); }
936 "#,
937             expect![[r#"
938                 f Function FileId(0) 22..31 25..26
939
940                 FileId(1) 11..12
941                 FileId(1) 24..25
942             "#]],
943         );
944     }
945
946     #[test]
947     fn test_find_all_refs_struct_pat() {
948         check(
949             r#"
950 struct S {
951     field$0: u8,
952 }
953
954 fn f(s: S) {
955     match s {
956         S { field } => {}
957     }
958 }
959 "#,
960             expect![[r#"
961                 field Field FileId(0) 15..24 15..20
962
963                 FileId(0) 68..73 Read
964             "#]],
965         );
966     }
967
968     #[test]
969     fn test_find_all_refs_enum_var_pat() {
970         check(
971             r#"
972 enum En {
973     Variant {
974         field$0: u8,
975     }
976 }
977
978 fn f(e: En) {
979     match e {
980         En::Variant { field } => {}
981     }
982 }
983 "#,
984             expect![[r#"
985                 field Field FileId(0) 32..41 32..37
986
987                 FileId(0) 102..107 Read
988             "#]],
989         );
990     }
991
992     #[test]
993     fn test_find_all_refs_enum_var_privacy() {
994         check(
995             r#"
996 mod m {
997     pub enum En {
998         Variant {
999             field$0: u8,
1000         }
1001     }
1002 }
1003
1004 fn f() -> m::En {
1005     m::En::Variant { field: 0 }
1006 }
1007 "#,
1008             expect![[r#"
1009                 field Field FileId(0) 56..65 56..61
1010
1011                 FileId(0) 125..130 Read
1012             "#]],
1013         );
1014     }
1015
1016     #[test]
1017     fn test_find_self_refs() {
1018         check(
1019             r#"
1020 struct Foo { bar: i32 }
1021
1022 impl Foo {
1023     fn foo(self) {
1024         let x = self$0.bar;
1025         if true {
1026             let _ = match () {
1027                 () => self,
1028             };
1029         }
1030     }
1031 }
1032 "#,
1033             expect![[r#"
1034                 self SelfParam FileId(0) 47..51 47..51
1035
1036                 FileId(0) 71..75 Read
1037                 FileId(0) 152..156 Read
1038             "#]],
1039         );
1040     }
1041
1042     #[test]
1043     fn test_find_self_refs_decl() {
1044         check(
1045             r#"
1046 struct Foo { bar: i32 }
1047
1048 impl Foo {
1049     fn foo(self$0) {
1050         self;
1051     }
1052 }
1053 "#,
1054             expect![[r#"
1055                 self SelfParam FileId(0) 47..51 47..51
1056
1057                 FileId(0) 63..67 Read
1058             "#]],
1059         );
1060     }
1061
1062     fn check(ra_fixture: &str, expect: Expect) {
1063         check_with_scope(ra_fixture, None, expect)
1064     }
1065
1066     fn check_with_scope(ra_fixture: &str, search_scope: Option<SearchScope>, expect: Expect) {
1067         let (analysis, pos) = fixture::position(ra_fixture);
1068         let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap();
1069
1070         let mut actual = String::new();
1071         if let Some(decl) = refs.declaration {
1072             format_to!(actual, "{}", decl.nav.debug_render());
1073             if let Some(access) = decl.access {
1074                 format_to!(actual, " {:?}", access)
1075             }
1076             actual += "\n\n";
1077         }
1078
1079         for (file_id, references) in refs.references {
1080             for (range, access) in references {
1081                 format_to!(actual, "{:?} {:?}", file_id, range);
1082                 if let Some(access) = access {
1083                     format_to!(actual, " {:?}", access);
1084                 }
1085                 actual += "\n";
1086             }
1087         }
1088         expect.assert_eq(actual.trim_start())
1089     }
1090
1091     #[test]
1092     fn test_find_lifetimes_function() {
1093         check(
1094             r#"
1095 trait Foo<'a> {}
1096 impl<'a> Foo<'a> for &'a () {}
1097 fn foo<'a, 'b: 'a>(x: &'a$0 ()) -> &'a () where &'a (): Foo<'a> {
1098     fn bar<'a>(_: &'a ()) {}
1099     x
1100 }
1101 "#,
1102             expect![[r#"
1103                 'a LifetimeParam FileId(0) 55..57 55..57
1104
1105                 FileId(0) 63..65
1106                 FileId(0) 71..73
1107                 FileId(0) 82..84
1108                 FileId(0) 95..97
1109                 FileId(0) 106..108
1110             "#]],
1111         );
1112     }
1113
1114     #[test]
1115     fn test_find_lifetimes_type_alias() {
1116         check(
1117             r#"
1118 type Foo<'a, T> where T: 'a$0 = &'a T;
1119 "#,
1120             expect![[r#"
1121                 'a LifetimeParam FileId(0) 9..11 9..11
1122
1123                 FileId(0) 25..27
1124                 FileId(0) 31..33
1125             "#]],
1126         );
1127     }
1128
1129     #[test]
1130     fn test_find_lifetimes_trait_impl() {
1131         check(
1132             r#"
1133 trait Foo<'a> {
1134     fn foo() -> &'a ();
1135 }
1136 impl<'a> Foo<'a> for &'a () {
1137     fn foo() -> &'a$0 () {
1138         unimplemented!()
1139     }
1140 }
1141 "#,
1142             expect![[r#"
1143                 'a LifetimeParam FileId(0) 47..49 47..49
1144
1145                 FileId(0) 55..57
1146                 FileId(0) 64..66
1147                 FileId(0) 89..91
1148             "#]],
1149         );
1150     }
1151
1152     #[test]
1153     fn test_map_range_to_original() {
1154         check(
1155             r#"
1156 macro_rules! foo {($i:ident) => {$i} }
1157 fn main() {
1158     let a$0 = "test";
1159     foo!(a);
1160 }
1161 "#,
1162             expect![[r#"
1163                 a Local FileId(0) 59..60 59..60
1164
1165                 FileId(0) 80..81 Read
1166             "#]],
1167         );
1168     }
1169
1170     #[test]
1171     fn test_map_range_to_original_ref() {
1172         check(
1173             r#"
1174 macro_rules! foo {($i:ident) => {$i} }
1175 fn main() {
1176     let a = "test";
1177     foo!(a$0);
1178 }
1179 "#,
1180             expect![[r#"
1181                 a Local FileId(0) 59..60 59..60
1182
1183                 FileId(0) 80..81 Read
1184             "#]],
1185         );
1186     }
1187
1188     #[test]
1189     fn test_find_labels() {
1190         check(
1191             r#"
1192 fn foo<'a>() -> &'a () {
1193     'a: loop {
1194         'b: loop {
1195             continue 'a$0;
1196         }
1197         break 'a;
1198     }
1199 }
1200 "#,
1201             expect![[r#"
1202                 'a Label FileId(0) 29..32 29..31
1203
1204                 FileId(0) 80..82
1205                 FileId(0) 108..110
1206             "#]],
1207         );
1208     }
1209
1210     #[test]
1211     fn test_find_const_param() {
1212         check(
1213             r#"
1214 fn foo<const FOO$0: usize>() -> usize {
1215     FOO
1216 }
1217 "#,
1218             expect![[r#"
1219                 FOO ConstParam FileId(0) 7..23 13..16
1220
1221                 FileId(0) 42..45
1222             "#]],
1223         );
1224     }
1225
1226     #[test]
1227     fn test_trait() {
1228         check(
1229             r#"
1230 trait Foo$0 where Self: {}
1231
1232 impl Foo for () {}
1233 "#,
1234             expect![[r#"
1235                 Foo Trait FileId(0) 0..24 6..9
1236
1237                 FileId(0) 31..34
1238             "#]],
1239         );
1240     }
1241
1242     #[test]
1243     fn test_trait_self() {
1244         check(
1245             r#"
1246 trait Foo where Self$0 {
1247     fn f() -> Self;
1248 }
1249
1250 impl Foo for () {}
1251 "#,
1252             expect![[r#"
1253                 Self TypeParam FileId(0) 6..9 6..9
1254
1255                 FileId(0) 16..20
1256                 FileId(0) 37..41
1257             "#]],
1258         );
1259     }
1260
1261     #[test]
1262     fn test_self_ty() {
1263         check(
1264             r#"
1265         struct $0Foo;
1266
1267         impl Foo where Self: {
1268             fn f() -> Self;
1269         }
1270         "#,
1271             expect![[r#"
1272                 Foo Struct FileId(0) 0..11 7..10
1273
1274                 FileId(0) 18..21
1275                 FileId(0) 28..32
1276                 FileId(0) 50..54
1277             "#]],
1278         );
1279         check(
1280             r#"
1281 struct Foo;
1282
1283 impl Foo where Self: {
1284     fn f() -> Self$0;
1285 }
1286 "#,
1287             expect![[r#"
1288                 impl Impl FileId(0) 13..57 18..21
1289
1290                 FileId(0) 18..21
1291                 FileId(0) 28..32
1292                 FileId(0) 50..54
1293             "#]],
1294         );
1295     }
1296     #[test]
1297     fn test_self_variant_with_payload() {
1298         check(
1299             r#"
1300 enum Foo { Bar() }
1301
1302 impl Foo {
1303     fn foo(self) {
1304         match self {
1305             Self::Bar$0() => (),
1306         }
1307     }
1308 }
1309
1310 "#,
1311             expect![[r#"
1312                 Bar Variant FileId(0) 11..16 11..14
1313
1314                 FileId(0) 89..92
1315             "#]],
1316         );
1317     }
1318
1319     #[test]
1320     fn test_attr_differs_from_fn_with_same_name() {
1321         check(
1322             r#"
1323 #[test]
1324 fn test$0() {
1325     test();
1326 }
1327 "#,
1328             expect![[r#"
1329                 test Function FileId(0) 0..33 11..15
1330
1331                 FileId(0) 24..28
1332             "#]],
1333         );
1334     }
1335
1336     #[test]
1337     fn test_const_in_pattern() {
1338         check(
1339             r#"
1340 const A$0: i32 = 42;
1341
1342 fn main() {
1343     match A {
1344         A => (),
1345         _ => (),
1346     }
1347     if let A = A {}
1348 }
1349 "#,
1350             expect![[r#"
1351                 A Const FileId(0) 0..18 6..7
1352
1353                 FileId(0) 42..43
1354                 FileId(0) 54..55
1355                 FileId(0) 97..98
1356                 FileId(0) 101..102
1357             "#]],
1358         );
1359     }
1360
1361     #[test]
1362     fn test_primitives() {
1363         check(
1364             r#"
1365 fn foo(_: bool) -> bo$0ol { true }
1366 "#,
1367             expect![[r#"
1368                 FileId(0) 10..14
1369                 FileId(0) 19..23
1370             "#]],
1371         );
1372     }
1373
1374     #[test]
1375     fn test_transitive() {
1376         check(
1377             r#"
1378 //- /level3.rs new_source_root:local crate:level3
1379 pub struct Fo$0o;
1380 //- /level2.rs new_source_root:local crate:level2 deps:level3
1381 pub use level3::Foo;
1382 //- /level1.rs new_source_root:local crate:level1 deps:level2
1383 pub use level2::Foo;
1384 //- /level0.rs new_source_root:local crate:level0 deps:level1
1385 pub use level1::Foo;
1386 "#,
1387             expect![[r#"
1388                 Foo Struct FileId(0) 0..15 11..14
1389
1390                 FileId(1) 16..19
1391                 FileId(2) 16..19
1392                 FileId(3) 16..19
1393             "#]],
1394         );
1395     }
1396
1397     #[test]
1398     fn test_decl_macro_references() {
1399         check(
1400             r#"
1401 //- /lib.rs crate:lib
1402 #[macro_use]
1403 mod qux;
1404 mod bar;
1405
1406 pub use self::foo;
1407 //- /qux.rs
1408 #[macro_export]
1409 macro_rules! foo$0 {
1410     () => {struct Foo;};
1411 }
1412 //- /bar.rs
1413 foo!();
1414 //- /other.rs crate:other deps:lib new_source_root:local
1415 lib::foo!();
1416 "#,
1417             expect![[r#"
1418                 foo Macro FileId(1) 0..61 29..32
1419
1420                 FileId(0) 46..49
1421                 FileId(2) 0..3
1422                 FileId(3) 5..8
1423             "#]],
1424         );
1425     }
1426
1427     #[test]
1428     fn macro_doesnt_reference_attribute_on_call() {
1429         check(
1430             r#"
1431 macro_rules! m {
1432     () => {};
1433 }
1434
1435 #[proc_macro_test::attr_noop]
1436 m$0!();
1437
1438 "#,
1439             expect![[r#"
1440                 m Macro FileId(0) 0..32 13..14
1441
1442                 FileId(0) 64..65
1443             "#]],
1444         );
1445     }
1446 }