github.com/wiselike/revel-cmd@v1.2.1/model/type_expr.go (about) 1 package model 2 3 // TypeExpr provides a type name that may be rewritten to use a package name. 4 import ( 5 "fmt" 6 "go/ast" 7 ) 8 9 type TypeExpr struct { 10 Expr string // The unqualified type expression, e.g. "[]*MyType" 11 PkgName string // The default package idenifier 12 pkgIndex int // The index where the package identifier should be inserted. 13 Valid bool 14 } 15 16 // Returns a new type from the data. 17 func NewTypeExprFromData(expr, pkgName string, pkgIndex int, valid bool) TypeExpr { 18 return TypeExpr{expr, pkgName, pkgIndex, valid} 19 } 20 21 // NewTypeExpr returns the syntactic expression for referencing this type in Go. 22 func NewTypeExprFromAst(pkgName string, expr ast.Expr) TypeExpr { 23 err := "" 24 switch t := expr.(type) { 25 case *ast.Ident: 26 if IsBuiltinType(t.Name) { 27 pkgName = "" 28 } 29 return TypeExpr{t.Name, pkgName, 0, true} 30 case *ast.SelectorExpr: 31 e := NewTypeExprFromAst(pkgName, t.X) 32 return NewTypeExprFromData(t.Sel.Name, e.Expr, 0, e.Valid) 33 case *ast.StarExpr: 34 e := NewTypeExprFromAst(pkgName, t.X) 35 return NewTypeExprFromData("*"+e.Expr, e.PkgName, e.pkgIndex+1, e.Valid) 36 case *ast.ArrayType: 37 e := NewTypeExprFromAst(pkgName, t.Elt) 38 return NewTypeExprFromData("[]"+e.Expr, e.PkgName, e.pkgIndex+2, e.Valid) 39 case *ast.MapType: 40 if identKey, ok := t.Key.(*ast.Ident); ok && IsBuiltinType(identKey.Name) { 41 e := NewTypeExprFromAst(pkgName, t.Value) 42 return NewTypeExprFromData("map["+identKey.Name+"]"+e.Expr, e.PkgName, e.pkgIndex+len("map["+identKey.Name+"]"), e.Valid) 43 } 44 err = fmt.Sprintf("Failed to generate name for Map field :%v. Make sure the field name is valid.", t.Key) 45 case *ast.Ellipsis: 46 e := NewTypeExprFromAst(pkgName, t.Elt) 47 return NewTypeExprFromData("[]"+e.Expr, e.PkgName, e.pkgIndex+2, e.Valid) 48 default: 49 err = fmt.Sprintf("Failed to generate name for field: %v Package: %v. Make sure the field name is valid.", expr, pkgName) 50 } 51 return NewTypeExprFromData(err, "", 0, false) 52 } 53 54 // TypeName returns the fully-qualified type name for this expression. 55 // The caller may optionally specify a package name to override the default. 56 func (e TypeExpr) TypeName(pkgOverride string) string { 57 pkgName := FirstNonEmpty(pkgOverride, e.PkgName) 58 if pkgName == "" { 59 return e.Expr 60 } 61 return e.Expr[:e.pkgIndex] + pkgName + "." + e.Expr[e.pkgIndex:] 62 } 63 64 var builtInTypes = map[string]struct{}{ //nolint:gochecknoglobals 65 "bool": {}, 66 "byte": {}, 67 "complex128": {}, 68 "complex64": {}, 69 "error": {}, 70 "float32": {}, 71 "float64": {}, 72 "int": {}, 73 "int16": {}, 74 "int32": {}, 75 "int64": {}, 76 "int8": {}, 77 "rune": {}, 78 "string": {}, 79 "uint": {}, 80 "uint16": {}, 81 "uint32": {}, 82 "uint64": {}, 83 "uint8": {}, 84 "uintptr": {}, 85 } 86 87 // IsBuiltinType checks the given type is built-in types of Go. 88 func IsBuiltinType(name string) bool { 89 _, ok := builtInTypes[name] 90 return ok 91 } 92 93 // Returns the first non empty string from a list of arguments. 94 func FirstNonEmpty(strs ...string) string { 95 for _, str := range strs { 96 if len(str) > 0 { 97 return str 98 } 99 } 100 return "" 101 }