// 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() }
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 }
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()) }
func (p *Parser) Qualifier(pkg *types.Package) string { if pkg.Name() == p.Package { return "" } return pkg.Name() }
//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 }
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 }
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 "" }
func (g *objcGen) namePrefixOf(pkg *types.Package) string { p := g.prefix if p == "" { p = "Go" } return p + strings.Title(pkg.Name()) }
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()) } }
// 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() + "." }
func (b *binder) GenObjc(pkg *types.Package, allPkg []*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") gohfile := filepath.Join(outdir, pkg.Name()+".h") conf := &bind.GeneratorConfig{ Fset: b.fset, Pkg: pkg, AllPkg: allPkg, } generate := func(w io.Writer) error { if buildX { printcmd("gobind %s -outdir=%s %s", bindOption, outdir, pkg.Path()) } if buildN { return nil } conf.Writer = w return bind.GenObjc(conf, bindPrefix, bind.ObjcM) } if err := writeFile(mfile, generate); err != nil { return "", err } generate = func(w io.Writer) error { if buildN { return nil } conf.Writer = w return bind.GenObjc(conf, bindPrefix, bind.ObjcH) } if err := writeFile(hfile, generate); err != nil { return "", err } generate = func(w io.Writer) error { if buildN { return nil } conf.Writer = w return bind.GenObjc(conf, bindPrefix, bind.ObjcGoH) } if err := writeFile(gohfile, generate); err != nil { return "", err } return fileBase, nil }
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()) }
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 }
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 }
// 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 } }
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) }
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 }
// 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 }
// 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 }
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 }
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 "" }
func (p *exporter) pkg(pkg *types.Package) { if trace { p.tracef("package { ") defer p.tracef("} ") } if pkg == nil { panic("unexpected nil pkg") } // if the package was seen before, write its index (>= 0) if i, ok := p.pkgIndex[pkg]; ok { p.int(i) return } p.pkgIndex[pkg] = len(p.pkgIndex) // otherwise, write the package tag (< 0) and package data p.int(packageTag) p.string(pkg.Name()) p.string(pkg.Path()) }
func (b *binder) GenJava(pkg *types.Package, outdir string) error { className := strings.Title(pkg.Name()) javaFile := filepath.Join(outdir, className+".java") bindOption := "-lang=java" if bindJavaPkg != "" { bindOption += " -javapkg=" + bindJavaPkg } generate := func(w io.Writer) error { if buildX { printcmd("gobind %s -outdir=%s %s", bindOption, outdir, pkg.Path()) } if buildN { return nil } return bind.GenJava(w, b.fset, pkg, bindJavaPkg) } if err := writeFile(javaFile, generate); err != nil { return err } return nil }
func main() { var fset *token.FileSet var file *ast.File var pkg *types.Package var err error fset = token.NewFileSet() file, err = parser.ParseFile(fset, "greet.go", src, 0) if err != nil { log.Fatal(err) } 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), Selections: make(map[*ast.SelectorExpr]*types.Selection), Scopes: make(map[ast.Node]*types.Scope), InitOrder: make([]*types.Initializer, 0), } var conf types.Config pkg, err = conf.Check("greet", fset, []*ast.File{file}, &info) if err != nil { log.Fatal(err) } fmt.Printf("Package %s sucsessfully parsed\n", pkg.Name()) printTypes(info.Types, fset) printDefs(info.Defs, fset) printUses(info.Uses, fset) printImplicits(info.Implicits, fset) printSelections(info.Selections, fset) printScopes(info.Scopes, fset) printInitOrder(info.InitOrder, fset) }
// ExportData serializes the interface (exported package objects) // of package pkg and returns the corresponding data. The export // format is described elsewhere (TODO). func ExportData(pkg *types.Package) []byte { p := exporter{ data: append([]byte(magic), format()), pkgIndex: make(map[*types.Package]int), typIndex: make(map[types.Type]int), } // populate typIndex with predeclared types for _, t := range predeclared { p.typIndex[t] = len(p.typIndex) } if trace { p.tracef("export %s\n", pkg.Name()) defer p.tracef("\n") } p.string(version) p.pkg(pkg) // collect exported objects from package scope var list []types.Object scope := pkg.Scope() for _, name := range scope.Names() { if exported(name) { list = append(list, scope.Lookup(name)) } } // write objects p.int(len(list)) for _, obj := range list { p.obj(obj) } return p.data }
func (g *javaGen) javaPkgName(pkg *types.Package) string { if g.javaPkg != "" { return g.javaPkg } s := javaNameReplacer.Replace(pkg.Name()) // Look for Java keywords that are not Go keywords, and avoid using // them as a package name. // // This is not a problem for normal Go identifiers as we only expose // exported symbols. The upper case first letter saves everything // from accidentally matching except for the package name. // // Note that basic type names (like int) are not keywords in Go. switch s { case "abstract", "assert", "boolean", "byte", "catch", "char", "class", "do", "double", "enum", "extends", "final", "finally", "float", "implements", "instanceof", "int", "long", "native", "private", "protected", "public", "short", "static", "strictfp", "super", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while": s += "_" } return "go." + s }
func genPkg(p *types.Package, allPkg []*types.Package) { fname := defaultFileName(*lang, p) conf := &bind.GeneratorConfig{ Fset: fset, Pkg: p, AllPkg: allPkg, } switch *lang { case "java": w, closer := writer(fname) conf.Writer = w processErr(bind.GenJava(conf, *javaPkg, bind.Java)) closer() cname := "java_" + p.Name() + ".c" w, closer = writer(cname) conf.Writer = w processErr(bind.GenJava(conf, *javaPkg, bind.JavaC)) closer() hname := p.Name() + ".h" w, closer = writer(hname) conf.Writer = w processErr(bind.GenJava(conf, *javaPkg, bind.JavaH)) closer() case "go": w, closer := writer(fname) conf.Writer = w processErr(bind.GenGo(conf)) closer() case "objc": gohname := p.Name() + ".h" w, closer := writer(gohname) conf.Writer = w processErr(bind.GenObjc(conf, *prefix, bind.ObjcGoH)) closer() hname := fname[:len(fname)-2] + ".h" w, closer = writer(hname) conf.Writer = w processErr(bind.GenObjc(conf, *prefix, bind.ObjcH)) closer() w, closer = writer(fname) conf.Writer = w processErr(bind.GenObjc(conf, *prefix, bind.ObjcM)) closer() default: errorf("unknown target language: %q", *lang) } }
func (b *binder) GenJava(pkg *types.Package, allPkg []*types.Package, outdir, javadir string) error { className := strings.Title(pkg.Name()) javaFile := filepath.Join(javadir, className+".java") cFile := filepath.Join(outdir, "java_"+pkg.Name()+".c") hFile := filepath.Join(outdir, pkg.Name()+".h") bindOption := "-lang=java" if bindJavaPkg != "" { bindOption += " -javapkg=" + bindJavaPkg } conf := &bind.GeneratorConfig{ Fset: b.fset, Pkg: pkg, AllPkg: allPkg, } generate := func(w io.Writer) error { if buildX { printcmd("gobind %s -outdir=%s %s", bindOption, javadir, pkg.Path()) } if buildN { return nil } conf.Writer = w return bind.GenJava(conf, bindJavaPkg, bind.Java) } if err := writeFile(javaFile, generate); err != nil { return err } generate = func(w io.Writer) error { if buildN { return nil } conf.Writer = w return bind.GenJava(conf, bindJavaPkg, bind.JavaC) } if err := writeFile(cFile, generate); err != nil { return err } generate = func(w io.Writer) error { if buildN { return nil } conf.Writer = w return bind.GenJava(conf, bindJavaPkg, bind.JavaH) } return writeFile(hFile, generate) }
// 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 { return pkg.Name() }
func (g Generator) qf(pkg *types.Package) string { if g.pkg == pkg { return "" } return pkg.Name() }