woodpecker/vendor/github.com/golangci/dupl/syntax/golang/golang.go
Lukas c28f7cb29f
Add golangci-lint (#502)
Initial part of #435
2021-11-14 21:01:54 +01:00

392 lines
7.1 KiB
Go

package golang
import (
"go/ast"
"go/parser"
"go/token"
"github.com/golangci/dupl/syntax"
)
const (
BadNode = iota
File
ArrayType
AssignStmt
BasicLit
BinaryExpr
BlockStmt
BranchStmt
CallExpr
CaseClause
ChanType
CommClause
CompositeLit
DeclStmt
DeferStmt
Ellipsis
EmptyStmt
ExprStmt
Field
FieldList
ForStmt
FuncDecl
FuncLit
FuncType
GenDecl
GoStmt
Ident
IfStmt
IncDecStmt
IndexExpr
InterfaceType
KeyValueExpr
LabeledStmt
MapType
ParenExpr
RangeStmt
ReturnStmt
SelectStmt
SelectorExpr
SendStmt
SliceExpr
StarExpr
StructType
SwitchStmt
TypeAssertExpr
TypeSpec
TypeSwitchStmt
UnaryExpr
ValueSpec
)
// Parse the given file and return uniform syntax tree.
func Parse(filename string) (*syntax.Node, error) {
fset := token.NewFileSet()
file, err := parser.ParseFile(fset, filename, nil, 0)
if err != nil {
return nil, err
}
t := &transformer{
fileset: fset,
filename: filename,
}
return t.trans(file), nil
}
type transformer struct {
fileset *token.FileSet
filename string
}
// trans transforms given golang AST to uniform tree structure.
func (t *transformer) trans(node ast.Node) (o *syntax.Node) {
o = syntax.NewNode()
o.Filename = t.filename
st, end := node.Pos(), node.End()
o.Pos, o.End = t.fileset.File(st).Offset(st), t.fileset.File(end).Offset(end)
switch n := node.(type) {
case *ast.ArrayType:
o.Type = ArrayType
if n.Len != nil {
o.AddChildren(t.trans(n.Len))
}
o.AddChildren(t.trans(n.Elt))
case *ast.AssignStmt:
o.Type = AssignStmt
for _, e := range n.Rhs {
o.AddChildren(t.trans(e))
}
for _, e := range n.Lhs {
o.AddChildren(t.trans(e))
}
case *ast.BasicLit:
o.Type = BasicLit
case *ast.BinaryExpr:
o.Type = BinaryExpr
o.AddChildren(t.trans(n.X), t.trans(n.Y))
case *ast.BlockStmt:
o.Type = BlockStmt
for _, stmt := range n.List {
o.AddChildren(t.trans(stmt))
}
case *ast.BranchStmt:
o.Type = BranchStmt
if n.Label != nil {
o.AddChildren(t.trans(n.Label))
}
case *ast.CallExpr:
o.Type = CallExpr
o.AddChildren(t.trans(n.Fun))
for _, arg := range n.Args {
o.AddChildren(t.trans(arg))
}
case *ast.CaseClause:
o.Type = CaseClause
for _, e := range n.List {
o.AddChildren(t.trans(e))
}
for _, stmt := range n.Body {
o.AddChildren(t.trans(stmt))
}
case *ast.ChanType:
o.Type = ChanType
o.AddChildren(t.trans(n.Value))
case *ast.CommClause:
o.Type = CommClause
if n.Comm != nil {
o.AddChildren(t.trans(n.Comm))
}
for _, stmt := range n.Body {
o.AddChildren(t.trans(stmt))
}
case *ast.CompositeLit:
o.Type = CompositeLit
if n.Type != nil {
o.AddChildren(t.trans(n.Type))
}
for _, e := range n.Elts {
o.AddChildren(t.trans(e))
}
case *ast.DeclStmt:
o.Type = DeclStmt
o.AddChildren(t.trans(n.Decl))
case *ast.DeferStmt:
o.Type = DeferStmt
o.AddChildren(t.trans(n.Call))
case *ast.Ellipsis:
o.Type = Ellipsis
if n.Elt != nil {
o.AddChildren(t.trans(n.Elt))
}
case *ast.EmptyStmt:
o.Type = EmptyStmt
case *ast.ExprStmt:
o.Type = ExprStmt
o.AddChildren(t.trans(n.X))
case *ast.Field:
o.Type = Field
for _, name := range n.Names {
o.AddChildren(t.trans(name))
}
o.AddChildren(t.trans(n.Type))
case *ast.FieldList:
o.Type = FieldList
for _, field := range n.List {
o.AddChildren(t.trans(field))
}
case *ast.File:
o.Type = File
for _, decl := range n.Decls {
if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.IMPORT {
// skip import declarations
continue
}
o.AddChildren(t.trans(decl))
}
case *ast.ForStmt:
o.Type = ForStmt
if n.Init != nil {
o.AddChildren(t.trans(n.Init))
}
if n.Cond != nil {
o.AddChildren(t.trans(n.Cond))
}
if n.Post != nil {
o.AddChildren(t.trans(n.Post))
}
o.AddChildren(t.trans(n.Body))
case *ast.FuncDecl:
o.Type = FuncDecl
if n.Recv != nil {
o.AddChildren(t.trans(n.Recv))
}
o.AddChildren(t.trans(n.Name), t.trans(n.Type))
if n.Body != nil {
o.AddChildren(t.trans(n.Body))
}
case *ast.FuncLit:
o.Type = FuncLit
o.AddChildren(t.trans(n.Type), t.trans(n.Body))
case *ast.FuncType:
o.Type = FuncType
o.AddChildren(t.trans(n.Params))
if n.Results != nil {
o.AddChildren(t.trans(n.Results))
}
case *ast.GenDecl:
o.Type = GenDecl
for _, spec := range n.Specs {
o.AddChildren(t.trans(spec))
}
case *ast.GoStmt:
o.Type = GoStmt
o.AddChildren(t.trans(n.Call))
case *ast.Ident:
o.Type = Ident
case *ast.IfStmt:
o.Type = IfStmt
if n.Init != nil {
o.AddChildren(t.trans(n.Init))
}
o.AddChildren(t.trans(n.Cond), t.trans(n.Body))
if n.Else != nil {
o.AddChildren(t.trans(n.Else))
}
case *ast.IncDecStmt:
o.Type = IncDecStmt
o.AddChildren(t.trans(n.X))
case *ast.IndexExpr:
o.Type = IndexExpr
o.AddChildren(t.trans(n.X), t.trans(n.Index))
case *ast.InterfaceType:
o.Type = InterfaceType
o.AddChildren(t.trans(n.Methods))
case *ast.KeyValueExpr:
o.Type = KeyValueExpr
o.AddChildren(t.trans(n.Key), t.trans(n.Value))
case *ast.LabeledStmt:
o.Type = LabeledStmt
o.AddChildren(t.trans(n.Label), t.trans(n.Stmt))
case *ast.MapType:
o.Type = MapType
o.AddChildren(t.trans(n.Key), t.trans(n.Value))
case *ast.ParenExpr:
o.Type = ParenExpr
o.AddChildren(t.trans(n.X))
case *ast.RangeStmt:
o.Type = RangeStmt
if n.Key != nil {
o.AddChildren(t.trans(n.Key))
}
if n.Value != nil {
o.AddChildren(t.trans(n.Value))
}
o.AddChildren(t.trans(n.X), t.trans(n.Body))
case *ast.ReturnStmt:
o.Type = ReturnStmt
for _, e := range n.Results {
o.AddChildren(t.trans(e))
}
case *ast.SelectStmt:
o.Type = SelectStmt
o.AddChildren(t.trans(n.Body))
case *ast.SelectorExpr:
o.Type = SelectorExpr
o.AddChildren(t.trans(n.X), t.trans(n.Sel))
case *ast.SendStmt:
o.Type = SendStmt
o.AddChildren(t.trans(n.Chan), t.trans(n.Value))
case *ast.SliceExpr:
o.Type = SliceExpr
o.AddChildren(t.trans(n.X))
if n.Low != nil {
o.AddChildren(t.trans(n.Low))
}
if n.High != nil {
o.AddChildren(t.trans(n.High))
}
if n.Max != nil {
o.AddChildren(t.trans(n.Max))
}
case *ast.StarExpr:
o.Type = StarExpr
o.AddChildren(t.trans(n.X))
case *ast.StructType:
o.Type = StructType
o.AddChildren(t.trans(n.Fields))
case *ast.SwitchStmt:
o.Type = SwitchStmt
if n.Init != nil {
o.AddChildren(t.trans(n.Init))
}
if n.Tag != nil {
o.AddChildren(t.trans(n.Tag))
}
o.AddChildren(t.trans(n.Body))
case *ast.TypeAssertExpr:
o.Type = TypeAssertExpr
o.AddChildren(t.trans(n.X))
if n.Type != nil {
o.AddChildren(t.trans(n.Type))
}
case *ast.TypeSpec:
o.Type = TypeSpec
o.AddChildren(t.trans(n.Name), t.trans(n.Type))
case *ast.TypeSwitchStmt:
o.Type = TypeSwitchStmt
if n.Init != nil {
o.AddChildren(t.trans(n.Init))
}
o.AddChildren(t.trans(n.Assign), t.trans(n.Body))
case *ast.UnaryExpr:
o.Type = UnaryExpr
o.AddChildren(t.trans(n.X))
case *ast.ValueSpec:
o.Type = ValueSpec
for _, name := range n.Names {
o.AddChildren(t.trans(name))
}
if n.Type != nil {
o.AddChildren(t.trans(n.Type))
}
for _, val := range n.Values {
o.AddChildren(t.trans(val))
}
default:
o.Type = BadNode
}
return o
}