Skip to content

Commit 7af5f7c

Browse files
committed
refactor: rewrite IdentifierMarker
1 parent 8f187ff commit 7af5f7c

File tree

2 files changed

+206
-157
lines changed

2 files changed

+206
-157
lines changed

pkg/result/processors/identifier_marker.go

Lines changed: 105 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -9,146 +9,134 @@ import (
99
var _ Processor = (*IdentifierMarker)(nil)
1010

1111
type replacePattern struct {
12-
re string
12+
exp *regexp.Regexp
1313
repl string
1414
}
1515

16-
type replaceRegexp struct {
17-
re *regexp.Regexp
18-
repl string
19-
}
20-
21-
var replacePatterns = []replacePattern{
22-
// unparam
23-
{`^(\S+) - (\S+) is unused$`, "`${1}` - `${2}` is unused"},
24-
{`^(\S+) - (\S+) always receives (\S+) \((.*)\)$`, "`${1}` - `${2}` always receives `${3}` (`${4}`)"},
25-
{`^(\S+) - (\S+) always receives (.*)$`, "`${1}` - `${2}` always receives `${3}`"},
26-
{`^(\S+) - result (\S+) is always (\S+)`, "`${1}` - result `${2}` is always `${3}`"},
27-
28-
// interfacer
29-
{`^(\S+) can be (\S+)$`, "`${1}` can be `${2}`"},
30-
31-
// govet
32-
{`^printf: (\S+) arg list ends with redundant newline$`, "printf: `${1}` arg list ends with redundant newline"},
33-
{`^composites: (\S+) composite literal uses unkeyed fields$`, "composites: `${1}` composite literal uses unkeyed fields"},
34-
35-
// gosec
36-
{
37-
`^(\S+): Blacklisted import (\S+): weak cryptographic primitive$`,
38-
"${1}: Blacklisted import `${2}`: weak cryptographic primitive",
39-
},
40-
{`^TLS InsecureSkipVerify set true.$`, "TLS `InsecureSkipVerify` set true."},
41-
42-
// gosimple
43-
{`should replace loop with (.*)$`, "should replace loop with `${1}`"},
44-
{
45-
`should use a simple channel send/receive instead of select with a single case`,
46-
"should use a simple channel send/receive instead of `select` with a single case",
47-
},
48-
{
49-
`should omit comparison to bool constant, can be simplified to (.+)$`,
50-
"should omit comparison to bool constant, can be simplified to `${1}`",
51-
},
52-
{`should write (.+) instead of (.+)$`, "should write `${1}` instead of `${2}`"},
53-
{`redundant return statement$`, "redundant `return` statement"},
54-
{
55-
`should replace this if statement with an unconditional strings.TrimPrefix`,
56-
"should replace this `if` statement with an unconditional `strings.TrimPrefix`",
57-
},
58-
59-
// staticcheck
60-
{`this value of (\S+) is never used$`, "this value of `${1}` is never used"},
61-
{
62-
`should use time.Since instead of time.Now\(\).Sub$`,
63-
"should use `time.Since` instead of `time.Now().Sub`",
64-
},
65-
{
66-
`should check returned error before deferring response.Close\(\)$`,
67-
"should check returned error before deferring `response.Close()`",
68-
},
69-
{`no value of type uint is less than 0$`, "no value of type `uint` is less than `0`"},
70-
71-
// unused
72-
{`(func|const|field|type|var) (\S+) is unused$`, "${1} `${2}` is unused"},
73-
74-
// typecheck
75-
{`^unknown field (\S+) in struct literal$`, "unknown field `${1}` in struct literal"},
76-
{
77-
`^invalid operation: (\S+) \(variable of type (\S+)\) has no field or method (\S+)$`,
78-
"invalid operation: `${1}` (variable of type `${2}`) has no field or method `${3}`",
79-
},
80-
{`^undeclared name: (\S+)$`, "undeclared name: `${1}`"},
81-
{
82-
`^cannot use addr \(variable of type (\S+)\) as (\S+) value in argument to (\S+)$`,
83-
"cannot use addr (variable of type `${1}`) as `${2}` value in argument to `${3}`",
84-
},
85-
{`^other declaration of (\S+)$`, "other declaration of `${1}`"},
86-
{`^(\S+) redeclared in this block$`, "`${1}` redeclared in this block"},
87-
88-
// golint
89-
{
90-
`^exported (type|method|function|var|const) (\S+) should have comment or be unexported$`,
91-
"exported ${1} `${2}` should have comment or be unexported",
92-
},
93-
{
94-
`^comment on exported (type|method|function|var|const) (\S+) should be of the form "(\S+) ..."$`,
95-
"comment on exported ${1} `${2}` should be of the form `${3} ...`",
96-
},
97-
{`^should replace (.+) with (.+)$`, "should replace `${1}` with `${2}`"},
98-
{
99-
`^if block ends with a return statement, so drop this else and outdent its block$`,
100-
"`if` block ends with a `return` statement, so drop this `else` and outdent its block",
101-
},
102-
{
103-
`^(struct field|var|range var|const|type|(?:func|method|interface method) (?:parameter|result)) (\S+) should be (\S+)$`,
104-
"${1} `${2}` should be `${3}`",
105-
},
106-
{
107-
`^don't use underscores in Go names; var (\S+) should be (\S+)$`,
108-
"don't use underscores in Go names; var `${1}` should be `${2}`",
109-
},
110-
}
111-
11216
type IdentifierMarker struct {
113-
replaceRegexps []replaceRegexp
17+
patterns map[string][]replacePattern
11418
}
11519

11620
func NewIdentifierMarker() *IdentifierMarker {
117-
var replaceRegexps []replaceRegexp
118-
for _, p := range replacePatterns {
119-
r := replaceRegexp{
120-
re: regexp.MustCompile(p.re),
121-
repl: p.repl,
122-
}
123-
replaceRegexps = append(replaceRegexps, r)
124-
}
125-
12621
return &IdentifierMarker{
127-
replaceRegexps: replaceRegexps,
22+
patterns: map[string][]replacePattern{
23+
"unparam": {
24+
{
25+
exp: regexp.MustCompile(`^(\S+) - (\S+) is unused$`),
26+
repl: "`${1}` - `${2}` is unused",
27+
},
28+
{
29+
exp: regexp.MustCompile(`^(\S+) - (\S+) always receives (\S+) \((.*)\)$`),
30+
repl: "`${1}` - `${2}` always receives `${3}` (`${4}`)",
31+
},
32+
{
33+
exp: regexp.MustCompile(`^(\S+) - (\S+) always receives (.*)$`),
34+
repl: "`${1}` - `${2}` always receives `${3}`",
35+
},
36+
{
37+
exp: regexp.MustCompile(`^(\S+) - result (\S+) is always (\S+)`),
38+
repl: "`${1}` - result `${2}` is always `${3}`",
39+
},
40+
},
41+
"govet": {
42+
{
43+
// printf
44+
exp: regexp.MustCompile(`^printf: (\S+) arg list ends with redundant newline$`),
45+
repl: "printf: `${1}` arg list ends with redundant newline",
46+
},
47+
},
48+
"gosec": {
49+
{
50+
exp: regexp.MustCompile(`^TLS InsecureSkipVerify set true.$`),
51+
repl: "TLS `InsecureSkipVerify` set true.",
52+
},
53+
},
54+
"gosimple": {
55+
{
56+
// s1011
57+
exp: regexp.MustCompile(`should replace loop with (.*)$`),
58+
repl: "should replace loop with `${1}`",
59+
},
60+
{
61+
// s1000
62+
exp: regexp.MustCompile(`should use a simple channel send/receive instead of select with a single case`),
63+
repl: "should use a simple channel send/receive instead of `select` with a single case",
64+
},
65+
{
66+
// s1002
67+
exp: regexp.MustCompile(`should omit comparison to bool constant, can be simplified to (.+)$`),
68+
repl: "should omit comparison to bool constant, can be simplified to `${1}`",
69+
},
70+
{
71+
// s1023
72+
exp: regexp.MustCompile(`redundant return statement$`),
73+
repl: "redundant `return` statement",
74+
},
75+
{
76+
// s1017
77+
exp: regexp.MustCompile(`should replace this if statement with an unconditional strings.TrimPrefix`),
78+
repl: "should replace this `if` statement with an unconditional `strings.TrimPrefix`",
79+
},
80+
},
81+
"staticcheck": {
82+
{
83+
// sa4006
84+
exp: regexp.MustCompile(`this value of (\S+) is never used$`),
85+
repl: "this value of `${1}` is never used",
86+
},
87+
{
88+
// s1012
89+
exp: regexp.MustCompile(`should use time.Since instead of time.Now\(\).Sub$`),
90+
repl: "should use `time.Since` instead of `time.Now().Sub`",
91+
},
92+
{
93+
// sa5001
94+
exp: regexp.MustCompile(`should check returned error before deferring response.Close\(\)$`),
95+
repl: "should check returned error before deferring `response.Close()`",
96+
},
97+
{
98+
// sa4003
99+
exp: regexp.MustCompile(`no value of type uint is less than 0$`),
100+
repl: "no value of type `uint` is less than `0`",
101+
},
102+
},
103+
"unused": {
104+
{
105+
exp: regexp.MustCompile(`(func|const|field|type|var) (\S+) is unused$`),
106+
repl: "${1} `${2}` is unused",
107+
},
108+
},
109+
},
128110
}
129111
}
130112

131-
func (IdentifierMarker) Name() string {
113+
func (*IdentifierMarker) Name() string {
132114
return "identifier_marker"
133115
}
134116

135-
func (p IdentifierMarker) Process(issues []result.Issue) ([]result.Issue, error) {
117+
func (p *IdentifierMarker) Process(issues []result.Issue) ([]result.Issue, error) {
136118
return transformIssues(issues, func(issue *result.Issue) *result.Issue {
119+
re, ok := p.patterns[issue.FromLinter]
120+
if !ok {
121+
return issue
122+
}
123+
137124
newIssue := *issue
138-
newIssue.Text = p.markIdentifiers(newIssue.Text)
125+
newIssue.Text = markIdentifiers(re, newIssue.Text)
126+
139127
return &newIssue
140128
}), nil
141129
}
142130

143-
func (IdentifierMarker) Finish() {}
131+
func (*IdentifierMarker) Finish() {}
144132

145-
func (p IdentifierMarker) markIdentifiers(s string) string {
146-
for _, rr := range p.replaceRegexps {
147-
rs := rr.re.ReplaceAllString(s, rr.repl)
148-
if rs != s {
133+
func markIdentifiers(re []replacePattern, text string) string {
134+
for _, rr := range re {
135+
rs := rr.exp.ReplaceAllString(text, rr.repl)
136+
if rs != text {
149137
return rs
150138
}
151139
}
152140

153-
return s
141+
return text
154142
}

0 commit comments

Comments
 (0)