golang.org/x/tools/gopls@v0.15.3/internal/test/integration/completion/postfix_snippet_test.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package completion 6 7 import ( 8 "strings" 9 "testing" 10 11 . "golang.org/x/tools/gopls/internal/test/integration" 12 ) 13 14 func TestPostfixSnippetCompletion(t *testing.T) { 15 const mod = ` 16 -- go.mod -- 17 module mod.com 18 19 go 1.12 20 ` 21 22 cases := []struct { 23 name string 24 before, after string 25 allowMultipleItem bool 26 }{ 27 { 28 name: "sort", 29 before: ` 30 package foo 31 32 func _() { 33 var foo []int 34 foo.sort 35 } 36 `, 37 after: ` 38 package foo 39 40 import "sort" 41 42 func _() { 43 var foo []int 44 sort.Slice(foo, func(i, j int) bool { 45 $0 46 }) 47 } 48 `, 49 }, 50 { 51 name: "sort_renamed_sort_package", 52 before: ` 53 package foo 54 55 import blahsort "sort" 56 57 var j int 58 59 func _() { 60 var foo []int 61 foo.sort 62 } 63 `, 64 after: ` 65 package foo 66 67 import blahsort "sort" 68 69 var j int 70 71 func _() { 72 var foo []int 73 blahsort.Slice(foo, func(i, j2 int) bool { 74 $0 75 }) 76 } 77 `, 78 }, 79 { 80 name: "last", 81 before: ` 82 package foo 83 84 func _() { 85 var s struct { i []int } 86 s.i.last 87 } 88 `, 89 after: ` 90 package foo 91 92 func _() { 93 var s struct { i []int } 94 s.i[len(s.i)-1] 95 } 96 `, 97 }, 98 { 99 name: "reverse", 100 before: ` 101 package foo 102 103 func _() { 104 var foo []int 105 foo.reverse 106 } 107 `, 108 after: ` 109 package foo 110 111 func _() { 112 var foo []int 113 for i, j := 0, len(foo)-1; i < j; i, j = i+1, j-1 { 114 foo[i], foo[j] = foo[j], foo[i] 115 } 116 117 } 118 `, 119 }, 120 { 121 name: "slice_range", 122 before: ` 123 package foo 124 125 func _() { 126 type myThing struct{} 127 var foo []myThing 128 foo.range 129 } 130 `, 131 after: ` 132 package foo 133 134 func _() { 135 type myThing struct{} 136 var foo []myThing 137 for ${1:}, ${2:} := range foo { 138 $0 139 } 140 } 141 `, 142 }, 143 { 144 name: "append_stmt", 145 before: ` 146 package foo 147 148 func _() { 149 var foo []int 150 foo.append 151 } 152 `, 153 after: ` 154 package foo 155 156 func _() { 157 var foo []int 158 foo = append(foo, $0) 159 } 160 `, 161 }, 162 { 163 name: "append_expr", 164 before: ` 165 package foo 166 167 func _() { 168 var foo []int 169 var _ []int = foo.append 170 } 171 `, 172 after: ` 173 package foo 174 175 func _() { 176 var foo []int 177 var _ []int = append(foo, $0) 178 } 179 `, 180 }, 181 { 182 name: "slice_copy", 183 before: ` 184 package foo 185 186 func _() { 187 var foo []int 188 foo.copy 189 } 190 `, 191 after: ` 192 package foo 193 194 func _() { 195 var foo []int 196 fooCopy := make([]int, len(foo)) 197 copy(fooCopy, foo) 198 199 } 200 `, 201 }, 202 { 203 name: "map_range", 204 before: ` 205 package foo 206 207 func _() { 208 var foo map[string]int 209 foo.range 210 } 211 `, 212 after: ` 213 package foo 214 215 func _() { 216 var foo map[string]int 217 for ${1:}, ${2:} := range foo { 218 $0 219 } 220 } 221 `, 222 }, 223 { 224 name: "map_clear", 225 before: ` 226 package foo 227 228 func _() { 229 var foo map[string]int 230 foo.clear 231 } 232 `, 233 after: ` 234 package foo 235 236 func _() { 237 var foo map[string]int 238 for k := range foo { 239 delete(foo, k) 240 } 241 242 } 243 `, 244 }, 245 { 246 name: "map_keys", 247 before: ` 248 package foo 249 250 func _() { 251 var foo map[string]int 252 foo.keys 253 } 254 `, 255 after: ` 256 package foo 257 258 func _() { 259 var foo map[string]int 260 keys := make([]string, 0, len(foo)) 261 for k := range foo { 262 keys = append(keys, k) 263 } 264 265 } 266 `, 267 }, 268 { 269 name: "channel_range", 270 before: ` 271 package foo 272 273 func _() { 274 foo := make(chan int) 275 foo.range 276 } 277 `, 278 after: ` 279 package foo 280 281 func _() { 282 foo := make(chan int) 283 for ${1:} := range foo { 284 $0 285 } 286 } 287 `, 288 }, 289 { 290 name: "var", 291 before: ` 292 package foo 293 294 func foo() (int, error) { return 0, nil } 295 296 func _() { 297 foo().var 298 } 299 `, 300 after: ` 301 package foo 302 303 func foo() (int, error) { return 0, nil } 304 305 func _() { 306 ${1:}, ${2:} := foo() 307 } 308 `, 309 allowMultipleItem: true, 310 }, 311 { 312 name: "var_single_value", 313 before: ` 314 package foo 315 316 func foo() error { return nil } 317 318 func _() { 319 foo().var 320 } 321 `, 322 allowMultipleItem: true, 323 after: ` 324 package foo 325 326 func foo() error { return nil } 327 328 func _() { 329 ${1:} := foo() 330 } 331 `, 332 }, 333 { 334 name: "var_same_type", 335 before: ` 336 package foo 337 338 func foo() (int, int) { return 0, 0 } 339 340 func _() { 341 foo().var 342 } 343 `, 344 after: ` 345 package foo 346 347 func foo() (int, int) { return 0, 0 } 348 349 func _() { 350 ${1:}, ${2:} := foo() 351 } 352 `, 353 }, 354 { 355 name: "print_scalar", 356 before: ` 357 package foo 358 359 func _() { 360 var foo int 361 foo.print 362 } 363 `, 364 after: ` 365 package foo 366 367 import "fmt" 368 369 func _() { 370 var foo int 371 fmt.Printf("foo: %v\n", foo) 372 } 373 `, 374 }, 375 { 376 name: "print_multi", 377 before: ` 378 package foo 379 380 func foo() (int, error) { return 0, nil } 381 382 func _() { 383 foo().print 384 } 385 `, 386 after: ` 387 package foo 388 389 import "fmt" 390 391 func foo() (int, error) { return 0, nil } 392 393 func _() { 394 fmt.Println(foo()) 395 } 396 `, 397 }, 398 { 399 name: "string split", 400 before: ` 401 package foo 402 403 func foo() []string { 404 x := "test" 405 return x.split 406 }`, 407 after: ` 408 package foo 409 410 import "strings" 411 412 func foo() []string { 413 x := "test" 414 return strings.Split(x, "$0") 415 }`, 416 }, 417 { 418 name: "string slice join", 419 before: ` 420 package foo 421 422 func foo() string { 423 x := []string{"a", "test"} 424 return x.join 425 }`, 426 after: ` 427 package foo 428 429 import "strings" 430 431 func foo() string { 432 x := []string{"a", "test"} 433 return strings.Join(x, "$0") 434 }`, 435 }, 436 { 437 name: "if not nil interface", 438 before: ` 439 package foo 440 441 func _() { 442 var foo error 443 foo.ifnotnil 444 } 445 `, 446 after: ` 447 package foo 448 449 func _() { 450 var foo error 451 if foo != nil { 452 $0 453 } 454 } 455 `, 456 }, 457 { 458 name: "if not nil pointer", 459 before: ` 460 package foo 461 462 func _() { 463 var foo *int 464 foo.ifnotnil 465 } 466 `, 467 after: ` 468 package foo 469 470 func _() { 471 var foo *int 472 if foo != nil { 473 $0 474 } 475 } 476 `, 477 }, 478 { 479 name: "if not nil slice", 480 before: ` 481 package foo 482 483 func _() { 484 var foo []int 485 foo.ifnotnil 486 } 487 `, 488 after: ` 489 package foo 490 491 func _() { 492 var foo []int 493 if foo != nil { 494 $0 495 } 496 } 497 `, 498 }, 499 { 500 name: "if not nil map", 501 before: ` 502 package foo 503 504 func _() { 505 var foo map[string]any 506 foo.ifnotnil 507 } 508 `, 509 after: ` 510 package foo 511 512 func _() { 513 var foo map[string]any 514 if foo != nil { 515 $0 516 } 517 } 518 `, 519 }, 520 { 521 name: "if not nil channel", 522 before: ` 523 package foo 524 525 func _() { 526 var foo chan int 527 foo.ifnotnil 528 } 529 `, 530 after: ` 531 package foo 532 533 func _() { 534 var foo chan int 535 if foo != nil { 536 $0 537 } 538 } 539 `, 540 }, 541 { 542 name: "if not nil function", 543 before: ` 544 package foo 545 546 func _() { 547 var foo func() 548 foo.ifnotnil 549 } 550 `, 551 after: ` 552 package foo 553 554 func _() { 555 var foo func() 556 if foo != nil { 557 $0 558 } 559 } 560 `, 561 }, 562 { 563 name: "slice_len", 564 before: ` 565 package foo 566 567 func _() { 568 var foo []int 569 foo.len 570 } 571 `, 572 after: ` 573 package foo 574 575 func _() { 576 var foo []int 577 len(foo) 578 } 579 `, 580 }, 581 { 582 name: "map_len", 583 before: ` 584 package foo 585 586 func _() { 587 var foo map[string]int 588 foo.len 589 } 590 `, 591 after: ` 592 package foo 593 594 func _() { 595 var foo map[string]int 596 len(foo) 597 } 598 `, 599 }, 600 { 601 name: "slice_for", 602 allowMultipleItem: true, 603 before: ` 604 package foo 605 606 func _() { 607 var foo []int 608 foo.for 609 } 610 `, 611 after: ` 612 package foo 613 614 func _() { 615 var foo []int 616 for ${1:} := range foo { 617 $0 618 } 619 } 620 `, 621 }, 622 { 623 name: "map_for", 624 allowMultipleItem: true, 625 before: ` 626 package foo 627 628 func _() { 629 var foo map[string]int 630 foo.for 631 } 632 `, 633 after: ` 634 package foo 635 636 func _() { 637 var foo map[string]int 638 for ${1:} := range foo { 639 $0 640 } 641 } 642 `, 643 }, 644 { 645 name: "chan_for", 646 allowMultipleItem: true, 647 before: ` 648 package foo 649 650 func _() { 651 var foo chan int 652 foo.for 653 } 654 `, 655 after: ` 656 package foo 657 658 func _() { 659 var foo chan int 660 for ${1:} := range foo { 661 $0 662 } 663 } 664 `, 665 }, 666 { 667 name: "slice_forr", 668 before: ` 669 package foo 670 671 func _() { 672 var foo []int 673 foo.forr 674 } 675 `, 676 after: ` 677 package foo 678 679 func _() { 680 var foo []int 681 for ${1:}, ${2:} := range foo { 682 $0 683 } 684 } 685 `, 686 }, 687 { 688 name: "slice_forr", 689 before: ` 690 package foo 691 692 func _() { 693 var foo []int 694 foo.forr 695 } 696 `, 697 after: ` 698 package foo 699 700 func _() { 701 var foo []int 702 for ${1:}, ${2:} := range foo { 703 $0 704 } 705 } 706 `, 707 }, 708 { 709 name: "map_forr", 710 before: ` 711 package foo 712 713 func _() { 714 var foo map[string]int 715 foo.forr 716 } 717 `, 718 after: ` 719 package foo 720 721 func _() { 722 var foo map[string]int 723 for ${1:}, ${2:} := range foo { 724 $0 725 } 726 } 727 `, 728 }, 729 } 730 731 r := WithOptions( 732 Settings{ 733 "experimentalPostfixCompletions": true, 734 }, 735 ) 736 r.Run(t, mod, func(t *testing.T, env *Env) { 737 env.CreateBuffer("foo.go", "") 738 739 for _, c := range cases { 740 t.Run(c.name, func(t *testing.T) { 741 c.before = strings.Trim(c.before, "\n") 742 c.after = strings.Trim(c.after, "\n") 743 744 env.SetBufferContent("foo.go", c.before) 745 746 loc := env.RegexpSearch("foo.go", "\n}") 747 completions := env.Completion(loc) 748 if len(completions.Items) < 1 { 749 t.Fatalf("expected at least one completion, got %v", completions.Items) 750 } 751 if !c.allowMultipleItem && len(completions.Items) > 1 { 752 t.Fatalf("expected one completion, got %v", completions.Items) 753 } 754 755 env.AcceptCompletion(loc, completions.Items[0]) 756 757 if buf := env.BufferText("foo.go"); buf != c.after { 758 t.Errorf("\nGOT:\n%s\nEXPECTED:\n%s", buf, c.after) 759 } 760 }) 761 } 762 }) 763 }