@@ -172,15 +172,15 @@ func LintErrorComparisons(info *TypesInfoExt) []analysis.Diagnostic {
172172 continue
173173 }
174174 // Comparing errors with nil is okay.
175- if isNilComparison (binExpr ) {
175+ if isNil (binExpr . X ) || isNil ( binExpr . Y ) {
176176 continue
177177 }
178178 // 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 ) {
180180 continue
181181 }
182182 // Some errors that are returned from some functions are exempt.
183- if isAllowedErrorComparison (info , binExpr ) {
183+ if isAllowedErrorComparison (info , binExpr . X , binExpr . Y ) {
184184 continue
185185 }
186186 // Comparisons that happen in `func (type) Is(error) bool` are okay.
@@ -201,43 +201,52 @@ func LintErrorComparisons(info *TypesInfoExt) []analysis.Diagnostic {
201201 continue
202202 }
203203 // Check whether the switch operates on an error type.
204- if switchStmt .Tag == nil {
204+ if ! isErrorType ( info . TypesInfo , switchStmt .Tag ) {
205205 continue
206206 }
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 {
209224 continue
210225 }
226+ // Comparisons that happen in `func (type) Is(error) bool` are okay.
211227 if isNodeInErrorIsFunc (info , switchStmt ) {
212228 continue
213229 }
214230
215231 if switchComparesNonNil (switchStmt ) {
216232 lints = append (lints , analysis.Diagnostic {
217233 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 (),
219235 })
220236 }
221-
222237 }
223238
224239 return lints
225240}
226241
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"
235245}
236246
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"
241250}
242251
243252func isNodeInErrorIsFunc (info * TypesInfoExt , node ast.Node ) bool {
0 commit comments