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:] }