aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/references.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/references.rs')
-rw-r--r--crates/ide/src/references.rs288
1 files changed, 121 insertions, 167 deletions
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index fa58fc319..df9c31aef 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -3,7 +3,7 @@
3//! or `ast::NameRef`. If it's a `ast::NameRef`, at the classification step we 3//! or `ast::NameRef`. If it's a `ast::NameRef`, at the classification step we
4//! try to resolve the direct tree parent of this element, otherwise 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 5//! already have a definition and just need to get its HIR together with
6//! some information that is needed for futher steps of searching. 6//! some information that is needed for further steps of searching.
7//! After that, we collect files that might contain references and look 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` 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 9//! at the index that the match starts at and its tree parent is
@@ -11,25 +11,26 @@
11 11
12pub(crate) mod rename; 12pub(crate) mod rename;
13 13
14use either::Either;
14use hir::Semantics; 15use hir::Semantics;
15use ide_db::{ 16use ide_db::{
17 base_db::FileId,
16 defs::{Definition, NameClass, NameRefClass}, 18 defs::{Definition, NameClass, NameRefClass},
17 search::Reference, 19 search::{FileReference, ReferenceAccess, ReferenceKind, SearchScope, UsageSearchResult},
18 search::{ReferenceAccess, ReferenceKind, SearchScope},
19 RootDatabase, 20 RootDatabase,
20}; 21};
21use syntax::{ 22use syntax::{
22 algo::find_node_at_offset, 23 algo::find_node_at_offset,
23 ast::{self, NameOwner}, 24 ast::{self, NameOwner},
24 match_ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TokenAtOffset, 25 AstNode, SyntaxNode, TextRange, TokenAtOffset, T,
25}; 26};
26 27
27use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind}; 28use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
28 29
29#[derive(Debug, Clone)] 30#[derive(Debug, Clone)]
30pub struct ReferenceSearchResult { 31pub struct ReferenceSearchResult {
31 declaration: Declaration, 32 declaration: Declaration,
32 references: Vec<Reference>, 33 references: UsageSearchResult,
33} 34}
34 35
35#[derive(Debug, Clone)] 36#[derive(Debug, Clone)]
@@ -48,10 +49,21 @@ impl ReferenceSearchResult {
48 &self.declaration.nav 49 &self.declaration.nav
49 } 50 }
50 51
51 pub fn references(&self) -> &[Reference] { 52 pub fn references(&self) -> &UsageSearchResult {
52 &self.references 53 &self.references
53 } 54 }
54 55
56 pub fn references_with_declaration(mut self) -> UsageSearchResult {
57 let decl_ref = FileReference {
58 range: self.declaration.nav.focus_or_full_range(),
59 kind: self.declaration.kind,
60 access: self.declaration.access,
61 };
62 let file_id = self.declaration.nav.file_id;
63 self.references.references.entry(file_id).or_default().push(decl_ref);
64 self.references
65 }
66
55 /// Total number of references 67 /// Total number of references
56 /// At least 1 since all valid references should 68 /// At least 1 since all valid references should
57 /// Have a declaration 69 /// Have a declaration
@@ -63,21 +75,11 @@ impl ReferenceSearchResult {
63// allow turning ReferenceSearchResult into an iterator 75// allow turning ReferenceSearchResult into an iterator
64// over References 76// over References
65impl IntoIterator for ReferenceSearchResult { 77impl IntoIterator for ReferenceSearchResult {
66 type Item = Reference; 78 type Item = (FileId, Vec<FileReference>);
67 type IntoIter = std::vec::IntoIter<Reference>; 79 type IntoIter = std::collections::hash_map::IntoIter<FileId, Vec<FileReference>>;
68 80
69 fn into_iter(mut self) -> Self::IntoIter { 81 fn into_iter(self) -> Self::IntoIter {
70 let mut v = Vec::with_capacity(self.len()); 82 self.references_with_declaration().into_iter()
71 v.push(Reference {
72 file_range: FileRange {
73 file_id: self.declaration.nav.file_id,
74 range: self.declaration.nav.focus_or_full_range(),
75 },
76 kind: self.declaration.kind,
77 access: self.declaration.access,
78 });
79 v.append(&mut self.references);
80 v.into_iter()
81 } 83 }
82} 84}
83 85
@@ -89,10 +91,6 @@ pub(crate) fn find_all_refs(
89 let _p = profile::span("find_all_refs"); 91 let _p = profile::span("find_all_refs");
90 let syntax = sema.parse(position.file_id).syntax().clone(); 92 let syntax = sema.parse(position.file_id).syntax().clone();
91 93
92 if let Some(res) = try_find_self_references(&syntax, position) {
93 return Some(res);
94 }
95
96 let (opt_name, search_kind) = if let Some(name) = 94 let (opt_name, search_kind) = if let Some(name) =
97 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) 95 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position)
98 { 96 {
@@ -109,34 +107,39 @@ pub(crate) fn find_all_refs(
109 107
110 let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; 108 let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?;
111 109
112 let references = def 110 let mut usages = def.usages(sema).set_scope(search_scope).all();
113 .usages(sema) 111 usages
114 .set_scope(search_scope) 112 .references
115 .all() 113 .values_mut()
116 .into_iter() 114 .for_each(|it| it.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind));
117 .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) 115 usages.references.retain(|_, it| !it.is_empty());
118 .collect();
119 116
120 let nav = def.try_to_nav(sema.db)?; 117 let nav = def.try_to_nav(sema.db)?;
121 let decl_range = nav.focus_or_full_range(); 118 let decl_range = nav.focus_or_full_range();
122 119
123 let mut kind = ReferenceKind::Other; 120 let mut kind = ReferenceKind::Other;
124 if let Definition::Local(local) = def { 121 if let Definition::Local(local) = def {
125 if let either::Either::Left(pat) = local.source(sema.db).value { 122 match local.source(sema.db).value {
126 if matches!( 123 Either::Left(pat) => {
127 pat.syntax().parent().and_then(ast::RecordPatField::cast), 124 if matches!(
128 Some(pat_field) if pat_field.name_ref().is_none() 125 pat.syntax().parent().and_then(ast::RecordPatField::cast),
129 ) { 126 Some(pat_field) if pat_field.name_ref().is_none()
130 kind = ReferenceKind::FieldShorthandForLocal; 127 ) {
128 kind = ReferenceKind::FieldShorthandForLocal;
129 }
131 } 130 }
131 Either::Right(_) => kind = ReferenceKind::SelfParam,
132 } 132 }
133 } else if matches!(def, Definition::LifetimeParam(_) | Definition::Label(_)) { 133 } else if matches!(
134 def,
135 Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_)
136 ) {
134 kind = ReferenceKind::Lifetime; 137 kind = ReferenceKind::Lifetime;
135 }; 138 };
136 139
137 let declaration = Declaration { nav, kind, access: decl_access(&def, &syntax, decl_range) }; 140 let declaration = Declaration { nav, kind, access: decl_access(&def, &syntax, decl_range) };
138 141
139 Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })) 142 Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references: usages }))
140} 143}
141 144
142fn find_name( 145fn find_name(
@@ -200,7 +203,7 @@ fn get_struct_def_name_for_struct_literal_search(
200 position: FilePosition, 203 position: FilePosition,
201) -> Option<ast::Name> { 204) -> Option<ast::Name> {
202 if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { 205 if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) {
203 if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { 206 if right.kind() != T!['{'] && right.kind() != T!['('] {
204 return None; 207 return None;
205 } 208 }
206 if let Some(name) = 209 if let Some(name) =
@@ -227,7 +230,7 @@ fn get_enum_def_name_for_struct_literal_search(
227 position: FilePosition, 230 position: FilePosition,
228) -> Option<ast::Name> { 231) -> Option<ast::Name> {
229 if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) { 232 if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) {
230 if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN { 233 if right.kind() != T!['{'] && right.kind() != T!['('] {
231 return None; 234 return None;
232 } 235 }
233 if let Some(name) = 236 if let Some(name) =
@@ -248,77 +251,6 @@ fn get_enum_def_name_for_struct_literal_search(
248 None 251 None
249} 252}
250 253
251fn try_find_self_references(
252 syntax: &SyntaxNode,
253 position: FilePosition,
254) -> Option<RangeInfo<ReferenceSearchResult>> {
255 let self_token =
256 syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW)?;
257 let parent = self_token.parent();
258 match_ast! {
259 match parent {
260 ast::SelfParam(it) => (),
261 ast::PathSegment(segment) => {
262 segment.self_token()?;
263 let path = segment.parent_path();
264 if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) {
265 return None;
266 }
267 },
268 _ => return None,
269 }
270 };
271 let function = parent.ancestors().find_map(ast::Fn::cast)?;
272 let self_param = function.param_list()?.self_param()?;
273 let param_self_token = self_param.self_token()?;
274
275 let declaration = Declaration {
276 nav: NavigationTarget {
277 file_id: position.file_id,
278 full_range: self_param.syntax().text_range(),
279 focus_range: Some(param_self_token.text_range()),
280 name: param_self_token.text().clone(),
281 kind: Some(SymbolKind::SelfParam),
282 container_name: None,
283 description: None,
284 docs: None,
285 },
286 kind: ReferenceKind::SelfKw,
287 access: Some(if self_param.mut_token().is_some() {
288 ReferenceAccess::Write
289 } else {
290 ReferenceAccess::Read
291 }),
292 };
293 let references = function
294 .body()
295 .map(|body| {
296 body.syntax()
297 .descendants()
298 .filter_map(ast::PathExpr::cast)
299 .filter_map(|expr| {
300 let path = expr.path()?;
301 if path.qualifier().is_none() {
302 path.segment()?.self_token()
303 } else {
304 None
305 }
306 })
307 .map(|token| Reference {
308 file_range: FileRange { file_id: position.file_id, range: token.text_range() },
309 kind: ReferenceKind::SelfKw,
310 access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration
311 })
312 .collect()
313 })
314 .unwrap_or_default();
315
316 Some(RangeInfo::new(
317 param_self_token.text_range(),
318 ReferenceSearchResult { declaration, references },
319 ))
320}
321
322#[cfg(test)] 254#[cfg(test)]
323mod tests { 255mod tests {
324 use expect_test::{expect, Expect}; 256 use expect_test::{expect, Expect};
@@ -331,7 +263,7 @@ mod tests {
331 fn test_struct_literal_after_space() { 263 fn test_struct_literal_after_space() {
332 check( 264 check(
333 r#" 265 r#"
334struct Foo <|>{ 266struct Foo $0{
335 a: i32, 267 a: i32,
336} 268}
337impl Foo { 269impl Foo {
@@ -354,7 +286,7 @@ fn main() {
354 fn test_struct_literal_before_space() { 286 fn test_struct_literal_before_space() {
355 check( 287 check(
356 r#" 288 r#"
357struct Foo<|> {} 289struct Foo$0 {}
358 fn main() { 290 fn main() {
359 let f: Foo; 291 let f: Foo;
360 f = Foo {}; 292 f = Foo {};
@@ -373,7 +305,7 @@ struct Foo<|> {}
373 fn test_struct_literal_with_generic_type() { 305 fn test_struct_literal_with_generic_type() {
374 check( 306 check(
375 r#" 307 r#"
376struct Foo<T> <|>{} 308struct Foo<T> $0{}
377 fn main() { 309 fn main() {
378 let f: Foo::<i32>; 310 let f: Foo::<i32>;
379 f = Foo {}; 311 f = Foo {};
@@ -391,7 +323,7 @@ struct Foo<T> <|>{}
391 fn test_struct_literal_for_tuple() { 323 fn test_struct_literal_for_tuple() {
392 check( 324 check(
393 r#" 325 r#"
394struct Foo<|>(i32); 326struct Foo$0(i32);
395 327
396fn main() { 328fn main() {
397 let f: Foo; 329 let f: Foo;
@@ -410,7 +342,7 @@ fn main() {
410 fn test_enum_after_space() { 342 fn test_enum_after_space() {
411 check( 343 check(
412 r#" 344 r#"
413enum Foo <|>{ 345enum Foo $0{
414 A, 346 A,
415 B, 347 B,
416} 348}
@@ -431,7 +363,7 @@ fn main() {
431 fn test_enum_before_space() { 363 fn test_enum_before_space() {
432 check( 364 check(
433 r#" 365 r#"
434enum Foo<|> { 366enum Foo$0 {
435 A, 367 A,
436 B, 368 B,
437} 369}
@@ -453,7 +385,7 @@ fn main() {
453 fn test_enum_with_generic_type() { 385 fn test_enum_with_generic_type() {
454 check( 386 check(
455 r#" 387 r#"
456enum Foo<T> <|>{ 388enum Foo<T> $0{
457 A(T), 389 A(T),
458 B, 390 B,
459} 391}
@@ -474,7 +406,7 @@ fn main() {
474 fn test_enum_for_tuple() { 406 fn test_enum_for_tuple() {
475 check( 407 check(
476 r#" 408 r#"
477enum Foo<|>{ 409enum Foo$0{
478 A(i8), 410 A(i8),
479 B(i8), 411 B(i8),
480} 412}
@@ -498,7 +430,7 @@ fn main() {
498fn main() { 430fn main() {
499 let mut i = 1; 431 let mut i = 1;
500 let j = 1; 432 let j = 1;
501 i = i<|> + j; 433 i = i$0 + j;
502 434
503 { 435 {
504 i = 0; 436 i = 0;
@@ -507,7 +439,7 @@ fn main() {
507 i = 5; 439 i = 5;
508}"#, 440}"#,
509 expect![[r#" 441 expect![[r#"
510 i Local FileId(0) 24..25 Other Write 442 i Local FileId(0) 20..25 24..25 Other Write
511 443
512 FileId(0) 50..51 Other Write 444 FileId(0) 50..51 Other Write
513 FileId(0) 54..55 Other Read 445 FileId(0) 54..55 Other Read
@@ -522,7 +454,7 @@ fn main() {
522 check( 454 check(
523 r#" 455 r#"
524fn foo() { 456fn foo() {
525 let spam<|> = 92; 457 let spam$0 = 92;
526 spam + spam 458 spam + spam
527} 459}
528fn bar() { 460fn bar() {
@@ -531,7 +463,7 @@ fn bar() {
531} 463}
532"#, 464"#,
533 expect![[r#" 465 expect![[r#"
534 spam Local FileId(0) 19..23 Other 466 spam Local FileId(0) 19..23 19..23 Other
535 467
536 FileId(0) 34..38 Other Read 468 FileId(0) 34..38 Other Read
537 FileId(0) 41..45 Other Read 469 FileId(0) 41..45 Other Read
@@ -543,10 +475,10 @@ fn bar() {
543 fn test_find_all_refs_for_param_inside() { 475 fn test_find_all_refs_for_param_inside() {
544 check( 476 check(
545 r#" 477 r#"
546fn foo(i : u32) -> u32 { i<|> } 478fn foo(i : u32) -> u32 { i$0 }
547"#, 479"#,
548 expect![[r#" 480 expect![[r#"
549 i ValueParam FileId(0) 7..8 Other 481 i ValueParam FileId(0) 7..8 7..8 Other
550 482
551 FileId(0) 25..26 Other Read 483 FileId(0) 25..26 Other Read
552 "#]], 484 "#]],
@@ -557,10 +489,10 @@ fn foo(i : u32) -> u32 { i<|> }
557 fn test_find_all_refs_for_fn_param() { 489 fn test_find_all_refs_for_fn_param() {
558 check( 490 check(
559 r#" 491 r#"
560fn foo(i<|> : u32) -> u32 { i } 492fn foo(i$0 : u32) -> u32 { i }
561"#, 493"#,
562 expect![[r#" 494 expect![[r#"
563 i ValueParam FileId(0) 7..8 Other 495 i ValueParam FileId(0) 7..8 7..8 Other
564 496
565 FileId(0) 25..26 Other Read 497 FileId(0) 25..26 Other Read
566 "#]], 498 "#]],
@@ -573,7 +505,7 @@ fn foo(i<|> : u32) -> u32 { i }
573 r#" 505 r#"
574//- /lib.rs 506//- /lib.rs
575struct Foo { 507struct Foo {
576 pub spam<|>: u32, 508 pub spam$0: u32,
577} 509}
578 510
579fn main(s: Foo) { 511fn main(s: Foo) {
@@ -594,7 +526,7 @@ fn main(s: Foo) {
594 r#" 526 r#"
595struct Foo; 527struct Foo;
596impl Foo { 528impl Foo {
597 fn f<|>(&self) { } 529 fn f$0(&self) { }
598} 530}
599"#, 531"#,
600 expect![[r#" 532 expect![[r#"
@@ -610,7 +542,7 @@ impl Foo {
610 r#" 542 r#"
611enum Foo { 543enum Foo {
612 A, 544 A,
613 B<|>, 545 B$0,
614 C, 546 C,
615} 547}
616"#, 548"#,
@@ -627,7 +559,7 @@ enum Foo {
627 r#" 559 r#"
628enum Foo { 560enum Foo {
629 A, 561 A,
630 B { field<|>: u8 }, 562 B { field$0: u8 },
631 C, 563 C,
632} 564}
633"#, 565"#,
@@ -669,7 +601,7 @@ pub struct Bar {
669} 601}
670 602
671fn f() { 603fn f() {
672 let i = foo::Foo<|> { n: 5 }; 604 let i = foo::Foo$0 { n: 5 };
673} 605}
674"#, 606"#,
675 expect![[r#" 607 expect![[r#"
@@ -689,7 +621,7 @@ fn f() {
689 check( 621 check(
690 r#" 622 r#"
691//- /lib.rs 623//- /lib.rs
692mod foo<|>; 624mod foo$0;
693 625
694use foo::Foo; 626use foo::Foo;
695 627
@@ -726,7 +658,7 @@ fn f() {
726} 658}
727 659
728//- /foo/some.rs 660//- /foo/some.rs
729pub(super) struct Foo<|> { 661pub(super) struct Foo$0 {
730 pub n: u32, 662 pub n: u32,
731} 663}
732"#, 664"#,
@@ -746,7 +678,7 @@ pub(super) struct Foo<|> {
746 mod foo; 678 mod foo;
747 mod bar; 679 mod bar;
748 680
749 pub fn quux<|>() {} 681 pub fn quux$0() {}
750 682
751 //- /foo.rs 683 //- /foo.rs
752 fn f() { super::quux(); } 684 fn f() { super::quux(); }
@@ -782,7 +714,7 @@ pub(super) struct Foo<|> {
782 check( 714 check(
783 r#" 715 r#"
784#[macro_export] 716#[macro_export]
785macro_rules! m1<|> { () => (()) } 717macro_rules! m1$0 { () => (()) }
786 718
787fn foo() { 719fn foo() {
788 m1(); 720 m1();
@@ -803,12 +735,12 @@ fn foo() {
803 check( 735 check(
804 r#" 736 r#"
805fn foo() { 737fn foo() {
806 let mut i<|> = 0; 738 let mut i$0 = 0;
807 i = i + 1; 739 i = i + 1;
808} 740}
809"#, 741"#,
810 expect![[r#" 742 expect![[r#"
811 i Local FileId(0) 23..24 Other Write 743 i Local FileId(0) 19..24 23..24 Other Write
812 744
813 FileId(0) 34..35 Other Write 745 FileId(0) 34..35 Other Write
814 FileId(0) 38..39 Other Read 746 FileId(0) 38..39 Other Read
@@ -826,7 +758,7 @@ struct S {
826 758
827fn foo() { 759fn foo() {
828 let mut s = S{f: 0}; 760 let mut s = S{f: 0};
829 s.f<|> = 0; 761 s.f$0 = 0;
830} 762}
831"#, 763"#,
832 expect![[r#" 764 expect![[r#"
@@ -843,12 +775,12 @@ fn foo() {
843 check( 775 check(
844 r#" 776 r#"
845fn foo() { 777fn foo() {
846 let i<|>; 778 let i$0;
847 i = 1; 779 i = 1;
848} 780}
849"#, 781"#,
850 expect![[r#" 782 expect![[r#"
851 i Local FileId(0) 19..20 Other 783 i Local FileId(0) 19..20 19..20 Other
852 784
853 FileId(0) 26..27 Other Write 785 FileId(0) 26..27 Other Write
854 "#]], 786 "#]],
@@ -863,7 +795,7 @@ mod foo {
863 pub struct Foo; 795 pub struct Foo;
864 796
865 impl Foo { 797 impl Foo {
866 pub fn new<|>() -> Foo { Foo } 798 pub fn new$0() -> Foo { Foo }
867 } 799 }
868} 800}
869 801
@@ -886,7 +818,7 @@ fn main() {
886//- /lib.rs 818//- /lib.rs
887mod foo { mod bar; } 819mod foo { mod bar; }
888 820
889fn f<|>() {} 821fn f$0() {}
890 822
891//- /foo/bar.rs 823//- /foo/bar.rs
892use crate::f; 824use crate::f;
@@ -907,7 +839,7 @@ fn g() { f(); }
907 check( 839 check(
908 r#" 840 r#"
909struct S { 841struct S {
910 field<|>: u8, 842 field$0: u8,
911} 843}
912 844
913fn f(s: S) { 845fn f(s: S) {
@@ -930,7 +862,7 @@ fn f(s: S) {
930 r#" 862 r#"
931enum En { 863enum En {
932 Variant { 864 Variant {
933 field<|>: u8, 865 field$0: u8,
934 } 866 }
935} 867}
936 868
@@ -955,7 +887,7 @@ fn f(e: En) {
955mod m { 887mod m {
956 pub enum En { 888 pub enum En {
957 Variant { 889 Variant {
958 field<|>: u8, 890 field$0: u8,
959 } 891 }
960 } 892 }
961} 893}
@@ -980,7 +912,7 @@ struct Foo { bar: i32 }
980 912
981impl Foo { 913impl Foo {
982 fn foo(self) { 914 fn foo(self) {
983 let x = self<|>.bar; 915 let x = self$0.bar;
984 if true { 916 if true {
985 let _ = match () { 917 let _ = match () {
986 () => self, 918 () => self,
@@ -990,10 +922,30 @@ impl Foo {
990} 922}
991"#, 923"#,
992 expect![[r#" 924 expect![[r#"
993 self SelfParam FileId(0) 47..51 47..51 SelfKw Read 925 self SelfParam FileId(0) 47..51 47..51 SelfParam
926
927 FileId(0) 71..75 Other Read
928 FileId(0) 152..156 Other Read
929 "#]],
930 );
931 }
932
933 #[test]
934 fn test_find_self_refs_decl() {
935 check(
936 r#"
937struct Foo { bar: i32 }
938
939impl Foo {
940 fn foo(self$0) {
941 self;
942 }
943}
944"#,
945 expect![[r#"
946 self SelfParam FileId(0) 47..51 47..51 SelfParam
994 947
995 FileId(0) 71..75 SelfKw Read 948 FileId(0) 63..67 Other Read
996 FileId(0) 152..156 SelfKw Read
997 "#]], 949 "#]],
998 ); 950 );
999 } 951 }
@@ -1016,12 +968,14 @@ impl Foo {
1016 actual += "\n\n"; 968 actual += "\n\n";
1017 } 969 }
1018 970
1019 for r in &refs.references { 971 for (file_id, references) in refs.references {
1020 format_to!(actual, "{:?} {:?} {:?}", r.file_range.file_id, r.file_range.range, r.kind); 972 for r in references {
1021 if let Some(access) = r.access { 973 format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind);
1022 format_to!(actual, " {:?}", access); 974 if let Some(access) = r.access {
975 format_to!(actual, " {:?}", access);
976 }
977 actual += "\n";
1023 } 978 }
1024 actual += "\n";
1025 } 979 }
1026 expect.assert_eq(&actual) 980 expect.assert_eq(&actual)
1027 } 981 }
@@ -1032,7 +986,7 @@ impl Foo {
1032 r#" 986 r#"
1033trait Foo<'a> {} 987trait Foo<'a> {}
1034impl<'a> Foo<'a> for &'a () {} 988impl<'a> Foo<'a> for &'a () {}
1035fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> { 989fn foo<'a, 'b: 'a>(x: &'a$0 ()) -> &'a () where &'a (): Foo<'a> {
1036 fn bar<'a>(_: &'a ()) {} 990 fn bar<'a>(_: &'a ()) {}
1037 x 991 x
1038} 992}
@@ -1053,7 +1007,7 @@ fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> {
1053 fn test_find_lifetimes_type_alias() { 1007 fn test_find_lifetimes_type_alias() {
1054 check( 1008 check(
1055 r#" 1009 r#"
1056type Foo<'a, T> where T: 'a<|> = &'a T; 1010type Foo<'a, T> where T: 'a$0 = &'a T;
1057"#, 1011"#,
1058 expect![[r#" 1012 expect![[r#"
1059 'a LifetimeParam FileId(0) 9..11 9..11 Lifetime 1013 'a LifetimeParam FileId(0) 9..11 9..11 Lifetime
@@ -1072,7 +1026,7 @@ trait Foo<'a> {
1072 fn foo() -> &'a (); 1026 fn foo() -> &'a ();
1073} 1027}
1074impl<'a> Foo<'a> for &'a () { 1028impl<'a> Foo<'a> for &'a () {
1075 fn foo() -> &'a<|> () { 1029 fn foo() -> &'a$0 () {
1076 unimplemented!() 1030 unimplemented!()
1077 } 1031 }
1078} 1032}
@@ -1093,12 +1047,12 @@ impl<'a> Foo<'a> for &'a () {
1093 r#" 1047 r#"
1094macro_rules! foo {($i:ident) => {$i} } 1048macro_rules! foo {($i:ident) => {$i} }
1095fn main() { 1049fn main() {
1096 let a<|> = "test"; 1050 let a$0 = "test";
1097 foo!(a); 1051 foo!(a);
1098} 1052}
1099"#, 1053"#,
1100 expect![[r#" 1054 expect![[r#"
1101 a Local FileId(0) 59..60 Other 1055 a Local FileId(0) 59..60 59..60 Other
1102 1056
1103 FileId(0) 80..81 Other Read 1057 FileId(0) 80..81 Other Read
1104 "#]], 1058 "#]],
@@ -1112,11 +1066,11 @@ fn main() {
1112macro_rules! foo {($i:ident) => {$i} } 1066macro_rules! foo {($i:ident) => {$i} }
1113fn main() { 1067fn main() {
1114 let a = "test"; 1068 let a = "test";
1115 foo!(a<|>); 1069 foo!(a$0);
1116} 1070}
1117"#, 1071"#,
1118 expect![[r#" 1072 expect![[r#"
1119 a Local FileId(0) 59..60 Other 1073 a Local FileId(0) 59..60 59..60 Other
1120 1074
1121 FileId(0) 80..81 Other Read 1075 FileId(0) 80..81 Other Read
1122 "#]], 1076 "#]],
@@ -1130,7 +1084,7 @@ fn main() {
1130fn foo<'a>() -> &'a () { 1084fn foo<'a>() -> &'a () {
1131 'a: loop { 1085 'a: loop {
1132 'b: loop { 1086 'b: loop {
1133 continue 'a<|>; 1087 continue 'a$0;
1134 } 1088 }
1135 break 'a; 1089 break 'a;
1136 } 1090 }
@@ -1149,7 +1103,7 @@ fn foo<'a>() -> &'a () {
1149 fn test_find_const_param() { 1103 fn test_find_const_param() {
1150 check( 1104 check(
1151 r#" 1105 r#"
1152fn foo<const FOO<|>: usize>() -> usize { 1106fn foo<const FOO$0: usize>() -> usize {
1153 FOO 1107 FOO
1154} 1108}
1155"#, 1109"#,