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