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