mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-11 11:06:29 +00:00
323 lines
4.7 KiB
Go
323 lines
4.7 KiB
Go
|
package ruleguard
|
||
|
|
||
|
import (
|
||
|
"go/ast"
|
||
|
"go/constant"
|
||
|
)
|
||
|
|
||
|
type astWalker struct {
|
||
|
nodePath *nodePath
|
||
|
|
||
|
filterParams *filterParams
|
||
|
|
||
|
visit func(ast.Node)
|
||
|
}
|
||
|
|
||
|
func (w *astWalker) Walk(root ast.Node, visit func(ast.Node)) {
|
||
|
w.visit = visit
|
||
|
w.walk(root)
|
||
|
}
|
||
|
|
||
|
func (w *astWalker) walkIdentList(list []*ast.Ident) {
|
||
|
for _, x := range list {
|
||
|
w.walk(x)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (w *astWalker) walkExprList(list []ast.Expr) {
|
||
|
for _, x := range list {
|
||
|
w.walk(x)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (w *astWalker) walkStmtList(list []ast.Stmt) {
|
||
|
for _, x := range list {
|
||
|
w.walk(x)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (w *astWalker) walkDeclList(list []ast.Decl) {
|
||
|
for _, x := range list {
|
||
|
w.walk(x)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (w *astWalker) walk(n ast.Node) {
|
||
|
w.nodePath.Push(n)
|
||
|
defer w.nodePath.Pop()
|
||
|
|
||
|
w.visit(n)
|
||
|
|
||
|
switch n := n.(type) {
|
||
|
case *ast.Field:
|
||
|
// TODO: handle field types.
|
||
|
// See #252
|
||
|
w.walkIdentList(n.Names)
|
||
|
w.walk(n.Type)
|
||
|
|
||
|
case *ast.FieldList:
|
||
|
for _, f := range n.List {
|
||
|
w.walk(f)
|
||
|
}
|
||
|
|
||
|
case *ast.Ellipsis:
|
||
|
if n.Elt != nil {
|
||
|
w.walk(n.Elt)
|
||
|
}
|
||
|
|
||
|
case *ast.FuncLit:
|
||
|
w.walk(n.Type)
|
||
|
w.walk(n.Body)
|
||
|
|
||
|
case *ast.CompositeLit:
|
||
|
if n.Type != nil {
|
||
|
w.walk(n.Type)
|
||
|
}
|
||
|
w.walkExprList(n.Elts)
|
||
|
|
||
|
case *ast.ParenExpr:
|
||
|
w.walk(n.X)
|
||
|
|
||
|
case *ast.SelectorExpr:
|
||
|
w.walk(n.X)
|
||
|
w.walk(n.Sel)
|
||
|
|
||
|
case *ast.IndexExpr:
|
||
|
w.walk(n.X)
|
||
|
w.walk(n.Index)
|
||
|
|
||
|
case *ast.SliceExpr:
|
||
|
w.walk(n.X)
|
||
|
if n.Low != nil {
|
||
|
w.walk(n.Low)
|
||
|
}
|
||
|
if n.High != nil {
|
||
|
w.walk(n.High)
|
||
|
}
|
||
|
if n.Max != nil {
|
||
|
w.walk(n.Max)
|
||
|
}
|
||
|
|
||
|
case *ast.TypeAssertExpr:
|
||
|
w.walk(n.X)
|
||
|
if n.Type != nil {
|
||
|
w.walk(n.Type)
|
||
|
}
|
||
|
|
||
|
case *ast.CallExpr:
|
||
|
w.walk(n.Fun)
|
||
|
w.walkExprList(n.Args)
|
||
|
|
||
|
case *ast.StarExpr:
|
||
|
w.walk(n.X)
|
||
|
|
||
|
case *ast.UnaryExpr:
|
||
|
w.walk(n.X)
|
||
|
|
||
|
case *ast.BinaryExpr:
|
||
|
w.walk(n.X)
|
||
|
w.walk(n.Y)
|
||
|
|
||
|
case *ast.KeyValueExpr:
|
||
|
w.walk(n.Key)
|
||
|
w.walk(n.Value)
|
||
|
|
||
|
case *ast.ArrayType:
|
||
|
if n.Len != nil {
|
||
|
w.walk(n.Len)
|
||
|
}
|
||
|
w.walk(n.Elt)
|
||
|
|
||
|
case *ast.StructType:
|
||
|
w.walk(n.Fields)
|
||
|
|
||
|
case *ast.FuncType:
|
||
|
if n.Params != nil {
|
||
|
w.walk(n.Params)
|
||
|
}
|
||
|
if n.Results != nil {
|
||
|
w.walk(n.Results)
|
||
|
}
|
||
|
|
||
|
case *ast.InterfaceType:
|
||
|
w.walk(n.Methods)
|
||
|
|
||
|
case *ast.MapType:
|
||
|
w.walk(n.Key)
|
||
|
w.walk(n.Value)
|
||
|
|
||
|
case *ast.ChanType:
|
||
|
w.walk(n.Value)
|
||
|
|
||
|
case *ast.DeclStmt:
|
||
|
w.walk(n.Decl)
|
||
|
|
||
|
case *ast.LabeledStmt:
|
||
|
w.walk(n.Label)
|
||
|
w.walk(n.Stmt)
|
||
|
|
||
|
case *ast.ExprStmt:
|
||
|
w.walk(n.X)
|
||
|
|
||
|
case *ast.SendStmt:
|
||
|
w.walk(n.Chan)
|
||
|
w.walk(n.Value)
|
||
|
|
||
|
case *ast.IncDecStmt:
|
||
|
w.walk(n.X)
|
||
|
|
||
|
case *ast.AssignStmt:
|
||
|
w.walkExprList(n.Lhs)
|
||
|
w.walkExprList(n.Rhs)
|
||
|
|
||
|
case *ast.GoStmt:
|
||
|
w.walk(n.Call)
|
||
|
|
||
|
case *ast.DeferStmt:
|
||
|
w.walk(n.Call)
|
||
|
|
||
|
case *ast.ReturnStmt:
|
||
|
w.walkExprList(n.Results)
|
||
|
|
||
|
case *ast.BranchStmt:
|
||
|
if n.Label != nil {
|
||
|
w.walk(n.Label)
|
||
|
}
|
||
|
|
||
|
case *ast.BlockStmt:
|
||
|
w.walkStmtList(n.List)
|
||
|
|
||
|
case *ast.IfStmt:
|
||
|
if n.Init != nil {
|
||
|
w.walk(n.Init)
|
||
|
}
|
||
|
w.walk(n.Cond)
|
||
|
deadcode := w.filterParams.deadcode
|
||
|
if !deadcode {
|
||
|
cv := w.filterParams.ctx.Types.Types[n.Cond].Value
|
||
|
if cv != nil {
|
||
|
w.filterParams.deadcode = !deadcode && !constant.BoolVal(cv)
|
||
|
w.walk(n.Body)
|
||
|
w.filterParams.deadcode = !w.filterParams.deadcode
|
||
|
if n.Else != nil {
|
||
|
w.walk(n.Else)
|
||
|
}
|
||
|
w.filterParams.deadcode = deadcode
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
w.walk(n.Body)
|
||
|
if n.Else != nil {
|
||
|
w.walk(n.Else)
|
||
|
}
|
||
|
|
||
|
case *ast.CaseClause:
|
||
|
w.walkExprList(n.List)
|
||
|
w.walkStmtList(n.Body)
|
||
|
|
||
|
case *ast.SwitchStmt:
|
||
|
if n.Init != nil {
|
||
|
w.walk(n.Init)
|
||
|
}
|
||
|
if n.Tag != nil {
|
||
|
w.walk(n.Tag)
|
||
|
}
|
||
|
w.walk(n.Body)
|
||
|
|
||
|
case *ast.TypeSwitchStmt:
|
||
|
if n.Init != nil {
|
||
|
w.walk(n.Init)
|
||
|
}
|
||
|
w.walk(n.Assign)
|
||
|
w.walk(n.Body)
|
||
|
|
||
|
case *ast.CommClause:
|
||
|
if n.Comm != nil {
|
||
|
w.walk(n.Comm)
|
||
|
}
|
||
|
w.walkStmtList(n.Body)
|
||
|
|
||
|
case *ast.SelectStmt:
|
||
|
w.walk(n.Body)
|
||
|
|
||
|
case *ast.ForStmt:
|
||
|
if n.Init != nil {
|
||
|
w.walk(n.Init)
|
||
|
}
|
||
|
if n.Cond != nil {
|
||
|
w.walk(n.Cond)
|
||
|
}
|
||
|
if n.Post != nil {
|
||
|
w.walk(n.Post)
|
||
|
}
|
||
|
w.walk(n.Body)
|
||
|
|
||
|
case *ast.RangeStmt:
|
||
|
if n.Key != nil {
|
||
|
w.walk(n.Key)
|
||
|
}
|
||
|
if n.Value != nil {
|
||
|
w.walk(n.Value)
|
||
|
}
|
||
|
w.walk(n.X)
|
||
|
w.walk(n.Body)
|
||
|
|
||
|
case *ast.ImportSpec:
|
||
|
if n.Name != nil {
|
||
|
w.walk(n.Name)
|
||
|
}
|
||
|
w.walk(n.Path)
|
||
|
if n.Comment != nil {
|
||
|
w.walk(n.Comment)
|
||
|
}
|
||
|
|
||
|
case *ast.ValueSpec:
|
||
|
if n.Doc != nil {
|
||
|
w.walk(n.Doc)
|
||
|
}
|
||
|
w.walkIdentList(n.Names)
|
||
|
if n.Type != nil {
|
||
|
w.walk(n.Type)
|
||
|
}
|
||
|
w.walkExprList(n.Values)
|
||
|
if n.Comment != nil {
|
||
|
w.walk(n.Comment)
|
||
|
}
|
||
|
|
||
|
case *ast.TypeSpec:
|
||
|
if n.Doc != nil {
|
||
|
w.walk(n.Doc)
|
||
|
}
|
||
|
w.walk(n.Name)
|
||
|
w.walk(n.Type)
|
||
|
if n.Comment != nil {
|
||
|
w.walk(n.Comment)
|
||
|
}
|
||
|
|
||
|
case *ast.GenDecl:
|
||
|
if n.Doc != nil {
|
||
|
w.walk(n.Doc)
|
||
|
}
|
||
|
for _, s := range n.Specs {
|
||
|
w.walk(s)
|
||
|
}
|
||
|
|
||
|
case *ast.FuncDecl:
|
||
|
if n.Doc != nil {
|
||
|
w.walk(n.Doc)
|
||
|
}
|
||
|
if n.Recv != nil {
|
||
|
w.walk(n.Recv)
|
||
|
}
|
||
|
w.walk(n.Name)
|
||
|
w.walk(n.Type)
|
||
|
if n.Body != nil {
|
||
|
w.walk(n.Body)
|
||
|
}
|
||
|
|
||
|
case *ast.File:
|
||
|
w.walk(n.Name)
|
||
|
w.walkDeclList(n.Decls)
|
||
|
}
|
||
|
}
|