@@ -19,7 +19,9 @@ package main
19
19
import (
20
20
"fmt"
21
21
"go/ast"
22
+ "go/token"
22
23
24
+ "golang.org/x/exp/utf8string"
23
25
"golang.org/x/tools/go/analysis"
24
26
"golang.org/x/tools/go/analysis/singlechecker"
25
27
)
@@ -48,7 +50,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
48
50
// passing all function calls to checkForFunctionExpr
49
51
if fexpr , ok := n .(* ast.CallExpr ); ok {
50
52
51
- checkForFunctionExpr (fexpr .Fun , pass )
53
+ checkForFunctionExpr (fexpr .Fun , fexpr . Args , pass )
52
54
}
53
55
54
56
return true
@@ -58,7 +60,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
58
60
}
59
61
60
62
// checkForFunctionExpr checks for unstructured logging function, prints error if found any.
61
- func checkForFunctionExpr (fun ast.Expr , pass * analysis.Pass ) {
63
+ func checkForFunctionExpr (fun ast.Expr , args []ast. Expr , pass * analysis.Pass ) {
62
64
63
65
/* we are extracting external package function calls e.g. klog.Infof fmt.Printf
64
66
and eliminating calls like setLocalHost()
@@ -80,6 +82,13 @@ func checkForFunctionExpr(fun ast.Expr, pass *analysis.Pass) {
80
82
// extracting package name
81
83
pName , ok := selExpr .X .(* ast.Ident )
82
84
85
+ if ok && pName .Name == "klog" && ! isUnstructured ((fName )) {
86
+ if fName == "InfoS" {
87
+ isKeysValid (args [1 :], fun , pass , fName )
88
+ } else if fName == "ErrorS" {
89
+ isKeysValid (args [2 :], fun , pass , fName )
90
+ }
91
+ }
83
92
// Matching if package name is klog and any unstructured logging function is used.
84
93
if ok && pName .Name == "klog" && isUnstructured ((fName )) {
85
94
@@ -110,3 +119,40 @@ func isUnstructured(fName string) bool {
110
119
111
120
return false
112
121
}
122
+
123
+ // isKeysValid check if all keys in keyAndValues is string type
124
+ func isKeysValid (keyValues []ast.Expr , fun ast.Expr , pass * analysis.Pass , funName string ) {
125
+ if len (keyValues )% 2 != 0 {
126
+ pass .Report (analysis.Diagnostic {
127
+ Pos : fun .Pos (),
128
+ Message : fmt .Sprintf ("Invalid Number of arguments for %s" , funName ),
129
+ })
130
+ }
131
+
132
+ for index , arg := range keyValues {
133
+ if index % 2 != 0 {
134
+ continue
135
+ }
136
+ if lit , ok := arg .(* ast.BasicLit ); ok {
137
+ if lit .Kind != token .STRING {
138
+ pass .Report (analysis.Diagnostic {
139
+ Pos : fun .Pos (),
140
+ Message : fmt .Sprintf ("Invalid value type for key %v" , lit .Value ),
141
+ })
142
+ continue
143
+ }
144
+ isASCII := utf8string .NewString (lit .Value ).IsASCII ()
145
+ if ! isASCII {
146
+ pass .Report (analysis.Diagnostic {
147
+ Pos : fun .Pos (),
148
+ Message : fmt .Sprintf ("Invalid value for key %v, it's must be ascii" , lit .Value ),
149
+ })
150
+ }
151
+ } else {
152
+ pass .Report (analysis.Diagnostic {
153
+ Pos : fun .Pos (),
154
+ Message : "Invalid value type for key" ,
155
+ })
156
+ }
157
+ }
158
+ }
0 commit comments