Skip to content

Commit

Permalink
ruleguard: implement Var.Object.IsGlobal() predicate (#370)
Browse files Browse the repository at this point in the history
  • Loading branch information
peakle committed Feb 2, 2022
1 parent 0e209b8 commit cb19258
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 32 deletions.
20 changes: 20 additions & 0 deletions analyzer/testdata/src/filtertest/f1.go
Expand Up @@ -872,3 +872,23 @@ func detectNode() {
nodeTest(rows[0][5], "IndexExpr") // want `true`
nodeTest("42", "IndexExpr")
}

var globalVar string
var globalVar2 string = time.Now().String() // want `\Qglobal var`
var globalVar3 = time.Now().String() // want `\Qglobal var`
var (
globalVar4 string
)

func detectGlobal() {
globalVar = time.Now().String() // want `\Qglobal var`
globalVar4 = time.Now().String() // want `\Qglobal var`
{
globalVar := time.Now().String() // shadowed global var
print(globalVar)
}
{
var globalVar = time.Now().String() // shadowed global var
print(globalVar)
}
}
7 changes: 7 additions & 0 deletions analyzer/testdata/src/filtertest/rules.go
Expand Up @@ -263,4 +263,11 @@ func testRules(m dsl.Matcher) {
m.Match(`typeTest($x, $y, "identical types")`).
Where(m["x"].Type.IdenticalTo(m["y"])).
Report(`true`)

m.Match(`$x = time.Now().String()`,
`var $x = time.Now().String()`,
`var $x $_ = time.Now().String()`,
`$x := time.Now().String()`).
Where(m["x"].Object.IsGlobal()).
Report(`global var`)
}
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -5,7 +5,7 @@ go 1.17
require (
github.com/go-toolsmith/astcopy v1.0.0
github.com/google/go-cmp v0.5.6
github.com/quasilyte/go-ruleguard/dsl v0.3.15
github.com/quasilyte/go-ruleguard/dsl v0.3.16
github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71
github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -10,8 +10,8 @@ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30=
github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quasilyte/go-ruleguard/dsl v0.3.15 h1:rClYn6lk8wUV5kXnQG4JVsRQjZhSetaNtwml5wkFp5g=
github.com/quasilyte/go-ruleguard/dsl v0.3.15/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quasilyte/go-ruleguard/dsl v0.3.16 h1:yJtIpd4oyNS+/c/gKqxNwoGO9+lPOsy1A4BzKjJRcrI=
github.com/quasilyte/go-ruleguard/dsl v0.3.16/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71 h1:CNooiryw5aisadVfzneSZPswRWvnVW8hF1bS/vo8ReI=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50=
Expand Down
17 changes: 15 additions & 2 deletions ruleguard/filters.go
Expand Up @@ -7,12 +7,13 @@ import (
"go/types"
"path/filepath"

"github.com/quasilyte/gogrep"
"github.com/quasilyte/gogrep/nodetag"

"github.com/quasilyte/go-ruleguard/internal/xtypes"
"github.com/quasilyte/go-ruleguard/ruleguard/quasigo"
"github.com/quasilyte/go-ruleguard/ruleguard/textmatch"
"github.com/quasilyte/go-ruleguard/ruleguard/typematch"
"github.com/quasilyte/gogrep"
"github.com/quasilyte/gogrep/nodetag"
)

const filterSuccess = matchFilterResult("")
Expand Down Expand Up @@ -363,6 +364,18 @@ func makeLineFilter(src, varname string, op token.Token, rhsVarname string) filt
}
}

func makeObjectIsGlobalFilter(src, varname string) filterFunc {
return func(params *filterParams) matchFilterResult {
obj := params.ctx.Types.ObjectOf(identOf(params.subExpr(varname)))
globalScope := params.ctx.Pkg.Scope()
if obj.Parent() == globalScope {
return filterSuccess
}

return filterFailure(src)
}
}

