Skip to content

Commit b51de3b

Browse files
committed
wip: try parsing comments out of regex
This doesn't actually work yet
1 parent e2bbe2f commit b51de3b

File tree

3 files changed

+37
-23
lines changed

3 files changed

+37
-23
lines changed

forbidigo/forbidigo_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ func foo() {
2020
})
2121

2222
t.Run("displays custom messages", func(t *testing.T) {
23-
linter, _ := NewLinter([]string{`#[Please don't use this!]fmt\.Printf`})
23+
linter, _ := NewLinter([]string{`fmt\.Printf(# Please don't use this!)?`})
2424
expectIssues(t, linter, `
25-
package bar
25+
package bar
2626
27-
func foo() {
27+
func foo() {
2828
fmt.Printf("here i am")
29-
}`, "use of `fmt.Printf` forbidden by pattern `fmt\\.Printf` at testing.go:5:2: Please don't use this!")
29+
}`, "use of `fmt.Printf` forbidden by pattern `fmt\\.Printf` at testing.go:5:2: Please don't use this!")
3030
})
3131

3232
t.Run("it doesn't require a package on the identifier", func(t *testing.T) {

forbidigo/patterns.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,46 @@ package forbidigo
33
import (
44
"fmt"
55
"regexp"
6+
"regexp/syntax"
7+
"strings"
68
)
79

8-
var ptrnWithMsg = regexp.MustCompile(`(#\[(?P<msg>[^\]]+)\])?(?P<pattern>.+)`)
9-
1010
type pattern struct {
1111
pattern *regexp.Regexp
1212
msg string
1313
}
1414

1515
func parse(ptrn string) (*pattern, error) {
1616
p := &pattern{}
17-
matches := ptrnWithMsg.FindStringSubmatch(ptrn)
18-
for i, name := range ptrnWithMsg.SubexpNames() {
19-
if name == "msg" {
20-
p.msg = matches[i]
21-
} else if name == "pattern" {
22-
re, err := regexp.Compile(matches[i])
23-
if err != nil {
24-
return nil, fmt.Errorf("unable to compile pattern `%s`: %s", matches[i], err)
25-
}
26-
p.pattern = re
17+
parsedPattern, err := syntax.Parse(ptrn, syntax.Perl)
18+
if err != nil {
19+
return nil, fmt.Errorf("unable to parse pattern: %s: %s", ptrn, err)
20+
}
21+
if len(parsedPattern.Sub) == 0 {
22+
p.pattern, err = regexp.Compile(parsedPattern.String())
23+
if err != nil {
24+
return nil, fmt.Errorf("unable to compile pattern: %s: %s", ptrn, err)
2725
}
26+
return p, nil
27+
}
28+
p.pattern, err = regexp.Compile(parsedPattern.Sub[0].String())
29+
if err != nil {
30+
return nil, fmt.Errorf("unable to compile pattern: %s: %s", ptrn, err)
31+
}
32+
if len(parsedPattern.Sub) < 2 {
33+
return p, nil
2834
}
35+
msgPattern := deepestSubmatch(parsedPattern).String()
36+
p.msg = strings.TrimSpace(strings.TrimPrefix(msgPattern, "#"))
2937

3038
return p, nil
3139
}
40+
41+
func deepestSubmatch(expr *syntax.Regexp) *syntax.Regexp {
42+
for {
43+
if len(expr.Sub) == 0 {
44+
return expr
45+
}
46+
expr = expr.Sub[len(expr.Sub)-1]
47+
}
48+
}

forbidigo/patterns_test.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,13 @@ func TestParseValidPattern(t *testing.T) {
1313
assert.Equal(t, `fmt\.Errorf`, ptrn.pattern.String())
1414
}
1515

16-
func TestParseValidPatternThatUsesSquareBrackets(t *testing.T) {
17-
ptrn, err := parse(`[f]mt\.Errorf`)
18-
require.Nil(t, err)
19-
assert.Equal(t, `[f]mt\.Errorf`, ptrn.pattern.String())
20-
}
21-
2216
func TestParseValidPatternWithCustomMessage(t *testing.T) {
23-
ptrn, err := parse(`#[Please don't use this!]fmt\.Println`)
17+
ptrn, err := parse(`fmt\.Println(# Please don't use this!)?`)
2418
require.Nil(t, err)
19+
20+
// Remove custom message from pattern so as not to duplicate it in the output.
2521
assert.Equal(t, `fmt\.Println`, ptrn.pattern.String())
22+
2623
assert.Equal(t, "Please don't use this!", ptrn.msg)
2724
}
2825

0 commit comments

Comments
 (0)