Beispiel #1
0
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()
}
Beispiel #2
0
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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
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 ""
}
Beispiel #5
0
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 ""
}
Beispiel #6
0
//!+
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
}
Beispiel #7
0
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())))
	}
}
Beispiel #8
0
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,
	}
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}
Beispiel #11
0
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
}
Beispiel #12
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)
}
Beispiel #13
0
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)
		}
	}
}
Beispiel #14
0
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)
		}
	}
}
Beispiel #15
0
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
}
Beispiel #16
0
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())
}
Beispiel #17
0
// 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))
}
Beispiel #18
0
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")
}
Beispiel #19
0
func getTypeString(t types.Type) string {
	return types.TypeString(t, func(*types.Package) string { return " " })
}
Beispiel #20
0
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
}
Beispiel #21
0
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)
	}
}
Beispiel #23
0
func (s symbol) gofmt() string {
	return types.TypeString(
		s.GoType(),
		func(*types.Package) string { return s.pkgname() },
	)
}
Beispiel #24
0
func (f Field) UnderlyingTypeName() string {
	return types.TypeString(f.UnderlyingType(), f.gen.qf)
}
Beispiel #25
0
func (f Field) Type() string {
	return types.TypeString(f.v.Type(), f.gen.qf)
}
Beispiel #26
0
func relType(t types.Type, from *types.Package) string {
	return types.TypeString(t, types.RelativeTo(from))
}
Beispiel #27
0
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))
}
Beispiel #28
0
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)
}
Beispiel #29
0
// 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
}