Пример #1
0
func (g *objcGen) namePrefixOf(pkg *types.Package) string {
	p := g.prefix
	if p == "" {
		p = "Go"
	}
	return p + strings.Title(pkg.Name())
}
Пример #2
0
func defaultFileName(lang string, pkg *types.Package) string {
	switch lang {
	case "java":
		if pkg == nil {
			return "Universe.java"
		}
		firstRune, size := utf8.DecodeRuneInString(pkg.Name())
		className := string(unicode.ToUpper(firstRune)) + pkg.Name()[size:]
		return className + ".java"
	case "go":
		if pkg == nil {
			return "go_universe.go"
		}
		return "go_" + pkg.Name() + ".go"
	case "objc":
		if pkg == nil {
			return "GoUniverse.m"
		}
		firstRune, size := utf8.DecodeRuneInString(pkg.Name())
		className := string(unicode.ToUpper(firstRune)) + pkg.Name()[size:]
		return "Go" + className + ".m"
	}
	errorf("unknown target language: %q", lang)
	os.Exit(exitStatus)
	return ""
}
Пример #3
0
func (p *exporter) pkg(pkg *types.Package, emptypath bool) {
	if pkg == nil {
		log.Fatalf("gcimporter: unexpected nil pkg")
	}

	// if we saw the package before, write its index (>= 0)
	if i, ok := p.pkgIndex[pkg]; ok {
		p.index('P', i)
		return
	}

	// otherwise, remember the package, write the package tag (< 0) and package data
	if trace {
		p.tracef("P%d = { ", len(p.pkgIndex))
		defer p.tracef("} ")
	}
	p.pkgIndex[pkg] = len(p.pkgIndex)

	p.tag(packageTag)
	p.string(pkg.Name())
	if emptypath {
		p.string("")
	} else {
		p.string(pkg.Path())
	}
}
Пример #4
0
func (p *Parser) Qualifier(pkg *types.Package) string {
	if pkg.Name() == p.Package {
		return ""
	}

	return pkg.Name()
}
Пример #5
0
// FindQueryMethods locates all methods in the given package (assumed to be
// package database/sql) with a string parameter named "query".
func FindQueryMethods(sql *types.Package, ssa *ssa.Program) []*QueryMethod {
	methods := make([]*QueryMethod, 0)
	scope := sql.Scope()
	for _, name := range scope.Names() {
		o := scope.Lookup(name)
		if !o.Exported() {
			continue
		}
		if _, ok := o.(*types.TypeName); !ok {
			continue
		}
		n := o.Type().(*types.Named)
		for i := 0; i < n.NumMethods(); i++ {
			m := n.Method(i)
			if !m.Exported() {
				continue
			}
			s := m.Type().(*types.Signature)
			if num, ok := FuncHasQuery(s); ok {
				methods = append(methods, &QueryMethod{
					Func:     m,
					SSA:      ssa.FuncValue(m),
					ArgCount: s.Params().Len(),
					Param:    num,
				})
			}
		}
	}
	return methods
}
Пример #6
0
func (b *binder) GenGo(pkg *types.Package, allPkg []*types.Package, outdir string) error {
	pkgName := "go_"
	pkgPath := ""
	if pkg != nil {
		pkgName += pkg.Name()
		pkgPath = pkg.Path()
	}
	goFile := filepath.Join(outdir, pkgName+"main.go")

	generate := func(w io.Writer) error {
		if buildX {
			printcmd("gobind -lang=go -outdir=%s %s", outdir, pkgPath)
		}
		if buildN {
			return nil
		}
		conf := &bind.GeneratorConfig{
			Writer: w,
			Fset:   b.fset,
			Pkg:    pkg,
			AllPkg: allPkg,
		}
		return bind.GenGo(conf)
	}
	if err := writeFile(goFile, generate); err != nil {
		return err
	}
	return nil
}
Пример #7
0
// pkgPrefix returns a prefix that disambiguates symbol names for binding
// multiple packages.
//
// TODO(elias.naur): Avoid (and test) name clashes from multiple packages
// with the same name. Perhaps use the index from the order the package is
// generated.
func pkgPrefix(pkg *types.Package) string {
	// The error type has no package
	if pkg == nil {
		return ""
	}
	return pkg.Name()
}
Пример #8
0
func find(pkg *types.Package, iface string) (*types.Interface, error) {
	scope := pkg.Scope()
	names := scope.Names()
	for _, n := range names {
		obj := scope.Lookup(n)

		tn, ok := obj.(*types.TypeName)
		if !ok {
			continue
		}
		if tn.Name() != iface {
			continue
		}
		if !obj.Exported() {
			return nil, fmt.Errorf("%s should exported", iface)
		}
		t := tn.Type().Underlying()
		i, ok := t.(*types.Interface)
		if !ok {
			return nil, fmt.Errorf("exptected interface, got %s for %s", t, iface)
		}
		return i, nil
	}
	return nil, fmt.Errorf("%s not found in %s", iface, pkg.Name())
}
Пример #9
0
//Collect going through package and collect info
//using conf.Check method. It's using this implementation
//of importer for check all inner packages and go/types/importer.Default()
//to check all built in packages (without sources)
func (_importer *CollectInfoImporter) Collect() (*types.Package, *token.FileSet, error) {
	var conf types.Config
	conf.Importer = _importer
	conf.Error = _importer.errorHandler

	if _importer.packages == nil {
		_importer.packages = make(map[string]*types.Package)
	}

	var pkg *types.Package
	var err error
	var files []string

	if files, err = fs.SourceFiles(_importer.Pkg, false); err != nil {
		return nil, nil, err
	}
	if _importer.fset, _importer.astFiles, err = doParseFiles(files, _importer.fset); err != nil {
		return nil, nil, err
	}

	//XXX: return positive result if check() returns error.
	pkg, _ = conf.Check(_importer.Pkg, _importer.fset, _importer.astFiles, _importer.Info)
	// if pkg, err = conf.Check(_importer.Pkg, _importer.fset, _importer.astFiles, _importer.Info); err != nil {
	// 	return pkg, _importer.fset, err
	// }

	_importer.packages[_importer.Pkg] = pkg
	util.Debug("package [%s] successfully parsed\n", pkg.Name())

	return pkg, _importer.fset, nil
}
Пример #10
0
// pkgName retuns the package name and adds the package to the list of
// imports.
func (g *goGen) pkgName(pkg *types.Package) string {
	// The error type has no package
	if pkg == nil {
		return ""
	}
	g.imports[pkg.Path()] = struct{}{}
	return pkg.Name() + "."
}
Пример #11
0
func getMethods(pkg *types.Package, typename string) map[string]*types.Func {
	r := make(map[string]*types.Func)
	mset := types.NewMethodSet(types.NewPointer(pkg.Scope().Lookup(typename).Type()))
	for i := 0; i < mset.Len(); i++ {
		fn := mset.At(i).Obj().(*types.Func)
		r[fn.Name()] = fn
	}
	return r
}
Пример #12
0
func newBinder(p *types.Package) (*binder, error) {
	if p.Name() == "main" {
		return nil, fmt.Errorf("package %q: can only bind a library package", p.Name())
	}
	b := &binder{
		fset: token.NewFileSet(),
		pkg:  p,
	}
	return b, nil
}
Пример #13
0
func (g *ObjcGen) namePrefixOf(pkg *types.Package) string {
	if pkg == nil {
		return "GoUniverse"
	}
	p := g.Prefix
	if p == "" {
		p = "Go"
	}
	return p + strings.Title(pkg.Name())
}
Пример #14
0
func joinQuery(pkg *types.Package, parent types.Object, obj types.Object, suffix string) string {
	var args []string
	args = append(args, pkg.Name())
	if parent != nil {
		args = append(args, parent.Name())
	}

	args = append(args, nameExported(obj.Name()))
	return strings.Join(args, ".") + suffix
}
Пример #15
0
func pkgFirstElem(p *types.Package) string {
	if p == nil {
		return ""
	}
	path := p.Path()
	idx := strings.Index(path, "/")
	if idx == -1 {
		return ""
	}
	return path[:idx]
}
Пример #16
0
func (c *funcContext) pkgVar(pkg *types.Package) string {
	if pkg == c.p.Pkg {
		return "$pkg"
	}

	pkgVar, found := c.p.pkgVars[pkg.Path()]
	if !found {
		pkgVar = fmt.Sprintf(`$packages["%s"]`, pkg.Path())
	}
	return pkgVar
}
Пример #17
0
// JavaPkgName returns the Java package name for a Go package
// given a pkg prefix. If the prefix is empty, "go" is used
// instead.
func JavaPkgName(pkgPrefix string, pkg *types.Package) string {
	if pkg == nil {
		return "go"
	}
	s := javaNameReplacer(pkg.Name())
	if pkgPrefix != "" {
		return pkgPrefix + "." + s
	} else {
		return "go." + s
	}
}
Пример #18
0
func declTypeName(pkg *types.Package, name string) *types.TypeName {
	scope := pkg.Scope()
	if obj := scope.Lookup(name); obj != nil {
		return obj.(*types.TypeName)
	}
	obj := types.NewTypeName(token.NoPos, pkg, name, nil)
	// a named type may be referred to before the underlying type
	// is known - set it up
	types.NewNamed(obj, nil, nil)
	scope.Insert(obj)
	return obj
}
Пример #19
0
// export emits the exported package features.
func (w *Walker) export(pkg *types.Package) {
	if *verbose {
		log.Println(pkg)
	}
	pop := w.pushScope("pkg " + pkg.Path())
	w.current = pkg
	scope := pkg.Scope()
	for _, name := range scope.Names() {
		if ast.IsExported(name) {
			w.emitObj(scope.Lookup(name))
		}
	}
	pop()
}
Пример #20
0
func (c *converter) convertPackage(v *gotypes.Package) *types.Package {
	if v == nil {
		return nil
	}
	if v, ok := c.converted[v]; ok {
		return v.(*types.Package)
	}

	ret := types.NewPackage(v.Path(), v.Name())
	if c.ret == nil {
		c.ret = ret
	}
	c.converted[v] = ret

	var imports []*types.Package
	for _, imported := range v.Imports() {
		imports = append(imports, c.convertPackage(imported))
	}
	ret.SetImports(imports)

	c.convertScope(ret.Scope(), v.Scope())

	for _, iface := range c.ifaces {
		iface.Complete()
	}

	return ret
}
Пример #21
0
func (r *renamer) checkExport(id *ast.Ident, pkg *types.Package, from types.Object) bool {
	// Reject cross-package references if r.to is unexported.
	// (Such references may be qualified identifiers or field/method
	// selections.)
	if !ast.IsExported(r.to) && pkg != from.Pkg() {
		r.errorf(from.Pos(),
			"renaming this %s %q to %q would make it unexported",
			objectKind(from), from.Name(), r.to)
		r.errorf(id.Pos(), "\tbreaking references from packages such as %q",
			pkg.Path())
		return false
	}
	return true
}
Пример #22
0
// addOwners updates pi.owner from the types in pkg, adding mapping from fields
// of package-level named struct types to the owning named struct type; from
// methods of package-level named interface types to the owning named interface
// type; and from parameters of package-level named function or method types to
// the owning named function or method.
//
// This relation is used to construct signatures for these fields/methods,
// since they may be referenced from another package and thus need
// deterministic names. An object does expose its "owner"; indeed, it may have
// several.
//
// Caveats:
//
// (1) This mapping is deterministic but not necessarily the best one according
// to the original syntax, to which, in general, we do not have access.  In
// these two examples, the type checker considers field X as belonging equally
// to types T and U, even though according the syntax, it belongs primarily to
// T in the first example and U in the second:
//
//      type T struct {X int}
//      type U T
//
//      type T U
//      type U struct {X int}
//
// Similarly:
//
//      type U struct {X int}
//      type V struct {U}
//
// TODO(adonovan): sameer@ points out a useful heuristic: in a case of struct
// or interface embedding, if one struct/interface has fewer fields/methods,
// then it must be the primary one.
//
// (2) This pass is not exhaustive: there remain objects that may be referenced
// from outside the package but for which we can't easily come up with good
// names.  Here are some examples:
//
//      // package p
//      var V1, V2 struct {X int} = ...
//      func F() struct{X int} {...}
//      type T struct {
//              Y struct { X int }
//      }
//
//      // main
//      p.V2.X = 1
//      print(p.F().X)
//      new(p.T).Y[0].X
//
// Also note that there may be arbitrary pointer, struct, chan, map, array, and
// slice type constructors between the type of the exported package member (V2,
// F or T) and the type of its X subelement.  For now, we simply ignore such
// names.  They should be rare in readable code.
func (pi *PackageInfo) addOwners(pkg *types.Package) {
	scope := pkg.Scope()
	for _, name := range scope.Names() {
		switch obj := scope.Lookup(name).(type) {
		case *types.TypeName:
			switch t := obj.Type().Underlying().(type) {
			case *types.Struct:
				// Inspect the fields of a struct.
				for i := 0; i < t.NumFields(); i++ {
					f := t.Field(i)
					if f.Pkg() != pkg {
						continue // wrong package
					}
					if _, ok := pi.owner[f]; !ok {
						pi.owner[f] = obj
					}
				}
			case *types.Interface:
				// Inspect the declared methods of an interface.
				for i := 0; i < t.NumMethods(); i++ {
					m := t.Method(i)
					if m.Pkg() != pkg {
						continue // wrong package
					}
					if _, ok := pi.owner[m]; !ok {
						pi.owner[m] = obj
					}
				}
			}

		case *types.Func:
			// Inspect the receiver, parameters, and result values.
			fsig := obj.Type().(*types.Signature)
			if recv := fsig.Recv(); recv != nil {
				pi.owner[recv] = obj
			}
			if params := fsig.Params(); params != nil {
				for i := 0; i < params.Len(); i++ {
					pi.owner[params.At(i)] = obj
				}
			}
			if res := fsig.Results(); res != nil {
				for i := 0; i < res.Len(); i++ {
					pi.owner[res.At(i)] = obj
				}
			}
		}
	}
}
Пример #23
0
func TestIssue13898(t *testing.T) {
	skipSpecialPlatforms(t)

	// This package only handles gc export data.
	if runtime.Compiler != "gc" {
		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
		return
	}

	// import go/internal/gcimporter which imports go/types partially
	imports := make(map[string]*types.Package)
	_, err := Import(imports, "go/internal/gcimporter", ".")
	if err != nil {
		t.Fatal(err)
	}

	// look for go/types package
	var goTypesPkg *types.Package
	for path, pkg := range imports {
		if path == "go/types" {
			goTypesPkg = pkg
			break
		}
	}
	if goTypesPkg == nil {
		t.Fatal("go/types not found")
	}

	// look for go/types.Object type
	obj := goTypesPkg.Scope().Lookup("Object")
	if obj == nil {
		t.Fatal("go/types.Object not found")
	}
	typ, ok := obj.Type().(*types.Named)
	if !ok {
		t.Fatalf("go/types.Object type is %v; wanted named type", typ)
	}

	// lookup go/types.Object.Pkg method
	m, index, indirect := types.LookupFieldOrMethod(typ, false, nil, "Pkg")
	if m == nil {
		t.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)", index, indirect)
	}

	// the method must belong to go/types
	if m.Pkg().Path() != "go/types" {
		t.Fatalf("found %v; want go/types", m.Pkg())
	}
}
Пример #24
0
func newPackageFrom(bpkg *build.Package, p *types.Package) (*bind.Package, error) {

	var pkgast *ast.Package
	pkgs, err := parser.ParseDir(fset, bpkg.Dir, nil, parser.ParseComments)
	if err != nil {
		return nil, err
	}
	pkgast = pkgs[p.Name()]
	if pkgast == nil {
		return nil, fmt.Errorf("gopy: could not find AST for package %q", p.Name())
	}

	pkgdoc := doc.New(pkgast, bpkg.ImportPath, 0)

	return bind.NewPackage(p, pkgdoc)
}
Пример #25
0
// GenCs generates a C# API from a Go package.
func GenCs(w io.Writer, fset *token.FileSet, pkg *types.Package, namespace string) error {
	if namespace == "" {
		namespace = namespaceName(pkg.Name())
	}
	buf := new(bytes.Buffer)
	g := &csGen{
		printer:   &printer{buf: buf, indentEach: []byte("    ")},
		fset:      fset,
		pkg:       pkg,
		namespace: namespace,
	}
	if err := g.gen(); err != nil {
		return err
	}
	_, err := io.Copy(w, buf)
	return err
}
Пример #26
0
func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) {
	const bindPrefixDefault = "Go"
	if bindPrefix == "" {
		bindPrefix = bindPrefixDefault
	}
	name := strings.Title(pkg.Name())
	bindOption := "-lang=objc"
	if bindPrefix != bindPrefixDefault {
		bindOption += " -prefix=" + bindPrefix
	}

	fileBase := bindPrefix + name
	mfile := filepath.Join(outdir, fileBase+".m")
	hfile := filepath.Join(outdir, fileBase+".h")

	generate := func(w io.Writer) error {
		if buildX {
			printcmd("gobind %s -outdir=%s %s", bindOption, outdir, pkg.Path())
		}
		if buildN {
			return nil
		}
		return bind.GenObjc(w, b.fset, pkg, bindPrefix, false)
	}
	if err := writeFile(mfile, generate); err != nil {
		return "", err
	}
	generate = func(w io.Writer) error {
		if buildN {
			return nil
		}
		return bind.GenObjc(w, b.fset, pkg, bindPrefix, true)
	}
	if err := writeFile(hfile, generate); err != nil {
		return "", err
	}

	objcPkg, err := ctx.Import("golang.org/x/mobile/bind/objc", "", build.FindOnly)
	if err != nil {
		return "", err
	}
	if err := copyFile(filepath.Join(outdir, "seq.h"), filepath.Join(objcPkg.Dir, "seq.h")); err != nil {
		return "", err
	}
	return fileBase, nil
}
Пример #27
0
// GenJava generates a Java API from a Go package.
func GenJava(w io.Writer, fset *token.FileSet, pkg *types.Package, javaPkg string) error {
	if javaPkg == "" {
		javaPkg = javaPkgName(pkg.Name())
	}
	buf := new(bytes.Buffer)
	g := &javaGen{
		printer: &printer{buf: buf, indentEach: []byte("    ")},
		fset:    fset,
		pkg:     pkg,
		javaPkg: javaPkg,
	}
	if err := g.gen(); err != nil {
		return err
	}
	_, err := io.Copy(w, buf)
	return err
}
Пример #28
0
func (b *binder) GenGo(pkg *types.Package, outdir string) error {
	pkgName := "go_" + pkg.Name()
	outdir = filepath.Join(outdir, pkgName)
	goFile := filepath.Join(outdir, pkgName+"main.go")

	generate := func(w io.Writer) error {
		if buildX {
			printcmd("gobind -lang=go -outdir=%s %s", outdir, pkg.Path())
		}
		if buildN {
			return nil
		}
		return bind.GenGo(w, b.fset, pkg)
	}
	if err := writeFile(goFile, generate); err != nil {
		return err
	}
	return nil
}
Пример #29
0
// BuildPackage builds an SSA program with IR for a single package.
//
// It populates pkg by type-checking the specified file ASTs.  All
// dependencies are loaded using the importer specified by tc, which
// typically loads compiler export data; SSA code cannot be built for
// those packages.  BuildPackage then constructs an ssa.Program with all
// dependency packages created, and builds and returns the SSA package
// corresponding to pkg.
//
// The caller must have set pkg.Path() to the import path.
//
// The operation fails if there were any type-checking or import errors.
//
// See ../ssa/example_test.go for an example.
//
func BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) {
	if fset == nil {
		panic("no token.FileSet")
	}
	if pkg.Path() == "" {
		panic("package has no import path")
	}

	info := &types.Info{
		Types:      make(map[ast.Expr]types.TypeAndValue),
		Defs:       make(map[*ast.Ident]types.Object),
		Uses:       make(map[*ast.Ident]types.Object),
		Implicits:  make(map[ast.Node]types.Object),
		Scopes:     make(map[ast.Node]*types.Scope),
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
	}
	if err := types.NewChecker(tc, fset, pkg, info).Files(files); err != nil {
		return nil, nil, err
	}

	prog := ssa.NewProgram(fset, mode)

	// Create SSA packages for all imports.
	// Order is not significant.
	created := make(map[*types.Package]bool)
	var createAll func(pkgs []*types.Package)
	createAll = func(pkgs []*types.Package) {
		for _, p := range pkgs {
			if !created[p] {
				created[p] = true
				prog.CreatePackage(p, nil, nil, true)
				createAll(p.Imports())
			}
		}
	}
	createAll(pkg.Imports())

	// Create and build the primary package.
	ssapkg := prog.CreatePackage(pkg, files, info, false)
	ssapkg.Build()
	return ssapkg, info, nil
}
Пример #30
0
func defaultFileName(lang string, pkg *types.Package) string {
	if *outdir == "" {
		return ""
	}

	switch lang {
	case "java":
		firstRune, size := utf8.DecodeRuneInString(pkg.Name())
		className := string(unicode.ToUpper(firstRune)) + pkg.Name()[size:]
		return filepath.Join(*outdir, className+".java")
	case "go":
		return filepath.Join(*outdir, "go_"+pkg.Name()+".go")
	case "objc":
		firstRune, size := utf8.DecodeRuneInString(pkg.Name())
		className := string(unicode.ToUpper(firstRune)) + pkg.Name()[size:]
		return filepath.Join(*outdir, "Go"+className+".m")
	}
	errorf("unknown target language: %q", lang)
	os.Exit(exitStatus)
	return ""
}