func packageForQualIdent(path []ast.Node, id *ast.Ident) string {
	if sel, ok := path[1].(*ast.SelectorExpr); ok && sel.Sel == id && ast.IsExported(id.Name) {
		if pkgid, ok := sel.X.(*ast.Ident); ok && pkgid.Obj == nil {
			f := path[len(path)-1].(*ast.File)
			for _, imp := range f.Imports {
				path, _ := strconv.Unquote(imp.Path.Value)
				if imp.Name != nil {
					if imp.Name.Name == pkgid.Name {
						return path  
					}
				} else if pathpkg.Base(path) == pkgid.Name {
					return path  
				}
			}
		}
	}
	return ""
}
packageForQualIdent returns the package p if id is X in a qualified
identifier p.X; it returns "" otherwise.

Precondition: id is path[0], and the parser did not resolve id to a
local object.  For speed, packageForQualIdent assumes that p is a
package iff it is the basename of an import path (and not, say, a
package-level decl in another file or a predeclared identifier).
package main
import (
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	pathpkg "path"
	"path/filepath"
	"strconv"
	"golang.org/x/tools/cmd/guru/serial"
	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
)
func definition(q *Query) error {
	{
		qpos, err := fastQueryPos(q.Build, q.Pos)
		if err != nil {
			return err
		}
		id, _ := qpos.path[0].(*ast.Ident)
		if id == nil {
			return fmt.Errorf("no identifier here")
		}
		if obj := id.Obj; obj != nil && obj.Pos().IsValid() {
			q.Output(qpos.fset, &definitionResult{
				pos:   obj.Pos(),
				descr: fmt.Sprintf("%s %s", obj.Kind, obj.Name),
			})
			return nil  
		}
		if pkg := packageForQualIdent(qpos.path, id); pkg != "" {
			srcdir := filepath.Dir(qpos.fset.File(qpos.start).Name())
			tok, pos, err := findPackageMember(q.Build, qpos.fset, srcdir, pkg, id.Name)
			if err != nil {
				return err
			}
			q.Output(qpos.fset, &definitionResult{
				pos:   pos,
				descr: fmt.Sprintf("%s %s.%s", tok, pkg, id.Name),
			})
			return nil  
		}
	}
	lconf := loader.Config{Build: q.Build}
	allowErrors(&lconf)
	if _, err := importQueryPackage(q.Pos, &lconf); err != nil {
		return err
	}
	lprog, err := lconf.Load()
	if err != nil {
		return err
	}
	qpos, err := parseQueryPos(lprog, q.Pos, false)
	if err != nil {
		return err
	}
	id, _ := qpos.path[0].(*ast.Ident)
	if id == nil {
		return fmt.Errorf("no identifier here")
	}
	obj := qpos.info.Uses[id]
	if obj == nil {
		obj = qpos.info.Defs[id]
		if obj == nil {
			return fmt.Errorf("no object for identifier")
		}
	}
	if !obj.Pos().IsValid() {
		return fmt.Errorf("%s is built in", obj.Name())
	}
	q.Output(lprog.Fset, &definitionResult{
		pos:   obj.Pos(),
		descr: qpos.objectString(obj),
	})
	return nil
}