aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/goto_definition.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/goto_definition.rs')
-rw-r--r--crates/ra_ide/src/goto_definition.rs1168
1 files changed, 572 insertions, 596 deletions
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index bea7fbfa7..4e3f428fa 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -7,7 +7,7 @@ use ra_syntax::{
7 ast::{self}, 7 ast::{self},
8 match_ast, AstNode, 8 match_ast, AstNode,
9 SyntaxKind::*, 9 SyntaxKind::*,
10 SyntaxToken, TokenAtOffset, 10 SyntaxToken, TokenAtOffset, T,
11}; 11};
12 12
13use crate::{ 13use crate::{
@@ -32,9 +32,10 @@ pub(crate) fn goto_definition(
32 let file = sema.parse(position.file_id).syntax().clone(); 32 let file = sema.parse(position.file_id).syntax().clone();
33 let original_token = pick_best(file.token_at_offset(position.offset))?; 33 let original_token = pick_best(file.token_at_offset(position.offset))?;
34 let token = sema.descend_into_macros(original_token.clone()); 34 let token = sema.descend_into_macros(original_token.clone());
35 let parent = token.parent();
35 36
36 let nav_targets = match_ast! { 37 let nav_targets = match_ast! {
37 match (token.parent()) { 38 match parent {
38 ast::NameRef(name_ref) => { 39 ast::NameRef(name_ref) => {
39 reference_definition(&sema, &name_ref).to_vec() 40 reference_definition(&sema, &name_ref).to_vec()
40 }, 41 },
@@ -57,7 +58,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
57 return tokens.max_by_key(priority); 58 return tokens.max_by_key(priority);
58 fn priority(n: &SyntaxToken) -> usize { 59 fn priority(n: &SyntaxToken) -> usize {
59 match n.kind() { 60 match n.kind() {
60 IDENT | INT_NUMBER => 2, 61 IDENT | INT_NUMBER | T![self] => 2,
61 kind if kind.is_trivia() => 0, 62 kind if kind.is_trivia() => 0,
62 _ => 1, 63 _ => 1,
63 } 64 }
@@ -103,205 +104,150 @@ pub(crate) fn reference_definition(
103 104
104#[cfg(test)] 105#[cfg(test)]
105mod tests { 106mod tests {
106 use test_utils::assert_eq_text; 107 use ra_db::FileRange;
107 108 use ra_syntax::{TextRange, TextSize};
108 use crate::mock_analysis::analysis_and_position; 109
109 110 use crate::mock_analysis::MockAnalysis;
110 fn check_goto(ra_fixture: &str, expected: &str, expected_range: &str) { 111
111 let (analysis, pos) = analysis_and_position(ra_fixture); 112 fn check(ra_fixture: &str) {
113 let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture);
114 let (mut expected, data) = mock.annotation();
115 let analysis = mock.analysis();
116 match data.as_str() {
117 "" => (),
118 "file" => {
119 expected.range =
120 TextRange::up_to(TextSize::of(&*analysis.file_text(expected.file_id).unwrap()))
121 }
122 data => panic!("bad data: {}", data),
123 }
112 124
113 let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; 125 let mut navs =
126 analysis.goto_definition(position).unwrap().expect("no definition found").info;
114 if navs.len() == 0 { 127 if navs.len() == 0 {
115 panic!("unresolved reference") 128 panic!("unresolved reference")
116 } 129 }
117 assert_eq!(navs.len(), 1); 130 assert_eq!(navs.len(), 1);
118 131
119 let nav = navs.pop().unwrap(); 132 let nav = navs.pop().unwrap();
120 let file_text = analysis.file_text(nav.file_id()).unwrap(); 133 assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() });
121
122 let mut actual = file_text[nav.full_range()].to_string();
123 if let Some(focus) = nav.focus_range() {
124 actual += "|";
125 actual += &file_text[focus];
126 }
127
128 if !expected_range.contains("...") {
129 test_utils::assert_eq_text!(&actual, expected_range);
130 } else {
131 let mut parts = expected_range.split("...");
132 let prefix = parts.next().unwrap();
133 let suffix = parts.next().unwrap();
134 assert!(
135 actual.starts_with(prefix) && actual.ends_with(suffix),
136 "\nExpected: {}\n Actual: {}\n",
137 expected_range,
138 actual
139 );
140 }
141
142 nav.assert_match(expected);
143 } 134 }
144 135
145 #[test] 136 #[test]
146 fn goto_def_in_items() { 137 fn goto_def_in_items() {
147 check_goto( 138 check(
148 " 139 r#"
149 //- /lib.rs 140struct Foo;
150 struct Foo; 141 //^^^
151 enum E { X(Foo<|>) } 142enum E { X(Foo<|>) }
152 ", 143"#,
153 "Foo STRUCT_DEF FileId(1) 0..11 7..10",
154 "struct Foo;|Foo",
155 ); 144 );
156 } 145 }
157 146
158 #[test] 147 #[test]
159 fn goto_def_at_start_of_item() { 148 fn goto_def_at_start_of_item() {
160 check_goto( 149 check(
161 " 150 r#"
162 //- /lib.rs 151struct Foo;
163 struct Foo; 152 //^^^
164 enum E { X(<|>Foo) } 153enum E { X(<|>Foo) }
165 ", 154"#,
166 "Foo STRUCT_DEF FileId(1) 0..11 7..10",
167 "struct Foo;|Foo",
168 ); 155 );
169 } 156 }
170 157
171 #[test] 158 #[test]
172 fn goto_definition_resolves_correct_name() { 159 fn goto_definition_resolves_correct_name() {
173 check_goto( 160 check(
174 " 161 r#"
175 //- /lib.rs 162//- /lib.rs
176 use a::Foo; 163use a::Foo;
177 mod a; 164mod a;
178 mod b; 165mod b;
179 enum E { X(Foo<|>) } 166enum E { X(Foo<|>) }
180 167
181 //- /a.rs 168//- /a.rs
182 struct Foo; 169struct Foo;
183 170 //^^^
184 //- /b.rs 171//- /b.rs
185 struct Foo; 172struct Foo;
186 ", 173"#,
187 "Foo STRUCT_DEF FileId(2) 0..11 7..10",
188 "struct Foo;|Foo",
189 ); 174 );
190 } 175 }
191 176
192 #[test] 177 #[test]
193 fn goto_def_for_module_declaration() { 178 fn goto_def_for_module_declaration() {
194 check_goto( 179 check(
195 r#" 180 r#"
196//- /lib.rs 181//- /lib.rs
197mod <|>foo; 182mod <|>foo;
198 183
199//- /foo.rs 184//- /foo.rs
200// empty 185// empty
186//^ file
201"#, 187"#,
202 "foo SOURCE_FILE FileId(2) 0..9",
203 "// empty\n",
204 ); 188 );
205 189
206 check_goto( 190 check(
207 r#" 191 r#"
208//- /lib.rs 192//- /lib.rs
209mod <|>foo; 193mod <|>foo;
210 194
211//- /foo/mod.rs 195//- /foo/mod.rs
212// empty 196// empty
197//^ file
213"#, 198"#,
214 "foo SOURCE_FILE FileId(2) 0..9",
215 "// empty\n",
216 ); 199 );
217 } 200 }
218 201
219 #[test] 202 #[test]
220 fn goto_def_for_macros() { 203 fn goto_def_for_macros() {
221 check_goto( 204 check(
222 " 205 r#"
223 //- /lib.rs 206macro_rules! foo { () => { () } }
224 macro_rules! foo { () => { () } } 207 //^^^
225 208fn bar() {
226 fn bar() { 209 <|>foo!();
227 <|>foo!(); 210}
228 } 211"#,
229 ",
230 "foo MACRO_CALL FileId(1) 0..33 13..16",
231 "macro_rules! foo { () => { () } }|foo",
232 ); 212 );
233 } 213 }
234 214
235 #[test] 215 #[test]
236 fn goto_def_for_macros_from_other_crates() { 216 fn goto_def_for_macros_from_other_crates() {
237 check_goto( 217 check(
238 "
239 //- /lib.rs
240 use foo::foo;
241 fn bar() {
242 <|>foo!();
243 }
244
245 //- /foo/lib.rs
246 #[macro_export]
247 macro_rules! foo { () => { () } }
248 ",
249 "foo MACRO_CALL FileId(2) 0..49 29..32",
250 "#[macro_export]\nmacro_rules! foo { () => { () } }|foo",
251 );
252 }
253
254 #[test]
255 fn goto_def_for_use_alias() {
256 check_goto(
257 r#" 218 r#"
258//- /lib.rs 219//- /lib.rs
259use foo as bar<|>; 220use foo::foo;
221fn bar() {
222 <|>foo!();
223}
260 224
261//- /foo/lib.rs 225//- /foo/lib.rs
262#[macro_export] 226#[macro_export]
263macro_rules! foo { () => { () } } 227macro_rules! foo { () => { () } }
228 //^^^
264"#, 229"#,
265 "SOURCE_FILE FileId(2) 0..50",
266 "#[macro_export]\nmacro_rules! foo { () => { () } }\n",
267 );
268 }
269
270 #[test]
271 fn goto_def_for_use_alias_foo_macro() {
272 check_goto(
273 "
274 //- /lib.rs
275 use foo::foo as bar<|>;
276
277 //- /foo/lib.rs
278 #[macro_export]
279 macro_rules! foo { () => { () } }
280 ",
281 "foo MACRO_CALL FileId(2) 0..49 29..32",
282 "#[macro_export]\nmacro_rules! foo { () => { () } }|foo",
283 ); 230 );
284 } 231 }
285 232
286 #[test] 233 #[test]
287 fn goto_def_for_macros_in_use_tree() { 234 fn goto_def_for_macros_in_use_tree() {
288 check_goto( 235 check(
289 " 236 r#"
290 //- /lib.rs 237//- /lib.rs
291 use foo::foo<|>; 238use foo::foo<|>;
292 239
293 //- /foo/lib.rs 240//- /foo/lib.rs
294 #[macro_export] 241#[macro_export]
295 macro_rules! foo { () => { () } } 242macro_rules! foo { () => { () } }
296 ", 243 //^^^
297 "foo MACRO_CALL FileId(2) 0..49 29..32", 244"#,
298 "#[macro_export]\nmacro_rules! foo { () => { () } }|foo",
299 ); 245 );
300 } 246 }
301 247
302 #[test] 248 #[test]
303 fn goto_def_for_macro_defined_fn_with_arg() { 249 fn goto_def_for_macro_defined_fn_with_arg() {
304 check_goto( 250 check(
305 r#" 251 r#"
306//- /lib.rs 252//- /lib.rs
307macro_rules! define_fn { 253macro_rules! define_fn {
@@ -309,522 +255,478 @@ macro_rules! define_fn {
309} 255}
310 256
311define_fn!(foo); 257define_fn!(foo);
258 //^^^
312 259
313fn bar() { 260fn bar() {
314 <|>foo(); 261 <|>foo();
315} 262}
316"#, 263"#,
317 "foo FN_DEF FileId(1) 65..81 76..79",
318 "define_fn!(foo);|foo",
319 ); 264 );
320 } 265 }
321 266
322 #[test] 267 #[test]
323 fn goto_def_for_macro_defined_fn_no_arg() { 268 fn goto_def_for_macro_defined_fn_no_arg() {
324 check_goto( 269 check(
325 r#" 270 r#"
326//- /lib.rs 271//- /lib.rs
327macro_rules! define_fn { 272macro_rules! define_fn {
328 () => (fn foo() {}) 273 () => (fn foo() {})
329} 274}
330 275
331define_fn!(); 276 define_fn!();
277//^^^^^^^^^^^^^
332 278
333fn bar() { 279fn bar() {
334 <|>foo(); 280 <|>foo();
335} 281}
336"#, 282"#,
337 "foo FN_DEF FileId(1) 52..65 52..65",
338 "define_fn!();|define_fn!();",
339 ); 283 );
340 } 284 }
341 285
342 #[test] 286 #[test]
343 fn goto_definition_works_for_macro_inside_pattern() { 287 fn goto_definition_works_for_macro_inside_pattern() {
344 check_goto( 288 check(
345 " 289 r#"
346 //- /lib.rs 290//- /lib.rs
347 macro_rules! foo {() => {0}} 291macro_rules! foo {() => {0}}
348 292 //^^^
349 fn bar() { 293
350 match (0,1) { 294fn bar() {
351 (<|>foo!(), _) => {} 295 match (0,1) {
352 } 296 (<|>foo!(), _) => {}
353 } 297 }
354 ", 298}
355 "foo MACRO_CALL FileId(1) 0..28 13..16", 299"#,
356 "macro_rules! foo {() => {0}}|foo",
357 ); 300 );
358 } 301 }
359 302
360 #[test] 303 #[test]
361 fn goto_definition_works_for_macro_inside_match_arm_lhs() { 304 fn goto_definition_works_for_macro_inside_match_arm_lhs() {
362 check_goto( 305 check(
363 " 306 r#"
364 //- /lib.rs 307//- /lib.rs
365 macro_rules! foo {() => {0}} 308macro_rules! foo {() => {0}}
366 309 //^^^
367 fn bar() { 310fn bar() {
368 match 0 { 311 match 0 {
369 <|>foo!() => {} 312 <|>foo!() => {}
370 } 313 }
371 } 314}
372 ", 315"#,
373 "foo MACRO_CALL FileId(1) 0..28 13..16", 316 );
374 "macro_rules! foo {() => {0}}|foo", 317 }
318
319 #[test]
320 fn goto_def_for_use_alias() {
321 check(
322 r#"
323//- /lib.rs
324use foo as bar<|>;
325
326//- /foo/lib.rs
327// empty
328//^ file
329"#,
330 );
331 }
332
333 #[test]
334 fn goto_def_for_use_alias_foo_macro() {
335 check(
336 r#"
337//- /lib.rs
338use foo::foo as bar<|>;
339
340//- /foo/lib.rs
341#[macro_export]
342macro_rules! foo { () => { () } }
343 //^^^
344"#,
375 ); 345 );
376 } 346 }
377 347
378 #[test] 348 #[test]
379 fn goto_def_for_methods() { 349 fn goto_def_for_methods() {
380 check_goto( 350 check(
381 " 351 r#"
382 //- /lib.rs 352//- /lib.rs
383 struct Foo; 353struct Foo;
384 impl Foo { 354impl Foo {
385 fn frobnicate(&self) { } 355 fn frobnicate(&self) { }
386 } 356 //^^^^^^^^^^
357}
387 358
388 fn bar(foo: &Foo) { 359fn bar(foo: &Foo) {
389 foo.frobnicate<|>(); 360 foo.frobnicate<|>();
390 } 361}
391 ", 362"#,
392 "frobnicate FN_DEF FileId(1) 27..51 30..40",
393 "fn frobnicate(&self) { }|frobnicate",
394 ); 363 );
395 } 364 }
396 365
397 #[test] 366 #[test]
398 fn goto_def_for_fields() { 367 fn goto_def_for_fields() {
399 check_goto( 368 check(
400 r" 369 r#"
401 //- /lib.rs 370struct Foo {
402 struct Foo { 371 spam: u32,
403 spam: u32, 372} //^^^^
404 }
405 373
406 fn bar(foo: &Foo) { 374fn bar(foo: &Foo) {
407 foo.spam<|>; 375 foo.spam<|>;
408 } 376}
409 ", 377"#,
410 "spam RECORD_FIELD_DEF FileId(1) 17..26 17..21",
411 "spam: u32|spam",
412 ); 378 );
413 } 379 }
414 380
415 #[test] 381 #[test]
416 fn goto_def_for_record_fields() { 382 fn goto_def_for_record_fields() {
417 check_goto( 383 check(
418 r" 384 r#"
419 //- /lib.rs 385//- /lib.rs
420 struct Foo { 386struct Foo {
421 spam: u32, 387 spam: u32,
422 } 388} //^^^^
423 389
424 fn bar() -> Foo { 390fn bar() -> Foo {
425 Foo { 391 Foo {
426 spam<|>: 0, 392 spam<|>: 0,
427 } 393 }
428 } 394}
429 ", 395"#,
430 "spam RECORD_FIELD_DEF FileId(1) 17..26 17..21",
431 "spam: u32|spam",
432 ); 396 );
433 } 397 }
434 398
435 #[test] 399 #[test]
436 fn goto_def_for_record_pat_fields() { 400 fn goto_def_for_record_pat_fields() {
437 check_goto( 401 check(
438 r" 402 r#"
439 //- /lib.rs 403//- /lib.rs
440 struct Foo { 404struct Foo {
441 spam: u32, 405 spam: u32,
442 } 406} //^^^^
443 407
444 fn bar(foo: Foo) -> Foo { 408fn bar(foo: Foo) -> Foo {
445 let Foo { spam<|>: _, } = foo 409 let Foo { spam<|>: _, } = foo
446 } 410}
447 ", 411"#,
448 "spam RECORD_FIELD_DEF FileId(1) 17..26 17..21",
449 "spam: u32|spam",
450 ); 412 );
451 } 413 }
452 414
453 #[test] 415 #[test]
454 fn goto_def_for_record_fields_macros() { 416 fn goto_def_for_record_fields_macros() {
455 check_goto( 417 check(
456 r" 418 r"
457 //- /lib.rs 419macro_rules! m { () => { 92 };}
458 macro_rules! m { () => { 92 };} 420struct Foo { spam: u32 }
459 struct Foo { spam: u32 } 421 //^^^^
460 422
461 fn bar() -> Foo { 423fn bar() -> Foo {
462 Foo { spam<|>: m!() } 424 Foo { spam<|>: m!() }
463 } 425}
464 ", 426",
465 "spam RECORD_FIELD_DEF FileId(1) 45..54 45..49",
466 "spam: u32|spam",
467 ); 427 );
468 } 428 }
469 429
470 #[test] 430 #[test]
471 fn goto_for_tuple_fields() { 431 fn goto_for_tuple_fields() {
472 check_goto( 432 check(
473 " 433 r#"
474 //- /lib.rs 434struct Foo(u32);
475 struct Foo(u32); 435 //^^^
476 436
477 fn bar() { 437fn bar() {
478 let foo = Foo(0); 438 let foo = Foo(0);
479 foo.<|>0; 439 foo.<|>0;
480 } 440}
481 ", 441"#,
482 "TUPLE_FIELD_DEF FileId(1) 11..14",
483 "u32",
484 ); 442 );
485 } 443 }
486 444
487 #[test] 445 #[test]
488 fn goto_def_for_ufcs_inherent_methods() { 446 fn goto_def_for_ufcs_inherent_methods() {
489 check_goto( 447 check(
490 " 448 r#"
491 //- /lib.rs 449struct Foo;
492 struct Foo; 450impl Foo {
493 impl Foo { 451 fn frobnicate() { }
494 fn frobnicate() { } 452} //^^^^^^^^^^
495 }
496 453
497 fn bar(foo: &Foo) { 454fn bar(foo: &Foo) {
498 Foo::frobnicate<|>(); 455 Foo::frobnicate<|>();
499 } 456}
500 ", 457"#,
501 "frobnicate FN_DEF FileId(1) 27..46 30..40",
502 "fn frobnicate() { }|frobnicate",
503 ); 458 );
504 } 459 }
505 460
506 #[test] 461 #[test]
507 fn goto_def_for_ufcs_trait_methods_through_traits() { 462 fn goto_def_for_ufcs_trait_methods_through_traits() {
508 check_goto( 463 check(
509 " 464 r#"
510 //- /lib.rs 465trait Foo {
511 trait Foo { 466 fn frobnicate();
512 fn frobnicate(); 467} //^^^^^^^^^^
513 }
514 468
515 fn bar() { 469fn bar() {
516 Foo::frobnicate<|>(); 470 Foo::frobnicate<|>();
517 } 471}
518 ", 472"#,
519 "frobnicate FN_DEF FileId(1) 16..32 19..29",
520 "fn frobnicate();|frobnicate",
521 ); 473 );
522 } 474 }
523 475
524 #[test] 476 #[test]
525 fn goto_def_for_ufcs_trait_methods_through_self() { 477 fn goto_def_for_ufcs_trait_methods_through_self() {
526 check_goto( 478 check(
527 " 479 r#"
528 //- /lib.rs 480struct Foo;
529 struct Foo; 481trait Trait {
530 trait Trait { 482 fn frobnicate();
531 fn frobnicate(); 483} //^^^^^^^^^^
532 } 484impl Trait for Foo {}
533 impl Trait for Foo {}
534 485
535 fn bar() { 486fn bar() {
536 Foo::frobnicate<|>(); 487 Foo::frobnicate<|>();
537 } 488}
538 ", 489"#,
539 "frobnicate FN_DEF FileId(1) 30..46 33..43",
540 "fn frobnicate();|frobnicate",
541 ); 490 );
542 } 491 }
543 492
544 #[test] 493 #[test]
545 fn goto_definition_on_self() { 494 fn goto_definition_on_self() {
546 check_goto( 495 check(
547 " 496 r#"
548 //- /lib.rs 497struct Foo;
549 struct Foo; 498impl Foo {
550 impl Foo { 499 //^^^
551 pub fn new() -> Self { 500 pub fn new() -> Self {
552 Self<|> {} 501 Self<|> {}
553 } 502 }
554 } 503}
555 ", 504"#,
556 "impl IMPL_DEF FileId(1) 12..73", 505 );
557 "impl Foo {...}", 506 check(
558 ); 507 r#"
559 508struct Foo;
560 check_goto( 509impl Foo {
561 " 510 //^^^
562 //- /lib.rs 511 pub fn new() -> Self<|> {
563 struct Foo; 512 Self {}
564 impl Foo { 513 }
565 pub fn new() -> Self<|> { 514}
566 Self {} 515"#,
567 } 516 );
568 } 517
569 ", 518 check(
570 "impl IMPL_DEF FileId(1) 12..73", 519 r#"
571 "impl Foo {...}", 520enum Foo { A }
572 ); 521impl Foo {
573 522 //^^^
574 check_goto( 523 pub fn new() -> Self<|> {
575 " 524 Foo::A
576 //- /lib.rs 525 }
577 enum Foo { A } 526}
578 impl Foo { 527"#,
579 pub fn new() -> Self<|> { 528 );
580 Foo::A 529
581 } 530 check(
582 } 531 r#"
583 ", 532enum Foo { A }
584 "impl IMPL_DEF FileId(1) 15..75", 533impl Foo {
585 "impl Foo {...}", 534 //^^^
586 ); 535 pub fn thing(a: &Self<|>) {
587 536 }
588 check_goto( 537}
589 " 538"#,
590 //- /lib.rs
591 enum Foo { A }
592 impl Foo {
593 pub fn thing(a: &Self<|>) {
594 }
595 }
596 ",
597 "impl IMPL_DEF FileId(1) 15..62",
598 "impl Foo {...}",
599 ); 539 );
600 } 540 }
601 541
602 #[test] 542 #[test]
603 fn goto_definition_on_self_in_trait_impl() { 543 fn goto_definition_on_self_in_trait_impl() {
604 check_goto( 544 check(
605 " 545 r#"
606 //- /lib.rs 546struct Foo;
607 struct Foo; 547trait Make {
608 trait Make { 548 fn new() -> Self;
609 fn new() -> Self; 549}
610 } 550impl Make for Foo {
611 impl Make for Foo { 551 //^^^
612 fn new() -> Self { 552 fn new() -> Self {
613 Self<|> {} 553 Self<|> {}
614 } 554 }
615 } 555}
616 ", 556"#,
617 "impl IMPL_DEF FileId(1) 49..115",
618 "impl Make for Foo {...}",
619 ); 557 );
620 558
621 check_goto( 559 check(
622 " 560 r#"
623 //- /lib.rs 561struct Foo;
624 struct Foo; 562trait Make {
625 trait Make { 563 fn new() -> Self;
626 fn new() -> Self; 564}
627 } 565impl Make for Foo {
628 impl Make for Foo { 566 //^^^
629 fn new() -> Self<|> { 567 fn new() -> Self<|> {
630 Self {} 568 Self {}
631 } 569 }
632 } 570}
633 ", 571"#,
634 "impl IMPL_DEF FileId(1) 49..115",
635 "impl Make for Foo {...}",
636 ); 572 );
637 } 573 }
638 574
639 #[test] 575 #[test]
640 fn goto_def_when_used_on_definition_name_itself() { 576 fn goto_def_when_used_on_definition_name_itself() {
641 check_goto( 577 check(
642 " 578 r#"
643 //- /lib.rs 579struct Foo<|> { value: u32 }
644 struct Foo<|> { value: u32 } 580 //^^^
645 ", 581 "#,
646 "Foo STRUCT_DEF FileId(1) 0..25 7..10",
647 "struct Foo { value: u32 }|Foo",
648 ); 582 );
649 583
650 check_goto( 584 check(
651 r#" 585 r#"
652 //- /lib.rs 586struct Foo {
653 struct Foo { 587 field<|>: string,
654 field<|>: string, 588} //^^^^^
655 } 589"#,
656 "#,
657 "field RECORD_FIELD_DEF FileId(1) 17..30 17..22",
658 "field: string|field",
659 ); 590 );
660 591
661 check_goto( 592 check(
662 " 593 r#"
663 //- /lib.rs 594fn foo_test<|>() { }
664 fn foo_test<|>() { } 595 //^^^^^^^^
665 ", 596"#,
666 "foo_test FN_DEF FileId(1) 0..17 3..11",
667 "fn foo_test() { }|foo_test",
668 ); 597 );
669 598
670 check_goto( 599 check(
671 " 600 r#"
672 //- /lib.rs 601enum Foo<|> { Variant }
673 enum Foo<|> { 602 //^^^
674 Variant, 603"#,
675 }
676 ",
677 "Foo ENUM_DEF FileId(1) 0..25 5..8",
678 "enum Foo {...}|Foo",
679 );
680
681 check_goto(
682 "
683 //- /lib.rs
684 enum Foo {
685 Variant1,
686 Variant2<|>,
687 Variant3,
688 }
689 ",
690 "Variant2 ENUM_VARIANT FileId(1) 29..37 29..37",
691 "Variant2|Variant2",
692 ); 604 );
693 605
694 check_goto( 606 check(
695 r#" 607 r#"
696 //- /lib.rs 608enum Foo {
697 static INNER<|>: &str = ""; 609 Variant1,
698 "#, 610 Variant2<|>,
699 "INNER STATIC_DEF FileId(1) 0..24 7..12", 611 //^^^^^^^^
700 "static INNER: &str = \"\";|INNER", 612 Variant3,
613}
614"#,
701 ); 615 );
702 616
703 check_goto( 617 check(
704 r#" 618 r#"
705 //- /lib.rs 619static INNER<|>: &str = "";
706 const INNER<|>: &str = ""; 620 //^^^^^
707 "#, 621"#,
708 "INNER CONST_DEF FileId(1) 0..23 6..11",
709 "const INNER: &str = \"\";|INNER",
710 ); 622 );
711 623
712 check_goto( 624 check(
713 r#" 625 r#"
714 //- /lib.rs 626const INNER<|>: &str = "";
715 type Thing<|> = Option<()>; 627 //^^^^^
716 "#, 628"#,
717 "Thing TYPE_ALIAS_DEF FileId(1) 0..24 5..10",
718 "type Thing = Option<()>;|Thing",
719 ); 629 );
720 630
721 check_goto( 631 check(
722 r#" 632 r#"
723 //- /lib.rs 633type Thing<|> = Option<()>;
724 trait Foo<|> { } 634 //^^^^^
725 "#, 635"#,
726 "Foo TRAIT_DEF FileId(1) 0..13 6..9",
727 "trait Foo { }|Foo",
728 ); 636 );
729 637
730 check_goto( 638 check(
731 r#" 639 r#"
732 //- /lib.rs 640trait Foo<|> { }
733 mod bar<|> { } 641 //^^^
734 "#, 642"#,
735 "bar MODULE FileId(1) 0..11 4..7", 643 );
736 "mod bar { }|bar", 644
645 check(
646 r#"
647mod bar<|> { }
648 //^^^
649"#,
737 ); 650 );
738 } 651 }
739 652
740 #[test] 653 #[test]
741 fn goto_from_macro() { 654 fn goto_from_macro() {
742 check_goto( 655 check(
743 " 656 r#"
744 //- /lib.rs 657macro_rules! id {
745 macro_rules! id { 658 ($($tt:tt)*) => { $($tt)* }
746 ($($tt:tt)*) => { $($tt)* } 659}
747 } 660fn foo() {}
748 fn foo() {} 661 //^^^
749 id! { 662id! {
750 fn bar() { 663 fn bar() {
751 fo<|>o(); 664 fo<|>o();
752 } 665 }
753 } 666}
754 mod confuse_index { fn foo(); } 667mod confuse_index { fn foo(); }
755 ", 668"#,
756 "foo FN_DEF FileId(1) 52..63 55..58",
757 "fn foo() {}|foo",
758 ); 669 );
759 } 670 }
760 671
761 #[test] 672 #[test]
762 fn goto_through_format() { 673 fn goto_through_format() {
763 check_goto( 674 check(
764 " 675 r#"
765 //- /lib.rs 676#[macro_export]
766 #[macro_export] 677macro_rules! format {
767 macro_rules! format { 678 ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
768 ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*))) 679}
769 } 680#[rustc_builtin_macro]
770 #[rustc_builtin_macro] 681#[macro_export]
771 #[macro_export] 682macro_rules! format_args {
772 macro_rules! format_args { 683 ($fmt:expr) => ({ /* compiler built-in */ });
773 ($fmt:expr) => ({ /* compiler built-in */ }); 684 ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
774 ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) 685}
775 } 686pub mod __export {
776 pub mod __export { 687 pub use crate::format_args;
777 pub use crate::format_args; 688 fn foo() {} // for index confusion
778 fn foo() {} // for index confusion 689}
779 } 690fn foo() -> i8 {}
780 fn foo() -> i8 {} 691 //^^^
781 fn test() { 692fn test() {
782 format!(\"{}\", fo<|>o()) 693 format!("{}", fo<|>o())
783 } 694}
784 ", 695"#,
785 "foo FN_DEF FileId(1) 398..415 401..404",
786 "fn foo() -> i8 {}|foo",
787 ); 696 );
788 } 697 }
789 698
790 #[test] 699 #[test]
791 fn goto_for_type_param() { 700 fn goto_for_type_param() {
792 check_goto( 701 check(
793 r#" 702 r#"
794 //- /lib.rs 703struct Foo<T: Clone> { t: <|>T }
795 struct Foo<T: Clone> { 704 //^
796 t: <|>T, 705"#,
797 }
798 "#,
799 "T TYPE_PARAM FileId(1) 11..19 11..12",
800 "T: Clone|T",
801 ); 706 );
802 } 707 }
803 708
804 #[test] 709 #[test]
805 fn goto_within_macro() { 710 fn goto_within_macro() {
806 check_goto( 711 check(
807 r#" 712 r#"
808//- /lib.rs
809macro_rules! id { 713macro_rules! id {
810 ($($tt:tt)*) => ($($tt)*) 714 ($($tt:tt)*) => ($($tt)*)
811} 715}
812 716
813fn foo() { 717fn foo() {
814 let x = 1; 718 let x = 1;
719 //^
815 id!({ 720 id!({
816 let y = <|>x; 721 let y = <|>x;
817 let z = y; 722 let z = y;
818 }); 723 });
819} 724}
820"#, 725"#,
821 "x BIND_PAT FileId(1) 70..71",
822 "x",
823 ); 726 );
824 727
825 check_goto( 728 check(
826 r#" 729 r#"
827//- /lib.rs
828macro_rules! id { 730macro_rules! id {
829 ($($tt:tt)*) => ($($tt)*) 731 ($($tt:tt)*) => ($($tt)*)
830} 732}
@@ -833,159 +735,233 @@ fn foo() {
833 let x = 1; 735 let x = 1;
834 id!({ 736 id!({
835 let y = x; 737 let y = x;
738 //^
836 let z = <|>y; 739 let z = <|>y;
837 }); 740 });
838} 741}
839"#, 742"#,
840 "y BIND_PAT FileId(1) 99..100",
841 "y",
842 ); 743 );
843 } 744 }
844 745
845 #[test] 746 #[test]
846 fn goto_def_in_local_fn() { 747 fn goto_def_in_local_fn() {
847 check_goto( 748 check(
848 " 749 r#"
849 //- /lib.rs 750fn main() {
850 fn main() { 751 fn foo() {
851 fn foo() { 752 let x = 92;
852 let x = 92; 753 //^
853 <|>x; 754 <|>x;
854 } 755 }
855 } 756}
856 ", 757"#,
857 "x BIND_PAT FileId(1) 39..40",
858 "x",
859 ); 758 );
860 } 759 }
861 760
862 #[test] 761 #[test]
863 fn goto_def_in_local_macro() { 762 fn goto_def_in_local_macro() {
864 check_goto( 763 check(
865 r" 764 r#"
866 //- /lib.rs 765fn bar() {
867 fn bar() { 766 macro_rules! foo { () => { () } }
868 macro_rules! foo { () => { () } } 767 //^^^
869 <|>foo!(); 768 <|>foo!();
870 } 769}
871 ", 770"#,
872 "foo MACRO_CALL FileId(1) 15..48 28..31",
873 "macro_rules! foo { () => { () } }|foo",
874 ); 771 );
875 } 772 }
876 773
877 #[test] 774 #[test]
878 fn goto_def_for_field_init_shorthand() { 775 fn goto_def_for_field_init_shorthand() {
879 check_goto( 776 check(
880 " 777 r#"
881 //- /lib.rs 778struct Foo { x: i32 }
882 struct Foo { x: i32 } 779fn main() {
883 fn main() { 780 let x = 92;
884 let x = 92; 781 //^
885 Foo { x<|> }; 782 Foo { x<|> };
886 } 783}
887 ", 784"#,
888 "x BIND_PAT FileId(1) 42..43",
889 "x",
890 ) 785 )
891 } 786 }
892 787
893 #[test] 788 #[test]
894 fn goto_def_for_enum_variant_field() { 789 fn goto_def_for_enum_variant_field() {
895 check_goto( 790 check(
896 " 791 r#"
897 //- /lib.rs 792enum Foo {
898 enum Foo { 793 Bar { x: i32 }
899 Bar { x: i32 } 794} //^
900 } 795fn baz(foo: Foo) {
901 fn baz(foo: Foo) { 796 match foo {
902 match foo { 797 Foo::Bar { x<|> } => x
903 Foo::Bar { x<|> } => x 798 };
904 }; 799}
905 } 800"#,
906 ",
907 "x RECORD_FIELD_DEF FileId(1) 21..27 21..22",
908 "x: i32|x",
909 ); 801 );
910 } 802 }
911 803
912 #[test] 804 #[test]
913 fn goto_def_for_enum_variant_self_pattern_const() { 805 fn goto_def_for_enum_variant_self_pattern_const() {
914 check_goto( 806 check(
915 " 807 r#"
916 //- /lib.rs 808enum Foo { Bar }
917 enum Foo { 809 //^^^
918 Bar, 810impl Foo {
919 } 811 fn baz(self) {
920 impl Foo { 812 match self { Self::Bar<|> => {} }
921 fn baz(self) { 813 }
922 match self { 814}
923 Self::Bar<|> => {} 815"#,
924 }
925 }
926 }
927 ",
928 "Bar ENUM_VARIANT FileId(1) 15..18 15..18",
929 "Bar|Bar",
930 ); 816 );
931 } 817 }
932 818
933 #[test] 819 #[test]
934 fn goto_def_for_enum_variant_self_pattern_record() { 820 fn goto_def_for_enum_variant_self_pattern_record() {
935 check_goto( 821 check(
936 " 822 r#"
937 //- /lib.rs 823enum Foo { Bar { val: i32 } }
938 enum Foo { 824 //^^^
939 Bar { val: i32 }, 825impl Foo {
940 } 826 fn baz(self) -> i32 {
941 impl Foo { 827 match self { Self::Bar<|> { val } => {} }
942 fn baz(self) -> i32 { 828 }
943 match self { 829}
944 Self::Bar<|> { val } => {} 830"#,
945 }
946 }
947 }
948 ",
949 "Bar ENUM_VARIANT FileId(1) 15..31 15..18",
950 "Bar { val: i32 }|Bar",
951 ); 831 );
952 } 832 }
953 833
954 #[test] 834 #[test]
955 fn goto_def_for_enum_variant_self_expr_const() { 835 fn goto_def_for_enum_variant_self_expr_const() {
956 check_goto( 836 check(
957 " 837 r#"
958 //- /lib.rs 838enum Foo { Bar }
959 enum Foo { 839 //^^^
960 Bar, 840impl Foo {
961 } 841 fn baz(self) { Self::Bar<|>; }
962 impl Foo { 842}
963 fn baz(self) { 843"#,
964 Self::Bar<|>;
965 }
966 }
967 ",
968 "Bar ENUM_VARIANT FileId(1) 15..18 15..18",
969 "Bar|Bar",
970 ); 844 );
971 } 845 }
972 846
973 #[test] 847 #[test]
974 fn goto_def_for_enum_variant_self_expr_record() { 848 fn goto_def_for_enum_variant_self_expr_record() {
975 check_goto( 849 check(
976 " 850 r#"
977 //- /lib.rs 851enum Foo { Bar { val: i32 } }
978 enum Foo { 852 //^^^
979 Bar { val: i32 }, 853impl Foo {
980 } 854 fn baz(self) { Self::Bar<|> {val: 4}; }
981 impl Foo { 855}
982 fn baz(self) { 856"#,
983 Self::Bar<|> {val: 4}; 857 );
984 } 858 }
985 } 859
986 ", 860 #[test]
987 "Bar ENUM_VARIANT FileId(1) 15..31 15..18", 861 fn goto_def_for_type_alias_generic_parameter() {
988 "Bar { val: i32 }|Bar", 862 check(
863 r#"
864type Alias<T> = T<|>;
865 //^
866"#,
867 )
868 }
869
870 #[test]
871 fn goto_def_for_macro_container() {
872 check(
873 r#"
874//- /lib.rs
875foo::module<|>::mac!();
876
877//- /foo/lib.rs
878pub mod module {
879 //^^^^^^
880 #[macro_export]
881 macro_rules! _mac { () => { () } }
882 pub use crate::_mac as mac;
883}
884"#,
885 );
886 }
887
888 #[test]
889 fn goto_def_for_assoc_ty_in_path() {
890 check(
891 r#"
892trait Iterator {
893 type Item;
894 //^^^^
895}
896
897fn f() -> impl Iterator<Item<|> = u8> {}
898"#,
899 );
900 }
901
902 #[test]
903 fn goto_def_for_assoc_ty_in_path_multiple() {
904 check(
905 r#"
906trait Iterator {
907 type A;
908 //^
909 type B;
910}
911
912fn f() -> impl Iterator<A<|> = u8, B = ()> {}
913"#,
914 );
915 check(
916 r#"
917trait Iterator {
918 type A;
919 type B;
920 //^
921}
922
923fn f() -> impl Iterator<A = u8, B<|> = ()> {}
924"#,
925 );
926 }
927
928 #[test]
929 fn goto_def_for_assoc_ty_ufcs() {
930 check(
931 r#"
932trait Iterator {
933 type Item;
934 //^^^^
935}
936
937fn g() -> <() as Iterator<Item<|> = ()>>::Item {}
938"#,
939 );
940 }
941
942 #[test]
943 fn goto_def_for_assoc_ty_ufcs_multiple() {
944 check(
945 r#"
946trait Iterator {
947 type A;
948 //^
949 type B;
950}
951
952fn g() -> <() as Iterator<A<|> = (), B = u8>>::B {}
953"#,
954 );
955 check(
956 r#"
957trait Iterator {
958 type A;
959 type B;
960 //^
961}
962
963fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {}
964"#,
989 ); 965 );
990 } 966 }
991} 967}