fe0d4f3360
When the type and the package name is the same for an anonymous parameter (ex: time.Time), and there are more than 1 such parameters, the generated name for both was the same. And the generated code would not be valid. Fix the bug by ensuring the parameter name does not conflict with package imports first before checking against other parameter names.
142 lines
2.9 KiB
Go
142 lines
2.9 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":
|
|
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:] }
|