-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ruleguard: implement
MatchComment
function from the DSL
Most `Where()` filters work for comments as one would expect. Named captures `?P<name>` can be accessed via `m["name"]`. `Report()` and `Suggest()` interpolation can work with named captures. The `$$` variable is bound to the entire regexp match (like `$0`).
- Loading branch information
Showing
16 changed files
with
423 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// +build ignore | ||
|
||
package gorules | ||
|
||
import "github.com/quasilyte/go-ruleguard/dsl" | ||
|
||
func nolintFormat(m dsl.Matcher) { | ||
m.MatchComment(`// nolint(?:$|\s)`).Report(`remove a space between // and "nolint" directive`) | ||
|
||
// Using ?s flag to match multiline text. | ||
m.MatchComment(`(?s)/\*.*nolint.*`). | ||
Report(`don't put "nolint" inside a multi-line comment`) | ||
} | ||
|
||
// Testing a pattern without capture groups. | ||
func nolintGocritic(m dsl.Matcher) { | ||
m.MatchComment(`//nolint:gocritic`). | ||
Report(`hey, this is kinda upsetting`) | ||
} | ||
|
||
// Testing Suggest. | ||
func nolint2quickfix(m dsl.Matcher) { | ||
m.MatchComment(`// nolint2(?P<rest>.*)`).Suggest(`//nolint2$rest`) | ||
} | ||
|
||
// Testing named groups. | ||
func directiveFormat(m dsl.Matcher) { | ||
m.MatchComment(`/\*(?P<directive>[\w-]+):`). | ||
Report(`directive should be written as //$directive`) | ||
} | ||
|
||
// Testing Where clause. | ||
func forbiddenGoDirective(m dsl.Matcher) { | ||
m.MatchComment(`//go:(?P<x>\w+)`). | ||
Where(m["x"].Text != "generate" && !m["x"].Text.Matches(`embed|noinline`)). | ||
Report("don't use $x go directive") | ||
} | ||
|
||
// Test that file-related things work for MatchComment too. | ||
func fooDirectives(m dsl.Matcher) { | ||
m.MatchComment(`//go:embed`). | ||
Where(m.File().Name.Matches(`^.*_foo.go$`)). | ||
Report("don't use go:embed in _foo files") | ||
} | ||
|
||
// Test multi-pattern matching. | ||
// Also test $$ interpolation. | ||
func commentTypo(m dsl.Matcher) { | ||
m.MatchComment(`begining`, `bizzare`).Report(`"$$" may contain a typo`) | ||
} | ||
|
||
// Test $$ with a more complex regexp that captures something. | ||
func commentTypo2(m dsl.Matcher) { | ||
m.MatchComment(`(?P<word>buisness) advice`).Report(`"$$" may contain a typo`) | ||
} | ||
|
||
// Test mixture of the named and unnamed captures. | ||
func commentTypo3(m dsl.Matcher) { | ||
m.MatchComment(`(?P<first>calender)|(error)`).Report(`first=$first`) | ||
m.MatchComment(`(error)|(?P<second>cemetary)`).Report(`second=$second`) | ||
} | ||
|
||
// Test a case where named group is empty. | ||
func commentTypo4(m dsl.Matcher) { | ||
m.MatchComment(`(?P<x>collegue)|(commitee)`).Report(`x="$x"`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package comments | ||
|
||
//go:embed | ||
|
||
/*foo-bar: baz*/ // want `\Qdirective should be written as //foo-bar` | ||
|
||
/*go:noinline*/ // want `\Qdirective should be written as //go` | ||
func f() { | ||
_ = 12 // nolint // want `\Qremove a space between // and "nolint" directive` | ||
|
||
_ = 30 // nolint2 foo bar // want `\Qsuggestion: //nolint2 foo bar` | ||
|
||
/* | ||
nolint // want `\Qdon't put "nolint" inside a multi-line comment` | ||
*/ | ||
|
||
//go:baddirective // want `\Qdon't use baddirective go directive` | ||
//go:noinline | ||
//go:generate foo bar | ||
|
||
//nolint:gocritic // want `hey, this is kinda upsetting` | ||
|
||
// This is a begining // want `\Q"begining" may contain a typo` | ||
// Of a bizzare text with typos. // want `\Q"bizzare" may contain a typo` | ||
|
||
// I can't give you a buisness advice. // want `\Q"buisness advice" may contain a typo` | ||
|
||
// calender // want `\Qfirst=calender` | ||
// cemetary // want `\Qsecond=cemetary` | ||
|
||
// collegue // want `\Qx="collegue"` | ||
// commitee // want `\Qx=""` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package comments | ||
|
||
//go:embed data.txt // want `don't use go:embed in _foo files` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package ruleguard | ||
|
||
import ( | ||
"go/ast" | ||
|
||
"github.com/quasilyte/go-ruleguard/internal/gogrep" | ||
) | ||
|
||
// matchData is used to handle both regexp and AST match sets in the same way. | ||
type matchData interface { | ||
// TODO: don't use gogrep.CapturedNode type here. | ||
|
||
Node() ast.Node | ||
CaptureList() []gogrep.CapturedNode | ||
CapturedByName(name string) (ast.Node, bool) | ||
} | ||
|
||
type commentMatchData struct { | ||
node ast.Node | ||
capture []gogrep.CapturedNode | ||
} | ||
|
||
func (m commentMatchData) Node() ast.Node { return m.node } | ||
|
||
func (m commentMatchData) CaptureList() []gogrep.CapturedNode { return m.capture } | ||
|
||
func (m commentMatchData) CapturedByName(name string) (ast.Node, bool) { | ||
for _, c := range m.capture { | ||
if c.Name == name { | ||
return c.Node, true | ||
} | ||
} | ||
return nil, false | ||
} | ||
|
||
type astMatchData struct { | ||
match gogrep.MatchData | ||
} | ||
|
||
func (m astMatchData) Node() ast.Node { return m.match.Node } | ||
|
||
func (m astMatchData) CaptureList() []gogrep.CapturedNode { return m.match.Capture } | ||
|
||
func (m astMatchData) CapturedByName(name string) (ast.Node, bool) { | ||
return m.match.CapturedByName(name) | ||
} |
Oops, something went wrong.