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