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  }