Ejemplo n.º 1
0
func (w *PkgWalker) LookupStructFromField(info *types.Info, cursorPkg *types.Package, cursorObj types.Object, cursorPos token.Pos) types.Object {
	if info == nil {
		conf := &PkgConfig{
			IgnoreFuncBodies: true,
			AllowBinary:      true,
			Info: &types.Info{
				Defs: make(map[*ast.Ident]types.Object),
			},
		}
		w.imported[cursorPkg.Path()] = nil
		pkg, _ := w.Import("", cursorPkg.Path(), conf)
		if pkg != nil {
			info = conf.Info
		}
	}
	for _, obj := range info.Defs {
		if obj == nil {
			continue
		}
		if _, ok := obj.(*types.TypeName); ok {
			if t, ok := obj.Type().Underlying().(*types.Struct); ok {
				for i := 0; i < t.NumFields(); i++ {
					if t.Field(i).Pos() == cursorPos {
						return obj
					}
				}
			}
		}
	}
	return nil
}
Ejemplo n.º 2
0
func (e *exporter) addImport(pkg *types.Package) {
	if _, found := e.imports[pkg]; found {
		return
	}
	fmt.Fprintf(e.out, "import %s \"%s\"\n", pkg.Name(), pkg.Path())
	e.imports[pkg] = true
}
Ejemplo n.º 3
0
Archivo: exports.go Proyecto: pcc/llgo
func (x *exporter) export(pkg *types.Package) error {
	x.pkg = pkg
	x.writeFunc = true
	exportsFile := packageExportsFile(x.context, pkg.Path())
	err := os.MkdirAll(filepath.Dir(exportsFile), 0755)
	if err != nil && !os.IsExist(err) {
		return err
	}
	f2, err := os.Create(exportsFile)
	if err != nil {
		return err
	}
	defer f2.Close()
	x.writer = f2
	x.write("package %s\n", pkg.Name())
	for _, imp := range pkg.Imports() {
		x.write("\timport %s \"%s\"\n", imp.Name(), imp.Path())
	}
	for _, n := range pkg.Scope().Names() {
		if obj := pkg.Scope().Lookup(n); obj != nil {
			x.exportObject(obj)
		}
	}
	x.write("$$")
	return nil
}
Ejemplo n.º 4
0
// pkgpath returns a package path suitable for naming symbols.
func pkgpath(p *types.Package) string {
	path := p.Path()
	name := p.Name()
	if path == "" || name == "main" {
		path = p.Name()
	}
	return path
}
Ejemplo n.º 5
0
// Export generates a file containing package export data
// suitable for importing with Importer.Import.
func Export(ctx *build.Context, pkg *types.Package) error {
	exportsPath := packageExportsFile(ctx, pkg.Path())
	err := os.MkdirAll(filepath.Dir(exportsPath), 0755)
	if err != nil && !os.IsExist(err) {
		return err
	}
	tracef("Writing import data to %q", exportsPath)
	return ioutil.WriteFile(exportsPath, importer.ExportData(pkg), 0644)
}
Ejemplo n.º 6
0
func describePackage(o *Oracle, qpos *QueryPos, path []ast.Node) (*describePackageResult, error) {
	var description string
	var pkg *types.Package
	switch n := path[0].(type) {
	case *ast.ImportSpec:
		var pkgname *types.PkgName
		if n.Name != nil {
			pkgname = qpos.info.Defs[n.Name].(*types.PkgName)
		} else if p := qpos.info.Implicits[n]; p != nil {
			pkgname = p.(*types.PkgName)
		}
		description = fmt.Sprintf("import of package %q", pkgname.Pkg().Path())
		pkg = pkgname.Pkg()

	case *ast.Ident:
		if _, isDef := path[1].(*ast.File); isDef {
			// e.g. package id
			pkg = qpos.info.Pkg
			description = fmt.Sprintf("definition of package %q", pkg.Path())
		} else {
			// e.g. import id "..."
			//  or  id.F()
			pkg = qpos.info.ObjectOf(n).Pkg()
			description = fmt.Sprintf("reference to package %q", pkg.Path())
		}

	default:
		// Unreachable?
		return nil, fmt.Errorf("unexpected AST for package: %T", n)
	}

	var members []*describeMember
	// NB: "unsafe" has no types.Package
	if pkg != nil {
		// Enumerate the accessible package members
		// in lexicographic order.
		for _, name := range pkg.Scope().Names() {
			if pkg == qpos.info.Pkg || ast.IsExported(name) {
				mem := pkg.Scope().Lookup(name)
				var methods []*types.Selection
				if mem, ok := mem.(*types.TypeName); ok {
					methods = accessibleMethods(mem.Type(), qpos.info.Pkg)
				}
				members = append(members, &describeMember{
					mem,
					methods,
				})

			}
		}
	}

	return &describePackageResult{o.fset, path[0], description, pkg, members}, nil
}
Ejemplo n.º 7
0
func typePackageToJson(p *types.Package) interface{} {
	if p == nil {
		return nil
	} else {
		return struct {
			Isa, Name, ImportPath string
		}{
			"Package", p.Name(), p.Path(),
		}
	}
}
Ejemplo n.º 8
0
func describePackage(o *Oracle, qpos *QueryPos, path []ast.Node) (*describePackageResult, error) {
	var description string
	var pkg *types.Package
	switch n := path[0].(type) {
	case *ast.ImportSpec:
		// Most ImportSpecs have no .Name Ident so we can't
		// use ObjectOf.
		// We could use the types.Info.Implicits mechanism,
		// but it's easier just to look it up by name.
		description = "import of package " + n.Path.Value
		importPath, _ := strconv.Unquote(n.Path.Value)
		pkg = o.prog.ImportedPackage(importPath).Object

	case *ast.Ident:
		if _, isDef := path[1].(*ast.File); isDef {
			// e.g. package id
			pkg = qpos.info.Pkg
			description = fmt.Sprintf("definition of package %q", pkg.Path())
		} else {
			// e.g. import id
			//  or  id.F()
			pkg = qpos.info.ObjectOf(n).Pkg()
			description = fmt.Sprintf("reference to package %q", pkg.Path())
		}

	default:
		// Unreachable?
		return nil, fmt.Errorf("unexpected AST for package: %T", n)
	}

	var members []*describeMember
	// NB: "unsafe" has no types.Package
	if pkg != nil {
		// Enumerate the accessible package members
		// in lexicographic order.
		for _, name := range pkg.Scope().Names() {
			if pkg == qpos.info.Pkg || ast.IsExported(name) {
				mem := pkg.Scope().Lookup(name)
				var methods []*types.Selection
				if mem, ok := mem.(*types.TypeName); ok {
					methods = accessibleMethods(mem.Type(), qpos.info.Pkg)
				}
				members = append(members, &describeMember{
					mem,
					methods,
				})

			}
		}
	}

	return &describePackageResult{o.prog.Fset, path[0], description, pkg, members}, nil
}
Ejemplo n.º 9
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
}
Ejemplo n.º 10
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()
}
Ejemplo n.º 11
0
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())
}
Ejemplo n.º 12
0
func (c *exporter) Export(pkg *types.Package) error {
	c.pkg = pkg
	c.writeFunc = true
	f2, err := os.Create(c.compiler.packageExportsFile(pkg.Path()))
	if err != nil {
		return err
	}
	defer f2.Close()
	c.writer = f2
	c.write("package %s\n", pkg.Name())
	for _, imp := range c.pkg.Imports() {
		c.write("\timport %s \"%s\"\n", imp.Name(), imp.Path())
	}

	for _, n := range pkg.Scope().Names() {
		if obj := pkg.Scope().Lookup(n); obj != nil {
			c.exportObject(obj)
		}
	}

	c.write("$$")
	return nil
}
Ejemplo n.º 13
0
func isJsPackage(pkg *types.Package) bool {
	return pkg != nil && pkg.Path() == "github.com/gopherjs/gopherjs/js"
}
Ejemplo n.º 14
0
func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) bool) {
	// collect objects by kind
	var (
		consts   []*types.Const
		typem    []*types.Named    // non-interface types with methods
		typez    []*types.TypeName // interfaces or types without methods
		vars     []*types.Var
		funcs    []*types.Func
		builtins []*types.Builtin
		methods  = make(map[*types.Named][]*types.Selection) // method sets for named types
	)
	scope := pkg.Scope()
	for _, name := range scope.Names() {
		obj := scope.Lookup(name)
		if obj.Exported() {
			// collect top-level exported and possibly filtered objects
			if filter == nil || filter(obj) {
				switch obj := obj.(type) {
				case *types.Const:
					consts = append(consts, obj)
				case *types.TypeName:
					// group into types with methods and types without
					if named, m := methodsFor(obj); named != nil {
						typem = append(typem, named)
						methods[named] = m
					} else {
						typez = append(typez, obj)
					}
				case *types.Var:
					vars = append(vars, obj)
				case *types.Func:
					funcs = append(funcs, obj)
				case *types.Builtin:
					// for unsafe.Sizeof, etc.
					builtins = append(builtins, obj)
				}
			}
		} else if filter == nil {
			// no filtering: collect top-level unexported types with methods
			if obj, _ := obj.(*types.TypeName); obj != nil {
				// see case *types.TypeName above
				if named, m := methodsFor(obj); named != nil {
					typem = append(typem, named)
					methods[named] = m
				}
			}
		}
	}

	p.printf("package %s  // %q\n", pkg.Name(), pkg.Path())

	p.printDecl("const", len(consts), func() {
		for _, obj := range consts {
			p.printObj(obj)
			p.print("\n")
		}
	})

	p.printDecl("var", len(vars), func() {
		for _, obj := range vars {
			p.printObj(obj)
			p.print("\n")
		}
	})

	p.printDecl("type", len(typez), func() {
		for _, obj := range typez {
			p.printf("%s ", obj.Name())
			p.writeType(p.pkg, obj.Type().Underlying())
			p.print("\n")
		}
	})

	// non-interface types with methods
	for _, named := range typem {
		first := true
		if obj := named.Obj(); obj.Exported() {
			if first {
				p.print("\n")
				first = false
			}
			p.printf("type %s ", obj.Name())
			p.writeType(p.pkg, named.Underlying())
			p.print("\n")
		}
		for _, m := range methods[named] {
			if obj := m.Obj(); obj.Exported() {
				if first {
					p.print("\n")
					first = false
				}
				p.printFunc(m.Recv(), obj.(*types.Func))
				p.print("\n")
			}
		}
	}

	if len(funcs) > 0 {
		p.print("\n")
		for _, obj := range funcs {
			p.printFunc(nil, obj)
			p.print("\n")
		}
	}

	// TODO(gri) better handling of builtins (package unsafe only)
	if len(builtins) > 0 {
		p.print("\n")
		for _, obj := range builtins {
			p.printf("func %s() // builtin\n", obj.Name())
		}
	}

	p.print("\n")
}
Ejemplo n.º 15
0
// Transform applies the transformation to the specified parsed file,
// whose type information is supplied in info, and returns the number
// of replacements that were made.
//
// It mutates the AST in place (the identity of the root node is
// unchanged), and may add nodes for which no type information is
// available in info.
//
// Derived from rewriteFile in $GOROOT/src/cmd/gofmt/rewrite.go.
//
func (tr *Transformer) Transform(info *types.Info, pkg *types.Package, file *ast.File) int {
	if !tr.seenInfos[info] {
		tr.seenInfos[info] = true
		mergeTypeInfo(&tr.info.Info, info)
	}
	tr.currentPkg = pkg
	tr.nsubsts = 0

	if tr.verbose {
		fmt.Fprintf(os.Stderr, "before: %s\n", astString(tr.fset, tr.before))
		fmt.Fprintf(os.Stderr, "after: %s\n", astString(tr.fset, tr.after))
	}

	var f func(rv reflect.Value) reflect.Value
	f = func(rv reflect.Value) reflect.Value {
		// don't bother if val is invalid to start with
		if !rv.IsValid() {
			return reflect.Value{}
		}

		rv = apply(f, rv)

		e := rvToExpr(rv)
		if e != nil {
			savedEnv := tr.env
			tr.env = make(map[string]ast.Expr) // inefficient!  Use a slice of k/v pairs

			if tr.matchExpr(tr.before, e) {
				if tr.verbose {
					fmt.Fprintf(os.Stderr, "%s matches %s",
						astString(tr.fset, tr.before), astString(tr.fset, e))
					if len(tr.env) > 0 {
						fmt.Fprintf(os.Stderr, " with:")
						for name, ast := range tr.env {
							fmt.Fprintf(os.Stderr, " %s->%s",
								name, astString(tr.fset, ast))
						}
					}
					fmt.Fprintf(os.Stderr, "\n")
				}
				tr.nsubsts++

				// Clone the replacement tree, performing parameter substitution.
				// We update all positions to n.Pos() to aid comment placement.
				rv = tr.subst(tr.env, reflect.ValueOf(tr.after),
					reflect.ValueOf(e.Pos()))
			}
			tr.env = savedEnv
		}

		return rv
	}
	file2 := apply(f, reflect.ValueOf(file)).Interface().(*ast.File)

	// By construction, the root node is unchanged.
	if file != file2 {
		panic("BUG")
	}

	// Add any necessary imports.
	// TODO(adonovan): remove no-longer needed imports too.
	if tr.nsubsts > 0 {
		pkgs := make(map[string]*types.Package)
		for obj := range tr.importedObjs {
			pkgs[obj.Pkg().Path()] = obj.Pkg()
		}

		for _, imp := range file.Imports {
			path, _ := strconv.Unquote(imp.Path.Value)
			delete(pkgs, path)
		}
		delete(pkgs, pkg.Path()) // don't import self

		// NB: AddImport may completely replace the AST!
		// It thus renders info and tr.info no longer relevant to file.
		var paths []string
		for path := range pkgs {
			paths = append(paths, path)
		}
		sort.Strings(paths)
		for _, path := range paths {
			astutil.AddImport(tr.fset, file, path)
		}
	}

	tr.currentPkg = nil

	return tr.nsubsts
}
Ejemplo n.º 16
0
func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) bool) {
	// collect objects by kind
	var (
		consts   []*types.Const
		typez    []*types.TypeName // types without methods
		typem    []*types.TypeName // types with methods
		vars     []*types.Var
		funcs    []*types.Func
		builtins []*types.Builtin
	)
	scope := pkg.Scope()
	for _, name := range scope.Names() {
		obj := scope.Lookup(name)
		if !filter(obj) {
			continue
		}
		switch obj := obj.(type) {
		case *types.Const:
			consts = append(consts, obj)
		case *types.TypeName:
			if named, _ := obj.Type().(*types.Named); named != nil && named.NumMethods() > 0 {
				typem = append(typem, obj)
			} else {
				typez = append(typez, obj)
			}
		case *types.Var:
			vars = append(vars, obj)
		case *types.Func:
			funcs = append(funcs, obj)
		case *types.Builtin:
			// for unsafe.Sizeof, etc.
			builtins = append(builtins, obj)
		}
	}

	p.printf("package %s  // %q\n\n", pkg.Name(), pkg.Path())

	if len(consts) > 0 {
		p.print("const (\n")
		p.indent++
		for _, obj := range consts {
			p.printObj(obj)
			p.print("\n")
		}
		p.indent--
		p.print(")\n\n")
	}

	if len(vars) > 0 {
		p.print("var (\n")
		p.indent++
		for _, obj := range vars {
			p.printObj(obj)
			p.print("\n")
		}
		p.indent--
		p.print(")\n\n")
	}

	if len(typez) > 0 {
		p.print("type (\n")
		p.indent++
		for _, obj := range typez {
			p.printf("%s ", obj.Name())
			p.writeType(p.pkg, obj.Type().Underlying())
			p.print("\n")
		}
		p.indent--
		p.print(")\n\n")
	}

	for _, obj := range typem {
		p.printf("type %s ", obj.Name())
		typ := obj.Type().(*types.Named)
		p.writeType(p.pkg, typ.Underlying())
		p.print("\n")
		for i, n := 0, typ.NumMethods(); i < n; i++ {
			p.printFunc(typ.Method(i))
			p.print("\n")
		}
		p.print("\n")
	}

	for _, obj := range funcs {
		p.printFunc(obj)
		p.print("\n")
	}

	// TODO(gri) better handling of builtins (package unsafe only)
	for _, obj := range builtins {
		p.printf("func %s() // builtin\n", obj.Name())
	}

	p.print("\n")
}