@@ -33,20 +33,23 @@ func extractVariable(fset *token.FileSet, rng span.Range, src []byte, file *ast.
33
33
// TODO: stricter rules for selectorExpr.
34
34
case * ast.BasicLit , * ast.CompositeLit , * ast.IndexExpr , * ast.SliceExpr ,
35
35
* ast.UnaryExpr , * ast.BinaryExpr , * ast.SelectorExpr :
36
- lhsNames = append (lhsNames , generateAvailableIdentifier (expr .Pos (), file , path , info , "x" , 0 ))
36
+ lhsName , _ := generateAvailableIdentifier (expr .Pos (), file , path , info , "x" , 0 )
37
+ lhsNames = append (lhsNames , lhsName )
37
38
case * ast.CallExpr :
38
39
tup , ok := info .TypeOf (expr ).(* types.Tuple )
39
40
if ! ok {
40
41
// If the call expression only has one return value, we can treat it the
41
42
// same as our standard extract variable case.
42
- lhsNames = append ( lhsNames ,
43
- generateAvailableIdentifier ( expr . Pos (), file , path , info , "x" , 0 ) )
43
+ lhsName , _ := generateAvailableIdentifier ( expr . Pos (), file , path , info , "x" , 0 )
44
+ lhsNames = append ( lhsNames , lhsName )
44
45
break
45
46
}
47
+ idx := 0
46
48
for i := 0 ; i < tup .Len (); i ++ {
47
49
// Generate a unique variable for each return value.
48
- lhsNames = append (lhsNames ,
49
- generateAvailableIdentifier (expr .Pos (), file , path , info , "x" , i ))
50
+ var lhsName string
51
+ lhsName , idx = generateAvailableIdentifier (expr .Pos (), file , path , info , "x" , idx )
52
+ lhsNames = append (lhsNames , lhsName )
50
53
}
51
54
default :
52
55
return nil , fmt .Errorf ("cannot extract %T" , expr )
@@ -133,15 +136,15 @@ func calculateIndentation(content []byte, tok *token.File, insertBeforeStmt ast.
133
136
}
134
137
135
138
// generateAvailableIdentifier adjusts the new function name until there are no collisons in scope.
136
- // Possible collisions include other function and variable names.
137
- func generateAvailableIdentifier (pos token.Pos , file * ast.File , path []ast.Node , info * types.Info , prefix string , idx int ) string {
139
+ // Possible collisions include other function and variable names. Returns the next index to check for prefix.
140
+ func generateAvailableIdentifier (pos token.Pos , file * ast.File , path []ast.Node , info * types.Info , prefix string , idx int ) ( string , int ) {
138
141
scopes := CollectScopes (info , path , pos )
139
142
name := prefix + fmt .Sprintf ("%d" , idx )
140
143
for file .Scope .Lookup (name ) != nil || ! isValidName (name , scopes ) {
141
144
idx ++
142
145
name = fmt .Sprintf ("%v%d" , prefix , idx )
143
146
}
144
- return name
147
+ return name , idx + 1
145
148
}
146
149
147
150
// isValidName checks for variable collision in scope.
@@ -465,7 +468,7 @@ func extractFunction(fset *token.FileSet, rng span.Range, src []byte, file *ast.
465
468
if canDefine {
466
469
sym = token .DEFINE
467
470
}
468
- funName := generateAvailableIdentifier (rng .Start , file , path , info , "fn" , 0 )
471
+ funName , _ := generateAvailableIdentifier (rng .Start , file , path , info , "fn" , 0 )
469
472
extractedFunCall := generateFuncCall (hasNonNestedReturn , hasReturnValues , params ,
470
473
append (returns , getNames (retVars )... ), funName , sym )
471
474
@@ -996,7 +999,8 @@ func generateReturnInfo(enclosing *ast.FuncType, pkg *types.Package, path []ast.
996
999
var cond * ast.Ident
997
1000
if ! hasNonNestedReturns {
998
1001
// Generate information for the added bool value.
999
- cond = & ast.Ident {Name : generateAvailableIdentifier (pos , file , path , info , "cond" , 0 )}
1002
+ name , _ := generateAvailableIdentifier (pos , file , path , info , "cond" , 0 )
1003
+ cond = & ast.Ident {Name : name }
1000
1004
retVars = append (retVars , & returnVariable {
1001
1005
name : cond ,
1002
1006
decl : & ast.Field {Type : ast .NewIdent ("bool" )},
@@ -1005,7 +1009,8 @@ func generateReturnInfo(enclosing *ast.FuncType, pkg *types.Package, path []ast.
1005
1009
}
1006
1010
// Generate information for the values in the return signature of the enclosing function.
1007
1011
if enclosing .Results != nil {
1008
- for i , field := range enclosing .Results .List {
1012
+ idx := 0
1013
+ for _ , field := range enclosing .Results .List {
1009
1014
typ := info .TypeOf (field .Type )
1010
1015
if typ == nil {
1011
1016
return nil , nil , fmt .Errorf (
@@ -1015,9 +1020,11 @@ func generateReturnInfo(enclosing *ast.FuncType, pkg *types.Package, path []ast.
1015
1020
if expr == nil {
1016
1021
return nil , nil , fmt .Errorf ("nil AST expression" )
1017
1022
}
1023
+ var name string
1024
+ name , idx = generateAvailableIdentifier (pos , file ,
1025
+ path , info , "ret" , idx )
1018
1026
retVars = append (retVars , & returnVariable {
1019
- name : ast .NewIdent (generateAvailableIdentifier (pos , file ,
1020
- path , info , "ret" , i )),
1027
+ name : ast .NewIdent (name ),
1021
1028
decl : & ast.Field {Type : expr },
1022
1029
zeroVal : analysisinternal .ZeroValue (
1023
1030
fset , file , pkg , typ ),
0 commit comments