func NewParam(name string, fi *ast.Field, usedNames map[string]bool, printer typePrinter) (*Param, error) {
	typ := fi.Type
	if name == "" || usedNames[name] {
		name = genName(typePrefix(typ), 1, usedNames)
	}
	usedNames[name] = true
	typeStr, err := printer.PrintType(typ)
	if err != nil {
		return nil, err
	}
	_, variadic := typ.(*ast.Ellipsis)
	p := &Param{
		Name:     name,
		Variadic: variadic,
		Type:     typeStr,
	}
	if fi.Doc != nil && len(fi.Doc.List) > 0 {
		p.Doc = make([]string, 0, len(fi.Doc.List))
		for _, comment := range fi.Doc.List {
			p.Doc = append(p.Doc, comment.Text)
		}
	}
	if fi.Comment != nil && len(fi.Comment.List) > 0 {
		p.Comment = make([]string, 0, len(fi.Comment.List))
		for _, comment := range fi.Comment.List {
			p.Comment = append(p.Comment, comment.Text)
		}
	}
	return p, nil
}
NewParam returns Param struct
package generator
import (
	"fmt"
	"go/ast"
	"strings"
)
type typePrinter interface {
	PrintType(ast.Node) (string, error)
}
type Method struct {
	Doc     []string
	Comment []string
	Name    string
	Params  ParamsSlice
	Results ParamsSlice
	ReturnsError   bool
	AcceptsContext bool
}
type Param struct {
	Doc      []string
	Comment  []string
	Name     string
	Type     string
	Variadic bool
}
type ParamsSlice []Param
func (ps ParamsSlice) String() string {
	ss := []string{}
	for _, p := range ps {
		ss = append(ss, p.Name+" "+p.Type)
	}
	return strings.Join(ss, ", ")
}
func (ps ParamsSlice) Pass() string {
	params := []string{}
	for _, p := range ps {
		params = append(params, p.Pass())
	}
	return strings.Join(params, ", ")
}
func (p Param) Pass() string {
	if p.Variadic {
		return p.Name + "..."
	}
	return p.Name
}
func NewMethod(name string, fi *ast.Field, printer typePrinter) (*Method, error) {
	f, ok := fi.Type.(*ast.FuncType)
	if !ok {
		return nil, fmt.Errorf("%q is not a method", name)
	}
	m := Method{Name: name}
	if fi.Doc != nil && len(fi.Doc.List) > 0 {
		m.Doc = make([]string, 0, len(fi.Doc.List))
		for _, comment := range fi.Doc.List {
			m.Doc = append(m.Doc, comment.Text)
		}
	}
	if fi.Comment != nil && len(fi.Comment.List) > 0 {
		m.Comment = make([]string, 0, len(fi.Comment.List))
		for _, comment := range fi.Comment.List {
			m.Comment = append(m.Comment, comment.Text)
		}
	}
	usedNames := map[string]bool{}
	if f.Results != nil {
		ident, ok := f.Results.List[len(f.Results.List)-1].Type.(*ast.Ident)
		m.ReturnsError = ok && ident.Name == "error"
		usedNames["err"] = true
	}
	if len(f.Params.List) > 0 {
		if se, ok := f.Params.List[0].Type.(*ast.SelectorExpr); ok {
			m.AcceptsContext = ok && se.Sel.Name == "Context"
			usedNames["ctx"] = true
		}
	}
	var err error
	m.Params, err = makeParams(f.Params, usedNames, printer)
	if err != nil {
		return nil, err
	}
	m.Results, err = makeParams(f.Results, usedNames, printer)
	if err != nil {
		return nil, err
	}
	if m.ReturnsError {
		m.Results[len(m.Results)-1].Name = "err"
	}
	if m.AcceptsContext {
		m.Params[0].Name = "ctx"
	}
	return &m, nil
}