514e30653d
When a custom type has a name that can shadow an in-built type, append MoqParam to the name. Example: var name stringMoqParam for null.String.
147 lines
3.1 KiB
Go
147 lines
3.1 KiB
Go
package registry
|
|
|
|
import (
|
|
"go/types"
|
|
"strings"
|
|
)
|
|
|
|
// Var represents a method variable/parameter.
|
|
//
|
|
// It should be created using a method scope instance.
|
|
type Var struct {
|
|
vr *types.Var
|
|
imports map[string]*Package
|
|
moqPkgPath string
|
|
|
|
Name string
|
|
}
|
|
|
|
// IsSlice returns whether the type (or the underlying type) is a slice.
|
|
func (v Var) IsSlice() bool {
|
|
_, ok := v.vr.Type().Underlying().(*types.Slice)
|
|
return ok
|
|
}
|
|
|
|
// TypeString returns the variable type with the package qualifier in the
|
|
// format 'pkg.Type'.
|
|
func (v Var) TypeString() string {
|
|
return types.TypeString(v.vr.Type(), v.packageQualifier)
|
|
}
|
|
|
|
// packageQualifier is a types.Qualifier.
|
|
func (v Var) packageQualifier(pkg *types.Package) string {
|
|
path := stripVendorPath(pkg.Path())
|
|
if v.moqPkgPath != "" && v.moqPkgPath == path {
|
|
return ""
|
|
}
|
|
|
|
return v.imports[path].Qualifier()
|
|
}
|
|
|
|
func varName(vr *types.Var, suffix string) string {
|
|
name := vr.Name()
|
|
if name != "" && name != "_" {
|
|
return name + suffix
|
|
}
|
|
|
|
name = varNameForType(vr.Type()) + suffix
|
|
|
|
switch name {
|
|
case "mock", "callInfo", "break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct",
|
|
"chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", "for",
|
|
"import", "return", "var",
|
|
// avoid shadowing basic types
|
|
"string", "bool", "byte", "rune", "uintptr",
|
|
"int", "int8", "int16", "int32", "int64",
|
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
|
"float32", "float64", "complex64", "complex128":
|
|
name += "MoqParam"
|
|
}
|
|
|
|
return name
|
|
}
|
|
|
|
// varNameForType generates a name for the variable using the type
|
|
// information.
|
|
//
|
|
// Examples:
|
|
// - string -> s
|
|
// - int -> n
|
|
// - chan int -> intCh
|
|
// - []a.MyType -> myTypes
|
|
// - map[string]int -> stringToInt
|
|
// - error -> err
|
|
// - a.MyType -> myType
|
|
func varNameForType(t types.Type) string {
|
|
nestedType := func(t types.Type) string {
|
|
if t, ok := t.(*types.Basic); ok {
|
|
return deCapitalise(t.String())
|
|
}
|
|
return varNameForType(t)
|
|
}
|
|
|
|
switch t := t.(type) {
|
|
case *types.Named:
|
|
if t.Obj().Name() == "error" {
|
|
return "err"
|
|
}
|
|
|
|
name := deCapitalise(t.Obj().Name())
|
|
if name == t.Obj().Name() {
|
|
name += "MoqParam"
|
|
}
|
|
|
|
return name
|
|
|
|
case *types.Basic:
|
|
return basicTypeVarName(t)
|
|
|
|
case *types.Array:
|
|
return nestedType(t.Elem()) + "s"
|
|
|
|
case *types.Slice:
|
|
return nestedType(t.Elem()) + "s"
|
|
|
|
case *types.Struct: // anonymous struct
|
|
return "val"
|
|
|
|
case *types.Pointer:
|
|
return varNameForType(t.Elem())
|
|
|
|
case *types.Signature:
|
|
return "fn"
|
|
|
|
case *types.Interface: // anonymous interface
|
|
return "ifaceVal"
|
|
|
|
case *types.Map:
|
|
return nestedType(t.Key()) + "To" + capitalise(nestedType(t.Elem()))
|
|
|
|
case *types.Chan:
|
|
return nestedType(t.Elem()) + "Ch"
|
|
}
|
|
|
|
return "v"
|
|
}
|
|
|
|
func basicTypeVarName(b *types.Basic) string {
|
|
switch b.Info() {
|
|
case types.IsBoolean:
|
|
return "b"
|
|
|
|
case types.IsInteger:
|
|
return "n"
|
|
|
|
case types.IsFloat:
|
|
return "f"
|
|
|
|
case types.IsString:
|
|
return "s"
|
|
}
|
|
|
|
return "v"
|
|
}
|
|
|
|
func capitalise(s string) string { return strings.ToUpper(s[:1]) + s[1:] }
|
|
func deCapitalise(s string) string { return strings.ToLower(s[:1]) + s[1:] }
|