-
Notifications
You must be signed in to change notification settings - Fork 1
/
globals_handling.go
100 lines (85 loc) · 2.87 KB
/
globals_handling.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package main
import (
"log"
"strings"
"bytes"
"go/ast"
"go/token"
)
func isErrorVariableName(name string) (bool) {
return strings.HasPrefix(name, "Err") || strings.HasSuffix(name, "Err")
}
func isErrorPointer(vspec *ast.ValueSpec) (bool) {
for i, val := range vspec.Values {
if i >= len(vspec.Names) {
continue
}
name := vspec.Names[i].Name
if !ast.IsExported(name) {
continue
}
if !isErrorVariableName(name) {
log.Printf("variable name %s is not an error name\n", name)
return false
}
switch v := val.(type) {
case *ast.UnaryExpr:
if v.Op != token.AND {
log.Printf("UnaryExpr %+v is not an addressing operation\n", v)
return false
}
composite, ok := v.X.(*ast.CompositeLit)
if !ok {
log.Printf("UnaryExpr %+v does not address an CompositeLit object\n", v)
return false
}
typeNameBuffer := new(bytes.Buffer)
emitType(typeNameBuffer, composite.Type)
typeName := typeNameBuffer.String()
if !strings.HasSuffix(typeName, "Error") {
log.Printf("CompositeLit %+v does not use an error type (%s)\n", v, typeName)
return false
}
case *ast.SelectorExpr:
if !isErrorVariableName(v.Sel.Name) {
log.Printf("SelectorExpr %+v does not select an error variable (%s)\n", v, v.Sel.Name)
return false
}
case *ast.CallExpr:
callSelector, ok := v.Fun.(*ast.SelectorExpr)
if !ok {
log.Printf("CallExpr %+v does not have a selector expression\n", v)
return false
}
pkg, ok := callSelector.X.(*ast.Ident)
if !ok {
log.Printf("SelectorExpr %+v does not have an Ident expression\n", callSelector)
return false
}
if pkg.Name != "errors" && pkg.Name != "awserr" {
log.Printf("package %s in variable value assignment is not \"errors\" or \"awserr\"\n", pkg.Name)
return false
}
if callSelector.Sel.Name != "New" {
log.Printf("function %s in variable value assignment is not \"errors.New()\"\n", callSelector.Sel.Name)
return false
}
default:
log.Printf("ValueSpec %+v of type %T is not an error pointer\n", v, v)
return false
}
}
return true
}
func isWhitelistedGlobal(vspec *ast.ValueSpec) (bool) {
return false
}
func isAllowedGlobalPointer(vspec *ast.ValueSpec) (bool) {
if isErrorPointer(vspec) {
return true
}
if isWhitelistedGlobal(vspec) {
return true
}
return false
}