aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r--crates/ide_assists/src/tests.rs46
-rw-r--r--crates/ide_assists/src/utils/suggest_name.rs994
2 files changed, 424 insertions, 616 deletions
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index 66820058b..b7f616760 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -12,7 +12,7 @@ use ide_db::{
12 RootDatabase, 12 RootDatabase,
13}; 13};
14use stdx::{format_to, trim_indent}; 14use stdx::{format_to, trim_indent};
15use syntax::{ast, AstNode, TextRange}; 15use syntax::TextRange;
16use test_utils::{assert_eq_text, extract_offset}; 16use test_utils::{assert_eq_text, extract_offset};
17 17
18use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists}; 18use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists};
@@ -180,50 +180,6 @@ fn labels(assists: &[Assist]) -> String {
180 labels.into_iter().collect::<String>() 180 labels.into_iter().collect::<String>()
181} 181}
182 182
183pub(crate) type NameSuggestion = fn(&ast::Expr, &Semantics<'_, RootDatabase>) -> Option<String>;
184
185#[track_caller]
186pub(crate) fn check_name_suggestion(
187 suggestion: NameSuggestion,
188 ra_fixture: &str,
189 suggested_name: &str,
190) {
191 check_name(suggestion, ra_fixture, Some(suggested_name));
192}
193
194#[track_caller]
195pub(crate) fn check_name_suggestion_not_applicable(suggestion: NameSuggestion, ra_fixture: &str) {
196 check_name(suggestion, ra_fixture, None);
197}
198
199#[track_caller]
200fn check_name(suggestion: NameSuggestion, ra_fixture: &str, expected: Option<&str>) {
201 let (db, file_with_carret_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture);
202 let frange = FileRange { file_id: file_with_carret_id, range: range_or_offset.into() };
203
204 let sema = Semantics::new(&db);
205 let source_file = sema.parse(frange.file_id);
206 let element = source_file.syntax().covering_element(frange.range);
207 let expr =
208 element.ancestors().find_map(ast::Expr::cast).expect("selection is not an expression");
209 assert_eq!(
210 expr.syntax().text_range(),
211 frange.range,
212 "selection is not an expression(yet contained in one)"
213 );
214
215 let name = suggestion(&expr, &sema);
216
217 match (name, expected) {
218 (Some(name), Some(expected_name)) => {
219 assert_eq_text!(&name, expected_name);
220 }
221 (Some(_), None) => panic!("name suggestion should not be applicable"),
222 (None, Some(_)) => panic!("name suggestion is not applicable"),
223 (None, None) => (),
224 }
225}
226
227#[test] 183#[test]
228fn assist_order_field_struct() { 184fn assist_order_field_struct() {
229 let before = "struct Foo { $0bar: u32 }"; 185 let before = "struct Foo { $0bar: u32 }";
diff --git a/crates/ide_assists/src/utils/suggest_name.rs b/crates/ide_assists/src/utils/suggest_name.rs
index d37c62642..533624c1f 100644
--- a/crates/ide_assists/src/utils/suggest_name.rs
+++ b/crates/ide_assists/src/utils/suggest_name.rs
@@ -11,17 +11,20 @@ use syntax::{
11 11
12/// Trait names, that will be ignored when in `impl Trait` and `dyn Trait` 12/// Trait names, that will be ignored when in `impl Trait` and `dyn Trait`
13const USELESS_TRAITS: &[&str] = &["Send", "Sync", "Copy", "Clone", "Eq", "PartialEq"]; 13const USELESS_TRAITS: &[&str] = &["Send", "Sync", "Copy", "Clone", "Eq", "PartialEq"];
14
14/// Identifier names that won't be suggested, ever 15/// Identifier names that won't be suggested, ever
15/// 16///
16/// **NOTE**: they all must be snake lower case 17/// **NOTE**: they all must be snake lower case
17const USELESS_NAMES: &[&str] = 18const USELESS_NAMES: &[&str] =
18 &["new", "default", "option", "some", "none", "ok", "err", "str", "string"]; 19 &["new", "default", "option", "some", "none", "ok", "err", "str", "string"];
20
19/// Generic types replaced by their first argument 21/// Generic types replaced by their first argument
20/// 22///
21/// # Examples 23/// # Examples
22/// `Option<Name>` -> `Name` 24/// `Option<Name>` -> `Name`
23/// `Result<User, Error>` -> `User` 25/// `Result<User, Error>` -> `User`
24const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"]; 26const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"];
27
25/// Prefixes to strip from methods names 28/// Prefixes to strip from methods names
26/// 29///
27/// # Examples 30/// # Examples
@@ -29,6 +32,7 @@ const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"];
29/// `args.into_config()` -> `config` 32/// `args.into_config()` -> `config`
30/// `bytes.to_vec()` -> `vec` 33/// `bytes.to_vec()` -> `vec`
31const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"]; 34const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"];
35
32/// Useless methods that are stripped from expression 36/// Useless methods that are stripped from expression
33/// 37///
34/// # Examples 38/// # Examples
@@ -253,625 +257,473 @@ fn trait_name(trait_: &hir::Trait, db: &RootDatabase) -> Option<String> {
253 257
254#[cfg(test)] 258#[cfg(test)]
255mod tests { 259mod tests {
256 use super::*; 260 use ide_db::base_db::{fixture::WithFixture, FileRange};
257
258 use crate::tests::check_name_suggestion;
259
260 mod from_func_call {
261 use super::*;
262
263 #[test]
264 fn no_args() {
265 check_name_suggestion(
266 |e, _| from_func_call(e),
267 r#"
268 fn foo() {
269 $0bar()$0
270 }"#,
271 "bar",
272 );
273 }
274 261
275 #[test] 262 use super::*;
276 fn single_arg() {
277 check_name_suggestion(
278 |e, _| from_func_call(e),
279 r#"
280 fn foo() {
281 $0bar(1)$0
282 }"#,
283 "bar",
284 );
285 }
286
287 #[test]
288 fn many_args() {
289 check_name_suggestion(
290 |e, _| from_func_call(e),
291 r#"
292 fn foo() {
293 $0bar(1, 2, 3)$0
294 }"#,
295 "bar",
296 );
297 }
298
299 #[test]
300 fn path() {
301 check_name_suggestion(
302 |e, _| from_func_call(e),
303 r#"
304 fn foo() {
305 $0i32::bar(1, 2, 3)$0
306 }"#,
307 "bar",
308 );
309 }
310 263
311 #[test] 264 #[track_caller]
312 fn generic_params() { 265 fn check(ra_fixture: &str, expected: &str) {
313 check_name_suggestion( 266 let (db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture);
314 |e, _| from_func_call(e), 267 let frange = FileRange { file_id, range: range_or_offset.into() };
315 r#" 268
316 fn foo() { 269 let sema = Semantics::new(&db);
317 $0bar::<i32>(1, 2, 3)$0 270 let source_file = sema.parse(frange.file_id);
318 }"#, 271 let element = source_file.syntax().covering_element(frange.range);
319 "bar", 272 let expr =
320 ); 273 element.ancestors().find_map(ast::Expr::cast).expect("selection is not an expression");
321 } 274 assert_eq!(
275 expr.syntax().text_range(),
276 frange.range,
277 "selection is not an expression(yet contained in one)"
278 );
279 let name = variable(&expr, &sema);
280 assert_eq!(&name, expected);
322 } 281 }
323 282
324 mod from_method_call { 283 #[test]
325 use super::*; 284 fn no_args() {
326 285 check(r#"fn foo() { $0bar()$0 }"#, "bar");
327 #[test] 286 check(r#"fn foo() { $0bar.frobnicate()$0 }"#, "frobnicate");
328 fn no_args() {
329 check_name_suggestion(
330 |e, _| from_method_call(e),
331 r#"
332 fn foo() {
333 $0bar.frobnicate()$0
334 }"#,
335 "frobnicate",
336 );
337 }
338
339 #[test]
340 fn generic_params() {
341 check_name_suggestion(
342 |e, _| from_method_call(e),
343 r#"
344 fn foo() {
345 $0bar.frobnicate::<i32, u32>()$0
346 }"#,
347 "frobnicate",
348 );
349 }
350
351 #[test]
352 fn to_name() {
353 check_name_suggestion(
354 |e, _| from_method_call(e),
355 r#"
356 struct Args;
357 struct Config;
358 impl Args {
359 fn to_config(&self) -> Config {}
360 }
361 fn foo() {
362 $0Args.to_config()$0;
363 }"#,
364 "config",
365 );
366 }
367 } 287 }
368 288
369 mod from_param { 289 #[test]
370 use crate::tests::check_name_suggestion_not_applicable; 290 fn single_arg() {
291 check(r#"fn foo() { $0bar(1)$0 }"#, "bar");
292 }
371 293
372 use super::*; 294 #[test]
295 fn many_args() {
296 check(r#"fn foo() { $0bar(1, 2, 3)$0 }"#, "bar");
297 }
373 298
374 #[test] 299 #[test]
375 fn plain_func() { 300 fn path() {
376 check_name_suggestion( 301 check(r#"fn foo() { $0i32::bar(1, 2, 3)$0 }"#, "bar");
377 from_param, 302 }
378 r#"
379 fn bar(n: i32, m: u32);
380 fn foo() {
381 bar($01$0, 2)
382 }"#,
383 "n",
384 );
385 }
386 303
387 #[test] 304 #[test]
388 fn mut_param() { 305 fn generic_params() {
389 check_name_suggestion( 306 check(r#"fn foo() { $0bar::<i32>(1, 2, 3)$0 }"#, "bar");
390 from_param, 307 check(r#"fn foo() { $0bar.frobnicate::<i32, u32>()$0 }"#, "frobnicate");
391 r#" 308 }
392 fn bar(mut n: i32, m: u32);
393 fn foo() {
394 bar($01$0, 2)
395 }"#,
396 "n",
397 );
398 }
399 309
400 #[test] 310 #[test]
401 fn func_does_not_exist() { 311 fn to_name() {
402 check_name_suggestion_not_applicable( 312 check(
403 from_param, 313 r#"
404 r#" 314struct Args;
405 fn foo() { 315struct Config;
406 bar($01$0, 2) 316impl Args {
407 }"#, 317 fn to_config(&self) -> Config {}
408 ); 318}
409 } 319fn foo() {
320 $0Args.to_config()$0;
321}
322"#,
323 "config",
324 );
325 }
410 326
411 #[test] 327 #[test]
412 fn unnamed_param() { 328 fn plain_func() {
413 check_name_suggestion_not_applicable( 329 check(
414 from_param, 330 r#"
415 r#" 331fn bar(n: i32, m: u32);
416 fn bar(_: i32, m: u32); 332fn foo() { bar($01$0, 2) }
417 fn foo() { 333"#,
418 bar($01$0, 2) 334 "n",
419 }"#, 335 );
420 ); 336 }
421 }
422 337
423 #[test] 338 #[test]
424 fn tuple_pat() { 339 fn mut_param() {
425 check_name_suggestion_not_applicable( 340 check(
426 from_param, 341 r#"
427 r#" 342fn bar(mut n: i32, m: u32);
428 fn bar((n, k): (i32, i32), m: u32); 343fn foo() { bar($01$0, 2) }
429 fn foo() { 344"#,
430 bar($0(1, 2)$0, 3) 345 "n",
431 }"#, 346 );
432 ); 347 }
433 }
434 348
435 #[test] 349 #[test]
436 fn ref_pat() { 350 fn func_does_not_exist() {
437 check_name_suggestion( 351 check(r#"fn foo() { bar($01$0, 2) }"#, "var_name");
438 from_param, 352 }
439 r#"
440 fn bar(&n: &i32, m: u32);
441 fn foo() {
442 bar($0&1$0, 3)
443 }"#,
444 "n",
445 );
446 }
447 353
448 #[test] 354 #[test]
449 fn box_pat() { 355 fn unnamed_param() {
450 check_name_suggestion( 356 check(
451 from_param, 357 r#"
452 r#" 358fn bar(_: i32, m: u32);
453 fn bar(box n: &i32, m: u32); 359fn foo() { bar($01$0, 2) }
454 fn foo() { 360"#,
455 bar($01$0, 3) 361 "var_name",
456 }"#, 362 );
457 "n", 363 }
458 );
459 }
460 364
461 #[test] 365 #[test]
462 fn param_out_of_index() { 366 fn tuple_pat() {
463 check_name_suggestion_not_applicable( 367 check(
464 from_param, 368 r#"
465 r#" 369fn bar((n, k): (i32, i32), m: u32);
466 fn bar(n: i32, m: u32); 370fn foo() {
467 fn foo() { 371 bar($0(1, 2)$0, 3)
468 bar(1, 2, $03$0) 372}
469 }"#, 373"#,
470 ); 374 "var_name",
471 } 375 );
376 }
472 377
473 #[test] 378 #[test]
474 fn generic_param_resolved() { 379 fn ref_pat() {
475 check_name_suggestion( 380 check(
476 from_param, 381 r#"
477 r#" 382fn bar(&n: &i32, m: u32);
478 fn bar<T>(n: T, m: u32); 383fn foo() { bar($0&1$0, 3) }
479 fn foo() { 384"#,
480 bar($01$0, 2) 385 "n",
481 }"#, 386 );
482 "n", 387 }
483 );
484 }
485 388
486 #[test] 389 #[test]
487 fn generic_param_unresolved() { 390 fn box_pat() {
488 check_name_suggestion( 391 check(
489 from_param, 392 r#"
490 r#" 393fn bar(box n: &i32, m: u32);
491 fn bar<T>(n: T, m: u32); 394fn foo() { bar($01$0, 3) }
492 fn foo<T>(x: T) { 395"#,
493 bar($0x$0, 2) 396 "n",
494 }"#, 397 );
495 "n", 398 }
496 );
497 }
498 399
499 #[test] 400 #[test]
500 fn method() { 401 fn param_out_of_index() {
501 check_name_suggestion( 402 check(
502 from_param, 403 r#"
503 r#" 404fn bar(n: i32, m: u32);
504 struct S; 405fn foo() { bar(1, 2, $03$0) }
505 impl S { 406"#,
506 fn bar(&self, n: i32, m: u32); 407 "var_name",
507 } 408 );
508 fn foo() { 409 }
509 S.bar($01$0, 2)
510 }"#,
511 "n",
512 );
513 }
514 410
515 #[test] 411 #[test]
516 fn method_ufcs() { 412 fn generic_param_resolved() {
517 check_name_suggestion( 413 check(
518 from_param, 414 r#"
519 r#" 415fn bar<T>(n: T, m: u32);
520 struct S; 416fn foo() { bar($01$0, 2) }
521 impl S { 417"#,
522 fn bar(&self, n: i32, m: u32); 418 "n",
523 } 419 );
524 fn foo() { 420 }
525 S::bar(&S, $01$0, 2)
526 }"#,
527 "n",
528 );
529 }
530 421
531 #[test] 422 #[test]
532 fn method_self() { 423 fn generic_param_unresolved() {
533 check_name_suggestion_not_applicable( 424 check(
534 from_param, 425 r#"
535 r#" 426fn bar<T>(n: T, m: u32);
536 struct S; 427fn foo<T>(x: T) { bar($0x$0, 2) }
537 impl S { 428"#,
538 fn bar(&self, n: i32, m: u32); 429 "n",
539 } 430 );
540 fn foo() { 431 }
541 S::bar($0&S$0, 1, 2)
542 }"#,
543 );
544 }
545 432
546 #[test] 433 #[test]
547 fn method_self_named() { 434 fn method() {
548 check_name_suggestion( 435 check(
549 from_param, 436 r#"
550 r#" 437struct S;
551 struct S; 438impl S { fn bar(&self, n: i32, m: u32); }
552 impl S { 439fn foo() { S.bar($01$0, 2) }
553 fn bar(strukt: &Self, n: i32, m: u32); 440"#,
554 } 441 "n",
555 fn foo() { 442 );
556 S::bar($0&S$0, 1, 2)
557 }"#,
558 "strukt",
559 );
560 }
561 } 443 }
562 444
563 mod from_type { 445 #[test]
564 use crate::tests::check_name_suggestion_not_applicable; 446 fn method_ufcs() {
447 check(
448 r#"
449struct S;
450impl S { fn bar(&self, n: i32, m: u32); }
451fn foo() { S::bar(&S, $01$0, 2) }
452"#,
453 "n",
454 );
455 }
565 456
566 use super::*; 457 #[test]
458 fn method_self() {
459 check(
460 r#"
461struct S;
462impl S { fn bar(&self, n: i32, m: u32); }
463fn foo() { S::bar($0&S$0, 1, 2) }
464"#,
465 "s",
466 );
467 }
567 468
568 #[test] 469 #[test]
569 fn i32() { 470 fn method_self_named() {
570 check_name_suggestion_not_applicable( 471 check(
571 from_type, 472 r#"
572 r#" 473struct S;
573 fn foo() { 474impl S { fn bar(strukt: &Self, n: i32, m: u32); }
574 let _: i32 = $01$0; 475fn foo() { S::bar($0&S$0, 1, 2) }
575 }"#, 476"#,
576 ); 477 "strukt",
577 } 478 );
479 }
578 480
579 #[test] 481 #[test]
580 fn u64() { 482 fn i32() {
581 check_name_suggestion_not_applicable( 483 check(r#"fn foo() { let _: i32 = $01$0; }"#, "var_name");
582 from_type, 484 }
583 r#"
584 fn foo() {
585 let _: u64 = $01$0;
586 }"#,
587 );
588 }
589 485
590 #[test] 486 #[test]
591 fn bool() { 487 fn u64() {
592 check_name_suggestion_not_applicable( 488 check(r#"fn foo() { let _: u64 = $01$0; }"#, "var_name");
593 from_type, 489 }
594 r#"
595 fn foo() {
596 let _: bool = $0true$0;
597 }"#,
598 );
599 }
600 490
601 #[test] 491 #[test]
602 fn struct_unit() { 492 fn bool() {
603 check_name_suggestion( 493 check(r#"fn foo() { let _: bool = $0true$0; }"#, "var_name");
604 from_type, 494 }
605 r#"
606 struct Seed;
607 fn foo() {
608 let _ = $0Seed$0;
609 }"#,
610 "seed",
611 );
612 }
613 495
614 #[test] 496 #[test]
615 fn struct_unit_to_snake() { 497 fn struct_unit() {
616 check_name_suggestion( 498 check(
617 from_type, 499 r#"
618 r#" 500struct Seed;
619 struct SeedState; 501fn foo() { let _ = $0Seed$0; }
620 fn foo() { 502"#,
621 let _ = $0SeedState$0; 503 "seed",
622 }"#, 504 );
623 "seed_state", 505 }
624 );
625 }
626 506
627 #[test] 507 #[test]
628 fn struct_single_arg() { 508 fn struct_unit_to_snake() {
629 check_name_suggestion( 509 check(
630 from_type, 510 r#"
631 r#" 511struct SeedState;
632 struct Seed(u32); 512fn foo() { let _ = $0SeedState$0; }
633 fn foo() { 513"#,
634 let _ = $0Seed(0)$0; 514 "seed_state",
635 }"#, 515 );
636 "seed", 516 }
637 );
638 }
639 517
640 #[test] 518 #[test]
641 fn struct_with_fields() { 519 fn struct_single_arg() {
642 check_name_suggestion( 520 check(
643 from_type, 521 r#"
644 r#" 522struct Seed(u32);
645 struct Seed { value: u32 } 523fn foo() { let _ = $0Seed(0)$0; }
646 fn foo() { 524"#,
647 let _ = $0Seed { value: 0 }$0; 525 "seed",
648 }"#, 526 );
649 "seed", 527 }
650 );
651 }
652 528
653 #[test] 529 #[test]
654 fn enum_() { 530 fn struct_with_fields() {
655 check_name_suggestion( 531 check(
656 from_type, 532 r#"
657 r#" 533struct Seed { value: u32 }
658 enum Kind { A, B } 534fn foo() { let _ = $0Seed { value: 0 }$0; }
659 fn foo() { 535"#,
660 let _ = $0Kind::A$0; 536 "seed",
661 }"#, 537 );
662 "kind", 538 }
663 );
664 }
665 539
666 #[test] 540 #[test]
667 fn enum_generic_resolved() { 541 fn enum_() {
668 check_name_suggestion( 542 check(
669 from_type, 543 r#"
670 r#" 544enum Kind { A, B }
671 enum Kind<T> { A(T), B } 545fn foo() { let _ = $0Kind::A$0; }
672 fn foo() { 546"#,
673 let _ = $0Kind::A(1)$0; 547 "kind",
674 }"#, 548 );
675 "kind", 549 }
676 );
677 }
678 550
679 #[test] 551 #[test]
680 fn enum_generic_unresolved() { 552 fn enum_generic_resolved() {
681 check_name_suggestion( 553 check(
682 from_type, 554 r#"
683 r#" 555enum Kind<T> { A { x: T }, B }
684 enum Kind<T> { A(T), B } 556fn foo() { let _ = $0Kind::A { x:1 }$0; }
685 fn foo<T>(x: T) { 557"#,
686 let _ = $0Kind::A(x)$0; 558 "kind",
687 }"#, 559 );
688 "kind", 560 }
689 );
690 }
691 561
692 #[test] 562 #[test]
693 fn dyn_trait() { 563 fn enum_generic_unresolved() {
694 check_name_suggestion( 564 check(
695 from_type, 565 r#"
696 r#" 566enum Kind<T> { A { x: T }, B }
697 trait DynHandler {} 567fn foo<T>(x: T) { let _ = $0Kind::A { x }$0; }
698 fn bar() -> dyn DynHandler {} 568"#,
699 fn foo() { 569 "kind",
700 $0bar()$0; 570 );
701 }"#, 571 }
702 "dyn_handler",
703 );
704 }
705 572
706 #[test] 573 #[test]
707 fn impl_trait() { 574 fn dyn_trait() {
708 check_name_suggestion( 575 check(
709 from_type, 576 r#"
710 r#" 577trait DynHandler {}
711 trait StaticHandler {} 578fn bar() -> dyn DynHandler {}
712 fn bar() -> impl StaticHandler {} 579fn foo() { $0(bar())$0; }
713 fn foo() { 580"#,
714 $0bar()$0; 581 "dyn_handler",
715 }"#, 582 );
716 "static_handler", 583 }
717 );
718 }
719 584
720 #[test] 585 #[test]
721 fn impl_trait_plus_clone() { 586 fn impl_trait() {
722 check_name_suggestion( 587 check(
723 from_type, 588 r#"
724 r#" 589trait StaticHandler {}
725 trait StaticHandler {} 590fn bar() -> impl StaticHandler {}
726 trait Clone {} 591fn foo() { $0(bar())$0; }
727 fn bar() -> impl StaticHandler + Clone {} 592"#,
728 fn foo() { 593 "static_handler",
729 $0bar()$0; 594 );
730 }"#, 595 }
731 "static_handler",
732 );
733 }
734 596
735 #[test] 597 #[test]
736 fn impl_trait_plus_lifetime() { 598 fn impl_trait_plus_clone() {
737 check_name_suggestion( 599 check(
738 from_type, 600 r#"
739 r#" 601trait StaticHandler {}
740 trait StaticHandler {} 602trait Clone {}
741 trait Clone {} 603fn bar() -> impl StaticHandler + Clone {}
742 fn bar<'a>(&'a i32) -> impl StaticHandler + 'a {} 604fn foo() { $0(bar())$0; }
743 fn foo() { 605"#,
744 $0bar(&1)$0; 606 "static_handler",
745 }"#, 607 );
746 "static_handler", 608 }
747 );
748 }
749 609
750 #[test] 610 #[test]
751 fn impl_trait_plus_trait() { 611 fn impl_trait_plus_lifetime() {
752 check_name_suggestion_not_applicable( 612 check(
753 from_type, 613 r#"
754 r#" 614trait StaticHandler {}
755 trait Handler {} 615trait Clone {}
756 trait StaticHandler {} 616fn bar<'a>(&'a i32) -> impl StaticHandler + 'a {}
757 fn bar() -> impl StaticHandler + Handler {} 617fn foo() { $0(bar(&1))$0; }
758 fn foo() { 618"#,
759 $0bar()$0; 619 "static_handler",
760 }"#, 620 );
761 ); 621 }
762 }
763 622
764 #[test] 623 #[test]
765 fn ref_value() { 624 fn impl_trait_plus_trait() {
766 check_name_suggestion( 625 check(
767 from_type, 626 r#"
768 r#" 627trait Handler {}
769 struct Seed; 628trait StaticHandler {}
770 fn bar() -> &Seed {} 629fn bar() -> impl StaticHandler + Handler {}
771 fn foo() { 630fn foo() { $0(bar())$0; }
772 $0bar()$0; 631"#,
773 }"#, 632 "bar",
774 "seed", 633 );
775 ); 634 }
776 }
777 635
778 #[test] 636 #[test]
779 fn box_value() { 637 fn ref_value() {
780 check_name_suggestion( 638 check(
781 from_type, 639 r#"
782 r#" 640struct Seed;
783 struct Box<T>(*const T); 641fn bar() -> &Seed {}
784 struct Seed; 642fn foo() { $0(bar())$0; }
785 fn bar() -> Box<Seed> {} 643"#,
786 fn foo() { 644 "seed",
787 $0bar()$0; 645 );
788 }"#, 646 }
789 "seed",
790 );
791 }
792 647
793 #[test] 648 #[test]
794 fn box_generic() { 649 fn box_value() {
795 check_name_suggestion_not_applicable( 650 check(
796 from_type, 651 r#"
797 r#" 652struct Box<T>(*const T);
798 struct Box<T>(*const T); 653struct Seed;
799 fn bar<T>() -> Box<T> {} 654fn bar() -> Box<Seed> {}
800 fn foo<T>() { 655fn foo() { $0(bar())$0; }
801 $0bar::<T>()$0; 656"#,
802 }"#, 657 "seed",
803 ); 658 );
804 } 659 }
805 660
806 #[test] 661 #[test]
807 fn option_value() { 662 fn box_generic() {
808 check_name_suggestion( 663 check(
809 from_type, 664 r#"
810 r#" 665struct Box<T>(*const T);
811 enum Option<T> { Some(T) } 666fn bar<T>() -> Box<T> {}
812 struct Seed; 667fn foo<T>() { $0(bar::<T>())$0; }
813 fn bar() -> Option<Seed> {} 668"#,
814 fn foo() { 669 "bar",
815 $0bar()$0; 670 );
816 }"#, 671 }
817 "seed",
818 );
819 }
820 672
821 #[test] 673 #[test]
822 fn result_value() { 674 fn option_value() {
823 check_name_suggestion( 675 check(
824 from_type, 676 r#"
825 r#" 677enum Option<T> { Some(T) }
826 enum Result<T, E> { Ok(T), Err(E) } 678struct Seed;
827 struct Seed; 679fn bar() -> Option<Seed> {}
828 struct Error; 680fn foo() { $0(bar())$0; }
829 fn bar() -> Result<Seed, Error> {} 681"#,
830 fn foo() { 682 "seed",
831 $0bar()$0; 683 );
832 }"#,
833 "seed",
834 );
835 }
836 } 684 }
837 685
838 mod variable { 686 #[test]
839 use super::*; 687 fn result_value() {
688 check(
689 r#"
690enum Result<T, E> { Ok(T), Err(E) }
691struct Seed;
692struct Error;
693fn bar() -> Result<Seed, Error> {}
694fn foo() { $0(bar())$0; }
695"#,
696 "seed",
697 );
698 }
840 699
841 #[test] 700 #[test]
842 fn ref_call() { 701 fn ref_call() {
843 check_name_suggestion( 702 check(
844 |e, c| Some(variable(e, c)), 703 r#"
845 r#" 704fn foo() { $0&bar(1, 3)$0 }
846 fn foo() { 705"#,
847 $0&bar(1, 3)$0 706 "bar",
848 }"#, 707 );
849 "bar", 708 }
850 );
851 }
852 709
853 #[test] 710 #[test]
854 fn name_to_string() { 711 fn name_to_string() {
855 check_name_suggestion( 712 check(
856 |e, c| Some(variable(e, c)), 713 r#"
857 r#" 714fn foo() { $0function.name().to_string()$0 }
858 fn foo() { 715"#,
859 $0function.name().to_string()$0 716 "name",
860 }"#, 717 );
861 "name", 718 }
862 );
863 }
864 719
865 #[test] 720 #[test]
866 fn nested_useless_method() { 721 fn nested_useless_method() {
867 check_name_suggestion( 722 check(
868 |e, c| Some(variable(e, c)), 723 r#"
869 r#" 724fn foo() { $0function.name().as_ref().unwrap().to_string()$0 }
870 fn foo() { 725"#,
871 $0function.name().as_ref().unwrap().to_string()$0 726 "name",
872 }"#, 727 );
873 "name",
874 );
875 }
876 } 728 }
877} 729}