honnef.co/go/tools@v0.5.0-0.dev.0.20240520180541-dcae280a5e87/pattern/convert.go (about)

     1  package pattern
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/token"
     7  	"go/types"
     8  	"reflect"
     9  )
    10  
    11  var astTypes = map[string]reflect.Type{
    12  	"Ellipsis":       reflect.TypeOf(ast.Ellipsis{}),
    13  	"RangeStmt":      reflect.TypeOf(ast.RangeStmt{}),
    14  	"AssignStmt":     reflect.TypeOf(ast.AssignStmt{}),
    15  	"IndexExpr":      reflect.TypeOf(ast.IndexExpr{}),
    16  	"IndexListExpr":  reflect.TypeOf(ast.IndexListExpr{}),
    17  	"Ident":          reflect.TypeOf(ast.Ident{}),
    18  	"ValueSpec":      reflect.TypeOf(ast.ValueSpec{}),
    19  	"GenDecl":        reflect.TypeOf(ast.GenDecl{}),
    20  	"BinaryExpr":     reflect.TypeOf(ast.BinaryExpr{}),
    21  	"ForStmt":        reflect.TypeOf(ast.ForStmt{}),
    22  	"ArrayType":      reflect.TypeOf(ast.ArrayType{}),
    23  	"DeferStmt":      reflect.TypeOf(ast.DeferStmt{}),
    24  	"MapType":        reflect.TypeOf(ast.MapType{}),
    25  	"ReturnStmt":     reflect.TypeOf(ast.ReturnStmt{}),
    26  	"SliceExpr":      reflect.TypeOf(ast.SliceExpr{}),
    27  	"StarExpr":       reflect.TypeOf(ast.StarExpr{}),
    28  	"UnaryExpr":      reflect.TypeOf(ast.UnaryExpr{}),
    29  	"SendStmt":       reflect.TypeOf(ast.SendStmt{}),
    30  	"SelectStmt":     reflect.TypeOf(ast.SelectStmt{}),
    31  	"ImportSpec":     reflect.TypeOf(ast.ImportSpec{}),
    32  	"IfStmt":         reflect.TypeOf(ast.IfStmt{}),
    33  	"GoStmt":         reflect.TypeOf(ast.GoStmt{}),
    34  	"Field":          reflect.TypeOf(ast.Field{}),
    35  	"SelectorExpr":   reflect.TypeOf(ast.SelectorExpr{}),
    36  	"StructType":     reflect.TypeOf(ast.StructType{}),
    37  	"KeyValueExpr":   reflect.TypeOf(ast.KeyValueExpr{}),
    38  	"FuncType":       reflect.TypeOf(ast.FuncType{}),
    39  	"FuncLit":        reflect.TypeOf(ast.FuncLit{}),
    40  	"FuncDecl":       reflect.TypeOf(ast.FuncDecl{}),
    41  	"ChanType":       reflect.TypeOf(ast.ChanType{}),
    42  	"CallExpr":       reflect.TypeOf(ast.CallExpr{}),
    43  	"CaseClause":     reflect.TypeOf(ast.CaseClause{}),
    44  	"CommClause":     reflect.TypeOf(ast.CommClause{}),
    45  	"CompositeLit":   reflect.TypeOf(ast.CompositeLit{}),
    46  	"EmptyStmt":      reflect.TypeOf(ast.EmptyStmt{}),
    47  	"SwitchStmt":     reflect.TypeOf(ast.SwitchStmt{}),
    48  	"TypeSwitchStmt": reflect.TypeOf(ast.TypeSwitchStmt{}),
    49  	"TypeAssertExpr": reflect.TypeOf(ast.TypeAssertExpr{}),
    50  	"TypeSpec":       reflect.TypeOf(ast.TypeSpec{}),
    51  	"InterfaceType":  reflect.TypeOf(ast.InterfaceType{}),
    52  	"BranchStmt":     reflect.TypeOf(ast.BranchStmt{}),
    53  	"IncDecStmt":     reflect.TypeOf(ast.IncDecStmt{}),
    54  	"BasicLit":       reflect.TypeOf(ast.BasicLit{}),
    55  }
    56  
    57  func ASTToNode(node interface{}) Node {
    58  	switch node := node.(type) {
    59  	case *ast.File:
    60  		panic("cannot convert *ast.File to Node")
    61  	case nil:
    62  		return Nil{}
    63  	case string:
    64  		return String(node)
    65  	case token.Token:
    66  		return Token(node)
    67  	case *ast.ExprStmt:
    68  		return ASTToNode(node.X)
    69  	case *ast.BlockStmt:
    70  		if node == nil {
    71  			return Nil{}
    72  		}
    73  		return ASTToNode(node.List)
    74  	case *ast.FieldList:
    75  		if node == nil {
    76  			return Nil{}
    77  		}
    78  		return ASTToNode(node.List)
    79  	case *ast.BasicLit:
    80  		if node == nil {
    81  			return Nil{}
    82  		}
    83  	case *ast.ParenExpr:
    84  		return ASTToNode(node.X)
    85  	}
    86  
    87  	if node, ok := node.(ast.Node); ok {
    88  		name := reflect.TypeOf(node).Elem().Name()
    89  		T, ok := structNodes[name]
    90  		if !ok {
    91  			panic(fmt.Sprintf("internal error: unhandled type %T", node))
    92  		}
    93  
    94  		if reflect.ValueOf(node).IsNil() {
    95  			return Nil{}
    96  		}
    97  		v := reflect.ValueOf(node).Elem()
    98  		objs := make([]Node, T.NumField())
    99  		for i := 0; i < T.NumField(); i++ {
   100  			f := v.FieldByName(T.Field(i).Name)
   101  			objs[i] = ASTToNode(f.Interface())
   102  		}
   103  
   104  		n, err := populateNode(name, objs, false)
   105  		if err != nil {
   106  			panic(fmt.Sprintf("internal error: %s", err))
   107  		}
   108  		return n
   109  	}
   110  
   111  	s := reflect.ValueOf(node)
   112  	if s.Kind() == reflect.Slice {
   113  		if s.Len() == 0 {
   114  			return List{}
   115  		}
   116  		if s.Len() == 1 {
   117  			return ASTToNode(s.Index(0).Interface())
   118  		}
   119  
   120  		tail := List{}
   121  		for i := s.Len() - 1; i >= 0; i-- {
   122  			head := ASTToNode(s.Index(i).Interface())
   123  			l := List{
   124  				Head: head,
   125  				Tail: tail,
   126  			}
   127  			tail = l
   128  		}
   129  		return tail
   130  	}
   131  
   132  	panic(fmt.Sprintf("internal error: unhandled type %T", node))
   133  }
   134  
   135  func NodeToAST(node Node, state State) interface{} {
   136  	switch node := node.(type) {
   137  	case Binding:
   138  		v, ok := state[node.Name]
   139  		if !ok {
   140  			// really we want to return an error here
   141  			panic("XXX")
   142  		}
   143  		switch v := v.(type) {
   144  		case types.Object:
   145  			return &ast.Ident{Name: v.Name()}
   146  		default:
   147  			return v
   148  		}
   149  	case Builtin, Any, Object, Symbol, Not, Or:
   150  		panic("XXX")
   151  	case List:
   152  		if (node == List{}) {
   153  			return []ast.Node{}
   154  		}
   155  		x := []ast.Node{NodeToAST(node.Head, state).(ast.Node)}
   156  		x = append(x, NodeToAST(node.Tail, state).([]ast.Node)...)
   157  		return x
   158  	case Token:
   159  		return token.Token(node)
   160  	case String:
   161  		return string(node)
   162  	case Nil:
   163  		return nil
   164  	}
   165  
   166  	name := reflect.TypeOf(node).Name()
   167  	T, ok := astTypes[name]
   168  	if !ok {
   169  		panic(fmt.Sprintf("internal error: unhandled type %T", node))
   170  	}
   171  	v := reflect.ValueOf(node)
   172  	out := reflect.New(T)
   173  	for i := 0; i < T.NumField(); i++ {
   174  		fNode := v.FieldByName(T.Field(i).Name)
   175  		if (fNode == reflect.Value{}) {
   176  			continue
   177  		}
   178  		fAST := out.Elem().FieldByName(T.Field(i).Name)
   179  		switch fAST.Type().Kind() {
   180  		case reflect.Slice:
   181  			c := reflect.ValueOf(NodeToAST(fNode.Interface().(Node), state))
   182  			if c.Kind() != reflect.Slice {
   183  				// it's a single node in the pattern, we have to wrap
   184  				// it in a slice
   185  				slice := reflect.MakeSlice(fAST.Type(), 1, 1)
   186  				slice.Index(0).Set(c)
   187  				c = slice
   188  			}
   189  			switch fAST.Interface().(type) {
   190  			case []ast.Node:
   191  				switch cc := c.Interface().(type) {
   192  				case []ast.Node:
   193  					fAST.Set(c)
   194  				case []ast.Expr:
   195  					var slice []ast.Node
   196  					for _, el := range cc {
   197  						slice = append(slice, el)
   198  					}
   199  					fAST.Set(reflect.ValueOf(slice))
   200  				default:
   201  					panic("XXX")
   202  				}
   203  			case []ast.Expr:
   204  				switch cc := c.Interface().(type) {
   205  				case []ast.Node:
   206  					var slice []ast.Expr
   207  					for _, el := range cc {
   208  						slice = append(slice, el.(ast.Expr))
   209  					}
   210  					fAST.Set(reflect.ValueOf(slice))
   211  				case []ast.Expr:
   212  					fAST.Set(c)
   213  				default:
   214  					panic("XXX")
   215  				}
   216  			default:
   217  				panic("XXX")
   218  			}
   219  		case reflect.Int:
   220  			c := reflect.ValueOf(NodeToAST(fNode.Interface().(Node), state))
   221  			switch c.Kind() {
   222  			case reflect.String:
   223  				tok, ok := tokensByString[c.Interface().(string)]
   224  				if !ok {
   225  					// really we want to return an error here
   226  					panic("XXX")
   227  				}
   228  				fAST.SetInt(int64(tok))
   229  			case reflect.Int:
   230  				fAST.Set(c)
   231  			default:
   232  				panic(fmt.Sprintf("internal error: unexpected kind %s", c.Kind()))
   233  			}
   234  		default:
   235  			r := NodeToAST(fNode.Interface().(Node), state)
   236  			if r != nil {
   237  				fAST.Set(reflect.ValueOf(r))
   238  			}
   239  		}
   240  	}
   241  
   242  	return out.Interface().(ast.Node)
   243  }