@@ -238,6 +238,8 @@ var codeActionProducers = [...]codeActionProducer{
238
238
{kind : settings .RefactorExtractToNewFile , fn : refactorExtractToNewFile },
239
239
{kind : settings .RefactorExtractConstant , fn : refactorExtractVariable , needPkg : true },
240
240
{kind : settings .RefactorExtractVariable , fn : refactorExtractVariable , needPkg : true },
241
+ {kind : settings .RefactorExtractConstantAll , fn : refactorExtractVariableAll , needPkg : true },
242
+ {kind : settings .RefactorExtractVariableAll , fn : refactorExtractVariableAll , needPkg : true },
241
243
{kind : settings .RefactorInlineCall , fn : refactorInlineCall , needPkg : true },
242
244
{kind : settings .RefactorRewriteChangeQuote , fn : refactorRewriteChangeQuote },
243
245
{kind : settings .RefactorRewriteFillStruct , fn : refactorRewriteFillStruct , needPkg : true },
@@ -467,14 +469,15 @@ func refactorExtractMethod(ctx context.Context, req *codeActionsRequest) error {
467
469
// See [extractVariable] for command implementation.
468
470
func refactorExtractVariable (ctx context.Context , req * codeActionsRequest ) error {
469
471
info := req .pkg .TypesInfo ()
470
- if expr , _ , err := canExtractVariable (info , req .pgf .File , req .start , req .end ); err == nil {
472
+ if exprs , err := canExtractVariable (info , req .pgf .File , req .start , req .end , false ); err == nil {
471
473
// Offer one of refactor.extract.{constant,variable}
472
474
// based on the constness of the expression; this is a
473
475
// limitation of the codeActionProducers mechanism.
474
476
// Beware that future evolutions of the refactorings
475
477
// may make them diverge to become non-complementary,
476
478
// for example because "if const x = ...; y {" is illegal.
477
- constant := info .Types [expr ].Value != nil
479
+ // Same as [refactorExtractVariableAll].
480
+ constant := info .Types [exprs [0 ]].Value != nil
478
481
if (req .kind == settings .RefactorExtractConstant ) == constant {
479
482
title := "Extract variable"
480
483
if constant {
@@ -486,6 +489,35 @@ func refactorExtractVariable(ctx context.Context, req *codeActionsRequest) error
486
489
return nil
487
490
}
488
491
492
+ // refactorExtractVariableAll produces "Extract N occurrences of EXPR" code action.
493
+ // See [extractAllOccursOfExpr] for command implementation.
494
+ func refactorExtractVariableAll (ctx context.Context , req * codeActionsRequest ) error {
495
+ info := req .pkg .TypesInfo ()
496
+ // Don't suggest if only one expr is found,
497
+ // otherwise it will duplicate with [refactorExtractVariable]
498
+ if exprs , err := canExtractVariable (info , req .pgf .File , req .start , req .end , true ); err == nil && len (exprs ) > 1 {
499
+ start , end , err := req .pgf .NodeOffsets (exprs [0 ])
500
+ if err != nil {
501
+ return err
502
+ }
503
+ desc := string (req .pgf .Src [start :end ])
504
+ if len (desc ) >= 40 || strings .Contains (desc , "\n " ) {
505
+ desc = astutil .NodeDescription (exprs [0 ])
506
+ }
507
+ constant := info .Types [exprs [0 ]].Value != nil
508
+ if (req .kind == settings .RefactorExtractConstantAll ) == constant {
509
+ var title string
510
+ if constant {
511
+ title = fmt .Sprintf ("Extract %d occurrences of const expression: %s" , len (exprs ), desc )
512
+ } else {
513
+ title = fmt .Sprintf ("Extract %d occurrences of %s" , len (exprs ), desc )
514
+ }
515
+ req .addApplyFixAction (title , fixExtractVariableAll , req .loc )
516
+ }
517
+ }
518
+ return nil
519
+ }
520
+
489
521
// refactorExtractToNewFile produces "Extract declarations to new file" code actions.
490
522
// See [server.commandHandler.ExtractToNewFile] for command implementation.
491
523
func refactorExtractToNewFile (ctx context.Context , req * codeActionsRequest ) error {
0 commit comments