func formatMember(obj types.Object, maxname int) string { qualifier := types.RelativeTo(obj.Pkg()) var buf bytes.Buffer fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name()) switch obj := obj.(type) { case *types.Const: fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Type(), qualifier), obj.Val().String()) case *types.Func: fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier)) case *types.TypeName: // Abbreviate long aggregate type names. var abbrev string switch t := obj.Type().Underlying().(type) { case *types.Interface: if t.NumMethods() > 1 { abbrev = "interface{...}" } case *types.Struct: if t.NumFields() > 1 { abbrev = "struct{...}" } } if abbrev == "" { fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type().Underlying(), qualifier)) } else { fmt.Fprintf(&buf, " %s", abbrev) } case *types.Var: fmt.Fprintf(&buf, " %s", types.TypeString(obj.Type(), qualifier)) } return buf.String() }
func (f *fn) Params() string { sig := f.TypeInfo.Type().(*types.Signature) params := sig.Params() p := "" comma := "" to := params.Len() var i int if sig.Variadic() { to-- } for i = 0; i < to; i++ { param := params.At(i) name := param.Name() if name == "" { name = fmt.Sprintf("p%d", i) } p += fmt.Sprintf("%s%s %s", comma, name, types.TypeString(param.Type(), f.Qualifier)) comma = ", " } if sig.Variadic() { param := params.At(params.Len() - 1) name := param.Name() if name == "" { name = fmt.Sprintf("p%d", to) } p += fmt.Sprintf("%s%s ...%s", comma, name, types.TypeString(param.Type().(*types.Slice).Elem(), f.Qualifier)) } return p }
// identicalSansNames compares two functions to check if their types are identical // according to the names. e.g. // - It does not care if the names of the parameters or return values differ // - It does not care if the implementations of the types differ func identicalSansNames(fa, fb *types.Func) bool { // must always succeed sigA := fa.Type().(*types.Signature) sigB := fb.Type().(*types.Signature) var ( lenParams = sigA.Params().Len() lenResults = sigA.Results().Len() ) if sigB.Params().Len() != lenParams { return false } if sigB.Results().Len() != lenResults { return false } for i := 0; i < lenParams; i++ { if types.TypeString(sigA.Params().At(i).Type(), nil) != types.TypeString(sigB.Params().At(i).Type(), nil) { return false } } for i := 0; i < lenResults; i++ { if types.TypeString(sigA.Results().At(i).Type(), nil) != types.TypeString(sigB.Results().At(i).Type(), nil) { return false } } return true }
func (g *goGen) typeString(typ types.Type) string { pkg := g.pkg switch t := typ.(type) { case *types.Named: obj := t.Obj() if obj.Pkg() == nil { // e.g. error type is *types.Named. return types.TypeString(typ, types.RelativeTo(pkg)) } if obj.Pkg() != g.pkg { g.errorf("type %s not defined in package %s", t, g.pkg) } switch t.Underlying().(type) { case *types.Interface, *types.Struct: return fmt.Sprintf("%s.%s", pkg.Name(), types.TypeString(typ, types.RelativeTo(pkg))) default: g.errorf("unsupported named type %s / %T", t, t) } case *types.Pointer: switch t := t.Elem().(type) { case *types.Named: return fmt.Sprintf("*%s", g.typeString(t)) default: g.errorf("not yet supported, pointer type %s / %T", t, t) } default: return types.TypeString(typ, types.RelativeTo(pkg)) } return "" }
func (g *goGen) typeString(typ types.Type) string { pkg := g.Pkg switch t := typ.(type) { case *types.Named: obj := t.Obj() if obj.Pkg() == nil { // e.g. error type is *types.Named. return types.TypeString(typ, types.RelativeTo(pkg)) } oPkg := obj.Pkg() if !g.validPkg(oPkg) && !isWrapperType(t) { g.errorf("type %s is defined in %s, which is not bound", t, oPkg) return "TODO" } switch t.Underlying().(type) { case *types.Interface, *types.Struct: return fmt.Sprintf("%s%s", g.pkgName(oPkg), types.TypeString(typ, types.RelativeTo(oPkg))) default: g.errorf("unsupported named type %s / %T", t, t) } case *types.Pointer: switch t := t.Elem().(type) { case *types.Named: return fmt.Sprintf("*%s", g.typeString(t)) default: g.errorf("not yet supported, pointer type %s / %T", t, t) } default: return types.TypeString(typ, types.RelativeTo(pkg)) } return "" }
//!+ func PrintSkeleton(pkg *types.Package, ifacename, concname string) error { obj := pkg.Scope().Lookup(ifacename) if obj == nil { return fmt.Errorf("%s.%s not found", pkg.Path(), ifacename) } if _, ok := obj.(*types.TypeName); !ok { return fmt.Errorf("%v is not a named type", obj) } iface, ok := obj.Type().Underlying().(*types.Interface) if !ok { return fmt.Errorf("type %v is a %T, not an interface", obj, obj.Type().Underlying()) } // Use first letter of type name as receiver parameter. if !isValidIdentifier(concname) { return fmt.Errorf("invalid concrete type name: %q", concname) } r, _ := utf8.DecodeRuneInString(concname) fmt.Printf("// *%s implements %s.%s.\n", concname, pkg.Path(), ifacename) fmt.Printf("type %s struct{}\n", concname) mset := types.NewMethodSet(iface) for i := 0; i < mset.Len(); i++ { meth := mset.At(i).Obj() sig := types.TypeString(meth.Type(), (*types.Package).Name) fmt.Printf("func (%c *%s) %s%s {\n\tpanic(\"unimplemented\")\n}\n", r, concname, meth.Name(), strings.TrimPrefix(sig, "func")) } return nil }
func printFields(printf printfFunc, node ast.Node, fields []describeField) { if len(fields) > 0 { printf(node, "Fields:") } // Align the names and the types (requires two passes). var width int var names []string for _, f := range fields { var buf bytes.Buffer for _, fld := range f.implicits { buf.WriteString(fld.Obj().Name()) buf.WriteByte('.') } buf.WriteString(f.field.Name()) name := buf.String() if n := utf8.RuneCountInString(name); n > width { width = n } names = append(names, name) } for i, f := range fields { // Print the field type relative to the package // in which it was defined, not the query package, printf(f.field, "\t%*s %s", -width, names[i], types.TypeString(f.field.Type(), types.RelativeTo(f.field.Pkg()))) } }
func (b *candidateCollector) asCandidate(obj types.Object) Candidate { objClass := classifyObject(obj) var typ types.Type switch objClass { case "const", "func", "var": typ = obj.Type() case "type": typ = obj.Type().Underlying() } var typStr string switch t := typ.(type) { case *types.Interface: typStr = "interface" case *types.Struct: typStr = "struct" default: if _, isBuiltin := obj.(*types.Builtin); isBuiltin { typStr = builtinTypes[obj.Name()] } else if t != nil { typStr = types.TypeString(t, b.qualify) } } return Candidate{ Class: objClass, Name: obj.Name(), Type: typStr, } }
func (m Method) listTypes(t *types.Tuple) []string { num := t.Len() list := make([]string, num) for i := 0; i < num; i++ { list[i] = types.TypeString(t.At(i).Type(), m.gen.qf) } return list }
func (f *testFunc) Params() string { sig := f.TypeInfo.Type().(*types.Signature) params := sig.Params() p := "" comma := "" to := params.Len() var i int if sig.Variadic() { to-- } for i = 1; i < to; i++ { param := params.At(i) p += fmt.Sprintf("%s%s %s", comma, param.Name(), types.TypeString(param.Type(), f.Qualifier)) comma = ", " } if sig.Variadic() { param := params.At(params.Len() - 1) p += fmt.Sprintf("%s%s ...%s", comma, param.Name(), types.TypeString(param.Type().(*types.Slice).Elem(), f.Qualifier)) } return p }
func (p *Parser) IsTable(typ types.Type) (bool, string, Relationship) { // log.Printf("--> %s %T\n", types.TypeString(typ, p.Qualifier), typ) switch utyp := typ.(type) { case *types.Named: is, table, rel := p.IsTable(utyp.Underlying()) if _, ok := utyp.Underlying().(*types.Pointer); !ok { table = types.TypeString(utyp, p.Qualifier) } return is, table, rel case *types.Pointer: return p.IsTable(utyp.Elem()) case *types.Struct: return true, types.TypeString(utyp, p.Qualifier), RelationshipHasOne case *types.Slice: is, table, _ := p.IsTable(utyp.Elem()) return is, table, RelationshipHasMany case *types.Array: is, table, _ := p.IsTable(utyp.Elem()) return is, table, RelationshipHasMany } return false, "", 0 }
// prettyFunc pretty-prints fn for the user interface. // TODO(adonovan): return HTML so we have more markup freedom. func prettyFunc(this *types.Package, fn *ssa.Function) string { if fn.Parent() != nil { return fmt.Sprintf("%s in %s", types.TypeString(fn.Signature, types.RelativeTo(this)), prettyFunc(this, fn.Parent())) } if fn.Synthetic != "" && fn.Name() == "init" { // (This is the actual initializer, not a declared 'func init'). if fn.Pkg.Pkg == this { return "package initializer" } return fmt.Sprintf("%q package initializer", fn.Pkg.Pkg.Path()) } return fn.RelString(this) }
func (r *freevarsResult) PrintPlain(printf printfFunc) { if len(r.refs) == 0 { printf(r.qpos, "No free identifiers.") } else { printf(r.qpos, "Free identifiers:") qualifier := types.RelativeTo(r.qpos.info.Pkg) for _, ref := range r.refs { // Avoid printing "type T T". var typstr string if ref.kind != "type" && ref.kind != "label" { typstr = " " + types.TypeString(ref.typ, qualifier) } printf(ref.obj, "%s %s%s", ref.kind, ref.ref, typstr) } } }
func TestIntuitiveMethodSet(t *testing.T) { const source = ` package P type A int func (A) f() func (*A) g() ` fset := token.NewFileSet() f, err := parser.ParseFile(fset, "hello.go", source, 0) if err != nil { t.Fatal(err) } var conf types.Config pkg, err := conf.Check("P", fset, []*ast.File{f}, nil) if err != nil { t.Fatal(err) } qual := types.RelativeTo(pkg) for _, test := range []struct { expr string // type expression want string // intuitive method set }{ {"A", "(A).f (*A).g"}, {"*A", "(*A).f (*A).g"}, {"error", "(error).Error"}, {"*error", ""}, {"struct{A}", "(struct{A}).f (*struct{A}).g"}, {"*struct{A}", "(*struct{A}).f (*struct{A}).g"}, } { tv, err := types.Eval(fset, pkg, 0, test.expr) if err != nil { t.Errorf("Eval(%s) failed: %v", test.expr, err) } var names []string for _, m := range typeutil.IntuitiveMethodSet(tv.Type, nil) { name := fmt.Sprintf("(%s).%s", types.TypeString(m.Recv(), qual), m.Obj().Name()) names = append(names, name) } got := strings.Join(names, " ") if got != test.want { t.Errorf("IntuitiveMethodSet(%s) = %q, want %q", test.expr, got, test.want) } } }
func (f *fn) ReturnTypes() string { sig := f.TypeInfo.Type().(*types.Signature) params := sig.Results() p := "" comma := "" to := params.Len() var i int for i = 0; i < to; i++ { param := params.At(i) p += fmt.Sprintf("%s %s", comma, types.TypeString(param.Type(), f.Qualifier)) comma = ", " } if to > 1 { p = fmt.Sprintf("(%s)", p) } return p }
func printResult(res *rta.Result, from *types.Package) string { var buf bytes.Buffer writeSorted := func(ss []string) { sort.Strings(ss) for _, s := range ss { fmt.Fprintf(&buf, " %s\n", s) } } buf.WriteString("Dynamic calls\n") var edges []string callgraph.GraphVisitEdges(res.CallGraph, func(e *callgraph.Edge) error { if strings.Contains(e.Description(), "dynamic") { edges = append(edges, fmt.Sprintf("%s --> %s", e.Caller.Func.RelString(from), e.Callee.Func.RelString(from))) } return nil }) writeSorted(edges) buf.WriteString("Reachable functions\n") var reachable []string for f := range res.Reachable { reachable = append(reachable, f.RelString(from)) } writeSorted(reachable) buf.WriteString("Reflect types\n") var rtypes []string res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) { if value == false { // accessible to reflection rtypes = append(rtypes, types.TypeString(key, types.RelativeTo(from))) } }) writeSorted(rtypes) return strings.TrimSpace(buf.String()) }
// TypeString prints type T relative to the query position. func (qpos *queryPos) typeString(T types.Type) string { return types.TypeString(T, types.RelativeTo(qpos.info.Pkg)) }
func (g *goGen) genFuncBody(f Func) { sig := f.Signature() results := sig.Results() for i := range results { if i > 0 { g.Printf(", ") } g.Printf("_gopy_%03d", i) } if len(results) > 0 { g.Printf(" := ") } g.Printf("%s.%s(", g.pkg.Name(), f.GoName()) args := sig.Params() for i, arg := range args { tail := "" if i+1 < len(args) { tail = ", " } head := arg.Name() if arg.needWrap() { head = fmt.Sprintf( "*(*%s)(unsafe.Pointer(%s))", types.TypeString( arg.GoType(), func(*types.Package) string { return g.pkg.Name() }, ), arg.Name(), ) } g.Printf("%s%s", head, tail) } g.Printf(")\n") if len(results) <= 0 { return } for i, res := range results { if !res.needWrap() { continue } g.Printf("cgopy_incref(unsafe.Pointer(&_gopy_%03d))\n", i) } g.Printf("return ") for i, res := range results { if i > 0 { g.Printf(", ") } // if needWrap(res.GoType()) { // g.Printf("") // } if res.needWrap() { g.Printf("%s(unsafe.Pointer(&", res.sym.cgoname) } g.Printf("_gopy_%03d", i) if res.needWrap() { g.Printf("))") } } g.Printf("\n") }
func getTypeString(t types.Type) string { return types.TypeString(t, func(*types.Package) string { return " " }) }
func (p *Parser) Parse(info types.Info) (err error) { for ident, obj := range info.Defs { if ident.Obj == nil { continue } switch ident.Obj.Kind { case ast.Con: p.Consts[obj.Name()], err = strconv.Unquote(info.Types[ident.Obj.Decl.(*ast.ValueSpec).Values[0]].Value.String()) if err != nil { return } case ast.Typ: struc, ok := obj.Type().Underlying().(*types.Struct) if !ok { continue } var table Table // table.struc = node table.Name = ident.Name table.RefName = strings.ToLower(ident.Name[:1]) table.VarName = strings.ToLower(ident.Name[:1]) + ident.Name[1:] table.ColName = inflect.Pluralize(table.Name) table.ColRefName = inflect.Pluralize(table.RefName) table.ColVarName = inflect.Pluralize(table.VarName) table.SQLName = inflect.Pluralize(toSnake(table.Name)) + TableNameSuffix for i := 0; i < struc.NumFields(); i++ { field := struc.Field(i) flags := strings.Split(reflect.StructTag(struc.Tag(i)).Get("go2sql"), ",") var column Column column.Name = field.Name() column.field = field column.flags = flags column.Table = &table column.parser = p if len(flags) > 0 && flags[0] != "" { if flags[0] == FlagIgnore { continue } column.SQLName = flags[0] } else { column.SQLName = toSnake(column.Name) } _, column.IsPointer = field.Type().(*types.Pointer) if contains(flags, FlagID) { table.IDColumn = &column } if contains(flags, FlagPK) { column.IsPrimaryKey = true table.PrimaryKeys = append(table.PrimaryKeys, &column) } column.Type = types.TypeString(field.Type(), p.Qualifier) column.IsTable, column.TableType, column.Relationship = p.IsTable(field.Type()) if column.IsTable && contains(flags, FlagInline) { column.IsTable = false } table.Columns = append(table.Columns, &column) } p.Tables[table.Name] = &table } } for _, host := range p.Tables { if name, ok := p.Consts[host.Name+TableNameSuffix]; ok { host.HasCustomSQLName = true host.SQLName = name } for _, hostc := range host.Columns { if !hostc.IsTable { continue } guest := p.Tables[hostc.TableType] if guest == nil { log.Printf("can't found struct %s\n", hostc.TableType) continue } hostc.TypeTable = guest if hostc.Relationship == RelationshipHasOne { // reanalyze if it's a valid belongs-to belongsTo := true for _, pk := range guest.PrimaryKeys { // TODO: custome primary key naming belongsTo = belongsTo && host.HasColumn(hostc.Name+pk.Name) } if belongsTo { hostc.Relationship = RelationshipBelongsTo continue } // reanalyze if it's a valid has-one hasOne := true for _, pk := range host.PrimaryKeys { // TODO: custome primary key naming hasOne = hasOne && guest.HasColumn(host.Name+pk.Name) } if !hasOne { hostc.Relationship = RelationshipNone } } else if hostc.Relationship == RelationshipHasMany { hasMany := true for _, pk := range host.PrimaryKeys { // TODO: custome primary key naming hasMany = hasMany && guest.HasColumn(host.Name+pk.Name) } if !hasMany { hostc.Relationship = RelationshipNone continue } many2Many := true for _, pk := range guest.PrimaryKeys { // TODO: custome primary key naming many2Many = many2Many && host.HasColumn(guest.Name+pk.Name) } if many2Many { hostc.Relationship = RelationshipManyToMany } } } } return }
func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]implementsFacts) { qualifier := types.RelativeTo(obj.Pkg()) T := obj.Type().(*types.Named) v := &TypeInfoJSON{ Name: obj.Name(), Size: sizes.Sizeof(T), Align: sizes.Alignof(T), Methods: []anchorJSON{}, // (JS wants non-nil) } // addFact adds the fact "is implemented by T" (by) or // "implements T" (!by) to group. addFact := func(group *implGroupJSON, T types.Type, by bool) { Tobj := deref(T).(*types.Named).Obj() var byKind string if by { // Show underlying kind of implementing type, // e.g. "slice", "array", "struct". s := reflect.TypeOf(T.Underlying()).String() byKind = strings.ToLower(strings.TrimPrefix(s, "*types.")) } group.Facts = append(group.Facts, implFactJSON{ ByKind: byKind, Other: anchorJSON{ Href: a.posURL(Tobj.Pos(), len(Tobj.Name())), Text: types.TypeString(T, qualifier), }, }) } // IMPLEMENTS if r, ok := implements[T]; ok { if isInterface(T) { // "T is implemented by <conc>" ... // "T is implemented by <iface>"... // "T implements <iface>"... group := implGroupJSON{ Descr: types.TypeString(T, qualifier), } // Show concrete types first; use two passes. for _, sub := range r.to { if !isInterface(sub) { addFact(&group, sub, true) } } for _, sub := range r.to { if isInterface(sub) { addFact(&group, sub, true) } } for _, super := range r.from { addFact(&group, super, false) } v.ImplGroups = append(v.ImplGroups, group) } else { // T is concrete. if r.from != nil { // "T implements <iface>"... group := implGroupJSON{ Descr: types.TypeString(T, qualifier), } for _, super := range r.from { addFact(&group, super, false) } v.ImplGroups = append(v.ImplGroups, group) } if r.fromPtr != nil { // "*C implements <iface>"... group := implGroupJSON{ Descr: "*" + types.TypeString(T, qualifier), } for _, psuper := range r.fromPtr { addFact(&group, psuper, false) } v.ImplGroups = append(v.ImplGroups, group) } } } // METHOD SETS for _, sel := range typeutil.IntuitiveMethodSet(T, &a.prog.MethodSets) { meth := sel.Obj().(*types.Func) pos := meth.Pos() // may be 0 for error.Error v.Methods = append(v.Methods, anchorJSON{ Href: a.posURL(pos, len(meth.Name())), Text: types.SelectionString(sel, qualifier), }) } // Since there can be many specs per decl, we // can't attach the link to the keyword 'type' // (as we do with 'func'); we use the Ident. fi, offset := a.fileAndOffset(obj.Pos()) fi.addLink(aLink{ start: offset, end: offset + len(obj.Name()), title: fmt.Sprintf("type info for %s", obj.Name()), onclick: fmt.Sprintf("onClickTypeInfo(%d)", fi.addData(v)), }) // Add info for exported package-level types to the package info. if obj.Exported() && isPackageLevel(obj) { // TODO(adonovan): Path is not unique! // It is possible to declare a non-test package called x_test. a.result.pkgInfo(obj.Pkg().Path()).addType(v) } }
func main() { RPCDir := findRPCDir() fset, pkg, info, clientAst := parseFiles(RPCDir) serverMethods := getMethods(pkg, "RPCServer") _ = serverMethods errcount := 0 for _, decl := range clientAst.Decls { fndecl := publicMethodOf(decl, "RPCClient") if fndecl == nil { continue } if fndecl.Name.Name == "Continue" { // complex function, skip check continue } callx := findCallCall(fndecl) if callx == nil { log.Printf("%s: could not find RPC call", fset.Position(fndecl.Pos())) errcount++ continue } if len(callx.Args) != 3 { log.Printf("%s: wrong number of arguments for RPC call", fset.Position(callx.Pos())) errcount++ continue } arg0, arg0islit := callx.Args[0].(*ast.BasicLit) arg1 := callx.Args[1] arg2 := callx.Args[2] if !arg0islit || arg0.Kind != token.STRING { continue } name, _ := strconv.Unquote(arg0.Value) serverMethod := serverMethods[name] if serverMethod == nil { log.Printf("%s: could not find RPC method %q", fset.Position(callx.Pos()), name) errcount++ continue } params := serverMethod.Type().(*types.Signature).Params() if a, e := info.TypeOf(arg1), params.At(0).Type(); !types.AssignableTo(a, e) { log.Printf("%s: wrong type of first argument %s, expected %s", fset.Position(callx.Pos()), types.TypeString(a, qf), types.TypeString(e, qf)) errcount++ continue } if a, e := info.TypeOf(arg2), params.At(1).Type(); !types.AssignableTo(a, e) { log.Printf("%s: wrong type of second argument %s, expected %s", fset.Position(callx.Pos()), types.TypeString(a, qf), types.TypeString(e, qf)) errcount++ continue } if c**t, ok := arg1.(*ast.CompositeLit); ok { typ := params.At(0).Type() st := typ.Underlying().(*types.Struct) if len(c**t.Elts) != st.NumFields() && types.TypeString(typ, qf) != "DebuggerCommand" { log.Printf("%s: wrong number of fields in first argument's literal %d, expected %d", fset.Position(callx.Pos()), len(c**t.Elts), st.NumFields()) errcount++ continue } } } if errcount > 0 { log.Printf("%d errors", errcount) os.Exit(1) } }
func (s symbol) gofmt() string { return types.TypeString( s.GoType(), func(*types.Package) string { return s.pkgname() }, ) }
func (f Field) UnderlyingTypeName() string { return types.TypeString(f.UnderlyingType(), f.gen.qf) }
func (f Field) Type() string { return types.TypeString(f.v.Type(), f.gen.qf) }
func relType(t types.Type, from *types.Package) string { return types.TypeString(t, types.RelativeTo(from)) }
func (sym *symtab) typename(t types.Type, pkg *types.Package) string { if pkg == nil { return types.TypeString(t, nil) } return types.TypeString(t, types.RelativeTo(pkg)) }
func main() { flag.Parse() exitStatus := 0 importPaths := gotool.ImportPaths(flag.Args()) if len(importPaths) == 0 { importPaths = []string{"."} } ctx := build.Default for _, pkgPath := range importPaths { visitor := &visitor{ m: make(map[types.Type]map[string]int), skip: make(map[types.Type]struct{}), } loadcfg := loader.Config{ Build: &ctx, } rest, err := loadcfg.FromArgs([]string{pkgPath}, *loadTestFiles) if err != nil { fmt.Fprintf(os.Stderr, "could not parse arguments: %s", err) continue } if len(rest) > 0 { fmt.Fprintf(os.Stderr, "unhandled extra arguments: %v", rest) continue } program, err := loadcfg.Load() if err != nil { fmt.Fprintf(os.Stderr, "could not type check: %s", err) continue } pkg := program.InitialPackages()[0] visitor.prog = program visitor.pkg = pkg for _, f := range pkg.Files { ast.Walk(visitor, f) } for t := range visitor.m { if _, skip := visitor.skip[t]; skip { continue } for fieldName, v := range visitor.m[t] { if !*reportExported && ast.IsExported(fieldName) { continue } if v == 0 { field, _, _ := types.LookupFieldOrMethod(t, false, pkg.Pkg, fieldName) if fieldName == "XMLName" { if named, ok := field.Type().(*types.Named); ok && named.Obj().Pkg().Path() == "encoding/xml" { continue } } pos := program.Fset.Position(field.Pos()) fmt.Printf("%s: %s:%d:%d: %s.%s\n", pkgPath, pos.Filename, pos.Line, pos.Column, types.TypeString(t, nil), fieldName, ) exitStatus = 1 } } } } os.Exit(exitStatus) }
// t is a tuple for representing parameters or return values of function. func (g *generator) parse(name string, t *types.Tuple) *args { ps := toList(t) var fields []*types.Var var tags []string imports := map[types.Object]*ast.SelectorExpr{} un := uniqueNames{} m := &args{} for _, p := range ps { n := p.Name() if n == "" { n = p.Type().String() if !validIdentifier(n) { n = "p" } } n = un.get(capitalize(n)) t := types.NewField(0, g.pkg, n, p.Type(), false) // Filter out context and error. switch p.Type().String() { case "golang.org/x/net/context.Context": ctxName := un.get("ctx") m.Args = append(m.Args, func(string) string { return ctxName }) m.CtxName = ctxName m.HasCtx = true m.Args2 = append(m.Args2, struct{ Name, Type string }{ctxName, types.TypeString(t.Type(), relativeTo(g.pkg))}) continue case "error": errName := un.get("err") m.Args = append(m.Args, func(string) string { return errName }) m.ErrName = errName m.HasErr = true m.Args2 = append(m.Args2, struct{ Name, Type string }{errName, types.TypeString(t.Type(), relativeTo(g.pkg))}) continue } m.Args2 = append(m.Args2, struct{ Name, Type string }{uncapitalize(n), types.TypeString(t.Type(), relativeTo(g.pkg))}) updateDeps(g.rev[p.Type()], g.info, imports) // Make sure all the names are unique. m.Args = append(m.Args, func(s string) string { return fmt.Sprintf("%s.%s", s, n) }) fields = append(fields, t) tags = append(tags, fmt.Sprintf(`json:"%s"`, toSnake(n))) } if !m.HasCtx { m.CtxName = un.get("ctx") } if !m.HasErr { m.ErrName = un.get("err") } imps := cleanImports(imports) m.StructDef = structDef{ Pkg: g.pkg.Name(), Imports: imps, Name: name, } for i, v := range fields { m.StructDef.Fields = append(m.StructDef.Fields, struct { Name string Tag string Type string }{ Name: v.Name(), Type: types.TypeString(v.Type(), relativeTo(g.pkg)), Tag: tags[i], }) } return m }