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