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