@@ -172,15 +172,15 @@ func LintErrorComparisons(info *TypesInfoExt) []analysis.Diagnostic {
172
172
continue
173
173
}
174
174
// Comparing errors with nil is okay.
175
- if isNilComparison (binExpr ) {
175
+ if isNil (binExpr . X ) || isNil ( binExpr . Y ) {
176
176
continue
177
177
}
178
178
// Find comparisons of which one side is a of type error.
179
- if ! isErrorComparison (info .TypesInfo , binExpr ) {
179
+ if ! isErrorType (info .TypesInfo , binExpr . X ) && ! isErrorType ( info . TypesInfo , binExpr . Y ) {
180
180
continue
181
181
}
182
182
// Some errors that are returned from some functions are exempt.
183
- if isAllowedErrorComparison (info , binExpr ) {
183
+ if isAllowedErrorComparison (info , binExpr . X , binExpr . Y ) {
184
184
continue
185
185
}
186
186
// Comparisons that happen in `func (type) Is(error) bool` are okay.
@@ -201,43 +201,52 @@ func LintErrorComparisons(info *TypesInfoExt) []analysis.Diagnostic {
201
201
continue
202
202
}
203
203
// Check whether the switch operates on an error type.
204
- if switchStmt .Tag == nil {
204
+ if ! isErrorType ( info . TypesInfo , switchStmt .Tag ) {
205
205
continue
206
206
}
207
- tagType := info .TypesInfo .Types [switchStmt .Tag ]
208
- if tagType .Type .String () != "error" {
207
+
208
+ var problematicCaseClause * ast.CaseClause
209
+ outer:
210
+ for _ , stmt := range switchStmt .Body .List {
211
+ caseClause := stmt .(* ast.CaseClause )
212
+ for _ , caseExpr := range caseClause .List {
213
+ if isNil (caseExpr ) {
214
+ continue
215
+ }
216
+ // Some errors that are returned from some functions are exempt.
217
+ if ! isAllowedErrorComparison (info , switchStmt .Tag , caseExpr ) {
218
+ problematicCaseClause = caseClause
219
+ break outer
220
+ }
221
+ }
222
+ }
223
+ if problematicCaseClause == nil {
209
224
continue
210
225
}
226
+ // Comparisons that happen in `func (type) Is(error) bool` are okay.
211
227
if isNodeInErrorIsFunc (info , switchStmt ) {
212
228
continue
213
229
}
214
230
215
231
if switchComparesNonNil (switchStmt ) {
216
232
lints = append (lints , analysis.Diagnostic {
217
233
Message : "switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors" ,
218
- Pos : switchStmt .Pos (),
234
+ Pos : problematicCaseClause .Pos (),
219
235
})
220
236
}
221
-
222
237
}
223
238
224
239
return lints
225
240
}
226
241
227
- func isNilComparison (binExpr * ast.BinaryExpr ) bool {
228
- if ident , ok := binExpr .X .(* ast.Ident ); ok && ident .Name == "nil" {
229
- return true
230
- }
231
- if ident , ok := binExpr .Y .(* ast.Ident ); ok && ident .Name == "nil" {
232
- return true
233
- }
234
- return false
242
+ func isNil (ex ast.Expr ) bool {
243
+ ident , ok := ex .(* ast.Ident )
244
+ return ok && ident .Name == "nil"
235
245
}
236
246
237
- func isErrorComparison (info * types.Info , binExpr * ast.BinaryExpr ) bool {
238
- tx := info .Types [binExpr .X ]
239
- ty := info .Types [binExpr .Y ]
240
- return tx .Type .String () == "error" || ty .Type .String () == "error"
247
+ func isErrorType (info * types.Info , ex ast.Expr ) bool {
248
+ t := info .Types [ex ].Type
249
+ return t != nil && t .String () == "error"
241
250
}
242
251
243
252
func isNodeInErrorIsFunc (info * TypesInfoExt , node ast.Node ) bool {
0 commit comments