@@ -27,6 +27,7 @@ import (
27
27
"golang.org/x/tools/gopls/internal/protocol"
28
28
"golang.org/x/tools/gopls/internal/protocol/command"
29
29
"golang.org/x/tools/gopls/internal/settings"
30
+ "golang.org/x/tools/gopls/internal/util/safetoken"
30
31
"golang.org/x/tools/gopls/internal/util/typesutil"
31
32
"golang.org/x/tools/internal/event"
32
33
"golang.org/x/tools/internal/imports"
@@ -236,6 +237,7 @@ var codeActionProducers = [...]codeActionProducer{
236
237
{kind : settings .RefactorExtractFunction , fn : refactorExtractFunction },
237
238
{kind : settings .RefactorExtractMethod , fn : refactorExtractMethod },
238
239
{kind : settings .RefactorExtractToNewFile , fn : refactorExtractToNewFile },
240
+ {kind : settings .RefactorExtractAllOccursOfExpr , fn : refactorExtractAllOccursOfExpr },
239
241
{kind : settings .RefactorExtractVariable , fn : refactorExtractVariable },
240
242
{kind : settings .RefactorInlineCall , fn : refactorInlineCall , needPkg : true },
241
243
{kind : settings .RefactorRewriteChangeQuote , fn : refactorRewriteChangeQuote },
@@ -449,11 +451,40 @@ func refactorExtractMethod(ctx context.Context, req *codeActionsRequest) error {
449
451
return nil
450
452
}
451
453
452
- // refactorExtractVariable produces "Extract variable " code actions.
454
+ // refactorExtractVariable produces "Extract expression " code actions.
453
455
// See [extractVariable] for command implementation.
454
456
func refactorExtractVariable (ctx context.Context , req * codeActionsRequest ) error {
455
- if _ , _ , ok , _ := canExtractVariable (req .start , req .end , req .pgf .File ); ok {
456
- req .addApplyFixAction ("Extract variable" , fixExtractVariable , req .loc )
457
+ if expr , _ , ok , _ := canExtractVariable (req .start , req .end , req .pgf .File ); ok {
458
+ startOffset , err := safetoken .Offset (req .pgf .Tok , expr .Pos ())
459
+ if err != nil {
460
+ return nil
461
+ }
462
+ endOffset , err := safetoken .Offset (req .pgf .Tok , expr .End ())
463
+ if err != nil {
464
+ return nil
465
+ }
466
+ expr := req .pgf .Src [startOffset :endOffset ]
467
+ req .addApplyFixAction (fmt .Sprintf ("Extract %s" , expr ), fixExtractVariable , req .loc )
468
+ }
469
+ return nil
470
+ }
471
+
472
+ // refactorExtractAllOccursOfExpr produces "Extract n occurrences of expression" code action.
473
+ // See [extractAllOccursOfExpr] for command implementation.
474
+ func refactorExtractAllOccursOfExpr (ctx context.Context , req * codeActionsRequest ) error {
475
+ // Don't suggest if only one expr is found,
476
+ // otherwise it will duplicate with [refactorExtractVariable]
477
+ if _ , exprs , ok , _ := canExtractVariable (req .start , req .end , req .pgf .File ); ok && len (exprs ) > 1 {
478
+ startOffset , err := safetoken .Offset (req .pgf .Tok , exprs [0 ].Pos ())
479
+ if err != nil {
480
+ return nil
481
+ }
482
+ endOffset , err := safetoken .Offset (req .pgf .Tok , exprs [0 ].End ())
483
+ if err != nil {
484
+ return nil
485
+ }
486
+ expr := req .pgf .Src [startOffset :endOffset ]
487
+ req .addApplyFixAction (fmt .Sprintf ("Extract %d occcurrances of %s" , len (exprs ), expr ), fixExtractAllOccursOfExpr , req .loc )
457
488
}
458
489
return nil
459
490
}
0 commit comments