-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathapi.go
130 lines (113 loc) · 3.21 KB
/
api.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package thriftlint
import (
"fmt"
"strings"
"github.com/alecthomas/go-thrift/parser"
)
// Severity of a linter message.
type Severity int
// Message severities.
const (
Warning Severity = iota
Error
)
func (s Severity) String() string {
if s == Warning {
return "warning"
}
return "error"
}
// Message represents a single linter message.
type Message struct {
// File that resulted in the message.
File *parser.Thrift
// ID of the Checker that generated this message.
Checker string
Severity Severity
Object interface{}
Message string
}
// Messages is the set of messages each check should return.
//
// Typically it will be used like so:
//
// func MyCheck(...) (messages Messages) {
// messages.Warning(t, "some warning")
// }
type Messages []*Message
// Warning adds a warning-level message to the Messages.
func (w *Messages) Warning(object interface{}, msg string, args ...interface{}) Messages {
message := &Message{Severity: Warning, Object: object, Message: fmt.Sprintf(msg, args...)}
*w = append(*w, message)
return *w
}
// Warning adds an error-level message to the Messages.
func (w *Messages) Error(object interface{}, msg string, args ...interface{}) Messages {
message := &Message{Severity: Error, Object: object, Message: fmt.Sprintf(msg, args...)}
*w = append(*w, message)
return *w
}
// Checks is a convenience wrapper around a slice of Checks.
type Checks []Check
// CloneAndDisable returns a copy of this Checks slice with all checks matching prefix disabled.
func (c Checks) CloneAndDisable(prefixes ...string) Checks {
out := Checks{}
skip:
for _, check := range c {
id := check.ID()
for _, prefix := range prefixes {
if prefix == id || strings.HasPrefix(id, prefix+".") {
continue skip
}
}
out = append(out, check)
}
return out
}
// Has returns true if the Checks slice contains any checks matching prefix.
func (c Checks) Has(prefix string) bool {
for _, check := range c {
id := check.ID()
if prefix == id || strings.HasPrefix(id, prefix+".") {
return true
}
}
return false
}
// Check implementations are used by the linter to check AST nodes.
type Check interface {
// ID of the Check. Must be unique across all checks.
//
// IDs may be hierarchical, separated by a period. eg. "enum", "enum.values"
ID() string
// Checker returns the checking function.
//
// The checking function has the signature "func(...) Messages", where "..." is a sequence of
// Thrift AST types that are matched against the current node's ancestors as the linter walks
// the AST of each file. "..." may also be "interface{}" in which case the checker function
// will be called for each node in the AST.
//
// For example, the function:
//
// func (s *parser.Struct, f *parser.Field) (messages Messages)
//
// Will match all each struct field, but not union fields.
Checker() interface{}
}
// MakeCheck creates a stateless Check type from an ID and a checker function.
func MakeCheck(id string, checker interface{}) Check {
return &statelessCheck{
id: id,
checker: checker,
}
}
type statelessCheck struct {
id string
checker interface{}
}
func (s *statelessCheck) ID() string {
return s.id
}
func (s *statelessCheck) Checker() interface{} {
return s.checker
}