Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add global property for Var #370

Merged
merged 17 commits into from Feb 2, 2022
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