Skip to content

Commit

Permalink
ruleguard: add Engine.LoadedGroups method
Browse files Browse the repository at this point in the history
It returns the sorted slice of the groups that have been
loaded so far.
  • Loading branch information
quasilyte committed Apr 28, 2021
1 parent 545e0d2 commit eff8d89
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 22 deletions.
2 changes: 1 addition & 1 deletion analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func runAnalyzer(pass *analysis.Pass) (interface{}, error) {
fullMessage := msg
if printRuleLocation {
fullMessage = fmt.Sprintf("%s: %s (%s:%d)",
info.Group, msg, filepath.Base(info.Group.Filename), info.Line)
info.Group.Name, msg, filepath.Base(info.Group.Filename), info.Line)
}
diag := analysis.Diagnostic{
Pos: n.Pos(),
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ 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/rules v0.0.0-20210203162857-b223e0831f88
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 @@ -19,6 +19,8 @@ github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1 h1:PX
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=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20210203162857-b223e0831f88/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7 h1:cRLFDAB53r5wIkxYvtQUMnn3+B09uZTAOPmefNfVk5I=
github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down
12 changes: 12 additions & 0 deletions ruleguard/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"go/ast"
"go/types"
"io"
"sort"
"strings"
"sync"

Expand All @@ -25,6 +26,17 @@ func newEngine() *engine {
}
}

func (e *engine) LoadedGroups() []GoRuleGroup {
result := make([]GoRuleGroup, 0, len(e.ruleSet.groups))
for _, g := range e.ruleSet.groups {
result = append(result, *g)
}
sort.Slice(result, func(i, j int) bool {
return result[i].Name < result[j].Name
})
return result
}

func (e *engine) Load(ctx *ParseContext, filename string, r io.Reader) error {
config := rulesParserConfig{
state: e.state,
Expand Down
18 changes: 8 additions & 10 deletions ruleguard/gorule.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package ruleguard
import (
"fmt"
"go/ast"
"go/token"
"go/types"
"regexp"

Expand All @@ -15,7 +14,7 @@ import (
type goRuleSet struct {
universal *scopedGoRuleSet

groups map[string]token.Position // To handle redefinitions
groups map[string]*GoRuleGroup // To handle redefinitions
}

type scopedGoRuleSet struct {
Expand All @@ -32,7 +31,6 @@ type goCommentRule struct {

type goRule struct {
group *GoRuleGroup
filename string
line int
pat *gogrep.Pattern
msg string
Expand Down Expand Up @@ -108,18 +106,18 @@ func cloneRuleSet(rset *goRuleSet) *goRuleSet {
func mergeRuleSets(toMerge []*goRuleSet) (*goRuleSet, error) {
out := &goRuleSet{
universal: &scopedGoRuleSet{},
groups: make(map[string]token.Position),
groups: make(map[string]*GoRuleGroup),
}

for _, x := range toMerge {
out.universal = appendScopedRuleSet(out.universal, x.universal)
for group, pos := range x.groups {
if prevPos, ok := out.groups[group]; ok {
newRef := fmt.Sprintf("%s:%d", pos.Filename, pos.Line)
oldRef := fmt.Sprintf("%s:%d", prevPos.Filename, prevPos.Line)
return nil, fmt.Errorf("%s: redefinition of %s(), previously defined at %s", newRef, group, oldRef)
for groupName, group := range x.groups {
if prevGroup, ok := out.groups[groupName]; ok {
newRef := fmt.Sprintf("%s:%d", group.Filename, group.Line)
oldRef := fmt.Sprintf("%s:%d", prevGroup.Filename, prevGroup.Line)
return nil, fmt.Errorf("%s: redefinition of %s(), previously defined at %s", newRef, groupName, oldRef)
}
out.groups[group] = pos
out.groups[groupName] = group
}
}

Expand Down
16 changes: 7 additions & 9 deletions ruleguard/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (p *rulesParser) ParseFile(filename string, r io.Reader) (*goRuleSet, error
p.filename = filename
p.res = &goRuleSet{
universal: &scopedGoRuleSet{},
groups: make(map[string]token.Position),
groups: make(map[string]*GoRuleGroup),
}

parserFlags := parser.ParseComments
Expand Down Expand Up @@ -304,7 +304,9 @@ func (p *rulesParser) parseRuleGroup(f *ast.FuncDecl) (err error) {
matcher := params[0].Names[0].Name

p.group = &GoRuleGroup{
Name: f.Name.Name,
Line: p.ctx.Fset.Position(f.Name.Pos()).Line,
Filename: p.filename,
Name: f.Name.Name,
}
if p.prefix != "" {
p.group.Name = p.prefix + "/" + p.group.Name
Expand All @@ -321,10 +323,7 @@ func (p *rulesParser) parseRuleGroup(f *ast.FuncDecl) (err error) {
if _, ok := p.res.groups[p.group.Name]; ok {
panic(fmt.Sprintf("duplicated function %s after the typecheck", p.group)) // Should never happen
}
p.res.groups[p.group.Name] = token.Position{
Filename: p.filename,
Line: p.ctx.Fset.Position(f.Name.Pos()).Line,
}
p.res.groups[p.group.Name] = p.group

p.itab.EnterScope()
defer p.itab.LeaveScope()
Expand Down Expand Up @@ -477,9 +476,8 @@ func (p *rulesParser) parseRule(matcher string, call *ast.CallExpr) error {
}

proto := goRule{
filename: p.filename,
line: p.ctx.Fset.Position(origCall.Pos()).Line,
group: p.group,
line: p.ctx.Fset.Position(origCall.Pos()).Line,
group: p.group,
}

// AST patterns for Match() or regexp patterns for MatchComment().
Expand Down
12 changes: 12 additions & 0 deletions ruleguard/ruleguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ func (e *Engine) Load(ctx *ParseContext, filename string, r io.Reader) error {
return e.impl.Load(ctx, filename, r)
}

// LoadedGroups returns information about all currently loaded rule groups.
func (e *Engine) LoadedGroups() []GoRuleGroup {
return e.impl.LoadedGroups()
}

// Run executes all loaded rules on a given file.
// Matched rules invoke `RunContext.Report()` method.
//
Expand Down Expand Up @@ -87,6 +92,13 @@ type GoRuleGroup struct {
// Name is a function name associated with this rule group.
Name string

// Pos is a location where this rule group was defined.
Pos token.Position

// Line is a source code line number inside associated file.
// A pair of Filename:Line form a conventional location string.
Line int

// Filename is a file that defined this rule group.
Filename string

Expand Down
2 changes: 1 addition & 1 deletion ruleguard/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (rr *rulesRunner) reject(rule goRule, reason string, m matchData) {

pos := rr.ctx.Fset.Position(m.Node().Pos())
rr.ctx.DebugPrint(fmt.Sprintf("%s:%d: [%s:%d] rejected by %s",
pos.Filename, pos.Line, filepath.Base(rule.filename), rule.line, reason))
pos.Filename, pos.Line, filepath.Base(rule.group.Filename), rule.line, reason))

values := make([]gogrep.CapturedNode, len(m.CaptureList()))
copy(values, m.CaptureList())
Expand Down

0 comments on commit eff8d89

Please sign in to comment.