Example #1
0
// TODO: use the version from ssa or go/types
func intuitiveMethodSet(T types.Type) []*types.Selection {
	var result []*types.Selection
	mset := types.NewMethodSet(T)
	if _, ok := T.Underlying().(*types.Interface); ok {
		for i, n := 0, mset.Len(); i < n; i++ {
			result = append(result, mset.At(i))
		}
	} else {
		pmset := types.NewMethodSet(types.NewPointer(T))
		for i, n := 0, pmset.Len(); i < n; i++ {
			meth := pmset.At(i)
			if m := mset.Lookup(meth.Obj.GetPkg(), meth.Obj.GetName()); m != nil {
				meth = m
			}
			result = append(result, meth)
		}
	}
	return result
}
Example #2
0
func (b browser) filteredObjs() (objs objects) {
	add := func(obj types.Object) {
		if invisible(obj, b.currentPkg) {
			return
		}
		if _, ok := obj.(*pkgObject); ok || b.options.objFilter == nil || b.options.objFilter(obj) {
			objs = append(objs, obj)
		}
	}

	addSubPkgs := func(importPath string) {
		seen := map[string]bool{}
		for _, srcDir := range build.Default.SrcDirs() {
			files, err := ioutil.ReadDir(filepath.Join(srcDir, importPath))
			if err != nil {
				continue
			}
			for _, f := range files {
				name := filepath.Base(f.Name())
				if !f.IsDir() || !unicode.IsLetter([]rune(name)[0]) || name == "testdata" || seen[name] {
					continue
				}
				if _, ok := b.newObj.(*pkgObject); ok && name == b.oldName {
					// when editing a package path, it will be added in filteredObjs as newObj, so don't add it here
					continue
				}
				seen[name] = true

				importPath := path.Join(importPath, name)
				pkgObj, ok := pkgObjects[importPath]
				if !ok {
					if pkg, err := build.Import(importPath, "", build.AllowBinary); err == nil {
						name = pkg.Name
					}
					pkgObj = &pkgObject{nil, path.Base(importPath), srcDir, importPath, name}
					pkgObjects[importPath] = pkgObj
				}
				add(pkgObj)
			}
		}
	}

	if b.typ != nil {
		mset := types.NewMethodSet(b.typ)
		for i := 0; i < mset.Len(); i++ {
			m := mset.At(i)
			// m.Type() has the correct receiver for inherited methods (m.Obj does not)
			add(types.NewFunc(0, m.Obj.GetPkg(), m.Obj.GetName(), m.Type().(*types.Signature)))
		}
		fset := types.NewFieldSet(b.typ)
		for i := 0; i < fset.Len(); i++ {
			f := fset.At(i)
			add(field{f.Obj.(*types.Var), f.Recv, f.Indirect})
		}
	} else if len(b.path) > 0 {
		switch obj := b.path[0].(type) {
		case *pkgObject:
			if pkg, err := getPackage(obj.importPath); err == nil {
				for _, obj := range pkg.Scope().Objects {
					add(obj)
				}
			} else {
				if _, ok := err.(*build.NoGoError); !ok {
					fmt.Println(err)
				}
				pkgs[obj.importPath] = types.NewPackage(obj.importPath, obj.pkgName, types.NewScope(types.Universe))
			}
			addSubPkgs(obj.importPath)
		case *types.TypeName:
			for _, m := range intuitiveMethodSet(obj.Type) {
				if types.IsIdentical(m.Obj.(*types.Func).Type.(*types.Signature).Recv.Type, m.Recv) {
					// preserve Object identity for non-inherited methods so that fluxObjs works
					add(m.Obj)
				} else {
					// m.Type() has the correct receiver for inherited methods (m.Obj does not)
					add(types.NewFunc(0, m.Obj.GetPkg(), m.Obj.GetName(), m.Type().(*types.Signature)))
				}
			}
		}
	} else {
		for _, name := range []string{"break", "call", "continue", "convert", "defer", "func", "go", "if", "loop", "return", "select", "typeAssert"} {
			add(special{newVar(name, nil)})
		}
		for _, name := range []string{"=", "*"} {
			add(newVar(name, nil))
		}
		pkgs := b.imports
		if b.currentPkg != nil {
			pkgs = append(pkgs, b.currentPkg)
		}
		for _, p := range pkgs {
			for _, obj := range p.Scope().Objects {
				add(obj)
			}
		}
		for _, obj := range types.Universe.Objects {
			switch obj.GetName() {
			case "nil", "print", "println":
				continue
			}
			add(obj)
		}
		for _, op := range []string{"!", "&&", "||", "+", "-", "*", "/", "%", "&", "|", "^", "&^", "<<", ">>", "==", "!=", "<", "<=", ">", ">=", "[]", "[:]", "<-"} {
			add(types.NewFunc(0, nil, op, nil))
		}
		for _, t := range []*types.TypeName{protoPointer, protoArray, protoSlice, protoMap, protoChan, protoFunc, protoInterface, protoStruct} {
			add(t)
		}
		addSubPkgs("")
	}

	sort.Sort(objs)
	return
}