]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/references.rs
Merge #7941
[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 pub(crate) mod rename;
13
14 use hir::{PathResolution, Semantics};
15 use ide_db::{
16     base_db::FileId,
17     defs::{Definition, NameClass, NameRefClass},
18     search::{ReferenceAccess, SearchScope},
19     RootDatabase,
20 };
21 use rustc_hash::FxHashMap;
22 use syntax::{
23     algo::find_node_at_offset,
24     ast::{self, NameOwner},
25     match_ast, AstNode, SyntaxNode, TextRange, T,
26 };
27
28 use crate::{display::TryToNav, FilePosition, NavigationTarget};
29
30 #[derive(Debug, Clone)]
31 pub struct ReferenceSearchResult {
32     pub declaration: Declaration,
33     pub references: FxHashMap<FileId, Vec<(TextRange, Option<ReferenceAccess>)>>,
34 }
35
36 #[derive(Debug, Clone)]
37 pub struct Declaration {
38     pub nav: NavigationTarget,
39     pub access: Option<ReferenceAccess>,
40 }
41
42 // Feature: Find All References
43 //
44 // Shows all references of the item at the cursor location
45 //
46 // |===
47 // | Editor  | Shortcut
48 //
49 // | VS Code | kbd:[Shift+Alt+F12]
50 // |===
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).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(_))
83             | Definition::ModuleDef(hir::ModuleDef::Variant(_)) => {
84                 refs.for_each(|it| {
85                     it.retain(|reference| {
86                         reference.name.as_name_ref().map_or(false, is_lit_name_ref)
87                     })
88                 });
89                 usages.references.retain(|_, it| !it.is_empty());
90             }
91             _ => {}
92         }
93     }
94     let nav = def.try_to_nav(sema.db)?;
95     let decl_range = nav.focus_or_full_range();
96
97     let declaration = Declaration { nav, access: decl_access(&def, &syntax, decl_range) };
98     let references = usages
99         .into_iter()
100         .map(|(file_id, refs)| {
101             (file_id, refs.into_iter().map(|file_ref| (file_ref.range, file_ref.access)).collect())
102         })
103         .collect();
104
105     Some(ReferenceSearchResult { declaration, references })
106 }
107
108 fn find_def(
109     sema: &Semantics<RootDatabase>,
110     syntax: &SyntaxNode,
111     position: FilePosition,
112 ) -> Option<Definition> {
113     let def = match sema.find_node_at_offset_with_descend(syntax, position.offset)? {
114         ast::NameLike::NameRef(name_ref) => {
115             NameRefClass::classify(sema, &name_ref)?.referenced(sema.db)
116         }
117         ast::NameLike::Name(name) => {
118             NameClass::classify(sema, &name)?.referenced_or_defined(sema.db)
119         }
120         ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
121             .map(|class| class.referenced(sema.db))
122             .or_else(|| {
123                 NameClass::classify_lifetime(sema, &lifetime)
124                     .map(|class| class.referenced_or_defined(sema.db))
125             })?,
126     };
127     Some(def)
128 }
129
130 fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Option<ReferenceAccess> {
131     match def {
132         Definition::Local(_) | Definition::Field(_) => {}
133         _ => return None,
134     };
135
136     let stmt = find_node_at_offset::<ast::LetStmt>(syntax, range.start())?;
137     if stmt.initializer().is_some() {
138         let pat = stmt.pat()?;
139         if let ast::Pat::IdentPat(it) = pat {
140             if it.mut_token().is_some() {
141                 return Some(ReferenceAccess::Write);
142             }
143         }
144     }
145
146     None
147 }
148
149 fn get_name_of_item_declaration(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {
150     let token = syntax.token_at_offset(position.offset).right_biased()?;
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         {
1008             let decl = refs.declaration;
1009             format_to!(actual, "{}", decl.nav.debug_render());
1010             if let Some(access) = decl.access {
1011                 format_to!(actual, " {:?}", access)
1012             }
1013             actual += "\n\n";
1014         }
1015
1016         for (file_id, references) in refs.references {
1017             for (range, access) in references {
1018                 format_to!(actual, "{:?} {:?}", file_id, range);
1019                 if let Some(access) = access {
1020                     format_to!(actual, " {:?}", access);
1021                 }
1022                 actual += "\n";
1023             }
1024         }
1025         expect.assert_eq(&actual)
1026     }
1027
1028     #[test]
1029     fn test_find_lifetimes_function() {
1030         check(
1031             r#"
1032 trait Foo<'a> {}
1033 impl<'a> Foo<'a> for &'a () {}
1034 fn foo<'a, 'b: 'a>(x: &'a$0 ()) -> &'a () where &'a (): Foo<'a> {
1035     fn bar<'a>(_: &'a ()) {}
1036     x
1037 }
1038 "#,
1039             expect![[r#"
1040                 'a LifetimeParam FileId(0) 55..57 55..57
1041
1042                 FileId(0) 63..65
1043                 FileId(0) 71..73
1044                 FileId(0) 82..84
1045                 FileId(0) 95..97
1046                 FileId(0) 106..108
1047             "#]],
1048         );
1049     }
1050
1051     #[test]
1052     fn test_find_lifetimes_type_alias() {
1053         check(
1054             r#"
1055 type Foo<'a, T> where T: 'a$0 = &'a T;
1056 "#,
1057             expect![[r#"
1058                 'a LifetimeParam FileId(0) 9..11 9..11
1059
1060                 FileId(0) 25..27
1061                 FileId(0) 31..33
1062             "#]],
1063         );
1064     }
1065
1066     #[test]
1067     fn test_find_lifetimes_trait_impl() {
1068         check(
1069             r#"
1070 trait Foo<'a> {
1071     fn foo() -> &'a ();
1072 }
1073 impl<'a> Foo<'a> for &'a () {
1074     fn foo() -> &'a$0 () {
1075         unimplemented!()
1076     }
1077 }
1078 "#,
1079             expect![[r#"
1080                 'a LifetimeParam FileId(0) 47..49 47..49
1081
1082                 FileId(0) 55..57
1083                 FileId(0) 64..66
1084                 FileId(0) 89..91
1085             "#]],
1086         );
1087     }
1088
1089     #[test]
1090     fn test_map_range_to_original() {
1091         check(
1092             r#"
1093 macro_rules! foo {($i:ident) => {$i} }
1094 fn main() {
1095     let a$0 = "test";
1096     foo!(a);
1097 }
1098 "#,
1099             expect![[r#"
1100                 a Local FileId(0) 59..60 59..60
1101
1102                 FileId(0) 80..81 Read
1103             "#]],
1104         );
1105     }
1106
1107     #[test]
1108     fn test_map_range_to_original_ref() {
1109         check(
1110             r#"
1111 macro_rules! foo {($i:ident) => {$i} }
1112 fn main() {
1113     let a = "test";
1114     foo!(a$0);
1115 }
1116 "#,
1117             expect![[r#"
1118                 a Local FileId(0) 59..60 59..60
1119
1120                 FileId(0) 80..81 Read
1121             "#]],
1122         );
1123     }
1124
1125     #[test]
1126     fn test_find_labels() {
1127         check(
1128             r#"
1129 fn foo<'a>() -> &'a () {
1130     'a: loop {
1131         'b: loop {
1132             continue 'a$0;
1133         }
1134         break 'a;
1135     }
1136 }
1137 "#,
1138             expect![[r#"
1139                 'a Label FileId(0) 29..32 29..31
1140
1141                 FileId(0) 80..82
1142                 FileId(0) 108..110
1143             "#]],
1144         );
1145     }
1146
1147     #[test]
1148     fn test_find_const_param() {
1149         check(
1150             r#"
1151 fn foo<const FOO$0: usize>() -> usize {
1152     FOO
1153 }
1154 "#,
1155             expect![[r#"
1156                 FOO ConstParam FileId(0) 7..23 13..16
1157
1158                 FileId(0) 42..45
1159             "#]],
1160         );
1161     }
1162
1163     #[test]
1164     fn test_find_self_ty_in_trait_def() {
1165         check(
1166             r#"
1167 trait Foo {
1168     fn f() -> Self$0;
1169 }
1170 "#,
1171             expect![[r#"
1172                 Self TypeParam FileId(0) 6..9 6..9
1173
1174                 FileId(0) 26..30
1175             "#]],
1176         );
1177     }
1178
1179     #[test]
1180     fn test_self_variant_with_payload() {
1181         check(
1182             r#"
1183 enum Foo { Bar() }
1184
1185 impl Foo {
1186     fn foo(self) {
1187         match self {
1188             Self::Bar$0() => (),
1189         }
1190     }
1191 }
1192
1193 "#,
1194             expect![[r#"
1195                 Bar Variant FileId(0) 11..16 11..14
1196
1197                 FileId(0) 89..92
1198             "#]],
1199         );
1200     }
1201
1202     #[test]
1203     fn test_attr_differs_from_fn_with_same_name() {
1204         check(
1205             r#"
1206 #[test]
1207 fn test$0() {
1208     test();
1209 }
1210 "#,
1211             expect![[r#"
1212                 test Function FileId(0) 0..33 11..15
1213
1214                 FileId(0) 24..28
1215             "#]],
1216         );
1217     }
1218
1219     #[test]
1220     fn test_attr_matches_proc_macro_fn() {
1221         check(
1222             r#"
1223 #[proc_macro_attribute]
1224 fn my_proc_macro() {}
1225
1226 #[my_proc_macro$0]
1227 fn test() {}
1228 "#,
1229             expect![[r#"
1230                 my_proc_macro Function FileId(0) 0..45 27..40
1231
1232                 FileId(0) 49..62
1233             "#]],
1234         );
1235     }
1236
1237     #[test]
1238     fn test_const_in_pattern() {
1239         check(
1240             r#"
1241 const A$0: i32 = 42;
1242
1243 fn main() {
1244     match A {
1245         A => (),
1246         _ => (),
1247     }
1248     if let A = A {}
1249 }
1250 "#,
1251             expect![[r#"
1252                 A Const FileId(0) 0..18 6..7
1253
1254                 FileId(0) 42..43
1255                 FileId(0) 54..55
1256                 FileId(0) 97..98
1257                 FileId(0) 101..102
1258             "#]],
1259         );
1260     }
1261 }