Skip to content

Commit

Permalink
ruleguard: implement Var.Line filter (#234)
Browse files Browse the repository at this point in the history
Fixes #146
  • Loading branch information
quasilyte authored May 1, 2021
1 parent a2b8e65 commit 2cb006b
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 1 deletion.
15 changes: 15 additions & 0 deletions analyzer/testdata/src/filtertest/f1.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,21 @@ func fileFilters1() {
importsTest(os.PathListSeparator, "path/filepath")
}

func detectLine() {
lineTest(1, 2, "same line") // want `YES`
lineTest(1,
2, "same line")

lineTest( // want `YES`
1,
2,
"different line",
)
lineTest(1, 2,
"different line")
lineTest(1, 2, "different line")
}

func detectNode() {
var i int
var s string
Expand Down
6 changes: 6 additions & 0 deletions analyzer/testdata/src/filtertest/linetest4.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package filtertest

func _() {
lineTest("", "line 4") // want `YES`
lineTest("", "line 4")
}
4 changes: 4 additions & 0 deletions analyzer/testdata/src/filtertest/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ func testRules(m dsl.Matcher) {
Where(!m["x"].Pure).
Report("!pure")

m.Match(`lineTest($x, "line 4")`).Where(m["x"].Line == 4).Report(`YES`)
m.Match(`lineTest($x, $y, "same line")`).Where(m["x"].Line == m["y"].Line).Report(`YES`)
m.Match(`lineTest($x, $y, "different line")`).Where(m["x"].Line != m["y"].Line).Report(`YES`)

m.Match(`textTest($x, "text=foo")`).Where(m["x"].Text == `foo`).Report(`YES`)
m.Match(`textTest($x, "text='foo'")`).Where(m["x"].Text == `"foo"`).Report(`YES`)
m.Match(`textTest($x, "text!='foo'")`).Where(m["x"].Text != `"foo"`).Report(`YES`)
Expand Down
1 change: 1 addition & 0 deletions analyzer/testdata/src/filtertest/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ func parensFilterTest(args ...interface{}) {}
func importsTest(args ...interface{}) {}
func fileTest(args ...interface{}) {}
func nodeTest(args ...interface{}) {}
func lineTest(args ...interface{}) {}

func random() int {
return 42
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.15
require (
github.com/go-toolsmith/astequal v1.0.0
github.com/google/go-cmp v0.5.2
github.com/quasilyte/go-ruleguard/dsl v0.3.2
github.com/quasilyte/go-ruleguard/dsl v0.3.3
github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7
golang.org/x/tools v0.0.0-20201230224404-63754364767c
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ github.com/quasilyte/go-ruleguard/dsl v0.3.1 h1:CHGOKP2LDz35P49TjW4Bx4BCfFI6ZZU/
github.com/quasilyte/go-ruleguard/dsl v0.3.1/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quasilyte/go-ruleguard/dsl v0.3.2 h1:ULi3SLXvDUgb0u2IM5xU6er9KeWBSaUh1NlDjCgLHU8=
github.com/quasilyte/go-ruleguard/dsl v0.3.2/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quasilyte/go-ruleguard/dsl v0.3.3 h1:mjurEAavnutTkwBMrSgXHlDcW1VG8XA8ZpJCWvIOe9E=
github.com/quasilyte/go-ruleguard/dsl v0.3.3/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1 h1:PX/E0GYUnSV8vwVfpOUEIBKnPG3KmYunmNOBlL+zDko=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20210203162857-b223e0831f88 h1:PeTrJiH/dSeruL/Z9Db39NRMwI/yoA3oHCdCkg+Wh8A=
Expand Down
24 changes: 24 additions & 0 deletions ruleguard/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,30 @@ func makeTypeAssignableToFilter(src, varname string, dstType types.Type) filterF
}
}

func makeLineFilter(src, varname string, op token.Token, rhsVarname string) filterFunc {
return func(params *filterParams) matchFilterResult {
line1 := params.ctx.Fset.Position(params.subNode(varname).Pos()).Line
line2 := params.ctx.Fset.Position(params.subNode(rhsVarname).Pos()).Line
lhsValue := constant.MakeInt64(int64(line1))
rhsValue := constant.MakeInt64(int64(line2))
if constant.Compare(lhsValue, op, rhsValue) {
return filterSuccess
}
return filterFailure(src)
}
}

func makeLineConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc {
return func(params *filterParams) matchFilterResult {
n := params.subNode(varname)
lhsValue := constant.MakeInt64(int64(params.ctx.Fset.Position(n.Pos()).Line))
if constant.Compare(lhsValue, op, rhsValue) {
return filterSuccess
}
return filterFailure(src)
}
}

func makeTypeSizeConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc {
return func(params *filterParams) matchFilterResult {
typ := params.typeofNode(params.subExpr(varname))
Expand Down
8 changes: 8 additions & 0 deletions ruleguard/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,14 @@ func (p *rulesParser) parseFilterExpr(e ast.Expr) matchFilter {
operand := p.toFilterOperand(e.X)
rhs := p.toFilterOperand(e.Y)
rhsValue := p.types.Types[e.Y].Value
if operand.path == "Line" && rhsValue != nil {
result.fn = makeLineConstFilter(result.src, operand.varName, e.Op, rhsValue)
return result
}
if operand.path == "Line" && rhs.path == "Line" && rhs.varName != "" {
result.fn = makeLineFilter(result.src, operand.varName, e.Op, rhs.varName)
return result
}
if operand.path == "Type.Size" && rhsValue != nil {
result.fn = makeTypeSizeConstFilter(result.src, operand.varName, e.Op, rhsValue)
return result
Expand Down

0 comments on commit 2cb006b

Please sign in to comment.