]>
Commit | Line | Data |
---|---|---|
f2b60f7d | 1 | use std::mem::discriminant; |
064997fb FG |
2 | |
3 | use crate::{doc_links::token_as_doc_comment, FilePosition, NavigationTarget, RangeInfo, TryToNav}; | |
4 | use hir::{AsAssocItem, AssocItem, Semantics}; | |
5 | use ide_db::{ | |
6 | base_db::{AnchoredPath, FileId, FileLoader}, | |
7 | defs::{Definition, IdentClass}, | |
8 | helpers::pick_best_token, | |
9 | RootDatabase, | |
10 | }; | |
11 | use itertools::Itertools; | |
12 | use syntax::{ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T}; | |
13 | ||
14 | // Feature: Go to Definition | |
15 | // | |
16 | // Navigates to the definition of an identifier. | |
17 | // | |
18 | // For outline modules, this will navigate to the source file of the module. | |
19 | // | |
20 | // |=== | |
21 | // | Editor | Shortcut | |
22 | // | |
23 | // | VS Code | kbd:[F12] | |
24 | // |=== | |
25 | // | |
26 | // image::https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif[] | |
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 = | |
34 | pick_best_token(file.token_at_offset(position.offset), |kind| match kind { | |
35 | IDENT | |
36 | | INT_NUMBER | |
37 | | LIFETIME_IDENT | |
38 | | T![self] | |
39 | | T![super] | |
40 | | T![crate] | |
41 | | T![Self] | |
f2b60f7d FG |
42 | | COMMENT => 4, |
43 | // index and prefix ops | |
44 | T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3, | |
45 | kind if kind.is_keyword() => 2, | |
46 | T!['('] | T![')'] => 2, | |
064997fb FG |
47 | kind if kind.is_trivia() => 0, |
48 | _ => 1, | |
49 | })?; | |
50 | if let Some(doc_comment) = token_as_doc_comment(&original_token) { | |
2b03887a FG |
51 | return doc_comment.get_definition_with_descend_at( |
52 | sema, | |
53 | position.offset, | |
54 | |def, _, link_range| { | |
55 | let nav = def.try_to_nav(db)?; | |
56 | Some(RangeInfo::new(link_range, vec![nav])) | |
57 | }, | |
58 | ); | |
064997fb FG |
59 | } |
60 | let navs = sema | |
61 | .descend_into_macros(original_token.clone()) | |
62 | .into_iter() | |
63 | .filter_map(|token| { | |
64 | let parent = token.parent()?; | |
65 | if let Some(tt) = ast::TokenTree::cast(parent) { | |
66 | if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), position.file_id) | |
67 | { | |
68 | return Some(vec![x]); | |
69 | } | |
70 | } | |
71 | Some( | |
72 | IdentClass::classify_token(sema, &token)? | |
73 | .definitions() | |
74 | .into_iter() | |
75 | .flat_map(|def| { | |
76 | try_filter_trait_item_definition(sema, &def) | |
77 | .unwrap_or_else(|| def_to_nav(sema.db, def)) | |
78 | }) | |
79 | .collect(), | |
80 | ) | |
81 | }) | |
82 | .flatten() | |
83 | .unique() | |
84 | .collect::<Vec<NavigationTarget>>(); | |
85 | ||
86 | Some(RangeInfo::new(original_token.text_range(), navs)) | |
87 | } | |
88 | ||
89 | fn try_lookup_include_path( | |
90 | sema: &Semantics<'_, RootDatabase>, | |
91 | tt: ast::TokenTree, | |
92 | token: SyntaxToken, | |
93 | file_id: FileId, | |
94 | ) -> Option<NavigationTarget> { | |
95 | let token = ast::String::cast(token)?; | |
96 | let path = token.value()?.into_owned(); | |
97 | let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?; | |
98 | let name = macro_call.path()?.segment()?.name_ref()?; | |
99 | if !matches!(&*name.text(), "include" | "include_str" | "include_bytes") { | |
100 | return None; | |
101 | } | |
2b03887a FG |
102 | |
103 | // Ignore non-built-in macros to account for shadowing | |
104 | if let Some(it) = sema.resolve_macro_call(¯o_call) { | |
105 | if !matches!(it.kind(sema.db), hir::MacroKind::BuiltIn) { | |
106 | return None; | |
107 | } | |
108 | } | |
109 | ||
064997fb FG |
110 | let file_id = sema.db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?; |
111 | let size = sema.db.file_text(file_id).len().try_into().ok()?; | |
112 | Some(NavigationTarget { | |
113 | file_id, | |
114 | full_range: TextRange::new(0.into(), size), | |
115 | name: path.into(), | |
116 | focus_range: None, | |
117 | kind: None, | |
118 | container_name: None, | |
119 | description: None, | |
120 | docs: None, | |
121 | }) | |
122 | } | |
123 | /// finds the trait definition of an impl'd item, except function | |
124 | /// e.g. | |
125 | /// ```rust | |
126 | /// trait A { type a; } | |
127 | /// struct S; | |
128 | /// impl A for S { type a = i32; } // <-- on this associate type, will get the location of a in the trait | |
129 | /// ``` | |
130 | fn try_filter_trait_item_definition( | |
131 | sema: &Semantics<'_, RootDatabase>, | |
132 | def: &Definition, | |
133 | ) -> Option<Vec<NavigationTarget>> { | |
134 | let db = sema.db; | |
135 | let assoc = def.as_assoc_item(db)?; | |
136 | match assoc { | |
137 | AssocItem::Function(..) => None, | |
138 | AssocItem::Const(..) | AssocItem::TypeAlias(..) => { | |
139 | let imp = match assoc.container(db) { | |
140 | hir::AssocItemContainer::Impl(imp) => imp, | |
141 | _ => return None, | |
142 | }; | |
143 | let trait_ = imp.trait_(db)?; | |
144 | let name = def.name(db)?; | |
145 | let discri_value = discriminant(&assoc); | |
146 | trait_ | |
147 | .items(db) | |
148 | .iter() | |
149 | .filter(|itm| discriminant(*itm) == discri_value) | |
150 | .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten()) | |
151 | .map(|it| vec![it]) | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
156 | fn def_to_nav(db: &RootDatabase, def: Definition) -> Vec<NavigationTarget> { | |
157 | def.try_to_nav(db).map(|it| vec![it]).unwrap_or_default() | |
158 | } | |
159 | ||
160 | #[cfg(test)] | |
161 | mod tests { | |
162 | use ide_db::base_db::FileRange; | |
163 | use itertools::Itertools; | |
164 | ||
165 | use crate::fixture; | |
166 | ||
167 | #[track_caller] | |
168 | fn check(ra_fixture: &str) { | |
169 | let (analysis, position, expected) = fixture::annotations(ra_fixture); | |
170 | let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info; | |
064997fb FG |
171 | |
172 | let cmp = |&FileRange { file_id, range }: &_| (file_id, range.start()); | |
173 | let navs = navs | |
174 | .into_iter() | |
175 | .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) | |
176 | .sorted_by_key(cmp) | |
177 | .collect::<Vec<_>>(); | |
178 | let expected = expected | |
179 | .into_iter() | |
180 | .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range }) | |
181 | .sorted_by_key(cmp) | |
182 | .collect::<Vec<_>>(); | |
183 | assert_eq!(expected, navs); | |
184 | } | |
185 | ||
186 | fn check_unresolved(ra_fixture: &str) { | |
187 | let (analysis, position) = fixture::position(ra_fixture); | |
188 | let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info; | |
189 | ||
f25598a0 | 190 | assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}") |
064997fb FG |
191 | } |
192 | ||
193 | #[test] | |
194 | fn goto_def_if_items_same_name() { | |
195 | check( | |
196 | r#" | |
197 | trait Trait { | |
198 | type A; | |
199 | const A: i32; | |
200 | //^ | |
201 | } | |
202 | ||
203 | struct T; | |
204 | impl Trait for T { | |
205 | type A = i32; | |
206 | const A$0: i32 = -9; | |
207 | }"#, | |
208 | ); | |
209 | } | |
210 | #[test] | |
211 | fn goto_def_in_mac_call_in_attr_invoc() { | |
212 | check( | |
213 | r#" | |
214 | //- proc_macros: identity | |
215 | pub struct Struct { | |
216 | // ^^^^^^ | |
217 | field: i32, | |
218 | } | |
219 | ||
220 | macro_rules! identity { | |
221 | ($($tt:tt)*) => {$($tt)*}; | |
222 | } | |
223 | ||
224 | #[proc_macros::identity] | |
225 | fn function() { | |
226 | identity!(Struct$0 { field: 0 }); | |
227 | } | |
228 | ||
229 | "#, | |
230 | ) | |
231 | } | |
232 | ||
233 | #[test] | |
234 | fn goto_def_for_extern_crate() { | |
235 | check( | |
236 | r#" | |
237 | //- /main.rs crate:main deps:std | |
238 | extern crate std$0; | |
239 | //- /std/lib.rs crate:std | |
240 | // empty | |
241 | //^file | |
242 | "#, | |
243 | ) | |
244 | } | |
245 | ||
246 | #[test] | |
247 | fn goto_def_for_renamed_extern_crate() { | |
248 | check( | |
249 | r#" | |
250 | //- /main.rs crate:main deps:std | |
251 | extern crate std as abc$0; | |
252 | //- /std/lib.rs crate:std | |
253 | // empty | |
254 | //^file | |
255 | "#, | |
256 | ) | |
257 | } | |
258 | ||
259 | #[test] | |
260 | fn goto_def_in_items() { | |
261 | check( | |
262 | r#" | |
263 | struct Foo; | |
264 | //^^^ | |
265 | enum E { X(Foo$0) } | |
266 | "#, | |
267 | ); | |
268 | } | |
269 | ||
270 | #[test] | |
271 | fn goto_def_at_start_of_item() { | |
272 | check( | |
273 | r#" | |
274 | struct Foo; | |
275 | //^^^ | |
276 | enum E { X($0Foo) } | |
277 | "#, | |
278 | ); | |
279 | } | |
280 | ||
281 | #[test] | |
282 | fn goto_definition_resolves_correct_name() { | |
283 | check( | |
284 | r#" | |
285 | //- /lib.rs | |
286 | use a::Foo; | |
287 | mod a; | |
288 | mod b; | |
289 | enum E { X(Foo$0) } | |
290 | ||
291 | //- /a.rs | |
487cf647 FG |
292 | pub struct Foo; |
293 | //^^^ | |
064997fb | 294 | //- /b.rs |
487cf647 | 295 | pub struct Foo; |
064997fb FG |
296 | "#, |
297 | ); | |
298 | } | |
299 | ||
300 | #[test] | |
301 | fn goto_def_for_module_declaration() { | |
302 | check( | |
303 | r#" | |
304 | //- /lib.rs | |
305 | mod $0foo; | |
306 | ||
307 | //- /foo.rs | |
308 | // empty | |
309 | //^file | |
310 | "#, | |
311 | ); | |
312 | ||
313 | check( | |
314 | r#" | |
315 | //- /lib.rs | |
316 | mod $0foo; | |
317 | ||
318 | //- /foo/mod.rs | |
319 | // empty | |
320 | //^file | |
321 | "#, | |
322 | ); | |
323 | } | |
324 | ||
325 | #[test] | |
326 | fn goto_def_for_macros() { | |
327 | check( | |
328 | r#" | |
329 | macro_rules! foo { () => { () } } | |
330 | //^^^ | |
331 | fn bar() { | |
332 | $0foo!(); | |
333 | } | |
334 | "#, | |
335 | ); | |
336 | } | |
337 | ||
338 | #[test] | |
339 | fn goto_def_for_macros_from_other_crates() { | |
340 | check( | |
341 | r#" | |
342 | //- /lib.rs crate:main deps:foo | |
343 | use foo::foo; | |
344 | fn bar() { | |
345 | $0foo!(); | |
346 | } | |
347 | ||
348 | //- /foo/lib.rs crate:foo | |
349 | #[macro_export] | |
350 | macro_rules! foo { () => { () } } | |
351 | //^^^ | |
352 | "#, | |
353 | ); | |
354 | } | |
355 | ||
356 | #[test] | |
357 | fn goto_def_for_macros_in_use_tree() { | |
358 | check( | |
359 | r#" | |
360 | //- /lib.rs crate:main deps:foo | |
361 | use foo::foo$0; | |
362 | ||
363 | //- /foo/lib.rs crate:foo | |
364 | #[macro_export] | |
365 | macro_rules! foo { () => { () } } | |
366 | //^^^ | |
367 | "#, | |
368 | ); | |
369 | } | |
370 | ||
371 | #[test] | |
372 | fn goto_def_for_macro_defined_fn_with_arg() { | |
373 | check( | |
374 | r#" | |
375 | //- /lib.rs | |
376 | macro_rules! define_fn { | |
377 | ($name:ident) => (fn $name() {}) | |
378 | } | |
379 | ||
380 | define_fn!(foo); | |
381 | //^^^ | |
382 | ||
383 | fn bar() { | |
384 | $0foo(); | |
385 | } | |
386 | "#, | |
387 | ); | |
388 | } | |
389 | ||
390 | #[test] | |
391 | fn goto_def_for_macro_defined_fn_no_arg() { | |
392 | check( | |
393 | r#" | |
394 | //- /lib.rs | |
395 | macro_rules! define_fn { | |
396 | () => (fn foo() {}) | |
397 | } | |
398 | ||
399 | define_fn!(); | |
400 | //^^^^^^^^^^^^^ | |
401 | ||
402 | fn bar() { | |
403 | $0foo(); | |
404 | } | |
405 | "#, | |
406 | ); | |
407 | } | |
408 | ||
409 | #[test] | |
410 | fn goto_definition_works_for_macro_inside_pattern() { | |
411 | check( | |
412 | r#" | |
413 | //- /lib.rs | |
414 | macro_rules! foo {() => {0}} | |
415 | //^^^ | |
416 | ||
417 | fn bar() { | |
418 | match (0,1) { | |
419 | ($0foo!(), _) => {} | |
420 | } | |
421 | } | |
422 | "#, | |
423 | ); | |
424 | } | |
425 | ||
426 | #[test] | |
427 | fn goto_definition_works_for_macro_inside_match_arm_lhs() { | |
428 | check( | |
429 | r#" | |
430 | //- /lib.rs | |
431 | macro_rules! foo {() => {0}} | |
432 | //^^^ | |
433 | fn bar() { | |
434 | match 0 { | |
435 | $0foo!() => {} | |
436 | } | |
437 | } | |
438 | "#, | |
439 | ); | |
440 | } | |
441 | ||
442 | #[test] | |
443 | fn goto_def_for_use_alias() { | |
444 | check( | |
445 | r#" | |
446 | //- /lib.rs crate:main deps:foo | |
447 | use foo as bar$0; | |
448 | ||
449 | //- /foo/lib.rs crate:foo | |
450 | // empty | |
451 | //^file | |
452 | "#, | |
453 | ); | |
454 | } | |
455 | ||
456 | #[test] | |
457 | fn goto_def_for_use_alias_foo_macro() { | |
458 | check( | |
459 | r#" | |
460 | //- /lib.rs crate:main deps:foo | |
461 | use foo::foo as bar$0; | |
462 | ||
463 | //- /foo/lib.rs crate:foo | |
464 | #[macro_export] | |
465 | macro_rules! foo { () => { () } } | |
466 | //^^^ | |
467 | "#, | |
468 | ); | |
469 | } | |
470 | ||
471 | #[test] | |
472 | fn goto_def_for_methods() { | |
473 | check( | |
474 | r#" | |
475 | struct Foo; | |
476 | impl Foo { | |
477 | fn frobnicate(&self) { } | |
478 | //^^^^^^^^^^ | |
479 | } | |
480 | ||
481 | fn bar(foo: &Foo) { | |
482 | foo.frobnicate$0(); | |
483 | } | |
484 | "#, | |
485 | ); | |
486 | } | |
487 | ||
488 | #[test] | |
489 | fn goto_def_for_fields() { | |
490 | check( | |
491 | r#" | |
492 | struct Foo { | |
493 | spam: u32, | |
494 | } //^^^^ | |
495 | ||
496 | fn bar(foo: &Foo) { | |
497 | foo.spam$0; | |
498 | } | |
499 | "#, | |
500 | ); | |
501 | } | |
502 | ||
503 | #[test] | |
504 | fn goto_def_for_record_fields() { | |
505 | check( | |
506 | r#" | |
507 | //- /lib.rs | |
508 | struct Foo { | |
509 | spam: u32, | |
510 | } //^^^^ | |
511 | ||
512 | fn bar() -> Foo { | |
513 | Foo { | |
514 | spam$0: 0, | |
515 | } | |
516 | } | |
517 | "#, | |
518 | ); | |
519 | } | |
520 | ||
521 | #[test] | |
522 | fn goto_def_for_record_pat_fields() { | |
523 | check( | |
524 | r#" | |
525 | //- /lib.rs | |
526 | struct Foo { | |
527 | spam: u32, | |
528 | } //^^^^ | |
529 | ||
530 | fn bar(foo: Foo) -> Foo { | |
531 | let Foo { spam$0: _, } = foo | |
532 | } | |
533 | "#, | |
534 | ); | |
535 | } | |
536 | ||
537 | #[test] | |
538 | fn goto_def_for_record_fields_macros() { | |
539 | check( | |
540 | r" | |
541 | macro_rules! m { () => { 92 };} | |
542 | struct Foo { spam: u32 } | |
543 | //^^^^ | |
544 | ||
545 | fn bar() -> Foo { | |
546 | Foo { spam$0: m!() } | |
547 | } | |
548 | ", | |
549 | ); | |
550 | } | |
551 | ||
552 | #[test] | |
553 | fn goto_for_tuple_fields() { | |
554 | check( | |
555 | r#" | |
556 | struct Foo(u32); | |
557 | //^^^ | |
558 | ||
559 | fn bar() { | |
560 | let foo = Foo(0); | |
561 | foo.$00; | |
562 | } | |
563 | "#, | |
564 | ); | |
565 | } | |
566 | ||
567 | #[test] | |
568 | fn goto_def_for_ufcs_inherent_methods() { | |
569 | check( | |
570 | r#" | |
571 | struct Foo; | |
572 | impl Foo { | |
573 | fn frobnicate() { } | |
574 | } //^^^^^^^^^^ | |
575 | ||
576 | fn bar(foo: &Foo) { | |
577 | Foo::frobnicate$0(); | |
578 | } | |
579 | "#, | |
580 | ); | |
581 | } | |
582 | ||
583 | #[test] | |
584 | fn goto_def_for_ufcs_trait_methods_through_traits() { | |
585 | check( | |
586 | r#" | |
587 | trait Foo { | |
588 | fn frobnicate(); | |
589 | } //^^^^^^^^^^ | |
590 | ||
591 | fn bar() { | |
592 | Foo::frobnicate$0(); | |
593 | } | |
594 | "#, | |
595 | ); | |
596 | } | |
597 | ||
598 | #[test] | |
599 | fn goto_def_for_ufcs_trait_methods_through_self() { | |
600 | check( | |
601 | r#" | |
602 | struct Foo; | |
603 | trait Trait { | |
604 | fn frobnicate(); | |
605 | } //^^^^^^^^^^ | |
606 | impl Trait for Foo {} | |
607 | ||
608 | fn bar() { | |
609 | Foo::frobnicate$0(); | |
610 | } | |
611 | "#, | |
612 | ); | |
613 | } | |
614 | ||
615 | #[test] | |
616 | fn goto_definition_on_self() { | |
617 | check( | |
618 | r#" | |
619 | struct Foo; | |
620 | impl Foo { | |
621 | //^^^ | |
622 | pub fn new() -> Self { | |
623 | Self$0 {} | |
624 | } | |
625 | } | |
626 | "#, | |
627 | ); | |
628 | check( | |
629 | r#" | |
630 | struct Foo; | |
631 | impl Foo { | |
632 | //^^^ | |
633 | pub fn new() -> Self$0 { | |
634 | Self {} | |
635 | } | |
636 | } | |
637 | "#, | |
638 | ); | |
639 | ||
640 | check( | |
641 | r#" | |
642 | enum Foo { A } | |
643 | impl Foo { | |
644 | //^^^ | |
645 | pub fn new() -> Self$0 { | |
646 | Foo::A | |
647 | } | |
648 | } | |
649 | "#, | |
650 | ); | |
651 | ||
652 | check( | |
653 | r#" | |
654 | enum Foo { A } | |
655 | impl Foo { | |
656 | //^^^ | |
657 | pub fn thing(a: &Self$0) { | |
658 | } | |
659 | } | |
660 | "#, | |
661 | ); | |
662 | } | |
663 | ||
664 | #[test] | |
665 | fn goto_definition_on_self_in_trait_impl() { | |
666 | check( | |
667 | r#" | |
668 | struct Foo; | |
669 | trait Make { | |
670 | fn new() -> Self; | |
671 | } | |
672 | impl Make for Foo { | |
673 | //^^^ | |
674 | fn new() -> Self { | |
675 | Self$0 {} | |
676 | } | |
677 | } | |
678 | "#, | |
679 | ); | |
680 | ||
681 | check( | |
682 | r#" | |
683 | struct Foo; | |
684 | trait Make { | |
685 | fn new() -> Self; | |
686 | } | |
687 | impl Make for Foo { | |
688 | //^^^ | |
689 | fn new() -> Self$0 { | |
690 | Self {} | |
691 | } | |
692 | } | |
693 | "#, | |
694 | ); | |
695 | } | |
696 | ||
697 | #[test] | |
698 | fn goto_def_when_used_on_definition_name_itself() { | |
699 | check( | |
700 | r#" | |
701 | struct Foo$0 { value: u32 } | |
702 | //^^^ | |
703 | "#, | |
704 | ); | |
705 | ||
706 | check( | |
707 | r#" | |
708 | struct Foo { | |
709 | field$0: string, | |
710 | } //^^^^^ | |
711 | "#, | |
712 | ); | |
713 | ||
714 | check( | |
715 | r#" | |
716 | fn foo_test$0() { } | |
717 | //^^^^^^^^ | |
718 | "#, | |
719 | ); | |
720 | ||
721 | check( | |
722 | r#" | |
723 | enum Foo$0 { Variant } | |
724 | //^^^ | |
725 | "#, | |
726 | ); | |
727 | ||
728 | check( | |
729 | r#" | |
730 | enum Foo { | |
731 | Variant1, | |
732 | Variant2$0, | |
733 | //^^^^^^^^ | |
734 | Variant3, | |
735 | } | |
736 | "#, | |
737 | ); | |
738 | ||
739 | check( | |
740 | r#" | |
741 | static INNER$0: &str = ""; | |
742 | //^^^^^ | |
743 | "#, | |
744 | ); | |
745 | ||
746 | check( | |
747 | r#" | |
748 | const INNER$0: &str = ""; | |
749 | //^^^^^ | |
750 | "#, | |
751 | ); | |
752 | ||
753 | check( | |
754 | r#" | |
755 | type Thing$0 = Option<()>; | |
756 | //^^^^^ | |
757 | "#, | |
758 | ); | |
759 | ||
760 | check( | |
761 | r#" | |
762 | trait Foo$0 { } | |
763 | //^^^ | |
764 | "#, | |
765 | ); | |
766 | ||
767 | check( | |
768 | r#" | |
769 | mod bar$0 { } | |
770 | //^^^ | |
771 | "#, | |
772 | ); | |
773 | } | |
774 | ||
775 | #[test] | |
776 | fn goto_from_macro() { | |
777 | check( | |
778 | r#" | |
779 | macro_rules! id { | |
780 | ($($tt:tt)*) => { $($tt)* } | |
781 | } | |
782 | fn foo() {} | |
783 | //^^^ | |
784 | id! { | |
785 | fn bar() { | |
786 | fo$0o(); | |
787 | } | |
788 | } | |
789 | mod confuse_index { fn foo(); } | |
790 | "#, | |
791 | ); | |
792 | } | |
793 | ||
794 | #[test] | |
795 | fn goto_through_format() { | |
796 | check( | |
797 | r#" | |
798 | #[macro_export] | |
799 | macro_rules! format { | |
800 | ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*))) | |
801 | } | |
802 | #[rustc_builtin_macro] | |
803 | #[macro_export] | |
804 | macro_rules! format_args { | |
805 | ($fmt:expr) => ({ /* compiler built-in */ }); | |
806 | ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) | |
807 | } | |
808 | pub mod __export { | |
809 | pub use crate::format_args; | |
810 | fn foo() {} // for index confusion | |
811 | } | |
812 | fn foo() -> i8 {} | |
813 | //^^^ | |
814 | fn test() { | |
815 | format!("{}", fo$0o()) | |
816 | } | |
817 | "#, | |
818 | ); | |
819 | } | |
820 | ||
821 | #[test] | |
822 | fn goto_through_included_file() { | |
823 | check( | |
824 | r#" | |
825 | //- /main.rs | |
826 | #[rustc_builtin_macro] | |
827 | macro_rules! include {} | |
828 | ||
829 | include!("foo.rs"); | |
830 | //^^^^^^^^^^^^^^^^^^^ | |
831 | ||
832 | fn f() { | |
833 | foo$0(); | |
834 | } | |
835 | ||
836 | mod confuse_index { | |
837 | pub fn foo() {} | |
838 | } | |
839 | ||
840 | //- /foo.rs | |
841 | fn foo() {} | |
842 | "#, | |
843 | ); | |
844 | } | |
845 | ||
846 | #[test] | |
847 | fn goto_for_type_param() { | |
848 | check( | |
849 | r#" | |
850 | struct Foo<T: Clone> { t: $0T } | |
851 | //^ | |
852 | "#, | |
853 | ); | |
854 | } | |
855 | ||
856 | #[test] | |
857 | fn goto_within_macro() { | |
858 | check( | |
859 | r#" | |
860 | macro_rules! id { | |
861 | ($($tt:tt)*) => ($($tt)*) | |
862 | } | |
863 | ||
864 | fn foo() { | |
865 | let x = 1; | |
866 | //^ | |
867 | id!({ | |
868 | let y = $0x; | |
869 | let z = y; | |
870 | }); | |
871 | } | |
872 | "#, | |
873 | ); | |
874 | ||
875 | check( | |
876 | r#" | |
877 | macro_rules! id { | |
878 | ($($tt:tt)*) => ($($tt)*) | |
879 | } | |
880 | ||
881 | fn foo() { | |
882 | let x = 1; | |
883 | id!({ | |
884 | let y = x; | |
885 | //^ | |
886 | let z = $0y; | |
887 | }); | |
888 | } | |
889 | "#, | |
890 | ); | |
891 | } | |
892 | ||
893 | #[test] | |
894 | fn goto_def_in_local_fn() { | |
895 | check( | |
896 | r#" | |
897 | fn main() { | |
898 | fn foo() { | |
899 | let x = 92; | |
900 | //^ | |
901 | $0x; | |
902 | } | |
903 | } | |
904 | "#, | |
905 | ); | |
906 | } | |
907 | ||
908 | #[test] | |
909 | fn goto_def_in_local_macro() { | |
910 | check( | |
911 | r#" | |
912 | fn bar() { | |
913 | macro_rules! foo { () => { () } } | |
914 | //^^^ | |
915 | $0foo!(); | |
916 | } | |
917 | "#, | |
918 | ); | |
919 | } | |
920 | ||
921 | #[test] | |
922 | fn goto_def_for_field_init_shorthand() { | |
923 | check( | |
924 | r#" | |
925 | struct Foo { x: i32 } | |
926 | //^ | |
927 | fn main() { | |
928 | let x = 92; | |
929 | //^ | |
930 | Foo { x$0 }; | |
931 | } | |
932 | "#, | |
933 | ) | |
934 | } | |
935 | ||
936 | #[test] | |
937 | fn goto_def_for_enum_variant_field() { | |
938 | check( | |
939 | r#" | |
940 | enum Foo { | |
941 | Bar { x: i32 } | |
942 | //^ | |
943 | } | |
944 | fn baz(foo: Foo) { | |
945 | match foo { | |
946 | Foo::Bar { x$0 } => x | |
947 | //^ | |
948 | }; | |
949 | } | |
950 | "#, | |
951 | ); | |
952 | } | |
953 | ||
954 | #[test] | |
955 | fn goto_def_for_enum_variant_self_pattern_const() { | |
956 | check( | |
957 | r#" | |
958 | enum Foo { Bar } | |
959 | //^^^ | |
960 | impl Foo { | |
961 | fn baz(self) { | |
962 | match self { Self::Bar$0 => {} } | |
963 | } | |
964 | } | |
965 | "#, | |
966 | ); | |
967 | } | |
968 | ||
969 | #[test] | |
970 | fn goto_def_for_enum_variant_self_pattern_record() { | |
971 | check( | |
972 | r#" | |
973 | enum Foo { Bar { val: i32 } } | |
974 | //^^^ | |
975 | impl Foo { | |
976 | fn baz(self) -> i32 { | |
977 | match self { Self::Bar$0 { val } => {} } | |
978 | } | |
979 | } | |
980 | "#, | |
981 | ); | |
982 | } | |
983 | ||
984 | #[test] | |
985 | fn goto_def_for_enum_variant_self_expr_const() { | |
986 | check( | |
987 | r#" | |
988 | enum Foo { Bar } | |
989 | //^^^ | |
990 | impl Foo { | |
991 | fn baz(self) { Self::Bar$0; } | |
992 | } | |
993 | "#, | |
994 | ); | |
995 | } | |
996 | ||
997 | #[test] | |
998 | fn goto_def_for_enum_variant_self_expr_record() { | |
999 | check( | |
1000 | r#" | |
1001 | enum Foo { Bar { val: i32 } } | |
1002 | //^^^ | |
1003 | impl Foo { | |
1004 | fn baz(self) { Self::Bar$0 {val: 4}; } | |
1005 | } | |
1006 | "#, | |
1007 | ); | |
1008 | } | |
1009 | ||
1010 | #[test] | |
1011 | fn goto_def_for_type_alias_generic_parameter() { | |
1012 | check( | |
1013 | r#" | |
1014 | type Alias<T> = T$0; | |
1015 | //^ | |
1016 | "#, | |
1017 | ) | |
1018 | } | |
1019 | ||
1020 | #[test] | |
1021 | fn goto_def_for_macro_container() { | |
1022 | check( | |
1023 | r#" | |
1024 | //- /lib.rs crate:main deps:foo | |
1025 | foo::module$0::mac!(); | |
1026 | ||
1027 | //- /foo/lib.rs crate:foo | |
1028 | pub mod module { | |
1029 | //^^^^^^ | |
1030 | #[macro_export] | |
1031 | macro_rules! _mac { () => { () } } | |
1032 | pub use crate::_mac as mac; | |
1033 | } | |
1034 | "#, | |
1035 | ); | |
1036 | } | |
1037 | ||
1038 | #[test] | |
1039 | fn goto_def_for_assoc_ty_in_path() { | |
1040 | check( | |
1041 | r#" | |
1042 | trait Iterator { | |
1043 | type Item; | |
1044 | //^^^^ | |
1045 | } | |
1046 | ||
1047 | fn f() -> impl Iterator<Item$0 = u8> {} | |
1048 | "#, | |
1049 | ); | |
1050 | } | |
1051 | ||
1052 | #[test] | |
1053 | fn goto_def_for_super_assoc_ty_in_path() { | |
1054 | check( | |
1055 | r#" | |
1056 | trait Super { | |
1057 | type Item; | |
1058 | //^^^^ | |
1059 | } | |
1060 | ||
1061 | trait Sub: Super {} | |
1062 | ||
1063 | fn f() -> impl Sub<Item$0 = u8> {} | |
1064 | "#, | |
1065 | ); | |
1066 | } | |
1067 | ||
1068 | #[test] | |
1069 | fn unknown_assoc_ty() { | |
1070 | check_unresolved( | |
1071 | r#" | |
1072 | trait Iterator { type Item; } | |
1073 | fn f() -> impl Iterator<Invalid$0 = u8> {} | |
1074 | "#, | |
1075 | ) | |
1076 | } | |
1077 | ||
1078 | #[test] | |
1079 | fn goto_def_for_assoc_ty_in_path_multiple() { | |
1080 | check( | |
1081 | r#" | |
1082 | trait Iterator { | |
1083 | type A; | |
1084 | //^ | |
1085 | type B; | |
1086 | } | |
1087 | ||
1088 | fn f() -> impl Iterator<A$0 = u8, B = ()> {} | |
1089 | "#, | |
1090 | ); | |
1091 | check( | |
1092 | r#" | |
1093 | trait Iterator { | |
1094 | type A; | |
1095 | type B; | |
1096 | //^ | |
1097 | } | |
1098 | ||
1099 | fn f() -> impl Iterator<A = u8, B$0 = ()> {} | |
1100 | "#, | |
1101 | ); | |
1102 | } | |
1103 | ||
1104 | #[test] | |
1105 | fn goto_def_for_assoc_ty_ufcs() { | |
1106 | check( | |
1107 | r#" | |
1108 | trait Iterator { | |
1109 | type Item; | |
1110 | //^^^^ | |
1111 | } | |
1112 | ||
1113 | fn g() -> <() as Iterator<Item$0 = ()>>::Item {} | |
1114 | "#, | |
1115 | ); | |
1116 | } | |
1117 | ||
1118 | #[test] | |
1119 | fn goto_def_for_assoc_ty_ufcs_multiple() { | |
1120 | check( | |
1121 | r#" | |
1122 | trait Iterator { | |
1123 | type A; | |
1124 | //^ | |
1125 | type B; | |
1126 | } | |
1127 | ||
1128 | fn g() -> <() as Iterator<A$0 = (), B = u8>>::B {} | |
1129 | "#, | |
1130 | ); | |
1131 | check( | |
1132 | r#" | |
1133 | trait Iterator { | |
1134 | type A; | |
1135 | type B; | |
1136 | //^ | |
1137 | } | |
1138 | ||
1139 | fn g() -> <() as Iterator<A = (), B$0 = u8>>::A {} | |
1140 | "#, | |
1141 | ); | |
1142 | } | |
1143 | ||
1144 | #[test] | |
1145 | fn goto_self_param_ty_specified() { | |
1146 | check( | |
1147 | r#" | |
1148 | struct Foo {} | |
1149 | ||
1150 | impl Foo { | |
1151 | fn bar(self: &Foo) { | |
1152 | //^^^^ | |
1153 | let foo = sel$0f; | |
1154 | } | |
1155 | }"#, | |
1156 | ) | |
1157 | } | |
1158 | ||
1159 | #[test] | |
1160 | fn goto_self_param_on_decl() { | |
1161 | check( | |
1162 | r#" | |
1163 | struct Foo {} | |
1164 | ||
1165 | impl Foo { | |
1166 | fn bar(&self$0) { | |
1167 | //^^^^ | |
1168 | } | |
1169 | }"#, | |
1170 | ) | |
1171 | } | |
1172 | ||
1173 | #[test] | |
1174 | fn goto_lifetime_param_on_decl() { | |
1175 | check( | |
1176 | r#" | |
1177 | fn foo<'foobar$0>(_: &'foobar ()) { | |
1178 | //^^^^^^^ | |
1179 | }"#, | |
1180 | ) | |
1181 | } | |
1182 | ||
1183 | #[test] | |
1184 | fn goto_lifetime_param_decl() { | |
1185 | check( | |
1186 | r#" | |
1187 | fn foo<'foobar>(_: &'foobar$0 ()) { | |
1188 | //^^^^^^^ | |
1189 | }"#, | |
1190 | ) | |
1191 | } | |
1192 | ||
1193 | #[test] | |
1194 | fn goto_lifetime_param_decl_nested() { | |
1195 | check( | |
1196 | r#" | |
1197 | fn foo<'foobar>(_: &'foobar ()) { | |
1198 | fn foo<'foobar>(_: &'foobar$0 ()) {} | |
1199 | //^^^^^^^ | |
1200 | }"#, | |
1201 | ) | |
1202 | } | |
1203 | ||
1204 | #[test] | |
1205 | fn goto_lifetime_hrtb() { | |
1206 | // FIXME: requires the HIR to somehow track these hrtb lifetimes | |
1207 | check_unresolved( | |
1208 | r#" | |
1209 | trait Foo<T> {} | |
1210 | fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {} | |
1211 | //^^ | |
1212 | "#, | |
1213 | ); | |
1214 | check_unresolved( | |
1215 | r#" | |
1216 | trait Foo<T> {} | |
1217 | fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {} | |
1218 | //^^ | |
1219 | "#, | |
1220 | ); | |
1221 | } | |
1222 | ||
1223 | #[test] | |
1224 | fn goto_lifetime_hrtb_for_type() { | |
1225 | // FIXME: requires ForTypes to be implemented | |
1226 | check_unresolved( | |
1227 | r#"trait Foo<T> {} | |
1228 | fn foo<T>() where T: for<'a> Foo<&'a$0 (u8, u16)>, {} | |
1229 | //^^ | |
1230 | "#, | |
1231 | ); | |
1232 | } | |
1233 | ||
1234 | #[test] | |
1235 | fn goto_label() { | |
1236 | check( | |
1237 | r#" | |
1238 | fn foo<'foo>(_: &'foo ()) { | |
1239 | 'foo: { | |
1240 | //^^^^ | |
1241 | 'bar: loop { | |
1242 | break 'foo$0; | |
1243 | } | |
1244 | } | |
1245 | }"#, | |
1246 | ) | |
1247 | } | |
1248 | ||
1249 | #[test] | |
1250 | fn goto_def_for_intra_doc_link_same_file() { | |
1251 | check( | |
1252 | r#" | |
1253 | /// Blah, [`bar`](bar) .. [`foo`](foo$0) has [`bar`](bar) | |
1254 | pub fn bar() { } | |
1255 | ||
1256 | /// You might want to see [`std::fs::read()`] too. | |
1257 | pub fn foo() { } | |
1258 | //^^^ | |
1259 | ||
1260 | }"#, | |
1261 | ) | |
1262 | } | |
1263 | ||
1264 | #[test] | |
1265 | fn goto_def_for_intra_doc_link_inner() { | |
1266 | check( | |
1267 | r#" | |
1268 | //- /main.rs | |
1269 | mod m; | |
1270 | struct S; | |
1271 | //^ | |
1272 | ||
1273 | //- /m.rs | |
1274 | //! [`super::S$0`] | |
1275 | "#, | |
1276 | ) | |
1277 | } | |
1278 | ||
1279 | #[test] | |
1280 | fn goto_incomplete_field() { | |
1281 | check( | |
1282 | r#" | |
1283 | struct A { a: u32 } | |
1284 | //^ | |
1285 | fn foo() { A { a$0: }; } | |
1286 | "#, | |
1287 | ) | |
1288 | } | |
1289 | ||
1290 | #[test] | |
1291 | fn goto_proc_macro() { | |
1292 | check( | |
1293 | r#" | |
1294 | //- /main.rs crate:main deps:mac | |
1295 | use mac::fn_macro; | |
1296 | ||
1297 | fn_macro$0!(); | |
1298 | ||
1299 | //- /mac.rs crate:mac | |
1300 | #![crate_type="proc-macro"] | |
1301 | #[proc_macro] | |
1302 | fn fn_macro() {} | |
1303 | //^^^^^^^^ | |
1304 | "#, | |
1305 | ) | |
1306 | } | |
1307 | ||
1308 | #[test] | |
1309 | fn goto_intra_doc_links() { | |
1310 | check( | |
1311 | r#" | |
1312 | ||
1313 | pub mod theitem { | |
1314 | /// This is the item. Cool! | |
1315 | pub struct TheItem; | |
1316 | //^^^^^^^ | |
1317 | } | |
1318 | ||
1319 | /// Gives you a [`TheItem$0`]. | |
1320 | /// | |
1321 | /// [`TheItem`]: theitem::TheItem | |
1322 | pub fn gimme() -> theitem::TheItem { | |
1323 | theitem::TheItem | |
1324 | } | |
1325 | "#, | |
1326 | ); | |
1327 | } | |
1328 | ||
1329 | #[test] | |
1330 | fn goto_ident_from_pat_macro() { | |
1331 | check( | |
1332 | r#" | |
1333 | macro_rules! pat { | |
1334 | ($name:ident) => { Enum::Variant1($name) } | |
1335 | } | |
1336 | ||
1337 | enum Enum { | |
1338 | Variant1(u8), | |
1339 | Variant2, | |
1340 | } | |
1341 | ||
1342 | fn f(e: Enum) { | |
1343 | match e { | |
1344 | pat!(bind) => { | |
1345 | //^^^^ | |
1346 | bind$0 | |
1347 | } | |
1348 | Enum::Variant2 => {} | |
1349 | } | |
1350 | } | |
1351 | "#, | |
1352 | ); | |
1353 | } | |
1354 | ||
1355 | #[test] | |
1356 | fn goto_include() { | |
1357 | check( | |
1358 | r#" | |
1359 | //- /main.rs | |
2b03887a FG |
1360 | |
1361 | #[rustc_builtin_macro] | |
1362 | macro_rules! include_str {} | |
1363 | ||
064997fb FG |
1364 | fn main() { |
1365 | let str = include_str!("foo.txt$0"); | |
1366 | } | |
1367 | //- /foo.txt | |
1368 | // empty | |
1369 | //^file | |
1370 | "#, | |
1371 | ); | |
1372 | } | |
2b03887a FG |
1373 | |
1374 | #[test] | |
1375 | fn goto_doc_include_str() { | |
1376 | check( | |
1377 | r#" | |
1378 | //- /main.rs | |
1379 | #[rustc_builtin_macro] | |
1380 | macro_rules! include_str {} | |
1381 | ||
1382 | #[doc = include_str!("docs.md$0")] | |
1383 | struct Item; | |
1384 | ||
1385 | //- /docs.md | |
1386 | // docs | |
1387 | //^file | |
1388 | "#, | |
1389 | ); | |
1390 | } | |
1391 | ||
1392 | #[test] | |
1393 | fn goto_shadow_include() { | |
1394 | check( | |
1395 | r#" | |
1396 | //- /main.rs | |
1397 | macro_rules! include { | |
1398 | ("included.rs") => {} | |
1399 | } | |
1400 | ||
1401 | include!("included.rs$0"); | |
1402 | ||
1403 | //- /included.rs | |
1404 | // empty | |
1405 | "#, | |
1406 | ); | |
1407 | } | |
1408 | ||
064997fb FG |
1409 | #[cfg(test)] |
1410 | mod goto_impl_of_trait_fn { | |
1411 | use super::check; | |
1412 | #[test] | |
1413 | fn cursor_on_impl() { | |
1414 | check( | |
1415 | r#" | |
1416 | trait Twait { | |
1417 | fn a(); | |
1418 | } | |
1419 | ||
1420 | struct Stwuct; | |
1421 | ||
1422 | impl Twait for Stwuct { | |
1423 | fn a$0(); | |
1424 | //^ | |
1425 | } | |
1426 | "#, | |
1427 | ); | |
1428 | } | |
1429 | #[test] | |
1430 | fn method_call() { | |
1431 | check( | |
1432 | r#" | |
1433 | trait Twait { | |
1434 | fn a(&self); | |
1435 | } | |
1436 | ||
1437 | struct Stwuct; | |
1438 | ||
1439 | impl Twait for Stwuct { | |
1440 | fn a(&self){}; | |
1441 | //^ | |
1442 | } | |
1443 | fn f() { | |
1444 | let s = Stwuct; | |
1445 | s.a$0(); | |
1446 | } | |
1447 | "#, | |
1448 | ); | |
1449 | } | |
1450 | #[test] | |
1451 | fn path_call() { | |
1452 | check( | |
1453 | r#" | |
1454 | trait Twait { | |
1455 | fn a(&self); | |
1456 | } | |
1457 | ||
1458 | struct Stwuct; | |
1459 | ||
1460 | impl Twait for Stwuct { | |
1461 | fn a(&self){}; | |
1462 | //^ | |
1463 | } | |
1464 | fn f() { | |
1465 | let s = Stwuct; | |
1466 | Stwuct::a$0(&s); | |
1467 | } | |
1468 | "#, | |
1469 | ); | |
1470 | } | |
1471 | #[test] | |
1472 | fn where_clause_can_work() { | |
1473 | check( | |
1474 | r#" | |
1475 | trait G { | |
1476 | fn g(&self); | |
1477 | } | |
1478 | trait Bound{} | |
1479 | trait EA{} | |
1480 | struct Gen<T>(T); | |
1481 | impl <T:EA> G for Gen<T> { | |
1482 | fn g(&self) { | |
1483 | } | |
1484 | } | |
1485 | impl <T> G for Gen<T> | |
1486 | where T : Bound | |
1487 | { | |
1488 | fn g(&self){ | |
1489 | //^ | |
1490 | } | |
1491 | } | |
1492 | struct A; | |
1493 | impl Bound for A{} | |
1494 | fn f() { | |
1495 | let gen = Gen::<A>(A); | |
1496 | gen.g$0(); | |
1497 | } | |
1498 | "#, | |
1499 | ); | |
1500 | } | |
1501 | #[test] | |
1502 | fn wc_case_is_ok() { | |
1503 | check( | |
1504 | r#" | |
1505 | trait G { | |
1506 | fn g(&self); | |
1507 | } | |
1508 | trait BParent{} | |
1509 | trait Bound: BParent{} | |
1510 | struct Gen<T>(T); | |
1511 | impl <T> G for Gen<T> | |
1512 | where T : Bound | |
1513 | { | |
1514 | fn g(&self){ | |
1515 | //^ | |
1516 | } | |
1517 | } | |
1518 | struct A; | |
1519 | impl Bound for A{} | |
1520 | fn f() { | |
1521 | let gen = Gen::<A>(A); | |
1522 | gen.g$0(); | |
1523 | } | |
1524 | "#, | |
1525 | ); | |
1526 | } | |
1527 | ||
1528 | #[test] | |
1529 | fn method_call_defaulted() { | |
1530 | check( | |
1531 | r#" | |
1532 | trait Twait { | |
1533 | fn a(&self) {} | |
1534 | //^ | |
1535 | } | |
1536 | ||
1537 | struct Stwuct; | |
1538 | ||
1539 | impl Twait for Stwuct { | |
1540 | } | |
1541 | fn f() { | |
1542 | let s = Stwuct; | |
1543 | s.a$0(); | |
1544 | } | |
1545 | "#, | |
1546 | ); | |
1547 | } | |
1548 | ||
1549 | #[test] | |
1550 | fn method_call_on_generic() { | |
1551 | check( | |
1552 | r#" | |
1553 | trait Twait { | |
1554 | fn a(&self) {} | |
1555 | //^ | |
1556 | } | |
1557 | ||
1558 | fn f<T: Twait>(s: T) { | |
1559 | s.a$0(); | |
1560 | } | |
1561 | "#, | |
1562 | ); | |
1563 | } | |
1564 | } | |
1565 | ||
1566 | #[test] | |
1567 | fn goto_def_of_trait_impl_const() { | |
1568 | check( | |
1569 | r#" | |
1570 | trait Twait { | |
1571 | const NOMS: bool; | |
1572 | // ^^^^ | |
1573 | } | |
1574 | ||
1575 | struct Stwuct; | |
1576 | ||
1577 | impl Twait for Stwuct { | |
1578 | const NOMS$0: bool = true; | |
1579 | } | |
1580 | "#, | |
1581 | ); | |
1582 | } | |
1583 | ||
1584 | #[test] | |
1585 | fn goto_def_of_trait_impl_type_alias() { | |
1586 | check( | |
1587 | r#" | |
1588 | trait Twait { | |
1589 | type IsBad; | |
1590 | // ^^^^^ | |
1591 | } | |
1592 | ||
1593 | struct Stwuct; | |
1594 | ||
1595 | impl Twait for Stwuct { | |
1596 | type IsBad$0 = !; | |
1597 | } | |
1598 | "#, | |
1599 | ); | |
1600 | } | |
1601 | ||
1602 | #[test] | |
1603 | fn goto_def_derive_input() { | |
1604 | check( | |
1605 | r#" | |
1606 | //- minicore:derive | |
1607 | #[rustc_builtin_macro] | |
1608 | pub macro Copy {} | |
1609 | // ^^^^ | |
1610 | #[derive(Copy$0)] | |
1611 | struct Foo; | |
1612 | "#, | |
1613 | ); | |
1614 | check( | |
1615 | r#" | |
1616 | //- minicore:derive | |
1617 | #[rustc_builtin_macro] | |
1618 | pub macro Copy {} | |
1619 | // ^^^^ | |
1620 | #[cfg_attr(feature = "false", derive)] | |
1621 | #[derive(Copy$0)] | |
1622 | struct Foo; | |
1623 | "#, | |
1624 | ); | |
1625 | check( | |
1626 | r#" | |
1627 | //- minicore:derive | |
1628 | mod foo { | |
1629 | #[rustc_builtin_macro] | |
1630 | pub macro Copy {} | |
1631 | // ^^^^ | |
1632 | } | |
1633 | #[derive(foo::Copy$0)] | |
1634 | struct Foo; | |
1635 | "#, | |
1636 | ); | |
1637 | check( | |
1638 | r#" | |
1639 | //- minicore:derive | |
1640 | mod foo { | |
1641 | // ^^^ | |
1642 | #[rustc_builtin_macro] | |
1643 | pub macro Copy {} | |
1644 | } | |
1645 | #[derive(foo$0::Copy)] | |
1646 | struct Foo; | |
1647 | "#, | |
1648 | ); | |
1649 | } | |
1650 | ||
1651 | #[test] | |
1652 | fn goto_def_in_macro_multi() { | |
1653 | check( | |
1654 | r#" | |
1655 | struct Foo { | |
1656 | foo: () | |
1657 | //^^^ | |
1658 | } | |
1659 | macro_rules! foo { | |
1660 | ($ident:ident) => { | |
1661 | fn $ident(Foo { $ident }: Foo) {} | |
1662 | } | |
1663 | } | |
1664 | foo!(foo$0); | |
1665 | //^^^ | |
1666 | //^^^ | |
1667 | "#, | |
1668 | ); | |
1669 | check( | |
1670 | r#" | |
1671 | fn bar() {} | |
1672 | //^^^ | |
1673 | struct bar; | |
1674 | //^^^ | |
1675 | macro_rules! foo { | |
1676 | ($ident:ident) => { | |
1677 | fn foo() { | |
1678 | let _: $ident = $ident; | |
1679 | } | |
1680 | } | |
1681 | } | |
1682 | ||
1683 | foo!(bar$0); | |
f2b60f7d FG |
1684 | "#, |
1685 | ); | |
1686 | } | |
1687 | ||
1688 | #[test] | |
1689 | fn goto_await_poll() { | |
1690 | check( | |
1691 | r#" | |
1692 | //- minicore: future | |
1693 | ||
1694 | struct MyFut; | |
1695 | ||
1696 | impl core::future::Future for MyFut { | |
1697 | type Output = (); | |
1698 | ||
1699 | fn poll( | |
1700 | //^^^^ | |
1701 | self: std::pin::Pin<&mut Self>, | |
1702 | cx: &mut std::task::Context<'_> | |
1703 | ) -> std::task::Poll<Self::Output> | |
1704 | { | |
1705 | () | |
1706 | } | |
1707 | } | |
1708 | ||
1709 | fn f() { | |
1710 | MyFut.await$0; | |
1711 | } | |
1712 | "#, | |
1713 | ); | |
1714 | } | |
1715 | ||
1716 | #[test] | |
1717 | fn goto_await_into_future_poll() { | |
1718 | check( | |
1719 | r#" | |
1720 | //- minicore: future | |
1721 | ||
1722 | struct Futurable; | |
1723 | ||
1724 | impl core::future::IntoFuture for Futurable { | |
1725 | type IntoFuture = MyFut; | |
1726 | } | |
1727 | ||
1728 | struct MyFut; | |
1729 | ||
1730 | impl core::future::Future for MyFut { | |
1731 | type Output = (); | |
1732 | ||
1733 | fn poll( | |
1734 | //^^^^ | |
1735 | self: std::pin::Pin<&mut Self>, | |
1736 | cx: &mut std::task::Context<'_> | |
1737 | ) -> std::task::Poll<Self::Output> | |
1738 | { | |
1739 | () | |
1740 | } | |
1741 | } | |
1742 | ||
1743 | fn f() { | |
1744 | Futurable.await$0; | |
1745 | } | |
1746 | "#, | |
1747 | ); | |
1748 | } | |
1749 | ||
1750 | #[test] | |
1751 | fn goto_try_op() { | |
1752 | check( | |
1753 | r#" | |
1754 | //- minicore: try | |
1755 | ||
1756 | struct Struct; | |
1757 | ||
1758 | impl core::ops::Try for Struct { | |
1759 | fn branch( | |
1760 | //^^^^^^ | |
1761 | self | |
1762 | ) {} | |
1763 | } | |
1764 | ||
1765 | fn f() { | |
1766 | Struct?$0; | |
1767 | } | |
1768 | "#, | |
1769 | ); | |
1770 | } | |
1771 | ||
1772 | #[test] | |
1773 | fn goto_index_op() { | |
1774 | check( | |
1775 | r#" | |
1776 | //- minicore: index | |
1777 | ||
1778 | struct Struct; | |
1779 | ||
1780 | impl core::ops::Index<usize> for Struct { | |
1781 | fn index( | |
1782 | //^^^^^ | |
1783 | self | |
1784 | ) {} | |
1785 | } | |
1786 | ||
1787 | fn f() { | |
1788 | Struct[0]$0; | |
1789 | } | |
1790 | "#, | |
1791 | ); | |
1792 | } | |
1793 | ||
1794 | #[test] | |
1795 | fn goto_prefix_op() { | |
1796 | check( | |
1797 | r#" | |
1798 | //- minicore: deref | |
1799 | ||
1800 | struct Struct; | |
1801 | ||
1802 | impl core::ops::Deref for Struct { | |
1803 | fn deref( | |
1804 | //^^^^^ | |
1805 | self | |
1806 | ) {} | |
1807 | } | |
1808 | ||
1809 | fn f() { | |
1810 | $0*Struct; | |
1811 | } | |
1812 | "#, | |
1813 | ); | |
1814 | } | |
1815 | ||
1816 | #[test] | |
1817 | fn goto_bin_op() { | |
1818 | check( | |
1819 | r#" | |
1820 | //- minicore: add | |
1821 | ||
1822 | struct Struct; | |
1823 | ||
1824 | impl core::ops::Add for Struct { | |
1825 | fn add( | |
1826 | //^^^ | |
1827 | self | |
1828 | ) {} | |
1829 | } | |
1830 | ||
1831 | fn f() { | |
1832 | Struct +$0 Struct; | |
1833 | } | |
064997fb FG |
1834 | "#, |
1835 | ); | |
1836 | } | |
487cf647 FG |
1837 | |
1838 | #[test] | |
1839 | fn goto_bin_op_multiple_impl() { | |
1840 | check( | |
1841 | r#" | |
1842 | //- minicore: add | |
1843 | struct S; | |
1844 | impl core::ops::Add for S { | |
1845 | fn add( | |
1846 | //^^^ | |
1847 | ) {} | |
1848 | } | |
1849 | impl core::ops::Add<usize> for S { | |
1850 | fn add( | |
1851 | ) {} | |
1852 | } | |
1853 | ||
1854 | fn f() { | |
1855 | S +$0 S | |
1856 | } | |
1857 | "#, | |
1858 | ); | |
1859 | ||
1860 | check( | |
1861 | r#" | |
1862 | //- minicore: add | |
1863 | struct S; | |
1864 | impl core::ops::Add for S { | |
1865 | fn add( | |
1866 | ) {} | |
1867 | } | |
1868 | impl core::ops::Add<usize> for S { | |
1869 | fn add( | |
1870 | //^^^ | |
1871 | ) {} | |
1872 | } | |
1873 | ||
1874 | fn f() { | |
1875 | S +$0 0usize | |
1876 | } | |
1877 | "#, | |
1878 | ); | |
1879 | } | |
1880 | ||
1881 | #[test] | |
1882 | fn path_call_multiple_trait_impl() { | |
1883 | check( | |
1884 | r#" | |
1885 | trait Trait<T> { | |
1886 | fn f(_: T); | |
1887 | } | |
1888 | impl Trait<i32> for usize { | |
1889 | fn f(_: i32) {} | |
1890 | //^ | |
1891 | } | |
1892 | impl Trait<i64> for usize { | |
1893 | fn f(_: i64) {} | |
1894 | } | |
1895 | fn main() { | |
1896 | usize::f$0(0i32); | |
1897 | } | |
1898 | "#, | |
1899 | ); | |
1900 | ||
1901 | check( | |
1902 | r#" | |
1903 | trait Trait<T> { | |
1904 | fn f(_: T); | |
1905 | } | |
1906 | impl Trait<i32> for usize { | |
1907 | fn f(_: i32) {} | |
1908 | } | |
1909 | impl Trait<i64> for usize { | |
1910 | fn f(_: i64) {} | |
1911 | //^ | |
1912 | } | |
1913 | fn main() { | |
1914 | usize::f$0(0i64); | |
1915 | } | |
1916 | "#, | |
1917 | ) | |
1918 | } | |
064997fb | 1919 | } |