func (g *objcGen) namePrefixOf(pkg *types.Package) string { p := g.prefix if p == "" { p = "Go" } return p + strings.Title(pkg.Name()) }
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 (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()) } }
func (p *Parser) Qualifier(pkg *types.Package) string { if pkg.Name() == p.Package { return "" } return pkg.Name() }
// 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 }
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 }
// 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 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()) }
//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 }
// 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 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 }
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 }
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 pkgFirstElem(p *types.Package) string { if p == nil { return "" } path := p.Path() idx := strings.Index(path, "/") if idx == -1 { return "" } return path[:idx] }
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 }
// 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 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 }
// 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() }
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 (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 }
// 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 } } } } }
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()) } }
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) }
// 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 }
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 }
// 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 }
// 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 }
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 "" }