github.com/relnod/pegomock@v2.0.1+incompatible/model/model.go (about) 1 // Copyright 2012 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package model contains the data model necessary for generating mock implementations. 16 package model 17 18 import ( 19 "fmt" 20 "io" 21 "strings" 22 ) 23 24 // Package is a Go package. It may be a subset. 25 type Package struct { 26 Name string 27 Interfaces []*Interface 28 DotImports []string 29 } 30 31 func (pkg *Package) Print(w io.Writer) { 32 fmt.Fprintf(w, "package %s\n", pkg.Name) 33 for _, intf := range pkg.Interfaces { 34 intf.Print(w) 35 } 36 } 37 38 // Imports returns the imports needed by the Package as a set of import paths. 39 func (pkg *Package) Imports() map[string]bool { 40 im := make(map[string]bool) 41 for _, intf := range pkg.Interfaces { 42 intf.addImports(im) 43 } 44 return im 45 } 46 47 // Interface is a Go interface. 48 type Interface struct { 49 Name string 50 Methods []*Method 51 } 52 53 func (intf *Interface) Print(w io.Writer) { 54 fmt.Fprintf(w, "interface %s\n", intf.Name) 55 for _, m := range intf.Methods { 56 m.Print(w) 57 } 58 } 59 60 func (intf *Interface) addImports(im map[string]bool) { 61 for _, m := range intf.Methods { 62 m.addImports(im) 63 } 64 } 65 66 // Method is a single method of an interface. 67 type Method struct { 68 Name string 69 In, Out []*Parameter 70 Variadic *Parameter // may be nil 71 } 72 73 func (m *Method) Print(w io.Writer) { 74 fmt.Fprintf(w, " - method %s\n", m.Name) 75 if len(m.In) > 0 { 76 fmt.Fprintf(w, " in:\n") 77 for _, p := range m.In { 78 p.Print(w) 79 } 80 } 81 if m.Variadic != nil { 82 fmt.Fprintf(w, " ...:\n") 83 m.Variadic.Print(w) 84 } 85 if len(m.Out) > 0 { 86 fmt.Fprintf(w, " out:\n") 87 for _, p := range m.Out { 88 p.Print(w) 89 } 90 } 91 } 92 93 func (m *Method) addImports(im map[string]bool) { 94 for _, p := range m.In { 95 p.Type.addImports(im) 96 } 97 if m.Variadic != nil { 98 m.Variadic.Type.addImports(im) 99 } 100 for _, p := range m.Out { 101 p.Type.addImports(im) 102 } 103 } 104 105 // Parameter is an argument or return parameter of a method. 106 type Parameter struct { 107 Name string // may be empty 108 Type Type 109 } 110 111 func (p *Parameter) Print(w io.Writer) { 112 n := p.Name 113 if n == "" { 114 n = `""` 115 } 116 fmt.Fprintf(w, " - %v: %v\n", n, p.Type.String(nil, "")) 117 } 118 119 // Type is a Go type. 120 type Type interface { 121 String(pm map[string]string, pkgOverride string) string 122 addImports(im map[string]bool) 123 } 124 125 // ArrayType is an array or slice type. 126 type ArrayType struct { 127 Len int // -1 for slices, >= 0 for arrays 128 Type Type 129 } 130 131 func (at *ArrayType) String(pm map[string]string, pkgOverride string) string { 132 s := "[]" 133 if at.Len > -1 { 134 s = fmt.Sprintf("[%d]", at.Len) 135 } 136 return s + at.Type.String(pm, pkgOverride) 137 } 138 139 func (at *ArrayType) addImports(im map[string]bool) { at.Type.addImports(im) } 140 141 // ChanType is a channel type. 142 type ChanType struct { 143 Dir ChanDir // 0, 1 or 2 144 Type Type 145 } 146 147 func (ct *ChanType) String(pm map[string]string, pkgOverride string) string { 148 s := ct.Type.String(pm, pkgOverride) 149 if ct.Dir == RecvDir { 150 return "<-chan " + s 151 } 152 if ct.Dir == SendDir { 153 return "chan<- " + s 154 } 155 return "chan " + s 156 } 157 158 func (ct *ChanType) addImports(im map[string]bool) { ct.Type.addImports(im) } 159 160 // ChanDir is a channel direction. 161 type ChanDir int 162 163 const ( 164 RecvDir ChanDir = 1 165 SendDir ChanDir = 2 166 ) 167 168 // FuncType is a function type. 169 type FuncType struct { 170 In, Out []*Parameter 171 Variadic *Parameter // may be nil 172 } 173 174 func (ft *FuncType) String(pm map[string]string, pkgOverride string) string { 175 args := make([]string, len(ft.In)) 176 for i, p := range ft.In { 177 args[i] = p.Type.String(pm, pkgOverride) 178 } 179 if ft.Variadic != nil { 180 args = append(args, "..."+ft.Variadic.Type.String(pm, pkgOverride)) 181 } 182 rets := make([]string, len(ft.Out)) 183 for i, p := range ft.Out { 184 rets[i] = p.Type.String(pm, pkgOverride) 185 } 186 retString := strings.Join(rets, ", ") 187 if nOut := len(ft.Out); nOut == 1 { 188 retString = " " + retString 189 } else if nOut > 1 { 190 retString = " (" + retString + ")" 191 } 192 return "func(" + strings.Join(args, ", ") + ")" + retString 193 } 194 195 func (ft *FuncType) addImports(im map[string]bool) { 196 for _, p := range ft.In { 197 p.Type.addImports(im) 198 } 199 if ft.Variadic != nil { 200 ft.Variadic.Type.addImports(im) 201 } 202 for _, p := range ft.Out { 203 p.Type.addImports(im) 204 } 205 } 206 207 // MapType is a map type. 208 type MapType struct { 209 Key, Value Type 210 } 211 212 func (mt *MapType) String(pm map[string]string, pkgOverride string) string { 213 return "map[" + mt.Key.String(pm, pkgOverride) + "]" + mt.Value.String(pm, pkgOverride) 214 } 215 216 func (mt *MapType) addImports(im map[string]bool) { 217 mt.Key.addImports(im) 218 mt.Value.addImports(im) 219 } 220 221 // NamedType is an exported type in a package. 222 type NamedType struct { 223 Package string // may be empty 224 Type string // TODO: should this be typed Type? 225 } 226 227 func (nt *NamedType) String(pm map[string]string, pkgOverride string) string { 228 // TODO: is this right? 229 if pkgOverride == nt.Package { 230 return nt.Type 231 } 232 return pm[nt.Package] + "." + nt.Type 233 } 234 func (nt *NamedType) addImports(im map[string]bool) { 235 if nt.Package != "" { 236 im[nt.Package] = true 237 } 238 } 239 240 // PointerType is a pointer to another type. 241 type PointerType struct { 242 Type Type 243 } 244 245 func (pt *PointerType) String(pm map[string]string, pkgOverride string) string { 246 return "*" + pt.Type.String(pm, pkgOverride) 247 } 248 func (pt *PointerType) addImports(im map[string]bool) { pt.Type.addImports(im) } 249 250 // PredeclaredType is a predeclared type such as "int". 251 type PredeclaredType string 252 253 func (pt PredeclaredType) String(pm map[string]string, pkgOverride string) string { return string(pt) } 254 func (pt PredeclaredType) addImports(im map[string]bool) {}