github.com/djui/moq@v0.3.3/internal/registry/var.go (about)

     1  package registry
     2  
     3  import (
     4  	"go/types"
     5  	"strings"
     6  )
     7  
     8  // Var represents a method variable/parameter.
     9  //
    10  // It should be created using a method scope instance.
    11  type Var struct {
    12  	vr         *types.Var
    13  	imports    map[string]*Package
    14  	moqPkgPath string
    15  
    16  	Name string
    17  }
    18  
    19  // IsSlice returns whether the type (or the underlying type) is a slice.
    20  func (v Var) IsSlice() bool {
    21  	_, ok := v.vr.Type().Underlying().(*types.Slice)
    22  	return ok
    23  }
    24  
    25  // TypeString returns the variable type with the package qualifier in the
    26  // format 'pkg.Type'.
    27  func (v Var) TypeString() string {
    28  	return types.TypeString(v.vr.Type(), v.packageQualifier)
    29  }
    30  
    31  // packageQualifier is a types.Qualifier.
    32  func (v Var) packageQualifier(pkg *types.Package) string {
    33  	path := stripVendorPath(pkg.Path())
    34  	if v.moqPkgPath != "" && v.moqPkgPath == path {
    35  		return ""
    36  	}
    37  
    38  	return v.imports[path].Qualifier()
    39  }
    40  
    41  func varName(vr *types.Var, suffix string) string {
    42  	name := vr.Name()
    43  	if name != "" && name != "_" {
    44  		return name + suffix
    45  	}
    46  
    47  	name = varNameForType(vr.Type()) + suffix
    48  
    49  	switch name {
    50  	case "mock", "callInfo", "break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct",
    51  		"chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", "for",
    52  		"import", "return", "var",
    53  		// avoid shadowing basic types
    54  		"string", "bool", "byte", "rune", "uintptr",
    55  		"int", "int8", "int16", "int32", "int64",
    56  		"uint", "uint8", "uint16", "uint32", "uint64",
    57  		"float32", "float64", "complex64", "complex128":
    58  		name += "MoqParam"
    59  	}
    60  
    61  	return name
    62  }
    63  
    64  // varNameForType generates a name for the variable using the type
    65  // information.
    66  //
    67  // Examples:
    68  // - string -> s
    69  // - int -> n
    70  // - chan int -> intCh
    71  // - []a.MyType -> myTypes
    72  // - map[string]int -> stringToInt
    73  // - error -> err
    74  // - a.MyType -> myType
    75  func varNameForType(t types.Type) string {
    76  	nestedType := func(t types.Type) string {
    77  		if t, ok := t.(*types.Basic); ok {
    78  			return deCapitalise(t.String())
    79  		}
    80  		return varNameForType(t)
    81  	}
    82  
    83  	switch t := t.(type) {
    84  	case *types.Named:
    85  		if t.Obj().Name() == "error" {
    86  			return "err"
    87  		}
    88  
    89  		name := deCapitalise(t.Obj().Name())
    90  		if name == t.Obj().Name() {
    91  			name += "MoqParam"
    92  		}
    93  
    94  		return name
    95  
    96  	case *types.Basic:
    97  		return basicTypeVarName(t)
    98  
    99  	case *types.Array:
   100  		return nestedType(t.Elem()) + "s"
   101  
   102  	case *types.Slice:
   103  		return nestedType(t.Elem()) + "s"
   104  
   105  	case *types.Struct: // anonymous struct
   106  		return "val"
   107  
   108  	case *types.Pointer:
   109  		return varNameForType(t.Elem())
   110  
   111  	case *types.Signature:
   112  		return "fn"
   113  
   114  	case *types.Interface: // anonymous interface
   115  		return "ifaceVal"
   116  
   117  	case *types.Map:
   118  		return nestedType(t.Key()) + "To" + capitalise(nestedType(t.Elem()))
   119  
   120  	case *types.Chan:
   121  		return nestedType(t.Elem()) + "Ch"
   122  	}
   123  
   124  	return "v"
   125  }
   126  
   127  func basicTypeVarName(b *types.Basic) string {
   128  	switch b.Info() {
   129  	case types.IsBoolean:
   130  		return "b"
   131  
   132  	case types.IsInteger:
   133  		return "n"
   134  
   135  	case types.IsFloat:
   136  		return "f"
   137  
   138  	case types.IsString:
   139  		return "s"
   140  	}
   141  
   142  	return "v"
   143  }
   144  
   145  func capitalise(s string) string   { return strings.ToUpper(s[:1]) + s[1:] }
   146  func deCapitalise(s string) string { return strings.ToLower(s[:1]) + s[1:] }