Skip to content

Commit 4bcb6ff

Browse files
authored
Merge pull request #13 from gostaticanalysis/fix-expr
Fix bugs for expressions
2 parents 1c60ede + 1ac5cc5 commit 4bcb6ff

File tree

2 files changed

+69
-49
lines changed

2 files changed

+69
-49
lines changed

forcetypeassert.go

Lines changed: 55 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,83 +25,89 @@ func run(pass *analysis.Pass) (interface{}, error) {
2525
nodeFilter := []ast.Node{
2626
(*ast.AssignStmt)(nil),
2727
(*ast.ValueSpec)(nil),
28+
(*ast.TypeAssertExpr)(nil),
2829
}
2930

30-
inspect.Preorder(nodeFilter, func(n ast.Node) {
31+
inspect.Nodes(nodeFilter, func(n ast.Node, push bool) bool {
32+
if !push {
33+
return false
34+
}
3135
switch n := n.(type) {
3236
case *ast.AssignStmt:
33-
checkAssignStmt(pass, n)
37+
return checkAssignStmt(pass, n)
3438
case *ast.ValueSpec:
35-
checkValueSpec(pass, n)
39+
return checkValueSpec(pass, n)
40+
case *ast.TypeAssertExpr:
41+
if n.Type != nil {
42+
pass.Reportf(n.Pos(), "type assertion must be checked")
43+
}
44+
return false
3645
}
46+
47+
return true
3748
})
3849

3950
return nil, nil
4051
}
4152

42-
func checkAssignStmt(pass *analysis.Pass, n *ast.AssignStmt) {
43-
if !hasTypeAssertion(n.Rhs) {
44-
return
53+
func checkAssignStmt(pass *analysis.Pass, n *ast.AssignStmt) bool {
54+
tae := findTypeAssertion(n.Rhs)
55+
if tae == nil {
56+
return true
4557
}
4658

59+
switch {
4760
// if right hand has 2 or more values, assign statement can't assert boolean value which describes type assertion is succeeded
48-
if len(n.Rhs) > 1 {
61+
case len(n.Rhs) > 1:
4962
pass.Reportf(n.Pos(), "right hand must be only type assertion")
50-
return
51-
}
52-
53-
if len(n.Lhs) == 2 {
54-
return
55-
}
56-
57-
tae, ok := n.Rhs[0].(*ast.TypeAssertExpr)
58-
if !ok {
59-
pass.Reportf(n.Pos(), "right hand is not TypeAssertion")
60-
return
61-
}
62-
63-
if tae.Type == nil {
64-
return
63+
return false
64+
case len(n.Lhs) != 2 && tae.Type != nil:
65+
pass.Reportf(n.Pos(), "type assertion must be checked")
66+
return false
67+
case len(n.Lhs) == 2:
68+
return false
6569
}
6670

67-
pass.Reportf(n.Pos(), "type assertion must be checked")
71+
return true
6872
}
6973

70-
func checkValueSpec(pass *analysis.Pass, n *ast.ValueSpec) {
71-
if !hasTypeAssertion(n.Values) {
72-
return
74+
func checkValueSpec(pass *analysis.Pass, n *ast.ValueSpec) bool {
75+
tae := findTypeAssertion(n.Values)
76+
if tae == nil {
77+
return true
7378
}
7479

80+
switch {
7581
// if right hand has 2 or more values, assign statement can't assert boolean value which describes type assertion is succeeded
76-
if len(n.Values) > 1 {
82+
case len(n.Values) > 1:
7783
pass.Reportf(n.Pos(), "right hand must be only type assertion")
78-
return
84+
return false
85+
case len(n.Names) != 2 && tae.Type != nil:
86+
pass.Reportf(n.Pos(), "type assertion must be checked")
87+
return false
88+
case len(n.Names) == 2:
89+
return false
7990
}
8091

81-
if len(n.Names) == 2 {
82-
return
83-
}
84-
85-
tae, ok := n.Values[0].(*ast.TypeAssertExpr)
86-
if !ok {
87-
pass.Reportf(n.Pos(), "right hand is not TypeAssertion")
88-
return
89-
}
90-
91-
if tae.Type == nil {
92-
return
93-
}
94-
95-
pass.Reportf(n.Pos(), "type assertion must be checked")
96-
92+
return true
9793
}
9894

99-
func hasTypeAssertion(exprs []ast.Expr) bool {
100-
for _, node := range exprs {
101-
_, ok := node.(*ast.TypeAssertExpr)
102-
if ok {
95+
func findTypeAssertion(exprs []ast.Expr) *ast.TypeAssertExpr {
96+
for _, expr := range exprs {
97+
var typeAssertExpr *ast.TypeAssertExpr
98+
ast.Inspect(expr, func(n ast.Node) bool {
99+
switch n := n.(type) {
100+
case *ast.FuncLit:
101+
return false
102+
case *ast.TypeAssertExpr:
103+
typeAssertExpr = n
104+
return false
105+
}
103106
return true
107+
})
108+
if typeAssertExpr != nil {
109+
return typeAssertExpr
104110
}
105111
}
106-
return false
112+
return nil
107113
}

testdata/src/a/a.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,18 @@ func f() {
3030
}
3131

3232
var _ = i.(string) // want `type assertion must be checked`
33+
34+
var _ = *i.(*string) // want `type assertion must be checked`
35+
36+
println(i.(string)) // want `type assertion must be checked`
37+
println(*i.(*string)) // want `type assertion must be checked`
38+
39+
_ = func() int {
40+
println(*i.(*string)) // want `type assertion must be checked`
41+
return 0
42+
}()
43+
44+
func() {
45+
println(*i.(*string)) // want `type assertion must be checked`
46+
}()
3347
}

0 commit comments

Comments
 (0)