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