woodpecker/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gogrep.go
2021-11-16 21:07:53 +01:00

96 lines
1.8 KiB
Go

package gogrep
import (
"go/ast"
"go/token"
"go/types"
"github.com/quasilyte/go-ruleguard/nodetag"
)
func IsEmptyNodeSlice(n ast.Node) bool {
if list, ok := n.(NodeSlice); ok {
return list.Len() == 0
}
return false
}
// MatchData describes a successful pattern match.
type MatchData struct {
Node ast.Node
Capture []CapturedNode
}
type CapturedNode struct {
Name string
Node ast.Node
}
func (data MatchData) CapturedByName(name string) (ast.Node, bool) {
if name == "$$" {
return data.Node, true
}
return findNamed(data.Capture, name)
}
type MatcherState struct {
Types *types.Info
// node values recorded by name, excluding "_" (used only by the
// actual matching phase)
capture []CapturedNode
pc int
}
func NewMatcherState() MatcherState {
return MatcherState{
capture: make([]CapturedNode, 0, 8),
}
}
type Pattern struct {
m *matcher
}
type PatternInfo struct {
Vars map[string]struct{}
}
func (p *Pattern) NodeTag() nodetag.Value {
return operationInfoTable[p.m.prog.insts[0].op].Tag
}
// MatchNode calls cb if n matches a pattern.
func (p *Pattern) MatchNode(state *MatcherState, n ast.Node, cb func(MatchData)) {
p.m.MatchNode(state, n, cb)
}
// Clone creates a pattern copy.
func (p *Pattern) Clone() *Pattern {
clone := *p
clone.m = &matcher{}
*clone.m = *p.m
return &clone
}
func Compile(fset *token.FileSet, src string, strict bool) (*Pattern, PatternInfo, error) {
info := newPatternInfo()
n, err := parseExpr(fset, src)
if err != nil {
return nil, info, err
}
var c compiler
prog, err := c.Compile(fset, n, &info, strict)
if err != nil {
return nil, info, err
}
m := newMatcher(prog)
return &Pattern{m: m}, info, nil
}
func newPatternInfo() PatternInfo {
return PatternInfo{
Vars: map[string]struct{}{},
}
}