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 nohash_hasher::IntMap;
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: IntMap<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[]
find_all_refs( sema: &Semantics<'_, RootDatabase>, position: FilePosition, search_scope: Option<SearchScope>, ) -> Option<Vec<ReferenceSearchResult>>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
find_defs<'a>( sema: &'a Semantics<'_, RootDatabase>, syntax: &SyntaxNode, offset: TextSize, ) -> Option<impl Iterator<Item = Definition> + 'a>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
decl_mutability(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> bool165 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
retain_adt_literal_usages( usages: &mut UsageSearchResult, def: Definition, sema: &Semantics<'_, RootDatabase>, )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
name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name>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
is_enum_lit_name_ref( sema: &Semantics<'_, RootDatabase>, enum_: hir::Enum, name_ref: &ast::NameRef, ) -> bool247 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
path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool274 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
is_lit_name_ref(name_ref: &ast::NameRef) -> bool280 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]
test_struct_literal_after_space()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]
test_struct_literal_before_space()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]
test_struct_literal_with_generic_type()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]
test_struct_literal_for_tuple()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]
test_struct_literal_for_union()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]
test_enum_after_space()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]
test_variant_record_after_space()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]
test_variant_tuple_before_paren()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]
test_enum_before_space()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]
test_enum_with_generic_type()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]
test_enum_for_tuple()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]
test_find_all_refs_for_local()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]
search_filters_by_range()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]
test_find_all_refs_for_param_inside()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]
test_find_all_refs_for_fn_param()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]
test_find_all_refs_field_name()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]
test_find_all_refs_impl_item_name()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]
test_find_all_refs_enum_var_name()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]
test_find_all_refs_enum_var_field()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]
test_find_all_refs_two_modules()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 foo
719
720 FileId(0) 53..56
721 FileId(2) 79..82
722 "#]],
723 );
724 }
725
726 #[test]
test_find_all_refs_decl_module()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]
test_find_all_refs_decl_module_on_self()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]
test_find_all_refs_decl_module_on_self_crate_root()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]
test_find_all_refs_super_mod_vis()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 some
807
808 FileId(1) 20..23 Import
809 FileId(1) 47..50
810 "#]],
811 );
812 }
813
814 #[test]
test_find_all_refs_with_scope()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]
test_find_all_refs_macro_def()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]
test_basic_highlight_read_write()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]
test_basic_highlight_field_read_write()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]
test_basic_highlight_decl_no_write()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]
test_find_struct_function_refs_outside_module()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]
test_find_all_refs_nested_module()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]
test_find_all_refs_struct_pat()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]
test_find_all_refs_enum_var_pat()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]
test_find_all_refs_enum_var_privacy()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]
test_find_self_refs()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]
test_find_self_refs_decl()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
check(ra_fixture: &str, expect: Expect)1093 fn check(ra_fixture: &str, expect: Expect) {
1094 check_with_scope(ra_fixture, None, expect)
1095 }
1096
check_with_scope(ra_fixture: &str, search_scope: Option<SearchScope>, expect: Expect)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]
test_find_lifetimes_function()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]
test_find_lifetimes_type_alias()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]
test_find_lifetimes_trait_impl()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]
test_map_range_to_original()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]
test_map_range_to_original_ref()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]
test_find_labels()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]
test_find_const_param()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]
test_trait()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]
test_trait_self()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) 0..44 6..9
1293
1294 FileId(0) 16..20
1295 FileId(0) 37..41
1296 "#]],
1297 );
1298 }
1299
1300 #[test]
test_self_ty()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]
test_self_variant_with_payload()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]
test_trait_alias()1359 fn test_trait_alias() {
1360 check(
1361 r#"
1362 trait Foo {}
1363 trait Bar$0 = Foo where Self: ;
1364 fn foo<T: Bar>(_: impl Bar, _: &dyn Bar) {}
1365 "#,
1366 expect![[r#"
1367 Bar TraitAlias FileId(0) 13..42 19..22
1368
1369 FileId(0) 53..56
1370 FileId(0) 66..69
1371 FileId(0) 79..82
1372 "#]],
1373 );
1374 }
1375
1376 #[test]
test_trait_alias_self()1377 fn test_trait_alias_self() {
1378 check(
1379 r#"
1380 trait Foo = where Self$0: ;
1381 "#,
1382 expect![[r#"
1383 Self TypeParam FileId(0) 0..25 6..9
1384
1385 FileId(0) 18..22
1386 "#]],
1387 );
1388 }
1389
1390 #[test]
test_attr_differs_from_fn_with_same_name()1391 fn test_attr_differs_from_fn_with_same_name() {
1392 check(
1393 r#"
1394 #[test]
1395 fn test$0() {
1396 test();
1397 }
1398 "#,
1399 expect![[r#"
1400 test Function FileId(0) 0..33 11..15
1401
1402 FileId(0) 24..28
1403 "#]],
1404 );
1405 }
1406
1407 #[test]
test_const_in_pattern()1408 fn test_const_in_pattern() {
1409 check(
1410 r#"
1411 const A$0: i32 = 42;
1412
1413 fn main() {
1414 match A {
1415 A => (),
1416 _ => (),
1417 }
1418 if let A = A {}
1419 }
1420 "#,
1421 expect![[r#"
1422 A Const FileId(0) 0..18 6..7
1423
1424 FileId(0) 42..43
1425 FileId(0) 54..55
1426 FileId(0) 97..98
1427 FileId(0) 101..102
1428 "#]],
1429 );
1430 }
1431
1432 #[test]
test_primitives()1433 fn test_primitives() {
1434 check(
1435 r#"
1436 fn foo(_: bool) -> bo$0ol { true }
1437 "#,
1438 expect![[r#"
1439 FileId(0) 10..14
1440 FileId(0) 19..23
1441 "#]],
1442 );
1443 }
1444
1445 #[test]
test_transitive()1446 fn test_transitive() {
1447 check(
1448 r#"
1449 //- /level3.rs new_source_root:local crate:level3
1450 pub struct Fo$0o;
1451 //- /level2.rs new_source_root:local crate:level2 deps:level3
1452 pub use level3::Foo;
1453 //- /level1.rs new_source_root:local crate:level1 deps:level2
1454 pub use level2::Foo;
1455 //- /level0.rs new_source_root:local crate:level0 deps:level1
1456 pub use level1::Foo;
1457 "#,
1458 expect![[r#"
1459 Foo Struct FileId(0) 0..15 11..14
1460
1461 FileId(1) 16..19 Import
1462 FileId(2) 16..19 Import
1463 FileId(3) 16..19 Import
1464 "#]],
1465 );
1466 }
1467
1468 #[test]
test_decl_macro_references()1469 fn test_decl_macro_references() {
1470 check(
1471 r#"
1472 //- /lib.rs crate:lib
1473 #[macro_use]
1474 mod qux;
1475 mod bar;
1476
1477 pub use self::foo;
1478 //- /qux.rs
1479 #[macro_export]
1480 macro_rules! foo$0 {
1481 () => {struct Foo;};
1482 }
1483 //- /bar.rs
1484 foo!();
1485 //- /other.rs crate:other deps:lib new_source_root:local
1486 lib::foo!();
1487 "#,
1488 expect![[r#"
1489 foo Macro FileId(1) 0..61 29..32
1490
1491 FileId(0) 46..49 Import
1492 FileId(2) 0..3
1493 FileId(3) 5..8
1494 "#]],
1495 );
1496 }
1497
1498 #[test]
macro_doesnt_reference_attribute_on_call()1499 fn macro_doesnt_reference_attribute_on_call() {
1500 check(
1501 r#"
1502 macro_rules! m {
1503 () => {};
1504 }
1505
1506 #[proc_macro_test::attr_noop]
1507 m$0!();
1508
1509 "#,
1510 expect![[r#"
1511 m Macro FileId(0) 0..32 13..14
1512
1513 FileId(0) 64..65
1514 "#]],
1515 );
1516 }
1517
1518 #[test]
multi_def()1519 fn multi_def() {
1520 check(
1521 r#"
1522 macro_rules! m {
1523 ($name:ident) => {
1524 mod module {
1525 pub fn $name() {}
1526 }
1527
1528 pub fn $name() {}
1529 }
1530 }
1531
1532 m!(func$0);
1533
1534 fn f() {
1535 func();
1536 module::func();
1537 }
1538 "#,
1539 expect![[r#"
1540 func Function FileId(0) 137..146 140..144
1541
1542 FileId(0) 161..165
1543
1544
1545 func Function FileId(0) 137..146 140..144 module
1546
1547 FileId(0) 181..185
1548 "#]],
1549 )
1550 }
1551
1552 #[test]
attr_expanded()1553 fn attr_expanded() {
1554 check(
1555 r#"
1556 //- proc_macros: identity
1557 #[proc_macros::identity]
1558 fn func$0() {
1559 func();
1560 }
1561 "#,
1562 expect![[r#"
1563 func Function FileId(0) 25..50 28..32
1564
1565 FileId(0) 41..45
1566 "#]],
1567 )
1568 }
1569
1570 #[test]
attr_assoc_item()1571 fn attr_assoc_item() {
1572 check(
1573 r#"
1574 //- proc_macros: identity
1575
1576 trait Trait {
1577 #[proc_macros::identity]
1578 fn func() {
1579 Self::func$0();
1580 }
1581 }
1582 "#,
1583 expect![[r#"
1584 func Function FileId(0) 48..87 51..55 Trait
1585
1586 FileId(0) 74..78
1587 "#]],
1588 )
1589 }
1590
1591 // FIXME: import is classified as function
1592 #[test]
attr()1593 fn attr() {
1594 check(
1595 r#"
1596 //- proc_macros: identity
1597 use proc_macros::identity;
1598
1599 #[proc_macros::$0identity]
1600 fn func() {}
1601 "#,
1602 expect![[r#"
1603 identity Attribute FileId(1) 1..107 32..40
1604
1605 FileId(0) 43..51
1606 "#]],
1607 );
1608 check(
1609 r#"
1610 #![crate_type="proc-macro"]
1611 #[proc_macro_attribute]
1612 fn func$0() {}
1613 "#,
1614 expect![[r#"
1615 func Attribute FileId(0) 28..64 55..59
1616
1617 (no references)
1618 "#]],
1619 );
1620 }
1621
1622 // FIXME: import is classified as function
1623 #[test]
proc_macro()1624 fn proc_macro() {
1625 check(
1626 r#"
1627 //- proc_macros: mirror
1628 use proc_macros::mirror;
1629
1630 mirror$0! {}
1631 "#,
1632 expect![[r#"
1633 mirror Macro FileId(1) 1..77 22..28
1634
1635 FileId(0) 26..32
1636 "#]],
1637 )
1638 }
1639
1640 #[test]
derive()1641 fn derive() {
1642 check(
1643 r#"
1644 //- proc_macros: derive_identity
1645 //- minicore: derive
1646 use proc_macros::DeriveIdentity;
1647
1648 #[derive(proc_macros::DeriveIdentity$0)]
1649 struct Foo;
1650 "#,
1651 expect![[r#"
1652 derive_identity Derive FileId(2) 1..107 45..60
1653
1654 FileId(0) 17..31 Import
1655 FileId(0) 56..70
1656 "#]],
1657 );
1658 check(
1659 r#"
1660 #![crate_type="proc-macro"]
1661 #[proc_macro_derive(Derive, attributes(x))]
1662 pub fn deri$0ve(_stream: TokenStream) -> TokenStream {}
1663 "#,
1664 expect![[r#"
1665 derive Derive FileId(0) 28..125 79..85
1666
1667 (no references)
1668 "#]],
1669 );
1670 }
1671
1672 #[test]
assoc_items_trait_def()1673 fn assoc_items_trait_def() {
1674 check(
1675 r#"
1676 trait Trait {
1677 const CONST$0: usize;
1678 }
1679
1680 impl Trait for () {
1681 const CONST: usize = 0;
1682 }
1683
1684 impl Trait for ((),) {
1685 const CONST: usize = 0;
1686 }
1687
1688 fn f<T: Trait>() {
1689 let _ = <()>::CONST;
1690
1691 let _ = T::CONST;
1692 }
1693 "#,
1694 expect![[r#"
1695 CONST Const FileId(0) 18..37 24..29 Trait
1696
1697 FileId(0) 71..76
1698 FileId(0) 125..130
1699 FileId(0) 183..188
1700 FileId(0) 206..211
1701 "#]],
1702 );
1703 check(
1704 r#"
1705 trait Trait {
1706 type TypeAlias$0;
1707 }
1708
1709 impl Trait for () {
1710 type TypeAlias = ();
1711 }
1712
1713 impl Trait for ((),) {
1714 type TypeAlias = ();
1715 }
1716
1717 fn f<T: Trait>() {
1718 let _: <() as Trait>::TypeAlias;
1719
1720 let _: T::TypeAlias;
1721 }
1722 "#,
1723 expect![[r#"
1724 TypeAlias TypeAlias FileId(0) 18..33 23..32 Trait
1725
1726 FileId(0) 66..75
1727 FileId(0) 117..126
1728 FileId(0) 181..190
1729 FileId(0) 207..216
1730 "#]],
1731 );
1732 check(
1733 r#"
1734 trait Trait {
1735 fn function$0() {}
1736 }
1737
1738 impl Trait for () {
1739 fn function() {}
1740 }
1741
1742 impl Trait for ((),) {
1743 fn function() {}
1744 }
1745
1746 fn f<T: Trait>() {
1747 let _ = <()>::function;
1748
1749 let _ = T::function;
1750 }
1751 "#,
1752 expect![[r#"
1753 function Function FileId(0) 18..34 21..29 Trait
1754
1755 FileId(0) 65..73
1756 FileId(0) 112..120
1757 FileId(0) 166..174
1758 FileId(0) 192..200
1759 "#]],
1760 );
1761 }
1762
1763 #[test]
assoc_items_trait_impl_def()1764 fn assoc_items_trait_impl_def() {
1765 check(
1766 r#"
1767 trait Trait {
1768 const CONST: usize;
1769 }
1770
1771 impl Trait for () {
1772 const CONST$0: usize = 0;
1773 }
1774
1775 impl Trait for ((),) {
1776 const CONST: usize = 0;
1777 }
1778
1779 fn f<T: Trait>() {
1780 let _ = <()>::CONST;
1781
1782 let _ = T::CONST;
1783 }
1784 "#,
1785 expect![[r#"
1786 CONST Const FileId(0) 65..88 71..76
1787
1788 FileId(0) 183..188
1789 "#]],
1790 );
1791 check(
1792 r#"
1793 trait Trait {
1794 type TypeAlias;
1795 }
1796
1797 impl Trait for () {
1798 type TypeAlias$0 = ();
1799 }
1800
1801 impl Trait for ((),) {
1802 type TypeAlias = ();
1803 }
1804
1805 fn f<T: Trait>() {
1806 let _: <() as Trait>::TypeAlias;
1807
1808 let _: T::TypeAlias;
1809 }
1810 "#,
1811 expect![[r#"
1812 TypeAlias TypeAlias FileId(0) 61..81 66..75
1813
1814 FileId(0) 23..32
1815 FileId(0) 117..126
1816 FileId(0) 181..190
1817 FileId(0) 207..216
1818 "#]],
1819 );
1820 check(
1821 r#"
1822 trait Trait {
1823 fn function() {}
1824 }
1825
1826 impl Trait for () {
1827 fn function$0() {}
1828 }
1829
1830 impl Trait for ((),) {
1831 fn function() {}
1832 }
1833
1834 fn f<T: Trait>() {
1835 let _ = <()>::function;
1836
1837 let _ = T::function;
1838 }
1839 "#,
1840 expect![[r#"
1841 function Function FileId(0) 62..78 65..73
1842
1843 FileId(0) 166..174
1844 "#]],
1845 );
1846 }
1847
1848 #[test]
assoc_items_ref()1849 fn assoc_items_ref() {
1850 check(
1851 r#"
1852 trait Trait {
1853 const CONST: usize;
1854 }
1855
1856 impl Trait for () {
1857 const CONST: usize = 0;
1858 }
1859
1860 impl Trait for ((),) {
1861 const CONST: usize = 0;
1862 }
1863
1864 fn f<T: Trait>() {
1865 let _ = <()>::CONST$0;
1866
1867 let _ = T::CONST;
1868 }
1869 "#,
1870 expect![[r#"
1871 CONST Const FileId(0) 65..88 71..76
1872
1873 FileId(0) 183..188
1874 "#]],
1875 );
1876 check(
1877 r#"
1878 trait Trait {
1879 type TypeAlias;
1880 }
1881
1882 impl Trait for () {
1883 type TypeAlias = ();
1884 }
1885
1886 impl Trait for ((),) {
1887 type TypeAlias = ();
1888 }
1889
1890 fn f<T: Trait>() {
1891 let _: <() as Trait>::TypeAlias$0;
1892
1893 let _: T::TypeAlias;
1894 }
1895 "#,
1896 expect![[r#"
1897 TypeAlias TypeAlias FileId(0) 18..33 23..32 Trait
1898
1899 FileId(0) 66..75
1900 FileId(0) 117..126
1901 FileId(0) 181..190
1902 FileId(0) 207..216
1903 "#]],
1904 );
1905 check(
1906 r#"
1907 trait Trait {
1908 fn function() {}
1909 }
1910
1911 impl Trait for () {
1912 fn function() {}
1913 }
1914
1915 impl Trait for ((),) {
1916 fn function() {}
1917 }
1918
1919 fn f<T: Trait>() {
1920 let _ = <()>::function$0;
1921
1922 let _ = T::function;
1923 }
1924 "#,
1925 expect![[r#"
1926 function Function FileId(0) 62..78 65..73
1927
1928 FileId(0) 166..174
1929 "#]],
1930 );
1931 }
1932
1933 #[test]
name_clashes()1934 fn name_clashes() {
1935 check(
1936 r#"
1937 trait Foo {
1938 fn method$0(&self) -> u8;
1939 }
1940
1941 struct Bar {
1942 method: u8,
1943 }
1944
1945 impl Foo for Bar {
1946 fn method(&self) -> u8 {
1947 self.method
1948 }
1949 }
1950 fn method() {}
1951 "#,
1952 expect![[r#"
1953 method Function FileId(0) 16..39 19..25 Foo
1954
1955 FileId(0) 101..107
1956 "#]],
1957 );
1958 check(
1959 r#"
1960 trait Foo {
1961 fn method(&self) -> u8;
1962 }
1963
1964 struct Bar {
1965 method$0: u8,
1966 }
1967
1968 impl Foo for Bar {
1969 fn method(&self) -> u8 {
1970 self.method
1971 }
1972 }
1973 fn method() {}
1974 "#,
1975 expect![[r#"
1976 method Field FileId(0) 60..70 60..66
1977
1978 FileId(0) 136..142 Read
1979 "#]],
1980 );
1981 check(
1982 r#"
1983 trait Foo {
1984 fn method(&self) -> u8;
1985 }
1986
1987 struct Bar {
1988 method: u8,
1989 }
1990
1991 impl Foo for Bar {
1992 fn method$0(&self) -> u8 {
1993 self.method
1994 }
1995 }
1996 fn method() {}
1997 "#,
1998 expect![[r#"
1999 method Function FileId(0) 98..148 101..107
2000
2001 (no references)
2002 "#]],
2003 );
2004 check(
2005 r#"
2006 trait Foo {
2007 fn method(&self) -> u8;
2008 }
2009
2010 struct Bar {
2011 method: u8,
2012 }
2013
2014 impl Foo for Bar {
2015 fn method(&self) -> u8 {
2016 self.method$0
2017 }
2018 }
2019 fn method() {}
2020 "#,
2021 expect![[r#"
2022 method Field FileId(0) 60..70 60..66
2023
2024 FileId(0) 136..142 Read
2025 "#]],
2026 );
2027 check(
2028 r#"
2029 trait Foo {
2030 fn method(&self) -> u8;
2031 }
2032
2033 struct Bar {
2034 method: u8,
2035 }
2036
2037 impl Foo for Bar {
2038 fn method(&self) -> u8 {
2039 self.method
2040 }
2041 }
2042 fn method$0() {}
2043 "#,
2044 expect![[r#"
2045 method Function FileId(0) 151..165 154..160
2046
2047 (no references)
2048 "#]],
2049 );
2050 }
2051
2052 #[test]
raw_identifier()2053 fn raw_identifier() {
2054 check(
2055 r#"
2056 fn r#fn$0() {}
2057 fn main() { r#fn(); }
2058 "#,
2059 expect![[r#"
2060 r#fn Function FileId(0) 0..12 3..7
2061
2062 FileId(0) 25..29
2063 "#]],
2064 );
2065 }
2066 }
2067