golang.org/x/tools/gopls@v0.15.3/internal/test/integration/misc/fix_test.go (about)

     1  // Copyright 2020 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 misc
     6  
     7  import (
     8  	"testing"
     9  
    10  	"golang.org/x/tools/gopls/internal/test/compare"
    11  	. "golang.org/x/tools/gopls/internal/test/integration"
    12  
    13  	"golang.org/x/tools/gopls/internal/protocol"
    14  )
    15  
    16  // A basic test for fillstruct, now that it uses a command and supports resolve edits.
    17  func TestFillStruct(t *testing.T) {
    18  	tc := []struct {
    19  		name         string
    20  		capabilities string
    21  		wantCommand  bool
    22  	}{
    23  		{"default", "{}", true},
    24  		{"no data", `{ "textDocument": {"codeAction": {	"resolveSupport": { "properties": ["edit"] } } } }`, true},
    25  		{"resolve support", `{ "textDocument": {"codeAction": {	"dataSupport": true, "resolveSupport": { "properties": ["edit"] } } } }`, false},
    26  	}
    27  
    28  	const basic = `
    29  -- go.mod --
    30  module mod.com
    31  
    32  go 1.14
    33  -- main.go --
    34  package main
    35  
    36  type Info struct {
    37  	WordCounts map[string]int
    38  	Words []string
    39  }
    40  
    41  func Foo() {
    42  	_ = Info{}
    43  }
    44  `
    45  
    46  	for _, tt := range tc {
    47  		t.Run(tt.name, func(t *testing.T) {
    48  			runner := WithOptions(CapabilitiesJSON([]byte(tt.capabilities)))
    49  
    50  			runner.Run(t, basic, func(t *testing.T, env *Env) {
    51  				env.OpenFile("main.go")
    52  				fixes, err := env.Editor.CodeActions(env.Ctx, env.RegexpSearch("main.go", "Info{}"), nil, protocol.RefactorRewrite)
    53  				if err != nil {
    54  					t.Fatal(err)
    55  				}
    56  				if len(fixes) != 1 {
    57  					t.Fatalf("expected 1 code action, got %v", len(fixes))
    58  				}
    59  				if tt.wantCommand {
    60  					if fixes[0].Command == nil || fixes[0].Data != nil {
    61  						t.Errorf("expected code action to have command not data, got %v", fixes[0])
    62  					}
    63  				} else {
    64  					if fixes[0].Command != nil || fixes[0].Data == nil {
    65  						t.Errorf("expected code action to have command not data, got %v", fixes[0])
    66  					}
    67  				}
    68  
    69  				// Apply the code action (handles resolving the code action), and check that the result is correct.
    70  				if err := env.Editor.RefactorRewrite(env.Ctx, env.RegexpSearch("main.go", "Info{}")); err != nil {
    71  					t.Fatal(err)
    72  				}
    73  				want := `package main
    74  
    75  type Info struct {
    76  	WordCounts map[string]int
    77  	Words []string
    78  }
    79  
    80  func Foo() {
    81  	_ = Info{
    82  		WordCounts: map[string]int{},
    83  		Words:      []string{},
    84  	}
    85  }
    86  `
    87  				if got := env.BufferText("main.go"); got != want {
    88  					t.Fatalf("TestFillStruct failed:\n%s", compare.Text(want, got))
    89  				}
    90  			})
    91  		})
    92  	}
    93  }
    94  
    95  func TestFillReturns(t *testing.T) {
    96  	const files = `
    97  -- go.mod --
    98  module mod.com
    99  
   100  go 1.12
   101  -- main.go --
   102  package main
   103  
   104  func Foo() error {
   105  	return
   106  }
   107  `
   108  	Run(t, files, func(t *testing.T, env *Env) {
   109  		env.OpenFile("main.go")
   110  		var d protocol.PublishDiagnosticsParams
   111  		env.AfterChange(
   112  			// The error message here changed in 1.18; "return values" covers both forms.
   113  			Diagnostics(env.AtRegexp("main.go", `return`), WithMessage("return values")),
   114  			ReadDiagnostics("main.go", &d),
   115  		)
   116  		codeActions := env.CodeAction("main.go", d.Diagnostics)
   117  		if len(codeActions) != 1 {
   118  			t.Fatalf("expected 1 code actions, got %v\n%v", len(codeActions), codeActions)
   119  		}
   120  		var foundQuickFix bool
   121  		for _, a := range codeActions {
   122  			if a.Kind == protocol.QuickFix {
   123  				foundQuickFix = true
   124  			}
   125  		}
   126  		if !foundQuickFix {
   127  			t.Fatalf("expected quickfix code action, got none")
   128  		}
   129  		env.ApplyQuickFixes("main.go", d.Diagnostics)
   130  		env.AfterChange(NoDiagnostics(ForFile("main.go")))
   131  	})
   132  }
   133  
   134  func TestUnusedParameter_Issue63755(t *testing.T) {
   135  	// This test verifies the fix for #63755, where codeActions panicked on parameters
   136  	// of functions with no function body.
   137  
   138  	// We should not detect parameters as unused for external functions.
   139  
   140  	const files = `
   141  -- go.mod --
   142  module unused.mod
   143  
   144  go 1.18
   145  
   146  -- external.go --
   147  package external
   148  
   149  func External(z int) //@codeaction("refactor.rewrite", "z", "z", recursive)
   150  
   151  func _() {
   152  	External(1)
   153  }
   154  	`
   155  	Run(t, files, func(t *testing.T, env *Env) {
   156  		env.OpenFile("external.go")
   157  		actions, err := env.Editor.CodeAction(env.Ctx, env.RegexpSearch("external.go", "z"), nil)
   158  		if err != nil {
   159  			t.Fatal(err)
   160  		}
   161  		if len(actions) > 0 {
   162  			t.Errorf("CodeAction(): got %d code actions, want 0", len(actions))
   163  		}
   164  	})
   165  }