From 38ed81a6b5538535b3f83203cf3bf0c6289e2291 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 3 Nov 2023 12:50:15 -0400 Subject: [PATCH] gopls/internal/regtest/marker: porting extract tests Port the extraction tests, which involved a mixture of suggestedfix, extractmethod, and extractfunc markers (notably, nothing was running the extractfunc markers!). To do this, extend the new codeaction markers to accept an option slice of titles to use for filtering. Modify the method/func extraction tests to reduce verbosity and long lines. For golang/go#54845 Change-Id: I319d1c731a4cdb4ad952944667bc57d781ad176d Reviewed-on: https://go-review.googlesource.com/c/tools/+/539481 Reviewed-by: Alan Donovan LUCI-TryBot-Result: Go LUCI --- gopls/internal/lsp/lsp_test.go | 52 --- gopls/internal/lsp/regtest/marker.go | 58 ++- .../extract/extract_method/extract_basic.go | 24 -- .../extract_method/extract_basic.go.golden | 364 ------------------ .../extract/extract_method/extract_context.go | 20 - .../extract_method/extract_context.go.golden | 52 --- .../extract_variable/extract_basic_lit.go | 6 - .../extract_basic_lit.go.golden | 18 - .../extract_variable/extract_func_call.go | 9 - .../extract_func_call.go.golden | 24 -- .../extract/extract_variable/extract_scope.go | 13 - .../extract_variable/extract_scope.go.golden | 32 -- .../internal/lsp/testdata/summary.txt.golden | 3 +- gopls/internal/lsp/tests/tests.go | 52 +-- .../testdata/codeaction/extract_method.txt | 244 ++++++++++++ .../testdata/codeaction/extract_variable.txt | 83 ++++ 16 files changed, 379 insertions(+), 675 deletions(-) delete mode 100644 gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go delete mode 100644 gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden delete mode 100644 gopls/internal/lsp/testdata/extract/extract_method/extract_context.go delete mode 100644 gopls/internal/lsp/testdata/extract/extract_method/extract_context.go.golden delete mode 100644 gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go delete mode 100644 gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden delete mode 100644 gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go delete mode 100644 gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden delete mode 100644 gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go delete mode 100644 gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden create mode 100644 gopls/internal/regtest/marker/testdata/codeaction/extract_method.txt create mode 100644 gopls/internal/regtest/marker/testdata/codeaction/extract_variable.txt diff --git a/gopls/internal/lsp/lsp_test.go b/gopls/internal/lsp/lsp_test.go index 34f3330520d..8ef127d8ff4 100644 --- a/gopls/internal/lsp/lsp_test.go +++ b/gopls/internal/lsp/lsp_test.go @@ -345,58 +345,6 @@ func (r *runner) SuggestedFix(t *testing.T, spn span.Span, actionKinds []tests.S } } -func (r *runner) MethodExtraction(t *testing.T, start span.Span, end span.Span) { - uri := start.URI() - m, err := r.data.Mapper(uri) - if err != nil { - t.Fatal(err) - } - spn := span.New(start.URI(), start.Start(), end.End()) - rng, err := m.SpanRange(spn) - if err != nil { - t.Fatal(err) - } - actionsRaw, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{ - TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.URIFromSpanURI(uri), - }, - Range: rng, - Context: protocol.CodeActionContext{ - Only: []protocol.CodeActionKind{"refactor.extract"}, - }, - }) - if err != nil { - t.Fatal(err) - } - var actions []protocol.CodeAction - for _, action := range actionsRaw { - if action.Command.Title == "Extract method" { - actions = append(actions, action) - } - } - // Hack: We assume that we only get one matching code action per range. - // TODO(rstambler): Support multiple code actions per test. - if len(actions) == 0 || len(actions) > 1 { - t.Fatalf("unexpected number of code actions, want 1, got %v", len(actions)) - } - _, err = r.server.ExecuteCommand(r.ctx, &protocol.ExecuteCommandParams{ - Command: actions[0].Command.Command, - Arguments: actions[0].Command.Arguments, - }) - if err != nil { - t.Fatal(err) - } - res := <-r.editRecv - for u, got := range res { - want := r.data.Golden(t, "methodextraction_"+tests.SpanName(spn), u.Filename(), func() ([]byte, error) { - return got, nil - }) - if diff := compare.Bytes(want, got); diff != "" { - t.Errorf("method extraction failed for %s:\n%s", u.Filename(), diff) - } - } -} - func (r *runner) InlayHints(t *testing.T, spn span.Span) { uri := spn.URI() filename := uri.Filename() diff --git a/gopls/internal/lsp/regtest/marker.go b/gopls/internal/lsp/regtest/marker.go index eea6e15d283..45ecc74e41a 100644 --- a/gopls/internal/lsp/regtest/marker.go +++ b/gopls/internal/lsp/regtest/marker.go @@ -153,15 +153,20 @@ var update = flag.Bool("update", false, "if set, update test data during marker // completion candidate produced at the given location with provided label // results in the given golden state. // -// - codeaction(start, end, kind, golden): specifies a code action to request -// for the given range. To support multi-line ranges, the range is defined -// to be between start.Start and end.End. The golden directory contains -// changed file content after the code action is applied. +// - codeaction(start, end, kind, golden, ...titles): specifies a code action +// to request for the given range. To support multi-line ranges, the range +// is defined to be between start.Start and end.End. The golden directory +// contains changed file content after the code action is applied. +// If titles are provided, they are used to filter the matching code +// action. // -// - codeactionedit(range, kind, golden): a shorter form of codeaction. -// Invokes a code action of the given kind for the given in-line range, and -// compares the resulting formatted unified *edits* (notably, not the full -// file content) with the golden directory. +// TODO(rfindley): consolidate with codeactionedit, via a @loc2 marker that +// allows binding multi-line locations. +// +// - codeactionedit(range, kind, golden, ...titles): a shorter form of +// codeaction. Invokes a code action of the given kind for the given +// in-line range, and compares the resulting formatted unified *edits* +// (notably, not the full file content) with the golden directory. // // - codeactionerr(start, end, kind, wantError): specifies a codeaction that // fails with an error that matches the expectation. @@ -381,12 +386,15 @@ var update = flag.Bool("update", false, "if set, update test data during marker // - Provide some means by which locations in the standard library // (or builtin.go) can be named, so that, for example, we can we // can assert that MyError implements the built-in error type. +// - If possible, improve handling for optional arguments. Rather than have +// multiple variations of a marker, it would be nice to support a more +// flexible signature: can codeaction, codeactionedit, codeactionerr, and +// suggestedfix be consolidated? // // Existing marker tests (in ../testdata) to port: // - CallHierarchy // - SemanticTokens // - SuggestedFixes -// - MethodExtractions // - InlayHints // - Renames // - SelectionRanges @@ -1924,13 +1932,13 @@ func applyDocumentChanges(env *Env, changes []protocol.DocumentChanges, fileChan return nil } -func codeActionMarker(mark marker, start, end protocol.Location, actionKind string, g *Golden) { +func codeActionMarker(mark marker, start, end protocol.Location, actionKind string, g *Golden, titles ...string) { // Request the range from start.Start to end.End. loc := start loc.Range.End = end.Range.End // Apply the fix it suggests. - changed, err := codeAction(mark.run.env, loc.URI, loc.Range, actionKind, nil) + changed, err := codeAction(mark.run.env, loc.URI, loc.Range, actionKind, nil, titles) if err != nil { mark.errorf("codeAction failed: %v", err) return @@ -1940,8 +1948,8 @@ func codeActionMarker(mark marker, start, end protocol.Location, actionKind stri checkChangedFiles(mark, changed, g) } -func codeActionEditMarker(mark marker, loc protocol.Location, actionKind string, g *Golden) { - changed, err := codeAction(mark.run.env, loc.URI, loc.Range, actionKind, nil) +func codeActionEditMarker(mark marker, loc protocol.Location, actionKind string, g *Golden, titles ...string) { + changed, err := codeAction(mark.run.env, loc.URI, loc.Range, actionKind, nil, titles) if err != nil { mark.errorf("codeAction failed: %v", err) return @@ -1953,7 +1961,7 @@ func codeActionEditMarker(mark marker, loc protocol.Location, actionKind string, func codeActionErrMarker(mark marker, start, end protocol.Location, actionKind string, wantErr wantError) { loc := start loc.Range.End = end.Range.End - _, err := codeAction(mark.run.env, loc.URI, loc.Range, actionKind, nil) + _, err := codeAction(mark.run.env, loc.URI, loc.Range, actionKind, nil, nil) wantErr.check(mark, err) } @@ -2037,7 +2045,7 @@ func suggestedfixMarker(mark marker, loc protocol.Location, re *regexp.Regexp, g } // Apply the fix it suggests. - changed, err := codeAction(mark.run.env, loc.URI, diag.Range, "quickfix", &diag) + changed, err := codeAction(mark.run.env, loc.URI, diag.Range, "quickfix", &diag, nil) if err != nil { mark.errorf("suggestedfix failed: %v. (Use @suggestedfixerr for expected errors.)", err) return @@ -2054,8 +2062,8 @@ func suggestedfixMarker(mark marker, loc protocol.Location, re *regexp.Regexp, g // The resulting map contains resulting file contents after the code action is // applied. Currently, this function does not support code actions that return // edits directly; it only supports code action commands. -func codeAction(env *Env, uri protocol.DocumentURI, rng protocol.Range, actionKind string, diag *protocol.Diagnostic) (map[string][]byte, error) { - changes, err := codeActionChanges(env, uri, rng, actionKind, diag) +func codeAction(env *Env, uri protocol.DocumentURI, rng protocol.Range, actionKind string, diag *protocol.Diagnostic, titles []string) (map[string][]byte, error) { + changes, err := codeActionChanges(env, uri, rng, actionKind, diag, titles) if err != nil { return nil, err } @@ -2069,7 +2077,8 @@ func codeAction(env *Env, uri protocol.DocumentURI, rng protocol.Range, actionKi // codeActionChanges executes a textDocument/codeAction request for the // specified location and kind, and captures the resulting document changes. // If diag is non-nil, it is used as the code action context. -func codeActionChanges(env *Env, uri protocol.DocumentURI, rng protocol.Range, actionKind string, diag *protocol.Diagnostic) ([]protocol.DocumentChanges, error) { +// If titles is non-empty, the code action title must be present among the provided titles. +func codeActionChanges(env *Env, uri protocol.DocumentURI, rng protocol.Range, actionKind string, diag *protocol.Diagnostic, titles []string) ([]protocol.DocumentChanges, error) { // Request all code actions that apply to the diagnostic. // (The protocol supports filtering using Context.Only={actionKind} // but we can give a better error if we don't filter.) @@ -2093,14 +2102,23 @@ func codeActionChanges(env *Env, uri protocol.DocumentURI, rng protocol.Range, a var candidates []protocol.CodeAction for _, act := range actions { if act.Kind == protocol.CodeActionKind(actionKind) { - candidates = append(candidates, act) + if len(titles) > 0 { + for _, f := range titles { + if act.Title == f { + candidates = append(candidates, act) + break + } + } + } else { + candidates = append(candidates, act) + } } } if len(candidates) != 1 { for _, act := range actions { env.T.Logf("found CodeAction Kind=%s Title=%q", act.Kind, act.Title) } - return nil, fmt.Errorf("found %d CodeActions of kind %s for this diagnostic, want 1", len(candidates), actionKind) + return nil, fmt.Errorf("found %d CodeActions of kind %s matching filters %v for this diagnostic, want 1", len(candidates), actionKind, titles) } action := candidates[0] diff --git a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go b/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go deleted file mode 100644 index c9a8d9dce38..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go +++ /dev/null @@ -1,24 +0,0 @@ -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} diff --git a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden b/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden deleted file mode 100644 index 3310d973e01..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_method/extract_basic.go.golden +++ /dev/null @@ -1,364 +0,0 @@ --- functionextraction_extract_basic_13_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := newFunction(a) //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func newFunction(a *A) int { - sum := a.x + a.y - return sum -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - --- functionextraction_extract_basic_14_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return newFunction(sum) //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func newFunction(sum int) int { - return sum -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - --- functionextraction_extract_basic_18_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return newFunction(a) //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func newFunction(a A) bool { - return a.x < a.y -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - --- functionextraction_extract_basic_22_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := newFunction(a) //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func newFunction(a A) int { - sum := a.x + a.y - return sum -} - --- functionextraction_extract_basic_23_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return newFunction(sum) //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func newFunction(sum int) int { - return sum -} - --- functionextraction_extract_basic_9_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return newFunction(a) //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func newFunction(a *A) bool { - return a.x < a.y -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - --- methodextraction_extract_basic_13_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.newMethod() //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a *A) newMethod() int { - sum := a.x + a.y - return sum -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - --- methodextraction_extract_basic_14_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return a.newMethod(sum) //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (*A) newMethod(sum int) int { - return sum -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - --- methodextraction_extract_basic_18_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.newMethod() //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) newMethod() bool { - return a.x < a.y -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - --- methodextraction_extract_basic_22_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.newMethod() //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) newMethod() int { - sum := a.x + a.y - return sum -} - --- methodextraction_extract_basic_23_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return a.newMethod(sum) //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (A) newMethod(sum int) int { - return sum -} - --- methodextraction_extract_basic_9_2 -- -package extract - -type A struct { - x int - y int -} - -func (a *A) XLessThanYP() bool { - return a.newMethod() //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a *A) newMethod() bool { - return a.x < a.y -} - -func (a *A) AddP() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - -func (a A) XLessThanY() bool { - return a.x < a.y //@extractmethod("return", "a.y"),extractfunc("return", "a.y") -} - -func (a A) Add() int { - sum := a.x + a.y //@extractmethod("sum", "a.y"),extractfunc("sum", "a.y") - return sum //@extractmethod("return", "sum"),extractfunc("return", "sum") -} - diff --git a/gopls/internal/lsp/testdata/extract/extract_method/extract_context.go b/gopls/internal/lsp/testdata/extract/extract_method/extract_context.go deleted file mode 100644 index 1fd7197d5fc..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_method/extract_context.go +++ /dev/null @@ -1,20 +0,0 @@ -package extract - -import "context" - -type B struct { - x int - y int -} - -func (b *B) AddP(ctx context.Context) (int, error) { - sum := b.x + b.y - return sum, ctx.Err() //@extractmethod("return", "ctx.Err()"),extractfunc("return", "ctx.Err()") -} - -func (b *B) LongList(ctx context.Context) (int, error) { - p1 := 1 - p2 := 1 - p3 := 1 - return p1 + p2 + p3, ctx.Err() //@extractmethod("return", "ctx.Err()"),extractfunc("return", "ctx.Err()") -} diff --git a/gopls/internal/lsp/testdata/extract/extract_method/extract_context.go.golden b/gopls/internal/lsp/testdata/extract/extract_method/extract_context.go.golden deleted file mode 100644 index 1a51a132f49..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_method/extract_context.go.golden +++ /dev/null @@ -1,52 +0,0 @@ --- methodextraction_extract_context_12_2 -- -package extract - -import "context" - -type B struct { - x int - y int -} - -func (b *B) AddP(ctx context.Context) (int, error) { - sum := b.x + b.y - return b.newMethod(ctx, sum) //@extractmethod("return", "ctx.Err()"),extractfunc("return", "ctx.Err()") -} - -func (*B) newMethod(ctx context.Context, sum int) (int, error) { - return sum, ctx.Err() -} - -func (b *B) LongList(ctx context.Context) (int, error) { - p1 := 1 - p2 := 1 - p3 := 1 - return p1 + p2 + p3, ctx.Err() //@extractmethod("return", "ctx.Err()"),extractfunc("return", "ctx.Err()") -} - --- methodextraction_extract_context_19_2 -- -package extract - -import "context" - -type B struct { - x int - y int -} - -func (b *B) AddP(ctx context.Context) (int, error) { - sum := b.x + b.y - return sum, ctx.Err() //@extractmethod("return", "ctx.Err()"),extractfunc("return", "ctx.Err()") -} - -func (b *B) LongList(ctx context.Context) (int, error) { - p1 := 1 - p2 := 1 - p3 := 1 - return b.newMethod(ctx, p1, p2, p3) //@extractmethod("return", "ctx.Err()"),extractfunc("return", "ctx.Err()") -} - -func (*B) newMethod(ctx context.Context, p1 int, p2 int, p3 int) (int, error) { - return p1 + p2 + p3, ctx.Err() -} - diff --git a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go b/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go deleted file mode 100644 index cbb70a04cd1..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go +++ /dev/null @@ -1,6 +0,0 @@ -package extract - -func _() { - var _ = 1 + 2 //@suggestedfix("1", "refactor.extract", "") - var _ = 3 + 4 //@suggestedfix("3 + 4", "refactor.extract", "") -} diff --git a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden b/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden deleted file mode 100644 index 3fd9b328711..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_basic_lit.go.golden +++ /dev/null @@ -1,18 +0,0 @@ --- suggestedfix_extract_basic_lit_4_10 -- -package extract - -func _() { - x := 1 - var _ = x + 2 //@suggestedfix("1", "refactor.extract", "") - var _ = 3 + 4 //@suggestedfix("3 + 4", "refactor.extract", "") -} - --- suggestedfix_extract_basic_lit_5_10 -- -package extract - -func _() { - var _ = 1 + 2 //@suggestedfix("1", "refactor.extract", "") - x := 3 + 4 - var _ = x //@suggestedfix("3 + 4", "refactor.extract", "") -} - diff --git a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go b/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go deleted file mode 100644 index a20b45f5869..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go +++ /dev/null @@ -1,9 +0,0 @@ -package extract - -import "strconv" - -func _() { - x0 := append([]int{}, 1) //@suggestedfix("append([]int{}, 1)", "refactor.extract", "") - str := "1" - b, err := strconv.Atoi(str) //@suggestedfix("strconv.Atoi(str)", "refactor.extract", "") -} diff --git a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden b/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden deleted file mode 100644 index d59c0ee99f2..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_func_call.go.golden +++ /dev/null @@ -1,24 +0,0 @@ --- suggestedfix_extract_func_call_6_8 -- -package extract - -import "strconv" - -func _() { - x := append([]int{}, 1) - x0 := x //@suggestedfix("append([]int{}, 1)", "refactor.extract", "") - str := "1" - b, err := strconv.Atoi(str) //@suggestedfix("strconv.Atoi(str)", "refactor.extract", "") -} - --- suggestedfix_extract_func_call_8_12 -- -package extract - -import "strconv" - -func _() { - x0 := append([]int{}, 1) //@suggestedfix("append([]int{}, 1)", "refactor.extract", "") - str := "1" - x, x1 := strconv.Atoi(str) - b, err := x, x1 //@suggestedfix("strconv.Atoi(str)", "refactor.extract", "") -} - diff --git a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go b/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go deleted file mode 100644 index c14ad709212..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go +++ /dev/null @@ -1,13 +0,0 @@ -package extract - -import "go/ast" - -func _() { - x0 := 0 - if true { - y := ast.CompositeLit{} //@suggestedfix("ast.CompositeLit{}", "refactor.extract", "") - } - if true { - x1 := !false //@suggestedfix("!false", "refactor.extract", "") - } -} diff --git a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden b/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden deleted file mode 100644 index 1c2f64b7df7..00000000000 --- a/gopls/internal/lsp/testdata/extract/extract_variable/extract_scope.go.golden +++ /dev/null @@ -1,32 +0,0 @@ --- suggestedfix_extract_scope_11_9 -- -package extract - -import "go/ast" - -func _() { - x0 := 0 - if true { - y := ast.CompositeLit{} //@suggestedfix("ast.CompositeLit{}", "refactor.extract", "") - } - if true { - x := !false - x1 := x //@suggestedfix("!false", "refactor.extract", "") - } -} - --- suggestedfix_extract_scope_8_8 -- -package extract - -import "go/ast" - -func _() { - x0 := 0 - if true { - x := ast.CompositeLit{} - y := x //@suggestedfix("ast.CompositeLit{}", "refactor.extract", "") - } - if true { - x1 := !false //@suggestedfix("!false", "refactor.extract", "") - } -} - diff --git a/gopls/internal/lsp/testdata/summary.txt.golden b/gopls/internal/lsp/testdata/summary.txt.golden index 2f610b5f2ba..b48a44d4dff 100644 --- a/gopls/internal/lsp/testdata/summary.txt.golden +++ b/gopls/internal/lsp/testdata/summary.txt.golden @@ -1,8 +1,7 @@ -- summary -- CallHierarchyCount = 2 SemanticTokenCount = 3 -SuggestedFixCount = 45 -MethodExtractionCount = 8 +SuggestedFixCount = 39 InlayHintsCount = 5 RenamesCount = 45 SelectionRangesCount = 3 diff --git a/gopls/internal/lsp/tests/tests.go b/gopls/internal/lsp/tests/tests.go index 822a39b205e..d310a2331cc 100644 --- a/gopls/internal/lsp/tests/tests.go +++ b/gopls/internal/lsp/tests/tests.go @@ -51,23 +51,21 @@ var UpdateGolden = flag.Bool("golden", false, "Update golden files") type CallHierarchy = map[span.Span]*CallHierarchyResult type SemanticTokens = []span.Span type SuggestedFixes = map[span.Span][]SuggestedFix -type MethodExtractions = map[span.Span]span.Span type Renames = map[span.Span]string type InlayHints = []span.Span type AddImport = map[span.URI]string type SelectionRanges = []span.Span type Data struct { - Config packages.Config - Exported *packagestest.Exported - CallHierarchy CallHierarchy - SemanticTokens SemanticTokens - SuggestedFixes SuggestedFixes - MethodExtractions MethodExtractions - Renames Renames - InlayHints InlayHints - AddImport AddImport - SelectionRanges SelectionRanges + Config packages.Config + Exported *packagestest.Exported + CallHierarchy CallHierarchy + SemanticTokens SemanticTokens + SuggestedFixes SuggestedFixes + Renames Renames + InlayHints InlayHints + AddImport AddImport + SelectionRanges SelectionRanges fragments map[string]string dir string @@ -90,7 +88,6 @@ type Tests interface { CallHierarchy(*testing.T, span.Span, *CallHierarchyResult) SemanticTokens(*testing.T, span.Span) SuggestedFix(*testing.T, span.Span, []SuggestedFix, int) - MethodExtraction(*testing.T, span.Span, span.Span) InlayHints(*testing.T, span.Span) Rename(*testing.T, span.Span, string) AddImport(*testing.T, span.URI, string) @@ -180,11 +177,10 @@ func RunTests(t *testing.T, dataDir string, includeMultiModule bool, f func(*tes func load(t testing.TB, mode string, dir string) *Data { datum := &Data{ - CallHierarchy: make(CallHierarchy), - Renames: make(Renames), - SuggestedFixes: make(SuggestedFixes), - MethodExtractions: make(MethodExtractions), - AddImport: make(AddImport), + CallHierarchy: make(CallHierarchy), + Renames: make(Renames), + SuggestedFixes: make(SuggestedFixes), + AddImport: make(AddImport), dir: dir, fragments: map[string]string{}, @@ -321,7 +317,6 @@ func load(t testing.TB, mode string, dir string) *Data { "inlayHint": datum.collectInlayHints, "rename": datum.collectRenames, "suggestedfix": datum.collectSuggestedFixes, - "extractmethod": datum.collectMethodExtractions, "incomingcalls": datum.collectIncomingCalls, "outgoingcalls": datum.collectOutgoingCalls, "addimport": datum.collectAddImports, @@ -414,20 +409,6 @@ func Run(t *testing.T, tests Tests, data *Data) { } }) - t.Run("MethodExtraction", func(t *testing.T) { - t.Helper() - for start, end := range data.MethodExtractions { - // Check if we should skip this spn if the -modfile flag is not available. - if shouldSkip(data, start.URI()) { - continue - } - t.Run(SpanName(start), func(t *testing.T) { - t.Helper() - tests.MethodExtraction(t, start, end) - }) - } - }) - t.Run("InlayHints", func(t *testing.T) { t.Helper() for _, src := range data.InlayHints { @@ -487,7 +468,6 @@ func checkData(t *testing.T, data *Data) { fmt.Fprintf(buf, "CallHierarchyCount = %v\n", len(data.CallHierarchy)) fmt.Fprintf(buf, "SemanticTokenCount = %v\n", len(data.SemanticTokens)) fmt.Fprintf(buf, "SuggestedFixCount = %v\n", len(data.SuggestedFixes)) - fmt.Fprintf(buf, "MethodExtractionCount = %v\n", len(data.MethodExtractions)) fmt.Fprintf(buf, "InlayHintsCount = %v\n", len(data.InlayHints)) fmt.Fprintf(buf, "RenamesCount = %v\n", len(data.Renames)) fmt.Fprintf(buf, "SelectionRangesCount = %v\n", len(data.SelectionRanges)) @@ -583,12 +563,6 @@ func (data *Data) collectSuggestedFixes(spn span.Span, actionKind, fix string) { data.SuggestedFixes[spn] = append(data.SuggestedFixes[spn], SuggestedFix{actionKind, fix}) } -func (data *Data) collectMethodExtractions(start span.Span, end span.Span) { - if _, ok := data.MethodExtractions[start]; !ok { - data.MethodExtractions[start] = end - } -} - func (data *Data) collectSelectionRanges(spn span.Span) { data.SelectionRanges = append(data.SelectionRanges, spn) } diff --git a/gopls/internal/regtest/marker/testdata/codeaction/extract_method.txt b/gopls/internal/regtest/marker/testdata/codeaction/extract_method.txt new file mode 100644 index 00000000000..3fc9f58923a --- /dev/null +++ b/gopls/internal/regtest/marker/testdata/codeaction/extract_method.txt @@ -0,0 +1,244 @@ +This test exercises function and method extraction. + +-- flags -- +-ignore_extra_diags + +-- basic.go -- +package extract + +//@codeactionedit(A_XLessThanYP, "refactor.extract", meth1, "Extract method") +//@codeactionedit(A_XLessThanYP, "refactor.extract", func1, "Extract function") +//@codeactionedit(A_AddP1, "refactor.extract", meth2, "Extract method") +//@codeactionedit(A_AddP1, "refactor.extract", func2, "Extract function") +//@codeactionedit(A_AddP2, "refactor.extract", meth3, "Extract method") +//@codeactionedit(A_AddP2, "refactor.extract", func3, "Extract function") +//@codeactionedit(A_XLessThanY, "refactor.extract", meth4, "Extract method") +//@codeactionedit(A_XLessThanY, "refactor.extract", func4, "Extract function") +//@codeactionedit(A_Add1, "refactor.extract", meth5, "Extract method") +//@codeactionedit(A_Add1, "refactor.extract", func5, "Extract function") +//@codeactionedit(A_Add2, "refactor.extract", meth6, "Extract method") +//@codeactionedit(A_Add2, "refactor.extract", func6, "Extract function") + +type A struct { + x int + y int +} + +func (a *A) XLessThanYP() bool { + return a.x < a.y //@loc(A_XLessThanYP, re`return.*a\.y`) +} + +func (a *A) AddP() int { + sum := a.x + a.y //@loc(A_AddP1, re`sum.*a\.y`) + return sum //@loc(A_AddP2, re`return.*sum`) +} + +func (a A) XLessThanY() bool { + return a.x < a.y //@loc(A_XLessThanY, re`return.*a\.y`) +} + +func (a A) Add() int { + sum := a.x + a.y //@loc(A_Add1, re`sum.*a\.y`) + return sum //@loc(A_Add2, re`return.*sum`) +} + +-- @func1/basic.go -- +--- before ++++ after +@@ -22 +22,5 @@ +- return a.x < a.y //@loc(A_XLessThanYP, re`return.*a\.y`) ++ return newFunction(a) //@loc(A_XLessThanYP, re`return.*a\.y`) ++} ++ ++func newFunction(a *A) bool { ++ return a.x < a.y +-- @func2/basic.go -- +--- before ++++ after +@@ -26,2 +26,7 @@ +- sum := a.x + a.y //@loc(A_AddP1, re`sum.*a\.y`) ++ sum := newFunction(a) //@loc(A_AddP1, re`sum.*a\.y`) +- return sum //@loc(A_AddP2, re`return.*sum`) ++ return sum //@loc(A_AddP2, re`return.*sum`) ++} ++ ++func newFunction(a *A) int { ++ sum := a.x + a.y ++ return sum +-- @func3/basic.go -- +--- before ++++ after +@@ -27 +27,5 @@ +- return sum //@loc(A_AddP2, re`return.*sum`) ++ return newFunction(sum) //@loc(A_AddP2, re`return.*sum`) ++} ++ ++func newFunction(sum int) int { ++ return sum +-- @func4/basic.go -- +--- before ++++ after +@@ -31 +31,5 @@ +- return a.x < a.y //@loc(A_XLessThanY, re`return.*a\.y`) ++ return newFunction(a) //@loc(A_XLessThanY, re`return.*a\.y`) ++} ++ ++func newFunction(a A) bool { ++ return a.x < a.y +-- @func5/basic.go -- +--- before ++++ after +@@ -35 +35 @@ +- sum := a.x + a.y //@loc(A_Add1, re`sum.*a\.y`) ++ sum := newFunction(a) //@loc(A_Add1, re`sum.*a\.y`) +@@ -39 +39,5 @@ ++func newFunction(a A) int { ++ sum := a.x + a.y ++ return sum ++} ++ +-- @func6/basic.go -- +--- before ++++ after +@@ -36 +36 @@ +- return sum //@loc(A_Add2, re`return.*sum`) ++ return newFunction(sum) //@loc(A_Add2, re`return.*sum`) +@@ -39 +39,4 @@ ++func newFunction(sum int) int { ++ return sum ++} ++ +-- @meth1/basic.go -- +--- before ++++ after +@@ -22 +22,5 @@ +- return a.x < a.y //@loc(A_XLessThanYP, re`return.*a\.y`) ++ return a.newMethod() //@loc(A_XLessThanYP, re`return.*a\.y`) ++} ++ ++func (a *A) newMethod() bool { ++ return a.x < a.y +-- @meth2/basic.go -- +--- before ++++ after +@@ -26,2 +26,7 @@ +- sum := a.x + a.y //@loc(A_AddP1, re`sum.*a\.y`) ++ sum := a.newMethod() //@loc(A_AddP1, re`sum.*a\.y`) +- return sum //@loc(A_AddP2, re`return.*sum`) ++ return sum //@loc(A_AddP2, re`return.*sum`) ++} ++ ++func (a *A) newMethod() int { ++ sum := a.x + a.y ++ return sum +-- @meth3/basic.go -- +--- before ++++ after +@@ -27 +27,5 @@ +- return sum //@loc(A_AddP2, re`return.*sum`) ++ return a.newMethod(sum) //@loc(A_AddP2, re`return.*sum`) ++} ++ ++func (*A) newMethod(sum int) int { ++ return sum +-- @meth4/basic.go -- +--- before ++++ after +@@ -31 +31,5 @@ +- return a.x < a.y //@loc(A_XLessThanY, re`return.*a\.y`) ++ return a.newMethod() //@loc(A_XLessThanY, re`return.*a\.y`) ++} ++ ++func (a A) newMethod() bool { ++ return a.x < a.y +-- @meth5/basic.go -- +--- before ++++ after +@@ -35 +35 @@ +- sum := a.x + a.y //@loc(A_Add1, re`sum.*a\.y`) ++ sum := a.newMethod() //@loc(A_Add1, re`sum.*a\.y`) +@@ -39 +39,5 @@ ++func (a A) newMethod() int { ++ sum := a.x + a.y ++ return sum ++} ++ +-- @meth6/basic.go -- +--- before ++++ after +@@ -36 +36 @@ +- return sum //@loc(A_Add2, re`return.*sum`) ++ return a.newMethod(sum) //@loc(A_Add2, re`return.*sum`) +@@ -39 +39,4 @@ ++func (A) newMethod(sum int) int { ++ return sum ++} ++ +-- context.go -- +package extract + +import "context" + +//@codeactionedit(B_AddP, "refactor.extract", contextMeth1, "Extract method") +//@codeactionedit(B_AddP, "refactor.extract", contextFunc1, "Extract function") +//@codeactionedit(B_LongList, "refactor.extract", contextMeth2, "Extract method") +//@codeactionedit(B_LongList, "refactor.extract", contextFunc2, "Extract function") + +type B struct { + x int + y int +} + +func (b *B) AddP(ctx context.Context) (int, error) { + sum := b.x + b.y + return sum, ctx.Err() //@loc(B_AddP, re`return.*ctx\.Err\(\)`) +} + +func (b *B) LongList(ctx context.Context) (int, error) { + p1 := 1 + p2 := 1 + p3 := 1 + return p1 + p2 + p3, ctx.Err() //@loc(B_LongList, re`return.*ctx\.Err\(\)`) +} +-- @contextMeth1/context.go -- +--- before ++++ after +@@ -17 +17,5 @@ +- return sum, ctx.Err() //@loc(B_AddP, re`return.*ctx\.Err\(\)`) ++ return b.newMethod(ctx, sum) //@loc(B_AddP, re`return.*ctx\.Err\(\)`) ++} ++ ++func (*B) newMethod(ctx context.Context, sum int) (int, error) { ++ return sum, ctx.Err() +-- @contextMeth2/context.go -- +--- before ++++ after +@@ -24 +24 @@ +- return p1 + p2 + p3, ctx.Err() //@loc(B_LongList, re`return.*ctx\.Err\(\)`) ++ return b.newMethod(ctx, p1, p2, p3) //@loc(B_LongList, re`return.*ctx\.Err\(\)`) +@@ -26 +26,4 @@ ++ ++func (*B) newMethod(ctx context.Context, p1 int, p2 int, p3 int) (int, error) { ++ return p1 + p2 + p3, ctx.Err() ++} +-- @contextFunc2/context.go -- +--- before ++++ after +@@ -24 +24 @@ +- return p1 + p2 + p3, ctx.Err() //@loc(B_LongList, re`return.*ctx\.Err\(\)`) ++ return newFunction(ctx, p1, p2, p3) //@loc(B_LongList, re`return.*ctx\.Err\(\)`) +@@ -26 +26,4 @@ ++ ++func newFunction(ctx context.Context, p1 int, p2 int, p3 int) (int, error) { ++ return p1 + p2 + p3, ctx.Err() ++} +-- @contextFunc1/context.go -- +--- before ++++ after +@@ -17 +17,5 @@ +- return sum, ctx.Err() //@loc(B_AddP, re`return.*ctx\.Err\(\)`) ++ return newFunction(ctx, sum) //@loc(B_AddP, re`return.*ctx\.Err\(\)`) ++} ++ ++func newFunction(ctx context.Context, sum int) (int, error) { ++ return sum, ctx.Err() diff --git a/gopls/internal/regtest/marker/testdata/codeaction/extract_variable.txt b/gopls/internal/regtest/marker/testdata/codeaction/extract_variable.txt new file mode 100644 index 00000000000..81226aed157 --- /dev/null +++ b/gopls/internal/regtest/marker/testdata/codeaction/extract_variable.txt @@ -0,0 +1,83 @@ +This test checks the behavior of the 'extract variable' code action. + +-- flags -- +-ignore_extra_diags + +-- basic_lit.go -- +package extract + +func _() { + var _ = 1 + 2 //@codeactionedit("1", "refactor.extract", basic_lit1) + var _ = 3 + 4 //@codeactionedit("3 + 4", "refactor.extract", basic_lit2) +} + +-- @basic_lit1/basic_lit.go -- +--- before ++++ after +@@ -3,2 +3,3 @@ +-func _() { ++func _() { ++ x := 1 +- var _ = 1 + 2 //@codeactionedit("1", "refactor.extract", basic_lit1) ++ var _ = x + 2 //@codeactionedit("1", "refactor.extract", basic_lit1) +-- @basic_lit2/basic_lit.go -- +--- before ++++ after +@@ -5 +5,2 @@ +- var _ = 3 + 4 //@codeactionedit("3 + 4", "refactor.extract", basic_lit2) ++ x := 3 + 4 ++ var _ = x //@codeactionedit("3 + 4", "refactor.extract", basic_lit2) +-- func_call.go -- +package extract + +import "strconv" + +func _() { + x0 := append([]int{}, 1) //@codeactionedit("append([]int{}, 1)", "refactor.extract", func_call1) + str := "1" + b, err := strconv.Atoi(str) //@codeactionedit("strconv.Atoi(str)", "refactor.extract", func_call2) +} + +-- @func_call1/func_call.go -- +--- before ++++ after +@@ -6 +6,2 @@ +- x0 := append([]int{}, 1) //@codeactionedit("append([]int{}, 1)", "refactor.extract", func_call1) ++ x := append([]int{}, 1) ++ x0 := x //@codeactionedit("append([]int{}, 1)", "refactor.extract", func_call1) +-- @func_call2/func_call.go -- +--- before ++++ after +@@ -8 +8,2 @@ +- b, err := strconv.Atoi(str) //@codeactionedit("strconv.Atoi(str)", "refactor.extract", func_call2) ++ x, x1 := strconv.Atoi(str) ++ b, err := x, x1 //@codeactionedit("strconv.Atoi(str)", "refactor.extract", func_call2) +-- scope.go -- +package extract + +import "go/ast" + +func _() { + x0 := 0 + if true { + y := ast.CompositeLit{} //@codeactionedit("ast.CompositeLit{}", "refactor.extract", scope1) + } + if true { + x1 := !false //@codeactionedit("!false", "refactor.extract", scope2) + } +} + +-- @scope1/scope.go -- +--- before ++++ after +@@ -8 +8,2 @@ +- y := ast.CompositeLit{} //@codeactionedit("ast.CompositeLit{}", "refactor.extract", scope1) ++ x := ast.CompositeLit{} ++ y := x //@codeactionedit("ast.CompositeLit{}", "refactor.extract", scope1) +-- @scope2/scope.go -- +--- before ++++ after +@@ -11 +11,2 @@ +- x1 := !false //@codeactionedit("!false", "refactor.extract", scope2) ++ x := !false ++ x1 := x //@codeactionedit("!false", "refactor.extract", scope2)