Skip to content

Commit f3c8b3c

Browse files
authored
Merge pull request #246 from meteorgan/type-assert
fix(type assert): add more check for type assert
2 parents b65821b + 2137b6c commit f3c8b3c

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

errcheck/errcheck.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -586,26 +586,38 @@ func (v *visitor) Visit(node ast.Node) ast.Visitor {
586586
for _, name := range vspec.Names {
587587
lhs = append(lhs, ast.Expr(name))
588588
}
589-
v.checkAssignment(lhs, vspec.Values)
589+
followed := v.checkAssignment(lhs, vspec.Values)
590+
if !followed {
591+
return nil
592+
}
590593
}
591594

592595
case *ast.AssignStmt:
593-
v.checkAssignment(stmt.Lhs, stmt.Rhs)
596+
followed := v.checkAssignment(stmt.Lhs, stmt.Rhs)
597+
if !followed {
598+
return nil
599+
}
600+
601+
case *ast.TypeAssertExpr:
602+
v.checkAssertExpr(stmt)
603+
return nil
594604

595605
default:
596606
}
597607
return v
598608
}
599609

600-
func (v *visitor) checkAssignment(lhs, rhs []ast.Expr) {
610+
// checkAssignment checks the assignment statement and returns a boolean value
611+
// indicating whether to continue checking the substructure in AssignStmt or not
612+
func (v *visitor) checkAssignment(lhs, rhs []ast.Expr) (followed bool) {
601613
if len(rhs) == 1 {
602614
// single value on rhs; check against lhs identifiers
603615
if call, ok := rhs[0].(*ast.CallExpr); ok {
604616
if !v.blank {
605-
return
617+
return true
606618
}
607619
if v.ignoreCall(call) {
608-
return
620+
return true
609621
}
610622
isError := v.errorsByArg(call)
611623
for i := 0; i < len(lhs); i++ {
@@ -619,11 +631,11 @@ func (v *visitor) checkAssignment(lhs, rhs []ast.Expr) {
619631
}
620632
} else if assert, ok := rhs[0].(*ast.TypeAssertExpr); ok {
621633
if !v.asserts {
622-
return
634+
return false
623635
}
624636
if assert.Type == nil {
625637
// type switch
626-
return
638+
return false
627639
}
628640
if len(lhs) < 2 {
629641
// assertion result not read
@@ -632,6 +644,7 @@ func (v *visitor) checkAssignment(lhs, rhs []ast.Expr) {
632644
// assertion result ignored
633645
v.addErrorAtPosition(id.NamePos, nil)
634646
}
647+
return false
635648
}
636649
} else {
637650
// multiple value on rhs; in this case a call can't return
@@ -661,6 +674,19 @@ func (v *visitor) checkAssignment(lhs, rhs []ast.Expr) {
661674
}
662675
}
663676
}
677+
678+
return true
679+
}
680+
681+
func (v *visitor) checkAssertExpr(expr *ast.TypeAssertExpr) {
682+
if !v.asserts {
683+
return
684+
}
685+
if expr.Type == nil {
686+
// type switch
687+
return
688+
}
689+
v.addErrorAtPosition(expr.Pos(), nil)
664690
}
665691

666692
func isErrorType(t types.Type) bool {

errcheck/testdata/src/assert/main.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,21 @@ package assert
33
func main() {
44
var i interface{}
55
_ = i.(string) // want "unchecked error"
6+
7+
handleInterface(i.(string)) // want "unchecked error"
8+
9+
if i.(string) == "hello" { // want "unchecked error"
10+
//
11+
}
12+
13+
switch i.(type) {
14+
case string:
15+
case int:
16+
_ = i.(int) // want "unchecked error"
17+
case nil:
18+
}
19+
}
20+
21+
func handleInterface(i interface{}) string {
22+
return i.(string) // want "unchecked error"
623
}

0 commit comments

Comments
 (0)