@@ -2,6 +2,7 @@ package forcetypeassert
2
2
3
3
import (
4
4
"go/ast"
5
+ "reflect"
5
6
6
7
"golang.org/x/tools/go/analysis"
7
8
"golang.org/x/tools/go/analysis/passes/inspect"
@@ -15,12 +16,35 @@ var Analyzer = &analysis.Analyzer{
15
16
Requires : []* analysis.Analyzer {
16
17
inspect .Analyzer ,
17
18
},
19
+ ResultType : reflect .TypeOf ((* Panicable )(nil )),
18
20
}
19
21
20
- const Doc = "forcetypeassert is finds type assertions which did forcely such as below."
22
+ // Panicable stores panicable type assertions.
23
+ type Panicable struct {
24
+ m map [ast.Node ]bool
25
+ nodes []ast.Node
26
+ }
27
+
28
+ // Check checks whether the node may occur panic or not.
29
+ func (p * Panicable ) Check (n ast.Node ) bool {
30
+ return p .m [n ]
31
+ }
32
+
33
+ // Len is number of panicable nodes.
34
+ func (p * Panicable ) Len () int {
35
+ return len (p .nodes )
36
+ }
37
+
38
+ // At returns the i-th panicable node.
39
+ func (p * Panicable ) At (i int ) ast.Node {
40
+ return p .nodes [i ]
41
+ }
42
+
43
+ const Doc = "forcetypeassert is finds type assertions which did forcely"
21
44
22
45
func run (pass * analysis.Pass ) (interface {}, error ) {
23
- inspect := pass .ResultOf [inspect .Analyzer ].(* inspector.Inspector )
46
+ inspect , _ := pass .ResultOf [inspect .Analyzer ].(* inspector.Inspector )
47
+ result := & Panicable {m : make (map [ast.Node ]bool )}
24
48
25
49
nodeFilter := []ast.Node {
26
50
(* ast .AssignStmt )(nil ),
@@ -34,11 +58,13 @@ func run(pass *analysis.Pass) (interface{}, error) {
34
58
}
35
59
switch n := n .(type ) {
36
60
case * ast.AssignStmt :
37
- return checkAssignStmt (pass , n )
61
+ return checkAssignStmt (pass , result , n )
38
62
case * ast.ValueSpec :
39
- return checkValueSpec (pass , n )
63
+ return checkValueSpec (pass , result , n )
40
64
case * ast.TypeAssertExpr :
41
65
if n .Type != nil {
66
+ result .m [n ] = true
67
+ result .nodes = append (result .nodes , n )
42
68
pass .Reportf (n .Pos (), "type assertion must be checked" )
43
69
}
44
70
return false
@@ -47,10 +73,10 @@ func run(pass *analysis.Pass) (interface{}, error) {
47
73
return true
48
74
})
49
75
50
- return nil , nil
76
+ return result , nil
51
77
}
52
78
53
- func checkAssignStmt (pass * analysis.Pass , n * ast.AssignStmt ) bool {
79
+ func checkAssignStmt (pass * analysis.Pass , result * Panicable , n * ast.AssignStmt ) bool {
54
80
tae := findTypeAssertion (n .Rhs )
55
81
if tae == nil {
56
82
return true
@@ -62,6 +88,8 @@ func checkAssignStmt(pass *analysis.Pass, n *ast.AssignStmt) bool {
62
88
pass .Reportf (n .Pos (), "right hand must be only type assertion" )
63
89
return false
64
90
case len (n .Lhs ) != 2 && tae .Type != nil :
91
+ result .m [n ] = true
92
+ result .nodes = append (result .nodes , n )
65
93
pass .Reportf (n .Pos (), "type assertion must be checked" )
66
94
return false
67
95
case len (n .Lhs ) == 2 :
@@ -71,7 +99,7 @@ func checkAssignStmt(pass *analysis.Pass, n *ast.AssignStmt) bool {
71
99
return true
72
100
}
73
101
74
- func checkValueSpec (pass * analysis.Pass , n * ast.ValueSpec ) bool {
102
+ func checkValueSpec (pass * analysis.Pass , result * Panicable , n * ast.ValueSpec ) bool {
75
103
tae := findTypeAssertion (n .Values )
76
104
if tae == nil {
77
105
return true
@@ -83,6 +111,8 @@ func checkValueSpec(pass *analysis.Pass, n *ast.ValueSpec) bool {
83
111
pass .Reportf (n .Pos (), "right hand must be only type assertion" )
84
112
return false
85
113
case len (n .Names ) != 2 && tae .Type != nil :
114
+ result .m [n ] = true
115
+ result .nodes = append (result .nodes , n )
86
116
pass .Reportf (n .Pos (), "type assertion must be checked" )
87
117
return false
88
118
case len (n .Names ) == 2 :
0 commit comments