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