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