@@ -24,17 +24,18 @@ import (
24
24
"golang.org/x/tools/gopls/internal/util/bug"
25
25
"golang.org/x/tools/gopls/internal/util/safetoken"
26
26
"golang.org/x/tools/internal/analysisinternal"
27
+ "golang.org/x/tools/internal/astutil/cursor"
27
28
"golang.org/x/tools/internal/typesinternal"
28
29
)
29
30
30
31
// extractVariable implements the refactor.extract.{variable,constant} CodeAction command.
31
- func extractVariable (fset * token.FileSet , start , end token.Pos , src []byte , file * ast. File , _ * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
32
- return extractExprs (fset , start , end , src , file , info , false )
32
+ func extractVariable (fset * token.FileSet , start , end token.Pos , src []byte , curFile cursor. Cursor , _ * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
33
+ return extractExprs (fset , start , end , src , curFile , info , false )
33
34
}
34
35
35
36
// extractVariableAll implements the refactor.extract.{variable,constant}-all CodeAction command.
36
- func extractVariableAll (fset * token.FileSet , start , end token.Pos , src []byte , file * ast. File , _ * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
37
- return extractExprs (fset , start , end , src , file , info , true )
37
+ func extractVariableAll (fset * token.FileSet , start , end token.Pos , src []byte , curFile cursor. Cursor , _ * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
38
+ return extractExprs (fset , start , end , src , curFile , info , true )
38
39
}
39
40
40
41
// extractExprs replaces occurrence(s) of a specified expression within the same function
@@ -43,9 +44,11 @@ func extractVariableAll(fset *token.FileSet, start, end token.Pos, src []byte, f
43
44
//
44
45
// The new variable/constant is declared as close as possible to the first found expression
45
46
// within the deepest common scope accessible to all candidate occurrences.
46
- func extractExprs (fset * token.FileSet , start , end token.Pos , src []byte , file * ast.File , info * types.Info , all bool ) (* token.FileSet , * analysis.SuggestedFix , error ) {
47
+ func extractExprs (fset * token.FileSet , start , end token.Pos , src []byte , curFile cursor.Cursor , info * types.Info , all bool ) (* token.FileSet , * analysis.SuggestedFix , error ) {
48
+ file := curFile .Node ().(* ast.File )
49
+ // TODO(adonovan): simplify, using Cursor.
47
50
tokFile := fset .File (file .FileStart )
48
- exprs , err := canExtractVariable (info , file , start , end , all )
51
+ exprs , err := canExtractVariable (info , curFile , start , end , all )
49
52
if err != nil {
50
53
return nil , nil , fmt .Errorf ("cannot extract: %v" , err )
51
54
}
@@ -381,10 +384,12 @@ func stmtToInsertVarBefore(path []ast.Node, variables []*variable) (ast.Stmt, er
381
384
// canExtractVariable reports whether the code in the given range can be
382
385
// extracted to a variable (or constant). It returns the selected expression or, if 'all',
383
386
// all structurally equivalent expressions within the same function body, in lexical order.
384
- func canExtractVariable (info * types.Info , file * ast. File , start , end token.Pos , all bool ) ([]ast.Expr , error ) {
387
+ func canExtractVariable (info * types.Info , curFile cursor. Cursor , start , end token.Pos , all bool ) ([]ast.Expr , error ) {
385
388
if start == end {
386
389
return nil , fmt .Errorf ("empty selection" )
387
390
}
391
+ file := curFile .Node ().(* ast.File )
392
+ // TODO(adonovan): simplify, using Cursor.
388
393
path , exact := astutil .PathEnclosingInterval (file , start , end )
389
394
if ! exact {
390
395
return nil , fmt .Errorf ("selection is not an expression" )
@@ -571,13 +576,13 @@ type returnVariable struct {
571
576
}
572
577
573
578
// extractMethod refactors the selected block of code into a new method.
574
- func extractMethod (fset * token.FileSet , start , end token.Pos , src []byte , file * ast. File , pkg * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
575
- return extractFunctionMethod (fset , start , end , src , file , pkg , info , true )
579
+ func extractMethod (fset * token.FileSet , start , end token.Pos , src []byte , curFile cursor. Cursor , pkg * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
580
+ return extractFunctionMethod (fset , start , end , src , curFile , pkg , info , true )
576
581
}
577
582
578
583
// extractFunction refactors the selected block of code into a new function.
579
- func extractFunction (fset * token.FileSet , start , end token.Pos , src []byte , file * ast. File , pkg * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
580
- return extractFunctionMethod (fset , start , end , src , file , pkg , info , false )
584
+ func extractFunction (fset * token.FileSet , start , end token.Pos , src []byte , curFile cursor. Cursor , pkg * types.Package , info * types.Info ) (* token.FileSet , * analysis.SuggestedFix , error ) {
585
+ return extractFunctionMethod (fset , start , end , src , curFile , pkg , info , false )
581
586
}
582
587
583
588
// extractFunctionMethod refactors the selected block of code into a new function/method.
@@ -588,17 +593,19 @@ func extractFunction(fset *token.FileSet, start, end token.Pos, src []byte, file
588
593
// and return values of the extracted function/method. Lastly, we construct the call
589
594
// of the function/method and insert this call as well as the extracted function/method into
590
595
// their proper locations.
591
- func extractFunctionMethod (fset * token.FileSet , start , end token.Pos , src []byte , file * ast. File , pkg * types.Package , info * types.Info , isMethod bool ) (* token.FileSet , * analysis.SuggestedFix , error ) {
596
+ func extractFunctionMethod (fset * token.FileSet , start , end token.Pos , src []byte , curFile cursor. Cursor , pkg * types.Package , info * types.Info , isMethod bool ) (* token.FileSet , * analysis.SuggestedFix , error ) {
592
597
errorPrefix := "extractFunction"
593
598
if isMethod {
594
599
errorPrefix = "extractMethod"
595
600
}
596
601
602
+ file := curFile .Node ().(* ast.File )
603
+ // TODO(adonovan): simplify, using Cursor.
597
604
tok := fset .File (file .FileStart )
598
605
if tok == nil {
599
606
return nil , nil , bug .Errorf ("no file for position" )
600
607
}
601
- p , ok , methodOk , err := canExtractFunction (tok , start , end , src , file )
608
+ p , ok , methodOk , err := canExtractFunction (tok , start , end , src , curFile )
602
609
if (! ok && ! isMethod ) || (! methodOk && isMethod ) {
603
610
return nil , nil , fmt .Errorf ("%s: cannot extract %s: %v" , errorPrefix ,
604
611
safetoken .StartPosition (fset , start ), err )
@@ -1086,7 +1093,10 @@ func moveParamToFrontIfFound(params []ast.Expr, paramTypes []*ast.Field, x, sel
1086
1093
// their cursors for whitespace. To support this use case, we must manually adjust the
1087
1094
// ranges to match the correct AST node. In this particular example, we would adjust
1088
1095
// rng.Start forward to the start of 'if' and rng.End backward to after '}'.
1089
- func adjustRangeForCommentsAndWhiteSpace (tok * token.File , start , end token.Pos , content []byte , file * ast.File ) (token.Pos , token.Pos , error ) {
1096
+ func adjustRangeForCommentsAndWhiteSpace (tok * token.File , start , end token.Pos , content []byte , curFile cursor.Cursor ) (token.Pos , token.Pos , error ) {
1097
+ file := curFile .Node ().(* ast.File )
1098
+ // TODO(adonovan): simplify, using Cursor.
1099
+
1090
1100
// Adjust the end of the range to after leading whitespace and comments.
1091
1101
prevStart := token .NoPos
1092
1102
startComment := sort .Search (len (file .Comments ), func (i int ) bool {
@@ -1410,12 +1420,14 @@ type fnExtractParams struct {
1410
1420
1411
1421
// canExtractFunction reports whether the code in the given range can be
1412
1422
// extracted to a function.
1413
- func canExtractFunction (tok * token.File , start , end token.Pos , src []byte , file * ast. File ) (* fnExtractParams , bool , bool , error ) {
1423
+ func canExtractFunction (tok * token.File , start , end token.Pos , src []byte , curFile cursor. Cursor ) (* fnExtractParams , bool , bool , error ) {
1414
1424
if start == end {
1415
1425
return nil , false , false , fmt .Errorf ("start and end are equal" )
1416
1426
}
1417
1427
var err error
1418
- start , end , err = adjustRangeForCommentsAndWhiteSpace (tok , start , end , src , file )
1428
+ file := curFile .Node ().(* ast.File )
1429
+ // TODO(adonovan): simplify, using Cursor.
1430
+ start , end , err = adjustRangeForCommentsAndWhiteSpace (tok , start , end , src , curFile )
1419
1431
if err != nil {
1420
1432
return nil , false , false , err
1421
1433
}
0 commit comments