github.com/mlmmr/revel-cmd@v0.21.2-0.20191112133115-68d8795776dd/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  	error := ""
    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  		error = 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  		error = fmt.Sprintf("Failed to generate name for field: %v Package: %v. Make sure the field name is valid.", expr, pkgName)
    50  
    51  	}
    52  	return NewTypeExprFromData(error, "", 0, false)
    53  }
    54  
    55  // TypeName returns the fully-qualified type name for this expression.
    56  // The caller may optionally specify a package name to override the default.
    57  func (e TypeExpr) TypeName(pkgOverride string) string {
    58  	pkgName := FirstNonEmpty(pkgOverride, e.PkgName)
    59  	if pkgName == "" {
    60  		return e.Expr
    61  	}
    62  	return e.Expr[:e.pkgIndex] + pkgName + "." + e.Expr[e.pkgIndex:]
    63  }
    64  
    65  var builtInTypes = map[string]struct{}{
    66  	"bool":       {},
    67  	"byte":       {},
    68  	"complex128": {},
    69  	"complex64":  {},
    70  	"error":      {},
    71  	"float32":    {},
    72  	"float64":    {},
    73  	"int":        {},
    74  	"int16":      {},
    75  	"int32":      {},
    76  	"int64":      {},
    77  	"int8":       {},
    78  	"rune":       {},
    79  	"string":     {},
    80  	"uint":       {},
    81  	"uint16":     {},
    82  	"uint32":     {},
    83  	"uint64":     {},
    84  	"uint8":      {},
    85  	"uintptr":    {},
    86  }
    87  
    88  // IsBuiltinType checks the given type is built-in types of Go
    89  func IsBuiltinType(name string) bool {
    90  	_, ok := builtInTypes[name]
    91  	return ok
    92  }
    93  
    94  // Returns the first non empty string from a list of arguements
    95  func FirstNonEmpty(strs ...string) string {
    96  	for _, str := range strs {
    97  		if len(str) > 0 {
    98  			return str
    99  		}
   100  	}
   101  	return ""
   102  }