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)                          {}