func guessImportPath(filename string, buildContext *build.Context) (srcdir, importPath string, err error) {
	absFile, err := filepath.Abs(filename)
	if err != nil {
		err = fmt.Errorf("can't form absolute path of %s", filename)
		return
	}
	absFileDir := segments(filepath.Dir(absFile))
	minD := 1024
	for _, gopathDir := range buildContext.SrcDirs() {
		absDir, err := filepath.Abs(gopathDir)
		if err != nil {
			continue  
		}
		d := prefixLen(segments(absDir), absFileDir)
		if d >= 0 && d < minD {
			minD = d
			srcdir = gopathDir
			importPath = strings.Join(absFileDir[len(absFileDir)-minD:], string(os.PathSeparator))
		}
	}
	if srcdir == "" {
		err = fmt.Errorf("directory %s is not beneath any of these GOROOT/GOPATH directories: %s",
			filepath.Dir(absFile), strings.Join(buildContext.SrcDirs(), ", "))
	}
	return
}
guessImportPath finds the package containing filename, and returns
its source directory (an element of $GOPATH) and its import path
relative to it.

TODO(adonovan): what about _test.go files that are not part of the
package?
package oracle
import (
	"fmt"
	"go/ast"
	"go/build"
	"go/token"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"github.com/visualfc/gotools/oracle/oracle/serial"
	"golang.org/x/tools/go/ast/astutil"
)
func what(q *Query) error {
	qpos, err := fastQueryPos(q.Pos)
	if err != nil {
		return err
	}
	q.Fset = qpos.fset
	srcdir, importPath, _ := guessImportPath(q.Fset.File(qpos.start).Name(), q.Build)
	enable := map[string]bool{
		"describe": true,  
	}
	if qpos.end > qpos.start {
		enable["freevars"] = true  
	}
	for _, n := range qpos.path {
		switch n := n.(type) {
		case *ast.Ident:
			enable["definition"] = true
			enable["referrers"] = true
			enable["implements"] = true
		case *ast.CallExpr:
			enable["callees"] = true
		case *ast.FuncDecl:
			enable["callers"] = true
			enable["callstack"] = true
		case *ast.SendStmt:
			enable["peers"] = true
		case *ast.UnaryExpr:
			if n.Op == token.ARROW {
				enable["peers"] = true
			}
		}
		if _, ok := enable["implements"]; !ok {
			switch n.(type) {
			case *ast.ArrayType,
				*ast.StructType,
				*ast.FuncType,
				*ast.InterfaceType,
				*ast.MapType,
				*ast.ChanType:
				enable["implements"] = true
			}
		}
		if _, ok := enable["pointsto"]; !ok {
			switch n.(type) {
			case ast.Stmt,
				*ast.ArrayType,
				*ast.StructType,
				*ast.FuncType,
				*ast.InterfaceType,
				*ast.MapType,
				*ast.ChanType:
				enable["pointsto"] = false  
			case ast.Expr, ast.Decl, *ast.ValueSpec:
				enable["pointsto"] = true  
			default:
			}
		}
	}
	if !qpos.exact {
		enable["callees"] = false
		enable["pointsto"] = false
		enable["whicherrs"] = false
		enable["describe"] = false
	}
	var modes []string
	for mode := range enable {
		modes = append(modes, mode)
	}
	sort.Strings(modes)
	q.result = &whatResult{
		path:       qpos.path,
		srcdir:     srcdir,
		importPath: importPath,
		modes:      modes,
	}
	return nil
}