diff options
Diffstat (limited to 'crates/ide/src/references.rs')
-rw-r--r-- | crates/ide/src/references.rs | 288 |
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 | ||
12 | pub(crate) mod rename; | 12 | pub(crate) mod rename; |
13 | 13 | ||
14 | use either::Either; | ||
14 | use hir::Semantics; | 15 | use hir::Semantics; |
15 | use ide_db::{ | 16 | use 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 | }; |
21 | use syntax::{ | 22 | use 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 | ||
27 | use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind}; | 28 | use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; |
28 | 29 | ||
29 | #[derive(Debug, Clone)] | 30 | #[derive(Debug, Clone)] |
30 | pub struct ReferenceSearchResult { | 31 | pub 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 |
65 | impl IntoIterator for ReferenceSearchResult { | 77 | impl 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 | ||
142 | fn find_name( | 145 | fn 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 | ||
251 | fn 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)] |
323 | mod tests { | 255 | mod 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#" |
334 | struct Foo <|>{ | 266 | struct Foo $0{ |
335 | a: i32, | 267 | a: i32, |
336 | } | 268 | } |
337 | impl Foo { | 269 | impl 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#" |
357 | struct Foo<|> {} | 289 | struct 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#" |
376 | struct Foo<T> <|>{} | 308 | struct 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#" |
394 | struct Foo<|>(i32); | 326 | struct Foo$0(i32); |
395 | 327 | ||
396 | fn main() { | 328 | fn 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#" |
413 | enum Foo <|>{ | 345 | enum 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#" |
434 | enum Foo<|> { | 366 | enum 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#" |
456 | enum Foo<T> <|>{ | 388 | enum 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#" |
477 | enum Foo<|>{ | 409 | enum Foo$0{ |
478 | A(i8), | 410 | A(i8), |
479 | B(i8), | 411 | B(i8), |
480 | } | 412 | } |
@@ -498,7 +430,7 @@ fn main() { | |||
498 | fn main() { | 430 | fn 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#" |
524 | fn foo() { | 456 | fn foo() { |
525 | let spam<|> = 92; | 457 | let spam$0 = 92; |
526 | spam + spam | 458 | spam + spam |
527 | } | 459 | } |
528 | fn bar() { | 460 | fn 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#" |
546 | fn foo(i : u32) -> u32 { i<|> } | 478 | fn 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#" |
560 | fn foo(i<|> : u32) -> u32 { i } | 492 | fn 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 |
575 | struct Foo { | 507 | struct Foo { |
576 | pub spam<|>: u32, | 508 | pub spam$0: u32, |
577 | } | 509 | } |
578 | 510 | ||
579 | fn main(s: Foo) { | 511 | fn main(s: Foo) { |
@@ -594,7 +526,7 @@ fn main(s: Foo) { | |||
594 | r#" | 526 | r#" |
595 | struct Foo; | 527 | struct Foo; |
596 | impl Foo { | 528 | impl 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#" |
611 | enum Foo { | 543 | enum 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#" |
628 | enum Foo { | 560 | enum 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 | ||
671 | fn f() { | 603 | fn 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 |
692 | mod foo<|>; | 624 | mod foo$0; |
693 | 625 | ||
694 | use foo::Foo; | 626 | use foo::Foo; |
695 | 627 | ||
@@ -726,7 +658,7 @@ fn f() { | |||
726 | } | 658 | } |
727 | 659 | ||
728 | //- /foo/some.rs | 660 | //- /foo/some.rs |
729 | pub(super) struct Foo<|> { | 661 | pub(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] |
785 | macro_rules! m1<|> { () => (()) } | 717 | macro_rules! m1$0 { () => (()) } |
786 | 718 | ||
787 | fn foo() { | 719 | fn foo() { |
788 | m1(); | 720 | m1(); |
@@ -803,12 +735,12 @@ fn foo() { | |||
803 | check( | 735 | check( |
804 | r#" | 736 | r#" |
805 | fn foo() { | 737 | fn 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 | ||
827 | fn foo() { | 759 | fn 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#" |
845 | fn foo() { | 777 | fn 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 |
887 | mod foo { mod bar; } | 819 | mod foo { mod bar; } |
888 | 820 | ||
889 | fn f<|>() {} | 821 | fn f$0() {} |
890 | 822 | ||
891 | //- /foo/bar.rs | 823 | //- /foo/bar.rs |
892 | use crate::f; | 824 | use crate::f; |
@@ -907,7 +839,7 @@ fn g() { f(); } | |||
907 | check( | 839 | check( |
908 | r#" | 840 | r#" |
909 | struct S { | 841 | struct S { |
910 | field<|>: u8, | 842 | field$0: u8, |
911 | } | 843 | } |
912 | 844 | ||
913 | fn f(s: S) { | 845 | fn f(s: S) { |
@@ -930,7 +862,7 @@ fn f(s: S) { | |||
930 | r#" | 862 | r#" |
931 | enum En { | 863 | enum 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) { | |||
955 | mod m { | 887 | mod 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 | ||
981 | impl Foo { | 913 | impl 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#" | ||
937 | struct Foo { bar: i32 } | ||
938 | |||
939 | impl 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#" |
1033 | trait Foo<'a> {} | 987 | trait Foo<'a> {} |
1034 | impl<'a> Foo<'a> for &'a () {} | 988 | impl<'a> Foo<'a> for &'a () {} |
1035 | fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> { | 989 | fn 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#" |
1056 | type Foo<'a, T> where T: 'a<|> = &'a T; | 1010 | type 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 | } |
1074 | impl<'a> Foo<'a> for &'a () { | 1028 | impl<'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#" |
1094 | macro_rules! foo {($i:ident) => {$i} } | 1048 | macro_rules! foo {($i:ident) => {$i} } |
1095 | fn main() { | 1049 | fn 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() { | |||
1112 | macro_rules! foo {($i:ident) => {$i} } | 1066 | macro_rules! foo {($i:ident) => {$i} } |
1113 | fn main() { | 1067 | fn 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() { | |||
1130 | fn foo<'a>() -> &'a () { | 1084 | fn 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#" |
1152 | fn foo<const FOO<|>: usize>() -> usize { | 1106 | fn foo<const FOO$0: usize>() -> usize { |
1153 | FOO | 1107 | FOO |
1154 | } | 1108 | } |
1155 | "#, | 1109 | "#, |