Skip to content

Commit

Permalink
feat: index func names (fast path)
Browse files Browse the repository at this point in the history
Signed-off-by: Timon Wong <[email protected]>
  • Loading branch information
timonwong committed Aug 29, 2022
1 parent ac84b09 commit 7bf6547
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 19 deletions.
42 changes: 27 additions & 15 deletions internal/rules/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"

"github.com/timonwong/loggercheck/internal/bytebufferpool"
"github.com/timonwong/loggercheck/internal/sets"
)

var ErrInvalidRule = errors.New("invalid rule format")
Expand All @@ -34,6 +35,8 @@ type Ruleset struct {
Name string
PackageImport string
Rules []FuncRule

funcNames sets.StringSet
}

func (rs *Ruleset) Match(fn *types.Func, pkg *types.Package) bool {
Expand All @@ -43,8 +46,15 @@ func (rs *Ruleset) Match(fn *types.Func, pkg *types.Package) bool {
}

sig := fn.Type().(*types.Signature) // it's safe since we already checked
for _, rule := range rs.Rules {
if rule.match(fn, sig) {

// Fail fast if func name not contains in index
if !rs.funcNames.Has(fn.Name()) {
return false
}

for i := range rs.Rules {
rule := &rs.Rules[i]
if matchRule(rule, sig) {
return true
}
}
Expand All @@ -54,18 +64,8 @@ func (rs *Ruleset) Match(fn *types.Func, pkg *types.Package) bool {

func emptyQualifier(*types.Package) string { return "" }

type FuncRule struct { // package import should be accessed from Rulset
ReceiverType string
MethodName string
IsReceiver bool
}

func (p *FuncRule) match(fn *types.Func, sig *types.Signature) bool {
// we do not check package import here since it's already checked
if fn.Name() != p.MethodName {
return false
}

func matchRule(p *FuncRule, sig *types.Signature) bool {
// we do not check package import and func name here since it's already checked in Match()
recv := sig.Recv()
isReceiver := recv != nil
if isReceiver != p.IsReceiver {
Expand All @@ -85,6 +85,12 @@ func (p *FuncRule) match(fn *types.Func, sig *types.Signature) bool {
return true
}

type FuncRule struct { // package import should be accessed from Rulset
ReceiverType string
FuncName string
IsReceiver bool
}

func ParseFuncRule(rule string) (packageImport string, pat FuncRule, err error) {
lastDot := strings.LastIndexFunc(rule, func(r rune) bool {
return r == '.' || r == '/'
Expand All @@ -94,7 +100,7 @@ func ParseFuncRule(rule string) (packageImport string, pat FuncRule, err error)
}

importOrReceiver := rule[:lastDot]
pat.MethodName = rule[lastDot+1:]
pat.FuncName = rule[lastDot+1:]

if strings.HasPrefix(rule, "(") { // package
if !strings.HasSuffix(importOrReceiver, ")") {
Expand Down Expand Up @@ -147,10 +153,16 @@ func ParseRules(lines []string) (result RulesetList, err error) {
}

for packageImport, rules := range rulesByImport {
funcNames := make([]string, 0, len(rules))
for _, rule := range rules {
funcNames = append(funcNames, rule.FuncName)
}

result = append(result, Ruleset{
Name: "", // NOTE(timonwong) Always "" for custom rule
PackageImport: packageImport,
Rules: rules,
funcNames: sets.NewString(funcNames...),
})
}
return result, nil
Expand Down
6 changes: 3 additions & 3 deletions internal/rules/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ func TestParseFuncRule(t *testing.T) {
wantRule: FuncRule{
IsReceiver: true,
ReceiverType: "*SugaredLogger",
MethodName: "Debugw",
FuncName: "Debugw",
},
},
{
name: "klog-no-receiver",
rule: "k8s.io/klog/v2.InfoS",
wantPackageImport: "k8s.io/klog/v2",
wantRule: FuncRule{
MethodName: "InfoS",
FuncName: "InfoS",
},
},
{
Expand All @@ -68,7 +68,7 @@ func TestParseFuncRule(t *testing.T) {
wantRule: FuncRule{
IsReceiver: true,
ReceiverType: "Logger",
MethodName: "Error",
FuncName: "Error",
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion loggercheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (l *loggercheck) checkLoggerArguments(pass *analysis.Pass, call *ast.CallEx
}

func (l *loggercheck) processConfig() error {
if l.ruleFile != "" {
if l.ruleFile != "" { // flags takes precedence over configs
f, err := os.Open(l.ruleFile)
if err != nil {
return fmt.Errorf("failed to open rule file: %w", err)
Expand Down

0 comments on commit 7bf6547

Please sign in to comment.