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  }