forked from golangci/golangci-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
identifier_marker.go
154 lines (132 loc) · 4.88 KB
/
identifier_marker.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package processors
import (
"regexp"
"github.com/nalekseevs/itns-golangci-lint/pkg/result"
)
var _ Processor = (*IdentifierMarker)(nil)
type replacePattern struct {
re string
repl string
}
type replaceRegexp struct {
re *regexp.Regexp
repl string
}
var replacePatterns = []replacePattern{
// unparam
{`^(\S+) - (\S+) is unused$`, "`${1}` - `${2}` is unused"},
{`^(\S+) - (\S+) always receives (\S+) \((.*)\)$`, "`${1}` - `${2}` always receives `${3}` (`${4}`)"},
{`^(\S+) - (\S+) always receives (.*)$`, "`${1}` - `${2}` always receives `${3}`"},
{`^(\S+) - result (\S+) is always (\S+)`, "`${1}` - result `${2}` is always `${3}`"},
// interfacer
{`^(\S+) can be (\S+)$`, "`${1}` can be `${2}`"},
// govet
{`^printf: (\S+) arg list ends with redundant newline$`, "printf: `${1}` arg list ends with redundant newline"},
{`^composites: (\S+) composite literal uses unkeyed fields$`, "composites: `${1}` composite literal uses unkeyed fields"},
// gosec
{
`^(\S+): Blacklisted import (\S+): weak cryptographic primitive$`,
"${1}: Blacklisted import `${2}`: weak cryptographic primitive",
},
{`^TLS InsecureSkipVerify set true.$`, "TLS `InsecureSkipVerify` set true."},
// gosimple
{`should replace loop with (.*)$`, "should replace loop with `${1}`"},
{
`should use a simple channel send/receive instead of select with a single case`,
"should use a simple channel send/receive instead of `select` with a single case",
},
{
`should omit comparison to bool constant, can be simplified to (.+)$`,
"should omit comparison to bool constant, can be simplified to `${1}`",
},
{`should write (.+) instead of (.+)$`, "should write `${1}` instead of `${2}`"},
{`redundant return statement$`, "redundant `return` statement"},
{
`should replace this if statement with an unconditional strings.TrimPrefix`,
"should replace this `if` statement with an unconditional `strings.TrimPrefix`",
},
// staticcheck
{`this value of (\S+) is never used$`, "this value of `${1}` is never used"},
{
`should use time.Since instead of time.Now\(\).Sub$`,
"should use `time.Since` instead of `time.Now().Sub`",
},
{
`should check returned error before deferring response.Close\(\)$`,
"should check returned error before deferring `response.Close()`",
},
{`no value of type uint is less than 0$`, "no value of type `uint` is less than `0`"},
// unused
{`(func|const|field|type|var) (\S+) is unused$`, "${1} `${2}` is unused"},
// typecheck
{`^unknown field (\S+) in struct literal$`, "unknown field `${1}` in struct literal"},
{
`^invalid operation: (\S+) \(variable of type (\S+)\) has no field or method (\S+)$`,
"invalid operation: `${1}` (variable of type `${2}`) has no field or method `${3}`",
},
{`^undeclared name: (\S+)$`, "undeclared name: `${1}`"},
{
`^cannot use addr \(variable of type (\S+)\) as (\S+) value in argument to (\S+)$`,
"cannot use addr (variable of type `${1}`) as `${2}` value in argument to `${3}`",
},
{`^other declaration of (\S+)$`, "other declaration of `${1}`"},
{`^(\S+) redeclared in this block$`, "`${1}` redeclared in this block"},
// golint
{
`^exported (type|method|function|var|const) (\S+) should have comment or be unexported$`,
"exported ${1} `${2}` should have comment or be unexported",
},
{
`^comment on exported (type|method|function|var|const) (\S+) should be of the form "(\S+) ..."$`,
"comment on exported ${1} `${2}` should be of the form `${3} ...`",
},
{`^should replace (.+) with (.+)$`, "should replace `${1}` with `${2}`"},
{
`^if block ends with a return statement, so drop this else and outdent its block$`,
"`if` block ends with a `return` statement, so drop this `else` and outdent its block",
},
{
`^(struct field|var|range var|const|type|(?:func|method|interface method) (?:parameter|result)) (\S+) should be (\S+)$`,
"${1} `${2}` should be `${3}`",
},
{
`^don't use underscores in Go names; var (\S+) should be (\S+)$`,
"don't use underscores in Go names; var `${1}` should be `${2}`",
},
}
type IdentifierMarker struct {
replaceRegexps []replaceRegexp
}
func NewIdentifierMarker() *IdentifierMarker {
var replaceRegexps []replaceRegexp
for _, p := range replacePatterns {
r := replaceRegexp{
re: regexp.MustCompile(p.re),
repl: p.repl,
}
replaceRegexps = append(replaceRegexps, r)
}
return &IdentifierMarker{
replaceRegexps: replaceRegexps,
}
}
func (IdentifierMarker) Name() string {
return "identifier_marker"
}
func (p IdentifierMarker) Process(issues []result.Issue) ([]result.Issue, error) {
return transformIssues(issues, func(issue *result.Issue) *result.Issue {
newIssue := *issue
newIssue.Text = p.markIdentifiers(newIssue.Text)
return &newIssue
}), nil
}
func (IdentifierMarker) Finish() {}
func (p IdentifierMarker) markIdentifiers(s string) string {
for _, rr := range p.replaceRegexps {
rs := rr.re.ReplaceAllString(s, rr.repl)
if rs != s {
return rs
}
}
return s
}