woodpecker/vendor/github.com/quasilyte/gogrep/gogrep.go
6543 56a854fe14
Update deps (#789)
* update github.com/docker/cli

* update github.com/docker/distribution

* update github.com/docker/docker

* update github.com/gin-gonic/gin

* update github.com/golang-jwt/jwt/v4

* update github.com/golangci/golangci-lint

* update github.com/gorilla/securecookie

* update github.com/mattn/go-sqlite3

* update github.com/moby/moby

* update github.com/prometheus/client_golang

* update github.com/xanzy/go-gitlab
2022-02-24 17:33:24 +01:00

123 lines
2.6 KiB
Go

package gogrep
import (
"go/ast"
"go/token"
"go/types"
"strings"
"github.com/quasilyte/gogrep/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
}
type CompileConfig struct {
Fset *token.FileSet
// Src is a gogrep pattern expression string.
Src string
// When strict is false, gogrep may consider 0xA and 10 to be identical.
// If true, a compiled pattern will require a full syntax match.
Strict bool
// WithTypes controls whether gogrep would have types.Info during the pattern execution.
// If set to true, it will compile a pattern to a potentially more precise form, where
// fmt.Printf maps to the stdlib function call but not Printf method call on some
// random fmt variable.
WithTypes bool
// Imports specifies packages that should be recognized for the type-aware matching.
// It maps a package name to a package path.
// Only used if WithTypes is true.
Imports map[string]string
}
func Compile(config CompileConfig) (*Pattern, PatternInfo, error) {
if strings.HasPrefix(config.Src, "import $") {
return compileImportPattern(config)
}
info := newPatternInfo()
n, err := parseExpr(config.Fset, config.Src)
if err != nil {
return nil, info, err
}
var c compiler
c.config = config
prog, err := c.Compile(n, &info)
if err != nil {
return nil, info, err
}
m := newMatcher(prog)
return &Pattern{m: m}, info, nil
}
func newPatternInfo() PatternInfo {
return PatternInfo{
Vars: make(map[string]struct{}),
}
}