func makeGoVersionFilter(src string, op token.Token, version GoVersion) filterFunc {
return func(params *filterParams) matchFilterResult {
if params.ctx.GoVersion.IsAny() {
Expand Down
54 changes: 30 additions & 24 deletions ruleguard/ir/filter_op.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ruleguard/ir/gen_filter_op.go
@@ -1,3 +1,4 @@
//go:build generate
// +build generate

package main
Expand Down Expand Up @@ -52,6 +53,7 @@ func main() {
{name: "VarFilter", comment: "m[$Value].Filter($Args[0])", valueType: "string", flags: flagHasVar},
{name: "VarNodeIs", comment: "m[$Value].Node.Is($Args[0])", valueType: "string", flags: flagHasVar},
{name: "VarObjectIs", comment: "m[$Value].Object.Is($Args[0])", valueType: "string", flags: flagHasVar},
{name: "VarObjectIsGlobal", comment: "m[$Value].Object.IsGlobal()", valueType: "string", flags: flagHasVar},
{name: "VarTypeIs", comment: "m[$Value].Type.Is($Args[0])", valueType: "string", flags: flagHasVar},
{name: "VarTypeIdenticalTo", comment: "m[$Value].Type.IdenticalTo($Args[0])", valueType: "string", flags: flagHasVar},
{name: "VarTypeUnderlyingIs", comment: "m[$Value].Type.Underlying().Is($Args[0])", valueType: "string", flags: flagHasVar},
Expand Down
7 changes: 5 additions & 2 deletions ruleguard/ir_loader.go
Expand Up @@ -11,13 +11,14 @@ import (
"io/ioutil"
"regexp"

"github.com/quasilyte/gogrep"
"github.com/quasilyte/gogrep/nodetag"

"github.com/quasilyte/go-ruleguard/ruleguard/goutil"
"github.com/quasilyte/go-ruleguard/ruleguard/ir"
"github.com/quasilyte/go-ruleguard/ruleguard/quasigo"
"github.com/quasilyte/go-ruleguard/ruleguard/textmatch"
"github.com/quasilyte/go-ruleguard/ruleguard/typematch"
"github.com/quasilyte/gogrep"
"github.com/quasilyte/gogrep/nodetag"
)

type irLoaderConfig struct {
Expand Down Expand Up @@ -675,6 +676,8 @@ func (l *irLoader) newFilter(filter ir.FilterExpr, info *filterInfo) (matchFilte
result.fn = makePureFilter(result.src, filter.Value.(string))
case ir.FilterVarConstOp:
result.fn = makeConstFilter(result.src, filter.Value.(string))
case ir.FilterVarObjectIsGlobalOp:
result.fn = makeObjectIsGlobalFilter(result.src, filter.Value.(string))
case ir.FilterVarConstSliceOp:
result.fn = makeConstSliceFilter(result.src, filter.Value.(string))
case ir.FilterVarAddressableOp:
Expand Down
5 changes: 4 additions & 1 deletion ruleguard/irconv/irconv.go
Expand Up @@ -11,9 +11,10 @@ import (
"strings"

"github.com/go-toolsmith/astcopy"
"golang.org/x/tools/go/ast/astutil"

"github.com/quasilyte/go-ruleguard/ruleguard/goutil"
"github.com/quasilyte/go-ruleguard/ruleguard/ir"
"golang.org/x/tools/go/ast/astutil"
)

type Context struct {
Expand Down Expand Up @@ -714,6 +715,8 @@ func (conv *converter) convertFilterExprImpl(e ast.Expr) ir.FilterExpr {
return ir.FilterExpr{Op: ir.FilterRootNodeParentIsOp, Args: args}
case "Object.Is":
return ir.FilterExpr{Op: ir.FilterVarObjectIsOp, Value: op.varName, Args: args}
case "Object.IsGlobal":
return ir.FilterExpr{Op: ir.FilterVarObjectIsGlobalOp, Value: op.varName}
case "Type.HasPointers":
return ir.FilterExpr{Op: ir.FilterVarTypeHasPointersOp, Value: op.varName}
case "Type.Is":
Expand Down

0 comments on commit cb19258

Please sign in to comment.