1
1
package wastedassign
2
2
3
3
import (
4
- "fmt "
4
+ "errors "
5
5
"go/ast"
6
6
"go/token"
7
7
"go/types"
@@ -14,7 +14,7 @@ import (
14
14
15
15
const doc = "wastedassign finds wasted assignment statements."
16
16
17
- // Analyzer is .. .
17
+ // Analyzer is the wastedassign analyzer .
18
18
var Analyzer = & analysis.Analyzer {
19
19
Name : "wastedassign" ,
20
20
Doc : doc ,
@@ -31,8 +31,7 @@ type wastedAssignStruct struct {
31
31
32
32
func run (pass * analysis.Pass ) (interface {}, error ) {
33
33
// Plundered from buildssa.Run.
34
- mode := ssa .NaiveForm
35
- prog := ssa .NewProgram (pass .Fset , mode )
34
+ prog := ssa .NewProgram (pass .Fset , ssa .NaiveForm )
36
35
37
36
// Create SSA packages for all imports.
38
37
// Order is not significant.
@@ -73,12 +72,12 @@ func run(pass *analysis.Pass) (interface{}, error) {
73
72
74
73
fn := pass .TypesInfo .Defs [fdecl .Name ].(* types.Func )
75
74
if fn == nil {
76
- return nil , fmt . Errorf ("failed to get func's typesinfo" )
75
+ return nil , errors . New ("failed to get func's typesinfo" )
77
76
}
78
77
79
78
f := ssapkg .Prog .FuncValue (fn )
80
79
if f == nil {
81
- return nil , fmt . Errorf ("failed to get func's SSA-form intermediate representation" )
80
+ return nil , errors . New ("failed to get func's SSA-form intermediate representation" )
82
81
}
83
82
84
83
var addAnons func (f * ssa.Function )
@@ -96,41 +95,50 @@ func run(pass *analysis.Pass) (interface{}, error) {
96
95
typeSwitchPos := map [int ]bool {}
97
96
inspect := pass .ResultOf [inspect .Analyzer ].(* inspector.Inspector )
98
97
inspect .Preorder ([]ast.Node {new (ast.TypeSwitchStmt )}, func (n ast.Node ) {
99
- switch n := n .(type ) {
100
- case * ast.TypeSwitchStmt :
98
+ if _ , ok := n .(* ast.TypeSwitchStmt ); ok {
101
99
typeSwitchPos [pass .Fset .Position (n .Pos ()).Line ] = true
102
100
}
103
101
})
104
102
105
- wastedAssignMap := []wastedAssignStruct {}
103
+ var wastedAssignMap []wastedAssignStruct
106
104
107
105
for _ , sf := range srcFuncs {
108
106
for _ , bl := range sf .Blocks {
109
107
blCopy := * bl
110
108
for _ , ist := range bl .Instrs {
111
109
blCopy .Instrs = rmInstrFromInstrs (blCopy .Instrs , ist )
112
- switch ist .(type ) {
113
- case * ssa.Store :
114
- var buf [10 ]* ssa.Value
115
- for _ , op := range ist .Operands (buf [:0 ]) {
116
- if (* op ) != nil && opInLocals (sf .Locals , op ) {
117
- if reason := isNextOperationToOpIsStore ([]* ssa.BasicBlock {& blCopy }, op , nil ); reason != notWasted {
118
- if ist .Pos () != 0 && ! typeSwitchPos [pass .Fset .Position (ist .Pos ()).Line ] {
119
- wastedAssignMap = append (wastedAssignMap , wastedAssignStruct {
120
- pos : ist .Pos (),
121
- reason : reason .String (),
122
- })
123
- }
124
- }
125
- }
110
+ if _ , ok := ist .(* ssa.Store ); ! ok {
111
+ continue
112
+ }
113
+
114
+ var buf [10 ]* ssa.Value
115
+ for _ , op := range ist .Operands (buf [:0 ]) {
116
+ if (* op ) == nil || ! opInLocals (sf .Locals , op ) {
117
+ continue
126
118
}
119
+
120
+ reason := isNextOperationToOpIsStore ([]* ssa.BasicBlock {& blCopy }, op , nil )
121
+ if reason == notWasted {
122
+ continue
123
+ }
124
+
125
+ if ist .Pos () == 0 || typeSwitchPos [pass .Fset .Position (ist .Pos ()).Line ] {
126
+ continue
127
+ }
128
+
129
+ wastedAssignMap = append (wastedAssignMap , wastedAssignStruct {
130
+ pos : ist .Pos (),
131
+ reason : reason .String (),
132
+ })
127
133
}
128
134
}
129
135
}
130
136
}
137
+
131
138
for _ , was := range wastedAssignMap {
132
139
pass .Reportf (was .pos , was .reason )
133
140
}
141
+
134
142
return nil , nil
135
143
}
136
144
@@ -150,28 +158,31 @@ func (wr wastedReason) String() string {
150
158
return "wasted assignment"
151
159
case notWasted :
152
160
return ""
161
+ default :
162
+ return ""
153
163
}
154
- return ""
155
164
}
156
165
157
- func isNextOperationToOpIsStore (bls []* ssa.BasicBlock , currentOp * ssa.Value , haveCheckedMap * map [int ]bool ) wastedReason {
158
- wastedReasons := []wastedReason {}
159
- wastedReasonsCurrentBls := []wastedReason {}
166
+ func isNextOperationToOpIsStore (bls []* ssa.BasicBlock , currentOp * ssa.Value , haveCheckedMap map [int ]bool ) wastedReason {
167
+ var wastedReasons []wastedReason
168
+ var wastedReasonsCurrentBls []wastedReason
160
169
161
170
if haveCheckedMap == nil {
162
- haveCheckedMap = & map [int ]bool {}
171
+ haveCheckedMap = map [int ]bool {}
163
172
}
164
173
165
174
for _ , bl := range bls {
166
- if ( * haveCheckedMap ) [bl .Index ] == true {
175
+ if haveCheckedMap [bl .Index ] {
167
176
continue
168
177
}
169
- (* haveCheckedMap )[bl .Index ] = true
178
+
179
+ haveCheckedMap [bl .Index ] = true
170
180
breakFlag := false
171
181
for _ , ist := range bl .Instrs {
172
182
if breakFlag {
173
183
break
174
184
}
185
+
175
186
switch w := ist .(type ) {
176
187
case * ssa.Store :
177
188
var buf [10 ]* ssa.Value
@@ -196,6 +207,7 @@ func isNextOperationToOpIsStore(bls []*ssa.BasicBlock, currentOp *ssa.Value, hav
196
207
}
197
208
}
198
209
}
210
+
199
211
if len (bl .Succs ) != 0 && ! breakFlag {
200
212
wastedReason := isNextOperationToOpIsStore (rmSameBlock (bl .Succs , bl ), currentOp , haveCheckedMap )
201
213
if wastedReason == notWasted {
@@ -207,17 +219,15 @@ func isNextOperationToOpIsStore(bls []*ssa.BasicBlock, currentOp *ssa.Value, hav
207
219
208
220
wastedReasons = append (wastedReasons , wastedReasonsCurrentBls ... )
209
221
210
- if len (wastedReasons ) != 0 {
211
- if containReassignedSoon (wastedReasons ) {
212
- return reassignedSoon
213
- }
214
- return noUseUntilReturn
222
+ if len (wastedReasons ) != 0 && containReassignedSoon (wastedReasons ) {
223
+ return reassignedSoon
215
224
}
225
+
216
226
return noUseUntilReturn
217
227
}
218
228
219
229
func rmSameBlock (bls []* ssa.BasicBlock , currentBl * ssa.BasicBlock ) []* ssa.BasicBlock {
220
- rto := []* ssa.BasicBlock {}
230
+ var rto []* ssa.BasicBlock
221
231
222
232
for _ , bl := range bls {
223
233
if bl != currentBl {
@@ -227,15 +237,6 @@ func rmSameBlock(bls []*ssa.BasicBlock, currentBl *ssa.BasicBlock) []*ssa.BasicB
227
237
return rto
228
238
}
229
239
230
- func containNotWasted (ws []wastedReason ) bool {
231
- for _ , w := range ws {
232
- if w == notWasted {
233
- return true
234
- }
235
- }
236
- return false
237
- }
238
-
239
240
func containReassignedSoon (ws []wastedReason ) bool {
240
241
for _ , w := range ws {
241
242
if w == reassignedSoon {
0 commit comments