diff options
Diffstat (limited to 'crates/ra_ide/src/goto_definition.rs')
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 1168 |
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 | ||
13 | use crate::{ | 13 | use 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)] |
105 | mod tests { | 106 | mod 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 | 140 | struct Foo; |
150 | struct Foo; | 141 | //^^^ |
151 | enum E { X(Foo<|>) } | 142 | enum 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 | 151 | struct Foo; |
163 | struct Foo; | 152 | //^^^ |
164 | enum E { X(<|>Foo) } | 153 | enum 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; | 163 | use a::Foo; |
177 | mod a; | 164 | mod a; |
178 | mod b; | 165 | mod b; |
179 | enum E { X(Foo<|>) } | 166 | enum E { X(Foo<|>) } |
180 | 167 | ||
181 | //- /a.rs | 168 | //- /a.rs |
182 | struct Foo; | 169 | struct Foo; |
183 | 170 | //^^^ | |
184 | //- /b.rs | 171 | //- /b.rs |
185 | struct Foo; | 172 | struct 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 |
197 | mod <|>foo; | 182 | mod <|>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 |
209 | mod <|>foo; | 193 | mod <|>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 | 206 | macro_rules! foo { () => { () } } |
224 | macro_rules! foo { () => { () } } | 207 | //^^^ |
225 | 208 | fn 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 |
259 | use foo as bar<|>; | 220 | use foo::foo; |
221 | fn bar() { | ||
222 | <|>foo!(); | ||
223 | } | ||
260 | 224 | ||
261 | //- /foo/lib.rs | 225 | //- /foo/lib.rs |
262 | #[macro_export] | 226 | #[macro_export] |
263 | macro_rules! foo { () => { () } } | 227 | macro_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<|>; | 238 | use foo::foo<|>; |
292 | 239 | ||
293 | //- /foo/lib.rs | 240 | //- /foo/lib.rs |
294 | #[macro_export] | 241 | #[macro_export] |
295 | macro_rules! foo { () => { () } } | 242 | macro_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 |
307 | macro_rules! define_fn { | 253 | macro_rules! define_fn { |
@@ -309,522 +255,478 @@ macro_rules! define_fn { | |||
309 | } | 255 | } |
310 | 256 | ||
311 | define_fn!(foo); | 257 | define_fn!(foo); |
258 | //^^^ | ||
312 | 259 | ||
313 | fn bar() { | 260 | fn 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 |
327 | macro_rules! define_fn { | 272 | macro_rules! define_fn { |
328 | () => (fn foo() {}) | 273 | () => (fn foo() {}) |
329 | } | 274 | } |
330 | 275 | ||
331 | define_fn!(); | 276 | define_fn!(); |
277 | //^^^^^^^^^^^^^ | ||
332 | 278 | ||
333 | fn bar() { | 279 | fn 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}} | 291 | macro_rules! foo {() => {0}} |
348 | 292 | //^^^ | |
349 | fn bar() { | 293 | |
350 | match (0,1) { | 294 | fn 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}} | 308 | macro_rules! foo {() => {0}} |
366 | 309 | //^^^ | |
367 | fn bar() { | 310 | fn 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 | ||
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 | "#, | ||
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; | 353 | struct Foo; |
384 | impl Foo { | 354 | impl Foo { |
385 | fn frobnicate(&self) { } | 355 | fn frobnicate(&self) { } |
386 | } | 356 | //^^^^^^^^^^ |
357 | } | ||
387 | 358 | ||
388 | fn bar(foo: &Foo) { | 359 | fn 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 | 370 | struct Foo { |
402 | struct Foo { | 371 | spam: u32, |
403 | spam: u32, | 372 | } //^^^^ |
404 | } | ||
405 | 373 | ||
406 | fn bar(foo: &Foo) { | 374 | fn 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 { | 386 | struct Foo { |
421 | spam: u32, | 387 | spam: u32, |
422 | } | 388 | } //^^^^ |
423 | 389 | ||
424 | fn bar() -> Foo { | 390 | fn 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 { | 404 | struct Foo { |
441 | spam: u32, | 405 | spam: u32, |
442 | } | 406 | } //^^^^ |
443 | 407 | ||
444 | fn bar(foo: Foo) -> Foo { | 408 | fn 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 | 419 | macro_rules! m { () => { 92 };} |
458 | macro_rules! m { () => { 92 };} | 420 | struct Foo { spam: u32 } |
459 | struct Foo { spam: u32 } | 421 | //^^^^ |
460 | 422 | ||
461 | fn bar() -> Foo { | 423 | fn 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 | 434 | struct Foo(u32); |
475 | struct Foo(u32); | 435 | //^^^ |
476 | 436 | ||
477 | fn bar() { | 437 | fn 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 | 449 | struct Foo; |
492 | struct Foo; | 450 | impl Foo { |
493 | impl Foo { | 451 | fn frobnicate() { } |
494 | fn frobnicate() { } | 452 | } //^^^^^^^^^^ |
495 | } | ||
496 | 453 | ||
497 | fn bar(foo: &Foo) { | 454 | fn 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 | 465 | trait Foo { |
511 | trait Foo { | 466 | fn frobnicate(); |
512 | fn frobnicate(); | 467 | } //^^^^^^^^^^ |
513 | } | ||
514 | 468 | ||
515 | fn bar() { | 469 | fn 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 | 480 | struct Foo; |
529 | struct Foo; | 481 | trait Trait { |
530 | trait Trait { | 482 | fn frobnicate(); |
531 | fn frobnicate(); | 483 | } //^^^^^^^^^^ |
532 | } | 484 | impl Trait for Foo {} |
533 | impl Trait for Foo {} | ||
534 | 485 | ||
535 | fn bar() { | 486 | fn 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 | 497 | struct Foo; |
549 | struct Foo; | 498 | impl 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 | 508 | struct Foo; | |
560 | check_goto( | 509 | impl 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 {...}", | 520 | enum Foo { A } |
572 | ); | 521 | impl 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 | ", | 532 | enum Foo { A } |
584 | "impl IMPL_DEF FileId(1) 15..75", | 533 | impl 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 | 546 | struct Foo; |
607 | struct Foo; | 547 | trait Make { |
608 | trait Make { | 548 | fn new() -> Self; |
609 | fn new() -> Self; | 549 | } |
610 | } | 550 | impl 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 | 561 | struct Foo; |
624 | struct Foo; | 562 | trait Make { |
625 | trait Make { | 563 | fn new() -> Self; |
626 | fn new() -> Self; | 564 | } |
627 | } | 565 | impl 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 | 579 | struct 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 | 586 | struct 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 | 594 | fn 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 | 601 | enum 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 | 608 | enum 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 | 619 | static 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 | 626 | const 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 | 633 | type 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 | 640 | trait 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#" | ||
647 | mod 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 | 657 | macro_rules! id { |
745 | macro_rules! id { | 658 | ($($tt:tt)*) => { $($tt)* } |
746 | ($($tt:tt)*) => { $($tt)* } | 659 | } |
747 | } | 660 | fn foo() {} |
748 | fn foo() {} | 661 | //^^^ |
749 | id! { | 662 | id! { |
750 | fn bar() { | 663 | fn bar() { |
751 | fo<|>o(); | 664 | fo<|>o(); |
752 | } | 665 | } |
753 | } | 666 | } |
754 | mod confuse_index { fn foo(); } | 667 | mod 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] | 677 | macro_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] | 682 | macro_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 | } | 686 | pub 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 | } | 690 | fn foo() -> i8 {} |
780 | fn foo() -> i8 {} | 691 | //^^^ |
781 | fn test() { | 692 | fn 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 | 703 | struct 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 | ||
809 | macro_rules! id { | 713 | macro_rules! id { |
810 | ($($tt:tt)*) => ($($tt)*) | 714 | ($($tt:tt)*) => ($($tt)*) |
811 | } | 715 | } |
812 | 716 | ||
813 | fn foo() { | 717 | fn 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 | ||
828 | macro_rules! id { | 730 | macro_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 | 750 | fn 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 | 765 | fn 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 | 778 | struct Foo { x: i32 } |
882 | struct Foo { x: i32 } | 779 | fn 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 | 792 | enum Foo { |
898 | enum Foo { | 793 | Bar { x: i32 } |
899 | Bar { x: i32 } | 794 | } //^ |
900 | } | 795 | fn 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 | 808 | enum Foo { Bar } |
917 | enum Foo { | 809 | //^^^ |
918 | Bar, | 810 | impl 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 | 823 | enum Foo { Bar { val: i32 } } |
938 | enum Foo { | 824 | //^^^ |
939 | Bar { val: i32 }, | 825 | impl 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 | 838 | enum Foo { Bar } |
959 | enum Foo { | 839 | //^^^ |
960 | Bar, | 840 | impl 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 | 851 | enum Foo { Bar { val: i32 } } |
978 | enum Foo { | 852 | //^^^ |
979 | Bar { val: i32 }, | 853 | impl 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#" | ||
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 | "#, | ||
989 | ); | 965 | ); |
990 | } | 966 | } |
991 | } | 967 | } |