Example #1
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 ""
}
Example #2
0
func formatMember(obj types.Object, maxname int) string {
	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.Pkg(), obj.Type()), obj.Val().String())

	case *types.Func:
		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type()))

	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.Pkg(), obj.Type().Underlying()))
		} else {
			fmt.Fprintf(&buf, " %s", abbrev)
		}

	case *types.Var:
		fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type()))
	}
	return buf.String()
}
Example #3
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
}
Example #4
0
func TestDemo(ot *testing.T) {
	importPath := "github.com/bronze1man/kmg/kmgGoSource"
	kmgCmd.MustRun("kmg go test -i " + importPath)
	pkgDir := kmgConfig.DefaultEnv().MustGetPathFromImportPath(importPath)
	fset := token.NewFileSet()
	astPkgMap, err := parser.ParseDir(fset, pkgDir, nil, 0)
	if err != nil {
		panic(err)
	}
	astPkg := astPkgMap["kmgGoSource_test"]
	astFileList := []*ast.File{}
	for _, file := range astPkg.Files {
		astFileList = append(astFileList, file)
	}
	//os.Chdir(kmgConfig.DefaultEnv().ProjectPath)
	pkg, err := types.Check(pkgDir, fset, astFileList)
	if err != nil {
		panic(err)
	}
	funcA := pkg.Scope().Lookup("FuncA")
	recvPkg := types.NewPackage("github.com/bronze1man/kmg/kmgGoSource", "kmgGoSource")
	kmgDebug.Println(types.TypeString(recvPkg, funcA.Type()))
	funTypParams := funcA.Type().(*types.Signature).Params()
	for i := 0; i < funTypParams.Len(); i++ {
		kmgDebug.Println(funTypParams.At(i).Name())
		kmgDebug.Println(funTypParams.At(i).Type().String())
	}
	//for _,p:=range funcA.Type().(*types.Signature).Params().
	//kmgDebug.Println(funcA.Type().(*types.Signature).Params().String())
}
Example #5
0
func main() {
	flag.Parse()
	exitStatus := 0
	importPaths := gotool.ImportPaths(flag.Args())
	if len(importPaths) == 0 {
		importPaths = []string{"."}
	}
	for _, pkgPath := range importPaths {
		visitor := &visitor{
			info: types.Info{
				Types:      make(map[ast.Expr]types.TypeAndValue),
				Defs:       make(map[*ast.Ident]types.Object),
				Selections: make(map[*ast.SelectorExpr]*types.Selection),
			},

			m:    make(map[types.Type]map[string]int),
			skip: make(map[types.Type]struct{}),
		}
		fset, astFiles := check.ASTFilesForPackage(pkgPath, *loadTestFiles)
		imp := importer.New()
		// Preliminary cgo support.
		imp.Config = importer.Config{UseGcFallback: true}
		config := types.Config{Import: imp.Import}
		var err error
		visitor.pkg, err = config.Check(pkgPath, fset, astFiles, &visitor.info)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s: %v\n", pkgPath, err)
			continue
		}
		for _, f := range astFiles {
			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, visitor.pkg, fieldName)
					if fieldName == "XMLName" {
						if named, ok := field.Type().(*types.Named); ok && named.Obj().Pkg().Path() == "encoding/xml" {
							continue
						}
					}
					pos := 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)
}
Example #6
0
func typeString(ty types.Type, pkg *types.Package) string {
	ret := types.TypeString(ty, types.RelativeTo(pkg))
	parts := strings.Split(ret, "/")
	prefix := ""
	if len(parts) > 1 {
		for _, r := range parts[0] {
			if r == '.' || unicode.IsLetter(r) {
				break
			}
			prefix += string(r)
		}
	}
	return prefix + parts[len(parts)-1]
}
Example #7
0
func (r *freevarsResult) display(printf printfFunc) {
	if len(r.refs) == 0 {
		printf(r.qpos, "No free identifiers.")
	} else {
		printf(r.qpos, "Free identifiers:")
		for _, ref := range r.refs {
			// Avoid printing "type T T".
			var typstr string
			if ref.kind != "type" {
				typstr = " " + types.TypeString(r.qpos.info.Pkg, ref.typ)
			}
			printf(ref.obj, "%s %s%s", ref.kind, ref.ref, typstr)
		}
	}
}
Example #8
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)
}
Example #9
0
// typeStr returns the type string to be used when using the
// given type. It adds any needed import paths to the given
// imports map (map from package path to package id).
func typeStr(t types.Type, imports map[string]string) string {
	if t == nil {
		return ""
	}
	qualify := func(pkg *types.Package) string {
		if name := imports[pkg.Path()]; name != "" {
			return name
		}
		name := pkg.Name()
		// Make sure we're not duplicating the name.
		// TODO if we are, make a new non-duplicated version.
		for oldPkg, oldName := range imports {
			if oldName == name {
				panic(errgo.Newf("duplicate package name %s vs %s", pkg.Path(), oldPkg))
			}
		}
		imports[pkg.Path()] = name
		return name
	}
	return types.TypeString(t, qualify)
}
Example #10
0
func loadStoreSuffix(T types.Type, hasParameters bool) string {
	if bt, ok := T.Underlying().(*types.Basic); ok {
		switch bt.Kind() {
		case types.Bool,
			types.Int8,
			types.Int16,
			types.Int64,
			types.Uint16,
			types.Uint64,
			types.Uintptr,
			types.Float32,
			types.Float64,
			types.Complex64,
			types.Complex128,
			types.String:
			return "_" + types.TypeString(T, nil /* TODO should be?: (*types.Package).Name*/) + "("
		case types.Uint8: // to avoid "byte"
			return "_uint8("
		case types.Int, types.Int32: // for int and to avoid "rune"
			return "_int32("
		case types.Uint, types.Uint32:
			return "_uint32("
		}
	}
	if _, ok := T.Underlying().(*types.Array); ok {
		ret := fmt.Sprintf("_object(%d", haxeStdSizes.Sizeof(T))
		if hasParameters {
			ret += ","
		}
		return ret
	}
	if _, ok := T.Underlying().(*types.Struct); ok {
		ret := fmt.Sprintf("_object(%d", haxeStdSizes.Sizeof(T))
		if hasParameters {
			ret += ","
		}
		return ret
	}
	return "(" // no suffix, so some dynamic type
}
Example #11
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(from, key))
		}
	})
	writeSorted(rtypes)

	return strings.TrimSpace(buf.String())
}
Example #12
0
func relType(t types.Type, from *types.Package) string {
	return types.TypeString(t, types.RelativeTo(from))
}
Example #13
0
File: debug.go Project: hinike/llgo
// DIType maps a Go type to DIType debug metadata value.
func (d *DIBuilder) DIType(t types.Type) llvm.Value {
	return d.typeDebugDescriptor(t, types.TypeString(nil, t))
}
Example #14
0
// TypeString prints type T relative to the query position.
func (qpos *QueryPos) TypeString(T types.Type) string {
	return types.TypeString(qpos.info.Pkg, T)
}
Example #15
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)
	}
}
Example #16
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))
}
Example #17
0
func (s symbol) gofmt() string {
	return types.TypeString(
		s.GoType(),
		func(*types.Package) string { return s.pkgname() },
	)
}
Example #18
0
func relType(t types.Type, from *types.Package) string {
	return types.TypeString(from, t)
}
Example #19
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)
}
Example #20
0
File: gengo.go Project: vkolev/gopy
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")
}
Example #21
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))
}
Example #22
0
func getTypeString(t types.Type) string {
	return types.TypeString(t, func(*types.Package) string { return " " })
}