1// Copyright 2011 The Go Authors.  All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Api computes the exported API of a set of Go packages.
6
7//modify 2013-2014 visualfc
8
9package goapi
10
11import (
12	"bufio"
13	"bytes"
14	"fmt"
15	"go/ast"
16	"go/build"
17	"go/doc"
18	"go/parser"
19	"go/printer"
20	"go/token"
21	"io"
22	"io/ioutil"
23	"log"
24	"os"
25	"os/exec"
26	"path"
27	"path/filepath"
28	"regexp"
29	"sort"
30	"strconv"
31	"strings"
32	"time"
33
34	"github.com/visualfc/gotools/pkg/command"
35)
36
37var Command = &command.Command{
38	Run:       runApi,
39	UsageLine: "goapi",
40	Short:     "golang api util",
41	Long:      `golang api util`,
42}
43
44var apiVerbose bool
45var apiAllmethods bool
46var apiAlldecls bool
47var apiShowpos bool
48var apiSeparate string
49var apiImportParser bool
50var apiDefaultCtx bool
51var apiCustomCtx string
52var apiLookupInfo string
53var apiLookupStdin bool
54var apiOutput string
55
56func init() {
57	Command.Flag.BoolVar(&apiVerbose, "v", false, "verbose debugging")
58	Command.Flag.BoolVar(&apiAllmethods, "e", true, "extract for all embedded methods")
59	Command.Flag.BoolVar(&apiAlldecls, "a", false, "extract for all declarations")
60	Command.Flag.BoolVar(&apiShowpos, "pos", false, "addition token position")
61	Command.Flag.StringVar(&apiSeparate, "sep", ", ", "setup separators")
62	Command.Flag.BoolVar(&apiImportParser, "dep", true, "parser package imports")
63	Command.Flag.BoolVar(&apiDefaultCtx, "default_ctx", true, "extract for default context")
64	Command.Flag.StringVar(&apiCustomCtx, "custom_ctx", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
65	Command.Flag.StringVar(&apiLookupInfo, "cursor_info", "", "lookup cursor node info\"file.go:pos\"")
66	Command.Flag.BoolVar(&apiLookupStdin, "cursor_std", false, "cursor_info use stdin")
67	Command.Flag.StringVar(&apiOutput, "o", "", "output file")
68}
69
70func runApi(cmd *command.Command, args []string) error {
71	if len(args) == 0 && apiLookupInfo == "" {
72		cmd.Usage()
73		return os.ErrInvalid
74	}
75	if apiVerbose {
76		now := time.Now()
77		defer func() {
78			log.Println("time", time.Now().Sub(now))
79		}()
80	}
81
82	var pkgs []string
83	if len(args) > 0 {
84		if args[0] == "std" || args[0] == "all" {
85			out, err := exec.Command("go", "list", "-e", args[0]).Output()
86			if err != nil {
87				log.Fatal(err)
88			}
89			pkgs = strings.Fields(string(out))
90		} else {
91			pkgs = args
92		}
93	}
94	var curinfo CursorInfo
95	if apiLookupInfo != "" {
96		pos := strings.Index(apiLookupInfo, ":")
97		if pos != -1 {
98			curinfo.file = (apiLookupInfo)[:pos]
99			if i, err := strconv.Atoi((apiLookupInfo)[pos+1:]); err == nil {
100				curinfo.pos = token.Pos(i)
101			}
102		}
103	}
104
105	if len(pkgs) == 1 && curinfo.pos != token.NoPos {
106		curinfo.pkg = pkgs[0]
107	}
108
109	if apiLookupStdin {
110		src, err := ioutil.ReadAll(os.Stdin)
111		if err == nil {
112			curinfo.src = src
113			curinfo.std = true
114		}
115	}
116
117	if apiCustomCtx != "" {
118		apiDefaultCtx = false
119		setCustomContexts()
120	}
121
122	var features []string
123	w := NewWalker()
124	if curinfo.pkg != "" {
125		w.cursorInfo = &curinfo
126	}
127	w.sep = apiSeparate
128
129	if apiDefaultCtx {
130		w.context = &build.Default
131
132		for _, pkg := range pkgs {
133			w.wantedPkg[pkg] = true
134		}
135
136		for _, pkg := range pkgs {
137			w.WalkPackage(pkg)
138		}
139		if w.cursorInfo != nil {
140			goto lookup
141		} else {
142			var file io.Writer
143			if apiOutput != "" {
144				var err error
145				file, err = os.Create(apiOutput)
146				if err != nil {
147					log.Fatal(err)
148				}
149			} else {
150				file = os.Stdout
151			}
152			bw := bufio.NewWriter(file)
153			defer bw.Flush()
154			for _, p := range w.packageMap {
155				if w.wantedPkg[p.name] {
156					for _, f := range p.Features() {
157						fmt.Fprintf(bw, "%s\n", f)
158					}
159				}
160			}
161			return nil
162		}
163		features = w.Features("")
164	} else {
165		for _, c := range contexts {
166			c.Compiler = build.Default.Compiler
167		}
168
169		for _, pkg := range pkgs {
170			w.wantedPkg[pkg] = true
171		}
172
173		var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true
174		for _, context := range contexts {
175			w.context = context
176			w.ctxName = contextName(w.context) + ":"
177
178			for _, pkg := range pkgs {
179				w.WalkPackage(pkg)
180			}
181			if w.cursorInfo != nil && w.cursorInfo.info != nil {
182				goto lookup
183			}
184		}
185
186		for pkg, p := range w.packageMap {
187			if w.wantedPkg[p.name] {
188				pos := strings.Index(pkg, ":")
189				if pos == -1 {
190					continue
191				}
192				ctxName := pkg[:pos]
193				for _, f := range p.Features() {
194					if featureCtx[f] == nil {
195						featureCtx[f] = make(map[string]bool)
196					}
197					featureCtx[f][ctxName] = true
198				}
199			}
200		}
201
202		for f, cmap := range featureCtx {
203			if len(cmap) == len(contexts) {
204				features = append(features, f)
205				continue
206			}
207			comma := strings.Index(f, ",")
208			for cname := range cmap {
209				f2 := fmt.Sprintf("%s (%s)%s", f[:comma], cname, f[comma:])
210				features = append(features, f2)
211			}
212		}
213		sort.Strings(features)
214	}
215
216lookup:
217	if w.cursorInfo != nil {
218		info := w.cursorInfo.info
219		if info == nil {
220			os.Exit(1)
221			return os.ErrInvalid
222		}
223		//		fmt.Println("kind,", info.Kind)
224		//		fmt.Println("name,", info.Name)
225		//		if info.Type != "" {
226		//			fmt.Println("type,", strings.TrimLeft(info.Type, "*"))
227		//		}
228		if info.Name == info.Type || info.Type == "" {
229			fmt.Printf("info, %s, %s\n", info.Kind, info.Name)
230		} else {
231			fmt.Printf("info, %s, %s, %s\n", info.Kind, info.Name, info.Type)
232		}
233		if info.Kind == KindImport || info.Kind == KindPackage {
234			if p := w.findPackage(info.Name); p != nil {
235				fmt.Println("help,", p.name)
236			}
237		}
238		if info.T != nil {
239			for _, text := range []string{info.Name, info.Type} {
240				typ := strings.TrimLeft(text, "*")
241				pos := strings.Index(typ, ".")
242				if pos != -1 {
243					if p := w.findPackage(typ[:pos]); p != nil {
244						fmt.Println("help,", p.name+typ[pos:])
245						break
246					}
247				}
248			}
249			fmt.Println("pos,", w.fset.Position(info.T.Pos()))
250		}
251		return nil
252	}
253
254	fail := false
255	defer func() {
256		if fail {
257			os.Exit(1)
258		}
259	}()
260
261	bw := bufio.NewWriter(os.Stdout)
262	defer bw.Flush()
263
264	for _, f := range features {
265		fmt.Fprintf(bw, "%s\n", f)
266	}
267	return nil
268}
269
270type CursorInfo struct {
271	pkg  string
272	file string
273	pos  token.Pos
274	src  []byte
275	std  bool
276	info *TypeInfo
277}
278
279// contexts are the default contexts which are scanned, unless
280// overridden by the -contexts flag.
281var contexts = []*build.Context{
282	{GOOS: "linux", GOARCH: "386", CgoEnabled: true},
283	{GOOS: "linux", GOARCH: "386"},
284	{GOOS: "linux", GOARCH: "amd64", CgoEnabled: true},
285	{GOOS: "linux", GOARCH: "amd64"},
286	{GOOS: "linux", GOARCH: "arm"},
287	{GOOS: "darwin", GOARCH: "386", CgoEnabled: true},
288	{GOOS: "darwin", GOARCH: "386"},
289	{GOOS: "darwin", GOARCH: "amd64", CgoEnabled: true},
290	{GOOS: "darwin", GOARCH: "amd64"},
291	{GOOS: "windows", GOARCH: "amd64"},
292	{GOOS: "windows", GOARCH: "386"},
293	{GOOS: "freebsd", GOARCH: "amd64"},
294	{GOOS: "freebsd", GOARCH: "386"},
295}
296
297func contextName(c *build.Context) string {
298	s := c.GOOS + "-" + c.GOARCH
299	if c.CgoEnabled {
300		return s + "-cgo"
301	}
302	return s
303}
304
305func osArchName(c *build.Context) string {
306	return c.GOOS + "-" + c.GOARCH
307}
308
309func parseContext(c string) *build.Context {
310	parts := strings.Split(c, "-")
311	if len(parts) < 2 {
312		log.Fatalf("bad context: %q", c)
313	}
314	bc := &build.Context{
315		GOOS:   parts[0],
316		GOARCH: parts[1],
317	}
318	if len(parts) == 3 {
319		if parts[2] == "cgo" {
320			bc.CgoEnabled = true
321		} else {
322			log.Fatalf("bad context: %q", c)
323		}
324	}
325	return bc
326}
327
328func setCustomContexts() {
329	contexts = []*build.Context{}
330	for _, c := range strings.Split(apiCustomCtx, ",") {
331		contexts = append(contexts, parseContext(c))
332	}
333}
334
335func set(items []string) map[string]bool {
336	s := make(map[string]bool)
337	for _, v := range items {
338		s[v] = true
339	}
340	return s
341}
342
343var spaceParensRx = regexp.MustCompile(` \(\S+?\)`)
344
345func featureWithoutContext(f string) string {
346	if !strings.Contains(f, "(") {
347		return f
348	}
349	return spaceParensRx.ReplaceAllString(f, "")
350}
351
352func compareAPI(w io.Writer, features, required, optional, exception []string, allowNew bool) (ok bool) {
353	ok = true
354
355	optionalSet := set(optional)
356	exceptionSet := set(exception)
357	featureSet := set(features)
358
359	sort.Strings(features)
360	sort.Strings(required)
361
362	take := func(sl *[]string) string {
363		s := (*sl)[0]
364		*sl = (*sl)[1:]
365		return s
366	}
367
368	for len(required) > 0 || len(features) > 0 {
369		switch {
370		case len(features) == 0 || (len(required) > 0 && required[0] < features[0]):
371			feature := take(&required)
372			if exceptionSet[feature] {
373				fmt.Fprintf(w, "~%s\n", feature)
374			} else if featureSet[featureWithoutContext(feature)] {
375				// okay.
376			} else {
377				fmt.Fprintf(w, "-%s\n", feature)
378				ok = false // broke compatibility
379			}
380		case len(required) == 0 || (len(features) > 0 && required[0] > features[0]):
381			newFeature := take(&features)
382			if optionalSet[newFeature] {
383				// Known added feature to the upcoming release.
384				// Delete it from the map so we can detect any upcoming features
385				// which were never seen.  (so we can clean up the nextFile)
386				delete(optionalSet, newFeature)
387			} else {
388				fmt.Fprintf(w, "+%s\n", newFeature)
389				if !allowNew {
390					ok = false // we're in lock-down mode for next release
391				}
392			}
393		default:
394			take(&required)
395			take(&features)
396		}
397	}
398
399	// In next file, but not in API.
400	var missing []string
401	for feature := range optionalSet {
402		missing = append(missing, feature)
403	}
404	sort.Strings(missing)
405	for _, feature := range missing {
406		fmt.Fprintf(w, "±%s\n", feature)
407	}
408	return
409}
410
411func fileFeatures(filename string) []string {
412	bs, err := ioutil.ReadFile(filename)
413	if err != nil {
414		log.Fatalf("Error reading file %s: %v", filename, err)
415	}
416	text := strings.TrimSpace(string(bs))
417	if text == "" {
418		return nil
419	}
420	return strings.Split(text, "\n")
421}
422
423func isExtract(name string) bool {
424	if apiAlldecls {
425		return true
426	}
427	return ast.IsExported(name)
428}
429
430// pkgSymbol represents a symbol in a package
431type pkgSymbol struct {
432	pkg    string // "net/http"
433	symbol string // "RoundTripper"
434}
435
436//expression kind
437type Kind int
438
439const (
440	KindBuiltin Kind = iota
441	KindPackage
442	KindImport
443	KindVar
444	KindConst
445	KindInterface
446	KindParam
447	KindStruct
448	KindMethod
449	KindField
450	KindType
451	KindFunc
452	KindChan
453	KindArray
454	KindMap
455	KindSlice
456	KindLabel
457	KindBranch
458)
459
460func (k Kind) String() string {
461	switch k {
462	case KindBuiltin:
463		return "builtin"
464	case KindPackage:
465		return "package"
466	case KindImport:
467		return "import"
468	case KindVar:
469		return "var"
470	case KindConst:
471		return "const"
472	case KindParam:
473		return "param"
474	case KindInterface:
475		return "interface"
476	case KindStruct:
477		return "struct"
478	case KindMethod:
479		return "method"
480	case KindField:
481		return "field"
482	case KindType:
483		return "type"
484	case KindFunc:
485		return "func"
486	case KindChan:
487		return "chan"
488	case KindMap:
489		return "map"
490	case KindArray:
491		return "array"
492	case KindSlice:
493		return "slice"
494	case KindLabel:
495		return "label"
496	case KindBranch:
497		return "branch"
498	}
499	return fmt.Sprint("unknown-kind")
500}
501
502//expression type
503type TypeInfo struct {
504	Kind Kind
505	Name string
506	Type string
507	X    ast.Expr
508	T    ast.Expr
509}
510
511type ExprType struct {
512	X ast.Expr
513	T string
514}
515
516type Package struct {
517	dpkg             *doc.Package
518	apkg             *ast.Package
519	interfaceMethods map[string]([]typeMethod)
520	interfaces       map[string]*ast.InterfaceType //interface
521	structs          map[string]*ast.StructType    //struct
522	types            map[string]ast.Expr           //type
523	functions        map[string]typeMethod         //function
524	consts           map[string]*ExprType          //const => type
525	vars             map[string]*ExprType          //var => type
526	name             string
527	dir              string
528	sep              string
529	deps             []string
530	features         map[string](token.Pos) // set
531}
532
533func NewPackage() *Package {
534	return &Package{
535		interfaceMethods: make(map[string]([]typeMethod)),
536		interfaces:       make(map[string]*ast.InterfaceType),
537		structs:          make(map[string]*ast.StructType),
538		types:            make(map[string]ast.Expr),
539		functions:        make(map[string]typeMethod),
540		consts:           make(map[string]*ExprType),
541		vars:             make(map[string]*ExprType),
542		features:         make(map[string](token.Pos)),
543		sep:              ", ",
544	}
545}
546
547func (p *Package) Features() (fs []string) {
548	for f, ps := range p.features {
549		if apiShowpos {
550			fs = append(fs, f+p.sep+strconv.Itoa(int(ps)))
551		} else {
552			fs = append(fs, f)
553		}
554	}
555	sort.Strings(fs)
556	return
557}
558
559func (p *Package) findType(name string) ast.Expr {
560	for k, v := range p.interfaces {
561		if k == name {
562			return v
563		}
564	}
565	for k, v := range p.structs {
566		if k == name {
567			return v
568		}
569	}
570	for k, v := range p.types {
571		if k == name {
572			return v
573		}
574	}
575	return nil
576}
577
578func funcRetType(ft *ast.FuncType, index int) ast.Expr {
579	if ft.Results != nil {
580		pos := 0
581		for _, fi := range ft.Results.List {
582			if fi.Names == nil {
583				if pos == index {
584					return fi.Type
585				}
586				pos++
587			} else {
588				for _ = range fi.Names {
589					if pos == index {
590						return fi.Type
591					}
592					pos++
593				}
594			}
595		}
596	}
597	return nil
598}
599
600func findFunction(funcs []*doc.Func, name string) (*ast.Ident, *ast.FuncType) {
601	for _, f := range funcs {
602		if f.Name == name {
603			return &ast.Ident{Name: name, NamePos: f.Decl.Pos()}, f.Decl.Type
604		}
605	}
606	return nil, nil
607}
608
609func (p *Package) findSelectorType(name string) ast.Expr {
610	if t, ok := p.vars[name]; ok {
611		return &ast.Ident{
612			NamePos: t.X.Pos(),
613			Name:    t.T,
614		}
615	}
616	if t, ok := p.consts[name]; ok {
617		return &ast.Ident{
618			NamePos: t.X.Pos(),
619			Name:    t.T,
620		}
621	}
622	if t, ok := p.functions[name]; ok {
623		return t.ft
624	}
625	for k, v := range p.structs {
626		if k == name {
627			return &ast.Ident{
628				NamePos: v.Pos(),
629				Name:    name,
630			}
631		}
632	}
633	for k, v := range p.interfaces {
634		if k == name {
635			return &ast.Ident{
636				NamePos: v.Pos(),
637				Name:    name,
638			}
639		}
640	}
641	for k, v := range p.types {
642		if k == name {
643			return v
644		}
645	}
646	return nil
647}
648
649func (p *Package) findCallFunc(name string) ast.Expr {
650	if fn, ok := p.functions[name]; ok {
651		return fn.ft
652	}
653	if s, ok := p.structs[name]; ok {
654		return s
655	}
656	if t, ok := p.types[name]; ok {
657		return t
658	}
659	if v, ok := p.vars[name]; ok {
660		if strings.HasPrefix(v.T, "func(") {
661			e, err := parser.ParseExpr(v.T + "{}")
662			if err == nil {
663				return e
664			}
665		}
666	}
667	return nil
668}
669
670func (p *Package) findCallType(name string, index int) ast.Expr {
671	if fn, ok := p.functions[name]; ok {
672		return funcRetType(fn.ft, index)
673	}
674	if s, ok := p.structs[name]; ok {
675		return &ast.Ident{
676			NamePos: s.Pos(),
677			Name:    name,
678		}
679	}
680	if t, ok := p.types[name]; ok {
681		return &ast.Ident{
682			NamePos: t.Pos(),
683			Name:    name,
684		}
685	}
686	return nil
687}
688
689func (p *Package) findMethod(typ, name string) (*ast.Ident, *ast.FuncType) {
690	if t, ok := p.interfaces[typ]; ok && t.Methods != nil {
691		for _, fd := range t.Methods.List {
692			switch ft := fd.Type.(type) {
693			case *ast.FuncType:
694				for _, ident := range fd.Names {
695					if ident.Name == name {
696						return ident, ft
697					}
698				}
699			}
700		}
701	}
702	for k, v := range p.interfaceMethods {
703		if k == typ {
704			for _, m := range v {
705				if m.name == name {
706					return &ast.Ident{Name: name, NamePos: m.pos}, m.ft
707				}
708			}
709		}
710	}
711	if p.dpkg == nil {
712		return nil, nil
713	}
714	for _, t := range p.dpkg.Types {
715		if t.Name == typ {
716			return findFunction(t.Methods, name)
717		}
718	}
719	return nil, nil
720}
721
722type Walker struct {
723	context *build.Context
724	fset    *token.FileSet
725	scope   []string
726	//	features        map[string](token.Pos) // set
727	lastConstType   string
728	curPackageName  string
729	sep             string
730	ctxName         string
731	curPackage      *Package
732	constDep        map[string]*ExprType // key's const identifier has type of future value const identifier
733	packageState    map[string]loadState
734	packageMap      map[string]*Package
735	interfaces      map[pkgSymbol]*ast.InterfaceType
736	selectorFullPkg map[string]string // "http" => "net/http", updated by imports
737	wantedPkg       map[string]bool   // packages requested on the command line
738	cursorInfo      *CursorInfo
739	localvar        map[string]*ExprType
740}
741
742func NewWalker() *Walker {
743	return &Walker{
744		fset: token.NewFileSet(),
745		//		features:        make(map[string]token.Pos),
746		packageState:    make(map[string]loadState),
747		interfaces:      make(map[pkgSymbol]*ast.InterfaceType),
748		packageMap:      make(map[string]*Package),
749		selectorFullPkg: make(map[string]string),
750		wantedPkg:       make(map[string]bool),
751		localvar:        make(map[string]*ExprType),
752		sep:             ", ",
753	}
754}
755
756// loadState is the state of a package's parsing.
757type loadState int
758
759const (
760	notLoaded loadState = iota
761	loading
762	loaded
763)
764
765func (w *Walker) Features(ctx string) (fs []string) {
766	for pkg, p := range w.packageMap {
767		if w.wantedPkg[p.name] {
768			if ctx == "" || strings.HasPrefix(pkg, ctx) {
769				fs = append(fs, p.Features()...)
770			}
771		}
772	}
773	sort.Strings(fs)
774	return
775}
776
777// fileDeps returns the imports in a file.
778func fileDeps(f *ast.File) (pkgs []string) {
779	for _, is := range f.Imports {
780		fpkg, err := strconv.Unquote(is.Path.Value)
781		if err != nil {
782			log.Fatalf("error unquoting import string %q: %v", is.Path.Value, err)
783		}
784		if fpkg != "C" {
785			pkgs = append(pkgs, fpkg)
786		}
787	}
788	return
789}
790
791func (w *Walker) findPackage(pkg string) *Package {
792	if full, ok := w.selectorFullPkg[pkg]; ok {
793		if w.ctxName != "" {
794			ctxName := w.ctxName + full
795			for k, v := range w.packageMap {
796				if k == ctxName {
797					return v
798				}
799			}
800		}
801		for k, v := range w.packageMap {
802			if k == full {
803				return v
804			}
805		}
806	}
807	return nil
808}
809
810func (w *Walker) findPackageOSArch(pkg string) *Package {
811	if full, ok := w.selectorFullPkg[pkg]; ok {
812		ctxName := osArchName(w.context) + ":" + full
813		for k, v := range w.packageMap {
814			if k == ctxName {
815				return v
816			}
817		}
818	}
819	return nil
820}
821
822// WalkPackage walks all files in package `name'.
823// WalkPackage does nothing if the package has already been loaded.
824
825func (w *Walker) WalkPackage(pkg string) {
826	if build.IsLocalImport(pkg) {
827		wd, err := os.Getwd()
828		if err != nil {
829			if apiVerbose {
830				log.Println(err)
831			}
832			return
833		}
834		dir := filepath.Clean(filepath.Join(wd, pkg))
835		bp, err := w.context.ImportDir(dir, 0)
836		if err != nil {
837			if apiVerbose {
838				log.Println(err)
839			}
840			return
841		}
842		if w.wantedPkg[pkg] == true {
843			w.wantedPkg[bp.Name] = true
844			delete(w.wantedPkg, pkg)
845		}
846		if w.cursorInfo != nil && w.cursorInfo.pkg == pkg {
847			w.cursorInfo.pkg = bp.Name
848		}
849		w.WalkPackageDir(bp.Name, bp.Dir, bp)
850	} else if filepath.IsAbs(pkg) {
851		bp, err := build.ImportDir(pkg, 0)
852		if err != nil {
853			if apiVerbose {
854				log.Println(err)
855			}
856		}
857		if w.wantedPkg[pkg] == true {
858			w.wantedPkg[bp.Name] = true
859			delete(w.wantedPkg, pkg)
860		}
861		if w.cursorInfo != nil && w.cursorInfo.pkg == pkg {
862			w.cursorInfo.pkg = bp.Name
863		}
864
865		w.WalkPackageDir(bp.Name, bp.Dir, bp)
866	} else {
867		bp, err := build.Import(pkg, "", build.FindOnly)
868		if err != nil {
869			if apiVerbose {
870				log.Println(err)
871			}
872			return
873		}
874		w.WalkPackageDir(pkg, bp.Dir, nil)
875	}
876}
877
878func (w *Walker) WalkPackageDir(name string, dir string, bp *build.Package) {
879	ctxName := w.ctxName + name
880	curName := name
881	switch w.packageState[ctxName] {
882	case loading:
883		log.Fatalf("import cycle loading package %q?", name)
884		return
885	case loaded:
886		return
887	}
888	w.packageState[ctxName] = loading
889	w.selectorFullPkg[name] = name
890
891	defer func() {
892		w.packageState[ctxName] = loaded
893	}()
894
895	sname := name[strings.LastIndexAny(name, ".-/\\")+1:]
896
897	apkg := &ast.Package{
898		Files: make(map[string]*ast.File),
899	}
900	if bp == nil {
901		bp, _ = w.context.ImportDir(dir, 0)
902	}
903	if bp == nil {
904		return
905	}
906	if w.ctxName != "" {
907		isCgo := (len(bp.CgoFiles) > 0) && w.context.CgoEnabled
908		if isCgo {
909			curName = ctxName
910		} else {
911			isOSArch := false
912			for _, file := range bp.GoFiles {
913				if isOSArchFile(w.context, file) {
914					isOSArch = true
915					break
916				}
917			}
918			var p *Package
919			if isOSArch {
920				curName = osArchName(w.context) + ":" + name
921				p = w.findPackageOSArch(name)
922			} else {
923				curName = name
924				p = w.findPackage(name)
925			}
926			if p != nil {
927				if apiImportParser {
928					for _, dep := range p.deps {
929						if _, ok := w.packageState[dep]; ok {
930							continue
931						}
932						w.WalkPackage(dep)
933					}
934				}
935				w.packageMap[ctxName] = p
936				return
937			}
938		}
939	}
940
941	files := append(append([]string{}, bp.GoFiles...), bp.CgoFiles...)
942
943	if w.cursorInfo != nil && w.cursorInfo.pkg == name {
944		files = append(files, bp.TestGoFiles...)
945		for _, v := range bp.XTestGoFiles {
946			if v == w.cursorInfo.file {
947				var xbp build.Package
948				xbp.Name = name + "_test"
949				xbp.GoFiles = append(xbp.GoFiles, bp.XTestGoFiles...)
950				w.cursorInfo.pkg = xbp.Name
951				w.WalkPackageDir(xbp.Name, dir, &xbp)
952				break
953			}
954		}
955	}
956
957	if len(files) == 0 {
958		if apiVerbose {
959			log.Println("no Go source files in", bp.Dir)
960		}
961		return
962	}
963	var deps []string
964
965	for _, file := range files {
966		var src interface{} = nil
967		if w.cursorInfo != nil &&
968			w.cursorInfo.pkg == name &&
969			w.cursorInfo.file == file &&
970			w.cursorInfo.std {
971			src = w.cursorInfo.src
972		}
973		f, err := parser.ParseFile(w.fset, filepath.Join(dir, file), src, 0)
974		if err != nil {
975			if apiVerbose {
976				log.Printf("error parsing package %s, file %s: %v", name, file, err)
977			}
978		}
979
980		if sname != f.Name.Name {
981			continue
982		}
983		apkg.Files[file] = f
984		if apiImportParser {
985			deps = fileDeps(f)
986			for _, dep := range deps {
987				if _, ok := w.packageState[dep]; ok {
988					continue
989				}
990				w.WalkPackage(dep)
991			}
992		}
993		if apiShowpos && w.wantedPkg[name] {
994			tf := w.fset.File(f.Pos())
995			if tf != nil {
996				fmt.Printf("pos %s%s%s%s%d%s%d\n", name, w.sep, filepath.Join(dir, file), w.sep, tf.Base(), w.sep, tf.Size())
997			}
998		}
999	}
1000	/* else {
1001		fdir, err := os.Open(dir)
1002		if err != nil {
1003			log.Fatalln(err)
1004		}
1005		infos, err := fdir.Readdir(-1)
1006		fdir.Close()
1007		if err != nil {
1008			log.Fatalln(err)
1009		}
1010
1011		for _, info := range infos {
1012			if info.IsDir() {
1013				continue
1014			}
1015			file := info.Name()
1016			if strings.HasPrefix(file, "_") || strings.HasSuffix(file, "_test.go") {
1017				continue
1018			}
1019			if strings.HasSuffix(file, ".go") {
1020				f, err := parser.ParseFile(w.fset, filepath.Join(dir, file), nil, 0)
1021				if err != nil {
1022					if apiVerbose {
1023						log.Printf("error parsing package %s, file %s: %v", name, file, err)
1024					}
1025					continue
1026				}
1027				if f.Name.Name != sname {
1028					continue
1029				}
1030
1031				apkg.Files[file] = f
1032				if apiImportParser {
1033					for _, dep := range fileDeps(f) {
1034						w.WalkPackage(dep)
1035					}
1036				}
1037				if apiShowpos && w.wantedPkg[name] {
1038					tf := w.fset.File(f.Pos())
1039					if tf != nil {
1040						fmt.Printf("pos %s%s%s%s%d:%d\n", name, w.sep, filepath.Join(dir, file), w.sep, tf.Base(), tf.Base()+tf.Size())
1041					}
1042				}
1043			}
1044		}
1045	}*/
1046	if curName != ctxName {
1047		w.packageState[curName] = loading
1048
1049		defer func() {
1050			w.packageState[curName] = loaded
1051		}()
1052	}
1053
1054	if apiVerbose {
1055		log.Printf("package %s => %s, %v", ctxName, curName, w.wantedPkg[curName])
1056	}
1057	pop := w.pushScope("pkg " + name)
1058	defer pop()
1059
1060	w.curPackageName = curName
1061	w.constDep = map[string]*ExprType{}
1062	w.curPackage = NewPackage()
1063	w.curPackage.apkg = apkg
1064	w.curPackage.name = name
1065	w.curPackage.dir = dir
1066	w.curPackage.deps = deps
1067	w.curPackage.sep = w.sep
1068	w.packageMap[curName] = w.curPackage
1069	w.packageMap[ctxName] = w.curPackage
1070
1071	for _, afile := range apkg.Files {
1072		w.recordTypes(afile)
1073	}
1074
1075	// Register all function declarations first.
1076	for _, afile := range apkg.Files {
1077		for _, di := range afile.Decls {
1078			if d, ok := di.(*ast.FuncDecl); ok {
1079				if !w.isExtract(d.Name.Name) {
1080					continue
1081				}
1082				w.peekFuncDecl(d)
1083			}
1084		}
1085	}
1086
1087	for _, afile := range apkg.Files {
1088		w.walkFile(afile)
1089	}
1090
1091	w.resolveConstantDeps()
1092
1093	if w.cursorInfo != nil && w.cursorInfo.pkg == name {
1094		for k, v := range apkg.Files {
1095			if k == w.cursorInfo.file {
1096				f := w.fset.File(v.Pos())
1097				if f == nil {
1098					log.Fatalf("error fset postion %v", v.Pos())
1099				}
1100				info, err := w.lookupFile(v, token.Pos(f.Base())+w.cursorInfo.pos-1)
1101				if err != nil {
1102					log.Fatalln("lookup error,", err)
1103				} else {
1104					if info != nil && info.Kind == KindImport {
1105						for _, is := range v.Imports {
1106							fpath, err := strconv.Unquote(is.Path.Value)
1107							if err == nil {
1108								if info.Name == path.Base(fpath) {
1109									info.T = is.Path
1110								}
1111							}
1112						}
1113					}
1114					w.cursorInfo.info = info
1115				}
1116				break
1117			}
1118		}
1119		return
1120	}
1121
1122	// Now that we're done walking types, vars and consts
1123	// in the *ast.Package, use go/doc to do the rest
1124	// (functions and methods). This is done here because
1125	// go/doc is destructive.  We can't use the
1126	// *ast.Package after this.
1127	var mode doc.Mode
1128	if apiAllmethods {
1129		mode |= doc.AllMethods
1130	}
1131	if apiAlldecls && w.wantedPkg[w.ctxName] {
1132		mode |= doc.AllDecls
1133	}
1134
1135	dpkg := doc.New(apkg, name, mode)
1136	w.curPackage.dpkg = dpkg
1137
1138	if w.wantedPkg[name] != true {
1139		return
1140	}
1141
1142	for _, t := range dpkg.Types {
1143		// Move funcs up to the top-level, not hiding in the Types.
1144		dpkg.Funcs = append(dpkg.Funcs, t.Funcs...)
1145
1146		for _, m := range t.Methods {
1147			w.walkFuncDecl(m.Decl)
1148		}
1149	}
1150
1151	for _, f := range dpkg.Funcs {
1152		w.walkFuncDecl(f.Decl)
1153	}
1154}
1155
1156// pushScope enters a new scope (walking a package, type, node, etc)
1157// and returns a function that will leave the scope (with sanity checking
1158// for mismatched pushes & pops)
1159func (w *Walker) pushScope(name string) (popFunc func()) {
1160	w.scope = append(w.scope, name)
1161	return func() {
1162		if len(w.scope) == 0 {
1163			log.Fatalf("attempt to leave scope %q with empty scope list", name)
1164		}
1165		if w.scope[len(w.scope)-1] != name {
1166			log.Fatalf("attempt to leave scope %q, but scope is currently %#v", name, w.scope)
1167		}
1168		w.scope = w.scope[:len(w.scope)-1]
1169	}
1170}
1171
1172func (w *Walker) recordTypes(file *ast.File) {
1173	cur := w.curPackage
1174	for _, di := range file.Decls {
1175		switch d := di.(type) {
1176		case *ast.GenDecl:
1177			switch d.Tok {
1178			case token.TYPE:
1179				for _, sp := range d.Specs {
1180					ts := sp.(*ast.TypeSpec)
1181					name := ts.Name.Name
1182					switch t := ts.Type.(type) {
1183					case *ast.InterfaceType:
1184						if isExtract(name) {
1185							w.noteInterface(name, t)
1186						}
1187						cur.interfaces[name] = t
1188					case *ast.StructType:
1189						cur.structs[name] = t
1190					default:
1191						cur.types[name] = ts.Type
1192					}
1193				}
1194			}
1195		}
1196	}
1197}
1198
1199func inRange(node ast.Node, p token.Pos) bool {
1200	if node == nil {
1201		return false
1202	}
1203	return p >= node.Pos() && p <= node.End()
1204}
1205
1206func (w *Walker) lookupLabel(body *ast.BlockStmt, name string) (*TypeInfo, error) {
1207	for _, stmt := range body.List {
1208		switch v := stmt.(type) {
1209		case *ast.BlockStmt:
1210			return w.lookupLabel(v, name)
1211		case *ast.LabeledStmt:
1212			return &TypeInfo{Kind: KindLabel, Name: v.Label.Name, Type: "branch", T: v.Label}, nil
1213		}
1214	}
1215	return nil, nil
1216}
1217
1218func (w *Walker) lookupFile(file *ast.File, p token.Pos) (*TypeInfo, error) {
1219	if inRange(file.Name, p) {
1220		return &TypeInfo{Kind: KindPackage, X: file.Name, Name: file.Name.Name, Type: file.Name.Name, T: file.Name}, nil
1221	}
1222	for _, di := range file.Decls {
1223		switch d := di.(type) {
1224		case *ast.GenDecl:
1225			if inRange(d, p) {
1226				return w.lookupDecl(d, p, false)
1227			}
1228		case *ast.FuncDecl:
1229			if inRange(d, p) {
1230				info, err := w.lookupDecl(d, p, false)
1231				if info != nil && info.Kind == KindBranch {
1232					return w.lookupLabel(d.Body, info.Name)
1233				}
1234				return info, err
1235			}
1236			if d.Body != nil && inRange(d.Body, p) {
1237				return w.lookupStmt(d.Body, p)
1238			}
1239		default:
1240			return nil, fmt.Errorf("un parser decl %T", di)
1241		}
1242	}
1243	return nil, fmt.Errorf("un find cursor %v", w.fset.Position(p))
1244}
1245
1246func (w *Walker) isExtract(name string) bool {
1247	if w.wantedPkg[w.curPackageName] || apiAlldecls {
1248		return true
1249	}
1250	return ast.IsExported(name)
1251}
1252
1253func (w *Walker) isType(typ string) *ExprType {
1254	pos := strings.Index(typ, ".")
1255	if pos != -1 {
1256		pkg := typ[:pos]
1257		typ = typ[pos+1:]
1258		if p := w.findPackage(pkg); p != nil {
1259			if t, ok := p.types[typ]; ok {
1260				if r := w.isType(typ); r != nil {
1261					return r
1262				}
1263				return &ExprType{X: t, T: w.pkgRetType(pkg, w.nodeString(t))}
1264			}
1265		}
1266		return nil
1267	}
1268	if t, ok := w.curPackage.types[typ]; ok {
1269		if r := w.isType(w.nodeString(t)); r != nil {
1270			return r
1271		}
1272		return &ExprType{X: t, T: w.nodeString(t)}
1273	}
1274	return nil
1275}
1276
1277func (w *Walker) lookupStmt(vi ast.Stmt, p token.Pos) (*TypeInfo, error) {
1278	if vi == nil {
1279		return nil, nil
1280	}
1281	switch v := vi.(type) {
1282	case *ast.BadStmt:
1283		//
1284	case *ast.EmptyStmt:
1285		//
1286	case *ast.LabeledStmt:
1287		if inRange(v.Label, p) {
1288			return &TypeInfo{Kind: KindLabel, Name: v.Label.Name}, nil
1289		}
1290		return w.lookupStmt(v.Stmt, p)
1291		//
1292	case *ast.DeclStmt:
1293		return w.lookupDecl(v.Decl, p, true)
1294	case *ast.AssignStmt:
1295		if len(v.Lhs) == len(v.Rhs) {
1296			for i := 0; i < len(v.Lhs); i++ {
1297				switch lt := v.Lhs[i].(type) {
1298				case *ast.Ident:
1299					typ, err := w.varValueType(v.Rhs[i], 0)
1300					if err == nil && v.Tok == token.DEFINE {
1301						w.localvar[lt.Name] = &ExprType{T: typ, X: lt}
1302					} else if apiVerbose {
1303						log.Println(err)
1304					}
1305				}
1306				if inRange(v.Lhs[i], p) {
1307					return w.lookupExprInfo(v.Lhs[i], p)
1308				} else if inRange(v.Rhs[i], p) {
1309					return w.lookupExprInfo(v.Rhs[i], p)
1310				}
1311				if fl, ok := v.Rhs[i].(*ast.FuncLit); ok {
1312					if inRange(fl, p) {
1313						return w.lookupStmt(fl.Body, p)
1314					}
1315				}
1316			}
1317		} else if len(v.Rhs) == 1 {
1318			for i := 0; i < len(v.Lhs); i++ {
1319				switch lt := v.Lhs[i].(type) {
1320				case *ast.Ident:
1321					typ, err := w.varValueType(v.Rhs[0], i)
1322					if err == nil && v.Tok == token.DEFINE {
1323						w.localvar[lt.Name] = &ExprType{T: typ, X: lt}
1324					} else if apiVerbose {
1325						log.Println(err)
1326					}
1327				}
1328				if inRange(v.Lhs[i], p) {
1329					return w.lookupExprInfo(v.Lhs[i], p)
1330				} else if inRange(v.Rhs[0], p) {
1331					return w.lookupExprInfo(v.Rhs[0], p)
1332				}
1333				if fl, ok := v.Rhs[0].(*ast.FuncLit); ok {
1334					if inRange(fl, p) {
1335						return w.lookupStmt(fl.Body, p)
1336					}
1337				}
1338			}
1339		}
1340		return nil, nil
1341	case *ast.ExprStmt:
1342		return w.lookupExprInfo(v.X, p)
1343	case *ast.BlockStmt:
1344		for _, st := range v.List {
1345			if inRange(st, p) {
1346				return w.lookupStmt(st, p)
1347			}
1348			_, err := w.lookupStmt(st, p)
1349			if err != nil {
1350				log.Println(err)
1351			}
1352		}
1353	case *ast.IfStmt:
1354		if inRange(v.Init, p) {
1355			return w.lookupStmt(v.Init, p)
1356		} else {
1357			w.lookupStmt(v.Init, p)
1358		}
1359		if inRange(v.Cond, p) {
1360			return w.lookupExprInfo(v.Cond, p)
1361		} else if inRange(v.Body, p) {
1362			return w.lookupStmt(v.Body, p)
1363		} else if inRange(v.Else, p) {
1364			return w.lookupStmt(v.Else, p)
1365		}
1366	case *ast.SendStmt:
1367		if inRange(v.Chan, p) {
1368			return w.lookupExprInfo(v.Chan, p)
1369		} else if inRange(v.Value, p) {
1370			return w.lookupExprInfo(v.Value, p)
1371		}
1372	case *ast.IncDecStmt:
1373		return w.lookupExprInfo(v.X, p)
1374	case *ast.GoStmt:
1375		return w.lookupExprInfo(v.Call, p)
1376	case *ast.DeferStmt:
1377		return w.lookupExprInfo(v.Call, p)
1378	case *ast.ReturnStmt:
1379		for _, r := range v.Results {
1380			if inRange(r, p) {
1381				return w.lookupExprInfo(r, p)
1382			}
1383		}
1384	case *ast.BranchStmt:
1385		if inRange(v.Label, p) {
1386			return &TypeInfo{Kind: KindBranch, Name: v.Label.Name, Type: "label", T: v.Label}, nil
1387		}
1388		//
1389	case *ast.CaseClause:
1390		for _, r := range v.List {
1391			if inRange(r, p) {
1392				return w.lookupExprInfo(r, p)
1393			}
1394		}
1395		for _, body := range v.Body {
1396			if inRange(body, p) {
1397				return w.lookupStmt(body, p)
1398			} else {
1399				w.lookupStmt(body, p)
1400			}
1401		}
1402	case *ast.SwitchStmt:
1403		if inRange(v.Init, p) {
1404			return w.lookupStmt(v.Init, p)
1405		} else {
1406			w.lookupStmt(v.Init, p)
1407		}
1408		if inRange(v.Tag, p) {
1409			return w.lookupExprInfo(v.Tag, p)
1410		} else if inRange(v.Body, p) {
1411			return w.lookupStmt(v.Body, p)
1412		}
1413	case *ast.TypeSwitchStmt:
1414		if inRange(v.Assign, p) {
1415			return w.lookupStmt(v.Assign, p)
1416		} else {
1417			w.lookupStmt(v.Assign, p)
1418		}
1419		if inRange(v.Init, p) {
1420			return w.lookupStmt(v.Init, p)
1421		} else {
1422			w.lookupStmt(v.Init, p)
1423		}
1424		var vs string
1425		if as, ok := v.Assign.(*ast.AssignStmt); ok {
1426			if len(as.Lhs) == 1 {
1427				vs = w.nodeString(as.Lhs[0])
1428			}
1429		}
1430		if inRange(v.Body, p) {
1431			for _, s := range v.Body.List {
1432				if inRange(s, p) {
1433					switch cs := s.(type) {
1434					case *ast.CaseClause:
1435						for _, r := range cs.List {
1436							if inRange(r, p) {
1437								return w.lookupExprInfo(r, p)
1438							} else if vs != "" {
1439								typ, err := w.varValueType(r, 0)
1440								if err == nil {
1441									w.localvar[vs] = &ExprType{T: typ, X: r}
1442								}
1443							}
1444						}
1445						for _, body := range cs.Body {
1446							if inRange(body, p) {
1447								return w.lookupStmt(body, p)
1448							} else {
1449								w.lookupStmt(body, p)
1450							}
1451						}
1452					default:
1453						return w.lookupStmt(cs, p)
1454					}
1455				}
1456			}
1457		}
1458	case *ast.CommClause:
1459		if inRange(v.Comm, p) {
1460			return w.lookupStmt(v.Comm, p)
1461		}
1462		for _, body := range v.Body {
1463			if inRange(body, p) {
1464				return w.lookupStmt(body, p)
1465			}
1466		}
1467	case *ast.SelectStmt:
1468		if inRange(v.Body, p) {
1469			return w.lookupStmt(v.Body, p)
1470		}
1471	case *ast.ForStmt:
1472		if inRange(v.Init, p) {
1473			return w.lookupStmt(v.Init, p)
1474		} else {
1475			w.lookupStmt(v.Init, p)
1476		}
1477		if inRange(v.Cond, p) {
1478			return w.lookupExprInfo(v.Cond, p)
1479		} else if inRange(v.Body, p) {
1480			return w.lookupStmt(v.Body, p)
1481		} else if inRange(v.Post, p) {
1482			return w.lookupStmt(v.Post, p)
1483		}
1484	case *ast.RangeStmt:
1485		if inRange(v.X, p) {
1486			return w.lookupExprInfo(v.X, p)
1487		} else if inRange(v.Key, p) {
1488			return &TypeInfo{Kind: KindBuiltin, Name: w.nodeString(v.Key), Type: "int"}, nil
1489		} else if inRange(v.Value, p) {
1490			typ, err := w.lookupExprInfo(v.X, p)
1491			if typ != nil {
1492				typ.Name = w.nodeString(v.Value)
1493				return typ, err
1494			}
1495		} else {
1496			typ, err := w.varValueType(v.X, 0)
1497			//check is type
1498			if t := w.isType(typ); t != nil {
1499				typ = t.T
1500			}
1501			if err == nil {
1502				var kt, vt string
1503				if strings.HasPrefix(typ, "[]") {
1504					kt = "int"
1505					vt = typ[2:]
1506				} else if strings.HasPrefix(typ, "map[") {
1507					node, err := parser.ParseExpr(typ + "{}")
1508					if err == nil {
1509						if cl, ok := node.(*ast.CompositeLit); ok {
1510							if m, ok := cl.Type.(*ast.MapType); ok {
1511								kt = w.nodeString(w.namelessType(m.Key))
1512								vt = w.nodeString(w.namelessType(m.Value))
1513							}
1514						}
1515					}
1516				}
1517				if inRange(v.Key, p) {
1518					return &TypeInfo{Kind: KindVar, X: v.Key, Name: w.nodeString(v.Key), T: v.X, Type: kt}, nil
1519				} else if inRange(v.Value, p) {
1520					return &TypeInfo{Kind: KindVar, X: v.Value, Name: w.nodeString(v.Value), T: v.X, Type: vt}, nil
1521				}
1522				if key, ok := v.Key.(*ast.Ident); ok {
1523					w.localvar[key.Name] = &ExprType{T: kt, X: v.Key}
1524				}
1525				if value, ok := v.Value.(*ast.Ident); ok {
1526					w.localvar[value.Name] = &ExprType{T: vt, X: v.Value}
1527				}
1528			}
1529		}
1530		if inRange(v.Body, p) {
1531			return w.lookupStmt(v.Body, p)
1532		}
1533	}
1534	return nil, nil //fmt.Errorf("not lookup stmt %v %T", vi, vi)
1535}
1536
1537func (w *Walker) lookupVar(vs *ast.ValueSpec, p token.Pos, local bool) (*TypeInfo, error) {
1538	if inRange(vs.Type, p) {
1539		return w.lookupExprInfo(vs.Type, p)
1540	}
1541	for _, v := range vs.Values {
1542		if inRange(v, p) {
1543			return w.lookupExprInfo(v, p)
1544		}
1545	}
1546	if vs.Type != nil {
1547		typ := w.nodeString(vs.Type)
1548		for _, ident := range vs.Names {
1549			if local {
1550				w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
1551			}
1552			if inRange(ident, p) {
1553				return &TypeInfo{Kind: KindVar, X: ident, Name: ident.Name, T: vs.Type, Type: typ}, nil
1554			}
1555		}
1556	} else if len(vs.Names) == len(vs.Values) {
1557		for n, ident := range vs.Names {
1558			typ := ""
1559			if !local {
1560				if t, ok := w.curPackage.vars[ident.Name]; ok {
1561					typ = t.T
1562				}
1563			} else {
1564				typ, err := w.varValueType(vs.Values[n], n)
1565				if err != nil {
1566					if apiVerbose {
1567						log.Printf("unknown type of variable2 %q, type %T, error = %v, pos=%s",
1568							ident.Name, vs.Values[n], err, w.fset.Position(vs.Pos()))
1569					}
1570					typ = "unknown-type"
1571				}
1572				w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
1573			}
1574			if inRange(ident, p) {
1575				return &TypeInfo{Kind: KindVar, X: ident, Name: ident.Name, T: ident, Type: typ}, nil
1576			}
1577		}
1578	} else if len(vs.Values) == 1 {
1579		for n, ident := range vs.Names {
1580			typ := ""
1581			if !local {
1582				if t, ok := w.curPackage.vars[ident.Name]; ok {
1583					typ = t.T
1584				}
1585			} else {
1586				typ, err := w.varValueType(vs.Values[0], n)
1587				if err != nil {
1588					if apiVerbose {
1589						log.Printf("unknown type of variable3 %q, type %T, error = %v, pos=%s",
1590							ident.Name, vs.Values[0], err, w.fset.Position(vs.Pos()))
1591					}
1592					typ = "unknown-type"
1593				}
1594				w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
1595			}
1596			if inRange(ident, p) {
1597				return &TypeInfo{Kind: KindVar, X: ident, Name: ident.Name, T: ident, Type: typ}, nil
1598			}
1599		}
1600	}
1601	return nil, fmt.Errorf("not lookup var local:%v value:%v type:s%T", local, w.nodeString(vs), vs)
1602}
1603
1604func (w *Walker) lookupConst(vs *ast.ValueSpec, p token.Pos, local bool) (*TypeInfo, error) {
1605	if inRange(vs.Type, p) {
1606		return w.lookupExprInfo(vs.Type, p)
1607	}
1608	for _, ident := range vs.Names {
1609		typ := ""
1610		if !local {
1611			if t, ok := w.curPackage.consts[ident.Name]; ok {
1612				typ = t.T
1613			}
1614		} else {
1615			litType := ""
1616			if vs.Type != nil {
1617				litType = w.nodeString(vs.Type)
1618			} else {
1619				litType = w.lastConstType
1620				if vs.Values != nil {
1621					if len(vs.Values) != 1 {
1622						if apiVerbose {
1623							log.Printf("const %q, values: %#v", ident.Name, vs.Values)
1624						}
1625						return nil, nil
1626					}
1627					var err error
1628					litType, err = w.constValueType(vs.Values[0])
1629					if err != nil {
1630						if apiVerbose {
1631							log.Printf("unknown kind in const %q (%T): %v", ident.Name, vs.Values[0], err)
1632						}
1633						litType = "unknown-type"
1634					}
1635				}
1636			}
1637			w.lastConstType = litType
1638			typ = litType
1639			w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
1640		}
1641		if inRange(ident, p) {
1642			return &TypeInfo{Kind: KindConst, X: ident, Name: ident.Name, T: ident, Type: typ}, nil
1643		}
1644	}
1645	return nil, nil
1646}
1647
1648func (w *Walker) lookupType(ts *ast.TypeSpec, p token.Pos, local bool) (*TypeInfo, error) {
1649	switch t := ts.Type.(type) {
1650	case *ast.StructType:
1651		if inRange(t.Fields, p) {
1652			for _, fd := range t.Fields.List {
1653				if inRange(fd.Type, p) {
1654					return w.lookupExprInfo(fd.Type, p)
1655				}
1656				for _, ident := range fd.Names {
1657					if inRange(ident, p) {
1658						return &TypeInfo{Kind: KindField, X: ident, Name: ts.Name.Name + "." + ident.Name, T: fd.Type, Type: w.nodeString(w.namelessType(fd.Type))}, nil
1659					}
1660				}
1661			}
1662		}
1663		return &TypeInfo{Kind: KindStruct, X: ts.Name, Name: ts.Name.Name, T: ts.Type, Type: "struct"}, nil
1664	case *ast.InterfaceType:
1665		if inRange(t.Methods, p) {
1666			for _, fd := range t.Methods.List {
1667				for _, ident := range fd.Names {
1668					if inRange(ident, p) {
1669						return &TypeInfo{Kind: KindMethod, X: ident, Name: ts.Name.Name + "." + ident.Name, T: ident, Type: w.nodeString(w.namelessType(fd.Type))}, nil
1670					}
1671				}
1672				if inRange(fd.Type, p) {
1673					return w.lookupExprInfo(fd.Type, p)
1674				}
1675			}
1676		}
1677		return &TypeInfo{Kind: KindInterface, X: ts.Name, Name: ts.Name.Name, T: ts.Type, Type: "interface"}, nil
1678	default:
1679		return &TypeInfo{Kind: KindType, X: ts.Name, Name: ts.Name.Name, T: ts.Type, Type: w.nodeString(w.namelessType(ts.Type))}, nil
1680	}
1681	return nil, nil
1682}
1683
1684func (w *Walker) lookupDecl(di ast.Decl, p token.Pos, local bool) (*TypeInfo, error) {
1685	switch d := di.(type) {
1686	case *ast.GenDecl:
1687		switch d.Tok {
1688		case token.IMPORT:
1689			for _, sp := range d.Specs {
1690				is := sp.(*ast.ImportSpec)
1691				fpath, err := strconv.Unquote(is.Path.Value)
1692				if err != nil {
1693					return nil, err
1694				}
1695				name := path.Base(fpath)
1696				if is.Name != nil {
1697					name = is.Name.Name
1698				}
1699				if inRange(sp, p) {
1700					return &TypeInfo{Kind: KindImport, X: is.Name, Name: name, T: is.Name, Type: fpath}, nil
1701				}
1702			}
1703		case token.CONST:
1704			for _, sp := range d.Specs {
1705				if inRange(sp, p) {
1706					return w.lookupConst(sp.(*ast.ValueSpec), p, local)
1707				} else {
1708					w.lookupConst(sp.(*ast.ValueSpec), p, local)
1709				}
1710			}
1711			return nil, nil
1712		case token.TYPE:
1713			for _, sp := range d.Specs {
1714				if inRange(sp, p) {
1715					return w.lookupType(sp.(*ast.TypeSpec), p, local)
1716				} else {
1717					w.lookupType(sp.(*ast.TypeSpec), p, local)
1718				}
1719			}
1720		case token.VAR:
1721			for _, sp := range d.Specs {
1722				if inRange(sp, p) {
1723					return w.lookupVar(sp.(*ast.ValueSpec), p, local)
1724				} else {
1725					w.lookupVar(sp.(*ast.ValueSpec), p, local)
1726				}
1727			}
1728			return nil, nil
1729		default:
1730			return nil, fmt.Errorf("unknown token type %d %T in GenDecl", d.Tok, d)
1731		}
1732	case *ast.FuncDecl:
1733		if d.Type.Params != nil {
1734			for _, fd := range d.Type.Params.List {
1735				if inRange(fd, p) {
1736					return w.lookupExprInfo(fd.Type, p)
1737				}
1738				for _, ident := range fd.Names {
1739					if inRange(ident, p) {
1740						info, err := w.lookupExprInfo(fd.Type, p)
1741						if err == nil {
1742							return &TypeInfo{Kind: KindParam, X: ident, Name: ident.Name, T: info.T, Type: info.Type}, nil
1743						}
1744					}
1745					typ, err := w.varValueType(fd.Type, 0)
1746					if err == nil {
1747						w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
1748					} else if apiVerbose {
1749						log.Println(err)
1750					}
1751				}
1752			}
1753		}
1754		if d.Type.Results != nil {
1755			for _, fd := range d.Type.Results.List {
1756				if inRange(fd, p) {
1757					return w.lookupExprInfo(fd.Type, p)
1758				}
1759				for _, ident := range fd.Names {
1760					typ, err := w.varValueType(fd.Type, 0)
1761					if err == nil {
1762						w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
1763					}
1764				}
1765			}
1766		}
1767		if d.Recv != nil {
1768			for _, fd := range d.Recv.List {
1769				if inRange(fd, p) {
1770					return w.lookupExprInfo(fd.Type, p)
1771				}
1772				for _, ident := range fd.Names {
1773					w.localvar[ident.Name] = &ExprType{T: w.nodeString(fd.Type), X: ident}
1774				}
1775			}
1776		}
1777		if inRange(d.Body, p) {
1778			return w.lookupStmt(d.Body, p)
1779		}
1780		var fname = d.Name.Name
1781		kind := KindFunc
1782		if d.Recv != nil {
1783			recvTypeName, imp := baseTypeName(d.Recv.List[0].Type)
1784			if imp {
1785				return nil, nil
1786			}
1787			fname = recvTypeName + "." + d.Name.Name
1788			kind = KindMethod
1789		}
1790		return &TypeInfo{Kind: kind, X: d.Name, Name: fname, T: d.Type, Type: w.nodeString(w.namelessType(d.Type))}, nil
1791	default:
1792		return nil, fmt.Errorf("unhandled %T, %#v\n", di, di)
1793	}
1794	return nil, fmt.Errorf("not lookupDecl %v %T", w.nodeString(di), di)
1795}
1796
1797func (w *Walker) lookupExprInfo(vi ast.Expr, p token.Pos) (*TypeInfo, error) {
1798	_, info, err := w.lookupExpr(vi, p)
1799	return info, err
1800}
1801
1802// lookupExpr , return name,info,error
1803func (w *Walker) lookupExpr(vi ast.Expr, p token.Pos) (string, *TypeInfo, error) {
1804	if apiVerbose {
1805		log.Printf("lookup expr %v %T", w.nodeString(vi), vi)
1806	}
1807	switch v := vi.(type) {
1808	case *ast.BasicLit:
1809		litType, ok := varType[v.Kind]
1810		if !ok {
1811			return "", nil, fmt.Errorf("unknown basic literal kind %#v", v)
1812		}
1813		name := v.Value
1814		if len(name) >= 128 {
1815			name = name[:128] + "..."
1816		}
1817		return litType, &TypeInfo{Kind: KindBuiltin, X: v, Name: name, T: v, Type: litType}, nil
1818	case *ast.StarExpr:
1819		s, info, err := w.lookupExpr(v.X, p)
1820		if err != nil {
1821			return "", nil, err
1822		}
1823		return "*" + s, &TypeInfo{Kind: info.Kind, X: v, Name: "*" + info.Name, T: info.T, Type: "*" + info.Type}, err
1824	case *ast.InterfaceType:
1825		return "interface{}", &TypeInfo{Kind: KindInterface, X: v, Name: w.nodeString(v), T: v, Type: "interface{}"}, nil
1826	case *ast.Ellipsis:
1827		s, info, err := w.lookupExpr(v.Elt, p)
1828		if err != nil {
1829			return "", nil, err
1830		}
1831		return "[]" + s, &TypeInfo{Kind: KindArray, X: v.Elt, Name: "..." + s, T: info.T, Type: "[]" + info.Type}, nil
1832	case *ast.KeyValueExpr:
1833		if inRange(v.Key, p) {
1834			return w.lookupExpr(v.Key, p)
1835		} else if inRange(v.Value, p) {
1836			return w.lookupExpr(v.Value, p)
1837		}
1838	case *ast.CompositeLit:
1839		typ, err := w.varValueType(v.Type, 0)
1840		if err == nil {
1841			typ = strings.TrimLeft(typ, "*")
1842			if strings.HasPrefix(typ, "[]") {
1843				typ = strings.TrimLeft(typ[2:], "*")
1844			}
1845			pos := strings.Index(typ, ".")
1846			var pt *Package = w.curPackage
1847			var pkgdot string
1848			if pos != -1 {
1849				pkg := typ[:pos]
1850				typ = typ[pos+1:]
1851				pt = w.findPackage(pkg)
1852				if pt != nil {
1853					pkgdot = pkg + "."
1854				}
1855			}
1856			if pt != nil {
1857				if ss, ok := pt.structs[typ]; ok {
1858					for _, elt := range v.Elts {
1859						if inRange(elt, p) {
1860							if cl, ok := elt.(*ast.CompositeLit); ok {
1861								for _, elt := range cl.Elts {
1862									if inRange(elt, p) {
1863										if kv, ok := elt.(*ast.KeyValueExpr); ok {
1864											if inRange(kv.Key, p) {
1865												n, t := w.findStructField(ss, w.nodeString(kv.Key))
1866												if n != nil {
1867													return pkgdot + typ + "." + w.nodeString(kv.Key), &TypeInfo{Kind: KindField, X: kv.Key, Name: pkgdot + typ + "." + w.nodeString(kv.Key), T: n, Type: w.nodeString(w.namelessType(t))}, nil
1868												}
1869											} else if inRange(kv.Value, p) {
1870												return w.lookupExpr(kv.Value, p)
1871											}
1872										}
1873									}
1874								}
1875							}
1876							if kv, ok := elt.(*ast.KeyValueExpr); ok {
1877								if inRange(kv.Key, p) {
1878									n, t := w.findStructField(ss, w.nodeString(kv.Key))
1879									if n != nil {
1880										return typ + "." + w.nodeString(kv.Key), &TypeInfo{Kind: KindField, X: kv.Key, Name: typ + "." + w.nodeString(kv.Key), T: n, Type: w.nodeString(w.namelessType(t))}, nil
1881									}
1882								} else if inRange(kv.Value, p) {
1883									return w.lookupExpr(kv.Value, p)
1884								}
1885							}
1886						}
1887					}
1888				}
1889			}
1890		}
1891		for _, elt := range v.Elts {
1892			if inRange(elt, p) {
1893				return w.lookupExpr(elt, p)
1894			}
1895		}
1896		return w.lookupExpr(v.Type, p)
1897	case *ast.UnaryExpr:
1898		s, info, err := w.lookupExpr(v.X, p)
1899		return v.Op.String() + s, info, err
1900	case *ast.TypeAssertExpr:
1901		if inRange(v.X, p) {
1902			return w.lookupExpr(v.X, p)
1903		}
1904		return w.lookupExpr(v.Type, p)
1905	case *ast.BinaryExpr:
1906		if inRange(v.X, p) {
1907			return w.lookupExpr(v.X, p)
1908		} else if inRange(v.Y, p) {
1909			return w.lookupExpr(v.Y, p)
1910		}
1911		return "", nil, nil
1912	case *ast.CallExpr:
1913		for _, arg := range v.Args {
1914			if inRange(arg, p) {
1915				return w.lookupExpr(arg, p)
1916			}
1917		}
1918		switch ft := v.Fun.(type) {
1919		case *ast.Ident:
1920			if typ, ok := w.localvar[ft.Name]; ok {
1921				return ft.Name, &TypeInfo{Kind: KindVar, X: ft, Name: ft.Name, T: typ.X, Type: typ.T}, nil
1922			}
1923			if typ, ok := w.curPackage.vars[ft.Name]; ok {
1924				return ft.Name, &TypeInfo{Kind: KindVar, X: v, Name: ft.Name, T: typ.X, Type: typ.T}, nil
1925			}
1926			if typ, ok := w.curPackage.functions[ft.Name]; ok {
1927				return ft.Name, &TypeInfo{Kind: KindFunc, X: ft, Name: ft.Name, T: typ.ft, Type: typ.sig}, nil
1928			}
1929			if typ, ok := w.curPackage.interfaces[ft.Name]; ok {
1930				return ft.Name, &TypeInfo{Kind: KindInterface, X: ft, Name: ft.Name, T: typ, Type: w.nodeString(w.namelessType(typ))}, nil
1931			}
1932			if typ, ok := w.curPackage.interfaces[ft.Name]; ok {
1933				return ft.Name, &TypeInfo{Kind: KindInterface, X: ft, Name: ft.Name, T: typ, Type: w.nodeString(w.namelessType(typ))}, nil
1934			}
1935			if typ, ok := w.curPackage.structs[ft.Name]; ok {
1936				return ft.Name, &TypeInfo{Kind: KindStruct, X: ft, Name: ft.Name, T: typ, Type: w.nodeString(w.namelessType(typ))}, nil
1937			}
1938			if typ, ok := w.curPackage.types[ft.Name]; ok {
1939				return ft.Name, &TypeInfo{Kind: KindType, X: ft, Name: ft.Name, T: typ, Type: w.nodeString(w.namelessType(typ))}, nil
1940			}
1941			if isBuiltinType(ft.Name) {
1942				return ft.Name, &TypeInfo{Kind: KindBuiltin, X: ft, Name: ft.Name}, nil
1943			}
1944			return "", nil, fmt.Errorf("lookup unknown ident %v", v)
1945		case *ast.FuncLit:
1946			if inRange(ft.Body, p) {
1947				info, err := w.lookupStmt(ft.Body, p)
1948				if err == nil {
1949					return "", info, nil
1950				}
1951				return "", nil, err
1952			}
1953			return w.lookupExpr(ft.Type, p)
1954		case *ast.ParenExpr:
1955			return w.lookupExpr(ft.X, p)
1956		case *ast.SelectorExpr:
1957			switch st := ft.X.(type) {
1958			case *ast.Ident:
1959				if inRange(st, p) {
1960					return w.lookupExpr(st, p)
1961				}
1962				s, info, err := w.lookupExpr(st, p)
1963				if err != nil {
1964					return "", nil, err
1965				}
1966				typ := info.Type
1967				if typ == "" {
1968					typ = s
1969				}
1970				fname := typ + "." + ft.Sel.Name
1971				typ = strings.TrimLeft(typ, "*")
1972				if fn, ok := w.curPackage.functions[fname]; ok {
1973					return fname, &TypeInfo{Kind: KindMethod, X: st, Name: fname, T: fn.ft, Type: w.nodeString(w.namelessType(fn.ft))}, nil
1974				}
1975				info, e := w.lookupFunction(typ, ft.Sel.Name)
1976				if e != nil {
1977					return "", nil, e
1978				}
1979				return fname, info, nil
1980			case *ast.SelectorExpr:
1981				if inRange(st.X, p) {
1982					return w.lookupExpr(st.X, p)
1983				}
1984				if inRange(st, p) {
1985					return w.lookupExpr(st, p)
1986				}
1987				typ, err := w.varValueType(st, 0)
1988				if err != nil {
1989					return "", nil, err
1990				}
1991				/*
1992					typ = strings.TrimLeft(typ, "*")
1993					if t := w.curPackage.findType(typ); t != nil {
1994						if ss, ok := t.(*ast.StructType); ok {
1995							for _, fi := range ss.Fields.List {
1996								for _, n := range fi.Names {
1997									if n.Name == st.Sel.Name {
1998										//return fname, &TypeInfo{Kind: KindField, X: n, Name: fname, T: fi.Type, Type: w.nodeString(w.namelessType(fi.Type))}, nil
1999										typ = w.nodeString(w.namelessType(fi.Type))
2000									}
2001								}
2002							}
2003						}
2004					}
2005				*/
2006				info, e := w.lookupFunction(typ, ft.Sel.Name)
2007				if e != nil {
2008					return "", nil, e
2009				}
2010				return typ + "." + st.Sel.Name, info, nil
2011			case *ast.CallExpr:
2012				if inRange(st, p) {
2013					return w.lookupExpr(st, p)
2014				}
2015				if info, err := w.lookupExprInfo(st, p); err == nil {
2016					if fn, ok := info.X.(*ast.FuncType); ok {
2017						if fn.Results.NumFields() == 1 {
2018							info, err := w.lookupFunction(w.nodeString(fn.Results.List[0].Type), ft.Sel.Name)
2019							if err == nil {
2020								return info.Name, info, err
2021							}
2022							return "", nil, err
2023						}
2024					}
2025				}
2026				//w.lookupFunction(w.nodeString(info.X))
2027				typ, err := w.varValueType(st, 0)
2028				if err != nil {
2029					return "", nil, err
2030				}
2031				info, e := w.lookupFunction(typ, ft.Sel.Name)
2032				if e != nil {
2033					return "", nil, e
2034				}
2035				return typ + "." + ft.Sel.Name, info, nil
2036			case *ast.TypeAssertExpr:
2037				if inRange(st.X, p) {
2038					return w.lookupExpr(st.X, p)
2039				}
2040				typ := w.nodeString(w.namelessType(st.Type))
2041				info, e := w.lookupFunction(typ, ft.Sel.Name)
2042				if e != nil {
2043					return "", nil, e
2044				}
2045				return typ + "." + ft.Sel.Name, info, nil
2046			default:
2047				return "", nil, fmt.Errorf("not find select %v %T", v, st)
2048			}
2049		}
2050		return "", nil, fmt.Errorf("not find call %v %T", w.nodeString(v), v.Fun)
2051	case *ast.SelectorExpr:
2052		switch st := v.X.(type) {
2053		case *ast.Ident:
2054			if inRange(st, p) {
2055				return w.lookupExpr(st, p)
2056			}
2057			info, err := w.lookupSelector(st.Name, v.Sel.Name)
2058			if err != nil {
2059				return "", nil, err
2060			}
2061			return st.Name + "." + v.Sel.Name, info, nil
2062			//		case *ast.CallExpr:
2063			//			typ, err := w.varValueType(v.X, index)
2064			//			if err == nil {
2065			//				if strings.HasPrefix(typ, "*") {
2066			//					typ = typ[1:]
2067			//				}
2068			//				t := w.curPackage.findType(typ)
2069			//				if st, ok := t.(*ast.StructType); ok {
2070			//					for _, fi := range st.Fields.List {
2071			//						for _, n := range fi.Names {
2072			//							if n.Name == v.Sel.Name {
2073			//								return w.varValueType(fi.Type, index)
2074			//							}
2075			//						}
2076			//					}
2077			//				}
2078			//			}
2079		case *ast.SelectorExpr:
2080			if inRange(st.X, p) {
2081				return w.lookupExpr(st.X, p)
2082			}
2083
2084			if inRange(st, p) {
2085				return w.lookupExpr(st, p)
2086			}
2087
2088			typ, err := w.varValueType(st, 0)
2089			if err == nil {
2090				info, err := w.lookupSelector(typ, v.Sel.Name)
2091				if err != nil {
2092					return "", nil, err
2093				}
2094				return typ + v.Sel.Name, info, nil
2095			}
2096			//		case *ast.IndexExpr:
2097			//			typ, err := w.varValueType(st.X, 0)
2098			//			log.Println(typ, err)
2099			//			if err == nil {
2100			//				if strings.HasPrefix(typ, "[]") {
2101			//					return w.varSelectorType(typ[2:], v.Sel.Name)
2102			//				}
2103			//			}
2104		}
2105		return "", nil, fmt.Errorf("unknown lookup selector expr: %T %s.%s", v.X, w.nodeString(v.X), v.Sel)
2106
2107		//		s, info, err := w.lookupExpr(v.X, p)
2108		//		if err != nil {
2109		//			return "", "", err
2110		//		}
2111		//		if strings.HasPrefix(s, "*") {
2112		//			s = s[1:]
2113		//		}
2114		//		if inRange(v.X, p) {
2115		//			return s, info, err
2116		//		}
2117		//		t := w.curPackage.findType(s)
2118		//		fname := s + "." + v.Sel.Name
2119		//		if st, ok := t.(*ast.StructType); ok {
2120		//			for _, fi := range st.Fields.List {
2121		//				for _, n := range fi.Names {
2122		//					if n.Name == v.Sel.Name {
2123		//						return fname, fmt.Sprintf("var,%s,%s,%s", fname, w.nodeString(w.namelessType(fi.Type)), w.fset.Position(n.Pos())), nil
2124		//					}
2125		//				}
2126		//			}
2127		//		}
2128		//		log.Println(">>", s)
2129		//		info, e := w.lookupSelector(s, v.Sel.Name)
2130		//		return fname, info, e
2131	case *ast.Ident:
2132		if typ, ok := w.localvar[v.Name]; ok {
2133			return typ.T, &TypeInfo{Kind: KindVar, X: v, Name: v.Name, T: typ.X, Type: typ.T}, nil
2134		}
2135		if typ, ok := w.curPackage.interfaces[v.Name]; ok {
2136			return v.Name, &TypeInfo{Kind: KindInterface, X: v, Name: v.Name, T: typ, Type: "interface"}, nil
2137		}
2138		if typ, ok := w.curPackage.structs[v.Name]; ok {
2139			return v.Name, &TypeInfo{Kind: KindStruct, X: v, Name: v.Name, T: typ, Type: "struct"}, nil
2140		}
2141		if typ, ok := w.curPackage.types[v.Name]; ok {
2142			return v.Name, &TypeInfo{Kind: KindType, X: v, Name: v.Name, T: typ, Type: v.Name}, nil
2143		}
2144		if typ, ok := w.curPackage.vars[v.Name]; ok {
2145			return v.Name, &TypeInfo{Kind: KindVar, X: v, Name: v.Name, T: typ.X, Type: typ.T}, nil
2146		}
2147		if typ, ok := w.curPackage.consts[v.Name]; ok {
2148			return v.Name, &TypeInfo{Kind: KindConst, X: v, Name: v.Name, T: typ.X, Type: typ.T}, nil
2149		}
2150		if typ, ok := w.curPackage.functions[v.Name]; ok {
2151			return v.Name, &TypeInfo{Kind: KindFunc, X: typ.ft, Name: v.Name, T: typ.ft, Type: typ.sig}, nil
2152		}
2153		if p := w.findPackage(v.Name); p != nil {
2154			return v.Name, &TypeInfo{Kind: KindImport, X: v, Name: v.Name, Type: p.name}, nil
2155		}
2156		if isBuiltinType(v.Name) {
2157			return v.Name, &TypeInfo{Kind: KindBuiltin, Name: v.Name}, nil
2158		}
2159		return "", nil, fmt.Errorf("lookup unknown ident %v", v)
2160		//return v.Name, &TypeInfo{Kind: KindVar, X: v, Name: v.Name, T: v, Type: v.Name}, nil
2161	case *ast.IndexExpr:
2162		if inRange(v.Index, p) {
2163			return w.lookupExpr(v.Index, p)
2164		}
2165		return w.lookupExpr(v.X, p)
2166	case *ast.ParenExpr:
2167		return w.lookupExpr(v.X, p)
2168	case *ast.FuncLit:
2169		if inRange(v.Type, p) {
2170			return w.lookupExpr(v.Type, p)
2171		} else {
2172			w.lookupExpr(v.Type, p)
2173		}
2174		typ, err := w.varValueType(v.Type, 0)
2175		if err != nil {
2176			return "", nil, err
2177		}
2178		info, e := w.lookupStmt(v.Body, p)
2179		if e != nil {
2180			return "", nil, err
2181		}
2182		return typ, info, nil
2183	case *ast.FuncType:
2184		if v.Params != nil {
2185			for _, fd := range v.Params.List {
2186				if inRange(fd, p) {
2187					return w.lookupExpr(fd.Type, p)
2188				}
2189				for _, ident := range fd.Names {
2190					typ, err := w.varValueType(fd.Type, 0)
2191					if err == nil {
2192						w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
2193					}
2194				}
2195			}
2196		}
2197		if v.Results != nil {
2198			for _, fd := range v.Results.List {
2199				if inRange(fd, p) {
2200					return w.lookupExpr(fd.Type, p)
2201				}
2202				for _, ident := range fd.Names {
2203					typ, err := w.varValueType(fd.Type, 0)
2204					if err == nil {
2205						w.localvar[ident.Name] = &ExprType{T: typ, X: ident}
2206					}
2207				}
2208			}
2209		}
2210		return "", nil, nil
2211	case *ast.ArrayType:
2212		s, info, err := w.lookupExpr(v.Elt, p)
2213		if err != nil {
2214			return "", nil, err
2215		}
2216		return "[]" + s, &TypeInfo{Kind: KindArray, Name: "[]" + info.Name, Type: "[]" + info.Type, T: info.T}, nil
2217	case *ast.SliceExpr:
2218		if inRange(v.High, p) {
2219			return w.lookupExpr(v.High, p)
2220		} else if inRange(v.Low, p) {
2221			return w.lookupExpr(v.Low, p)
2222		}
2223		return w.lookupExpr(v.X, p)
2224	case *ast.MapType:
2225		if inRange(v.Key, p) {
2226			return w.lookupExpr(v.Key, p)
2227		} else if inRange(v.Value, p) {
2228			return w.lookupExpr(v.Value, p)
2229		}
2230		typ, err := w.varValueType(v, 0)
2231		if err != nil {
2232			return "", nil, err
2233		}
2234		return typ, &TypeInfo{Kind: KindMap, X: v, Name: w.nodeString(v), T: v, Type: typ}, nil
2235	case *ast.ChanType:
2236		if inRange(v.Value, p) {
2237			return w.lookupExpr(v.Value, p)
2238		}
2239		typ, err := w.varValueType(v, 0)
2240		if err != nil {
2241			return "", nil, err
2242		}
2243		return typ, &TypeInfo{Kind: KindChan, X: v, Name: w.nodeString(v), T: v, Type: typ}, nil
2244	default:
2245		return "", nil, fmt.Errorf("not lookupExpr %v %T", w.nodeString(v), v)
2246	}
2247	return "", nil, fmt.Errorf("not lookupExpr %v %T", w.nodeString(vi), vi)
2248}
2249
2250func (w *Walker) walkFile(file *ast.File) {
2251	// Not entering a scope here; file boundaries aren't interesting.
2252	for _, di := range file.Decls {
2253		switch d := di.(type) {
2254		case *ast.GenDecl:
2255			switch d.Tok {
2256			case token.IMPORT:
2257				for _, sp := range d.Specs {
2258					is := sp.(*ast.ImportSpec)
2259					fpath, err := strconv.Unquote(is.Path.Value)
2260					if err != nil {
2261						log.Fatal(err)
2262					}
2263					//name := path.Base(fpath)
2264					name := fpath
2265					if i := strings.LastIndexAny(name, ".-/\\"); i > 0 {
2266						name = name[i+1:]
2267					}
2268					if is.Name != nil {
2269						name = is.Name.Name
2270					}
2271					w.selectorFullPkg[name] = fpath
2272				}
2273			case token.CONST:
2274				for _, sp := range d.Specs {
2275					w.walkConst(sp.(*ast.ValueSpec))
2276				}
2277			case token.TYPE:
2278				for _, sp := range d.Specs {
2279					w.walkTypeSpec(sp.(*ast.TypeSpec))
2280				}
2281			case token.VAR:
2282				for _, sp := range d.Specs {
2283					w.walkVar(sp.(*ast.ValueSpec))
2284				}
2285			default:
2286				log.Fatalf("unknown token type %d in GenDecl", d.Tok)
2287			}
2288		case *ast.FuncDecl:
2289			// Ignore. Handled in subsequent pass, by go/doc.
2290		default:
2291			log.Printf("unhandled %T, %#v\n", di, di)
2292			printer.Fprint(os.Stderr, w.fset, di)
2293			os.Stderr.Write([]byte("\n"))
2294		}
2295	}
2296}
2297
2298var constType = map[token.Token]string{
2299	token.INT:    "ideal-int",
2300	token.FLOAT:  "ideal-float",
2301	token.STRING: "ideal-string",
2302	token.CHAR:   "ideal-char",
2303	token.IMAG:   "ideal-imag",
2304}
2305
2306var varType = map[token.Token]string{
2307	token.INT:    "int",
2308	token.FLOAT:  "float64",
2309	token.STRING: "string",
2310	token.CHAR:   "rune",
2311	token.IMAG:   "complex128",
2312}
2313
2314var builtinTypes = []string{
2315	"bool", "byte", "complex64", "complex128", "error", "float32", "float64",
2316	"int", "int8", "int16", "int32", "int64", "rune", "string",
2317	"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
2318}
2319
2320func isBuiltinType(typ string) bool {
2321	for _, v := range builtinTypes {
2322		if v == typ {
2323			return true
2324		}
2325	}
2326	return false
2327}
2328
2329func constTypePriority(typ string) int {
2330	switch typ {
2331	case "complex128":
2332		return 100
2333	case "ideal-imag":
2334		return 99
2335	case "complex64":
2336		return 98
2337	case "float64":
2338		return 97
2339	case "ideal-float":
2340		return 96
2341	case "float32":
2342		return 95
2343	case "int64":
2344		return 94
2345	case "int", "uint", "uintptr":
2346		return 93
2347	case "ideal-int":
2348		return 92
2349	case "int16", "uint16", "int8", "uint8", "byte":
2350		return 91
2351	case "ideal-char":
2352		return 90
2353	}
2354	return 101
2355}
2356
2357func (w *Walker) constRealType(typ string) string {
2358	pos := strings.Index(typ, ".")
2359	if pos >= 0 {
2360		pkg := typ[:pos]
2361		if pkg == "C" {
2362			return "int"
2363		}
2364		typ = typ[pos+1:]
2365		if p := w.findPackage(pkg); p != nil {
2366			ret := p.findType(typ)
2367			if ret != nil {
2368				return w.nodeString(w.namelessType(ret))
2369			}
2370		}
2371	} else {
2372		ret := w.curPackage.findType(typ)
2373		if ret != nil {
2374			return w.nodeString(w.namelessType(ret))
2375		}
2376	}
2377	return typ
2378}
2379
2380func (w *Walker) constValueType(vi interface{}) (string, error) {
2381	switch v := vi.(type) {
2382	case *ast.BasicLit:
2383		litType, ok := constType[v.Kind]
2384		if !ok {
2385			return "", fmt.Errorf("unknown basic literal kind %#v", v)
2386		}
2387		return litType, nil
2388	case *ast.UnaryExpr:
2389		return w.constValueType(v.X)
2390	case *ast.SelectorExpr:
2391		lhs := w.nodeString(v.X)
2392		rhs := w.nodeString(v.Sel)
2393		//if CGO
2394		if lhs == "C" {
2395			return lhs + "." + rhs, nil
2396		}
2397		if p := w.findPackage(lhs); p != nil {
2398			if ret, ok := p.consts[rhs]; ok {
2399				return w.pkgRetType(p.name, ret.T), nil
2400			}
2401		}
2402		return "", fmt.Errorf("unknown constant reference to %s.%s", lhs, rhs)
2403	case *ast.Ident:
2404		if v.Name == "iota" {
2405			return "ideal-int", nil // hack.
2406		}
2407		if v.Name == "false" || v.Name == "true" {
2408			return "bool", nil
2409		}
2410		if t, ok := w.curPackage.consts[v.Name]; ok {
2411			return t.T, nil
2412		}
2413		return constDepPrefix + v.Name, nil
2414	case *ast.BinaryExpr:
2415		//== > < ! != >= <=
2416		if v.Op == token.EQL || v.Op == token.LSS || v.Op == token.GTR || v.Op == token.NOT ||
2417			v.Op == token.NEQ || v.Op == token.LEQ || v.Op == token.GEQ {
2418			return "bool", nil
2419		}
2420		left, err := w.constValueType(v.X)
2421		if err != nil {
2422			return "", err
2423		}
2424		if v.Op == token.SHL || v.Op == token.SHR {
2425			return left, err
2426		}
2427		right, err := w.constValueType(v.Y)
2428		if err != nil {
2429			return "", err
2430		}
2431		//const left != right , one or two is ideal-
2432		if left != right {
2433			if strings.HasPrefix(left, constDepPrefix) && strings.HasPrefix(right, constDepPrefix) {
2434				// Just pick one.
2435				// e.g. text/scanner GoTokens const-dependency:ScanIdents, const-dependency:ScanFloats
2436				return left, nil
2437			}
2438			lp := constTypePriority(w.constRealType(left))
2439			rp := constTypePriority(w.constRealType(right))
2440			if lp >= rp {
2441				return left, nil
2442			} else {
2443				return right, nil
2444			}
2445			return "", fmt.Errorf("in BinaryExpr, unhandled type mismatch; left=%q, right=%q", left, right)
2446		}
2447		return left, nil
2448	case *ast.CallExpr:
2449		// Not a call, but a type conversion.
2450		typ := w.nodeString(v.Fun)
2451		switch typ {
2452		case "complex":
2453			return "complex128", nil
2454		case "real", "imag":
2455			return "float64", nil
2456		}
2457		return typ, nil
2458	case *ast.ParenExpr:
2459		return w.constValueType(v.X)
2460	}
2461	return "", fmt.Errorf("unknown const value type %T", vi)
2462}
2463
2464func (w *Walker) pkgRetType(pkg, ret string) string {
2465	pkg = pkg[strings.LastIndex(pkg, "/")+1:]
2466	if strings.HasPrefix(ret, "[]") {
2467		return "[]" + w.pkgRetType(pkg, ret[2:])
2468	}
2469	if strings.HasPrefix(ret, "*") {
2470		return "*" + w.pkgRetType(pkg, ret[1:])
2471	}
2472	if ast.IsExported(ret) {
2473		return pkg + "." + ret
2474	}
2475	return ret
2476}
2477
2478func (w *Walker) findStructFieldType(st ast.Expr, name string) ast.Expr {
2479	_, expr := w.findStructField(st, name)
2480	return expr
2481}
2482
2483func (w *Walker) findStructFieldFunction(st ast.Expr, name string) (*TypeInfo, error) {
2484	if s, ok := st.(*ast.StructType); ok {
2485		for _, fi := range s.Fields.List {
2486			typ := fi.Type
2487			if fi.Names == nil {
2488				switch v := typ.(type) {
2489				case *ast.Ident:
2490					if t := w.curPackage.findType(v.Name); t != nil {
2491						return w.lookupFunction(v.Name, name)
2492					}
2493				case *ast.SelectorExpr:
2494					pt := w.nodeString(typ)
2495					pos := strings.Index(pt, ".")
2496					if pos != -1 {
2497						if p := w.findPackage(pt[:pos]); p != nil {
2498							if t := p.findType(pt[pos+1:]); t != nil {
2499								return w.lookupFunction(pt, name)
2500							}
2501						}
2502					}
2503				case *ast.StarExpr:
2504					return w.findStructFieldFunction(v.X, name)
2505				default:
2506					if apiVerbose {
2507						log.Printf("unable to handle embedded %T", typ)
2508					}
2509				}
2510			}
2511		}
2512	}
2513	return nil, nil
2514}
2515
2516func (w *Walker) findStructField(st ast.Expr, name string) (*ast.Ident, ast.Expr) {
2517	if s, ok := st.(*ast.StructType); ok {
2518		for _, fi := range s.Fields.List {
2519			typ := fi.Type
2520			for _, n := range fi.Names {
2521				if n.Name == name {
2522					return n, fi.Type
2523				}
2524			}
2525			if fi.Names == nil {
2526				switch v := typ.(type) {
2527				case *ast.Ident:
2528					if t := w.curPackage.findType(v.Name); t != nil {
2529						if v.Name == name {
2530							return v, v
2531						}
2532						id, expr := w.findStructField(t, name)
2533						if id != nil {
2534							return id, expr
2535						}
2536					}
2537				case *ast.StarExpr:
2538					switch vv := v.X.(type) {
2539					case *ast.Ident:
2540						if t := w.curPackage.findType(vv.Name); t != nil {
2541							if vv.Name == name {
2542								return vv, v.X
2543							}
2544							id, expr := w.findStructField(t, name)
2545							if id != nil {
2546								return id, expr
2547							}
2548						}
2549					case *ast.SelectorExpr:
2550						pt := w.nodeString(typ)
2551						pos := strings.Index(pt, ".")
2552						if pos != -1 {
2553							if p := w.findPackage(pt[:pos]); p != nil {
2554								if t := p.findType(pt[pos+1:]); t != nil {
2555									return w.findStructField(t, name)
2556								}
2557							}
2558						}
2559					default:
2560						if apiVerbose {
2561							log.Printf("unable to handle embedded starexpr before %T", typ)
2562						}
2563					}
2564				case *ast.SelectorExpr:
2565					pt := w.nodeString(typ)
2566					pos := strings.Index(pt, ".")
2567					if pos != -1 {
2568						if p := w.findPackage(pt[:pos]); p != nil {
2569							if t := p.findType(pt[pos+1:]); t != nil {
2570								return w.findStructField(t, name)
2571							}
2572						}
2573					}
2574				default:
2575					if apiVerbose {
2576						log.Printf("unable to handle embedded %T", typ)
2577					}
2578				}
2579			}
2580		}
2581	}
2582	return nil, nil
2583}
2584
2585func (w *Walker) lookupFunction(name, sel string) (*TypeInfo, error) {
2586	name = strings.TrimLeft(name, "*")
2587	if p := w.findPackage(name); p != nil {
2588		fn := p.findCallFunc(sel)
2589		if fn != nil {
2590			return &TypeInfo{Kind: KindFunc, X: fn, Name: name + "." + sel, T: fn, Type: w.nodeString(w.namelessType(fn))}, nil
2591		}
2592	}
2593	pos := strings.Index(name, ".")
2594	if pos != -1 {
2595		pkg := name[:pos]
2596		typ := name[pos+1:]
2597		if p := w.findPackage(pkg); p != nil {
2598			if ident, fn := p.findMethod(typ, sel); fn != nil {
2599				return &TypeInfo{Kind: KindMethod, X: fn, Name: name + "." + sel, T: ident, Type: w.nodeString(w.namelessType(fn))}, nil
2600			}
2601		}
2602		return nil, fmt.Errorf("not lookup pkg type function pkg: %s, %s. %s. %s", name, pkg, typ, sel)
2603	}
2604
2605	//find local var.func()
2606	if ns, nt, n := w.resolveName(name); n >= 0 {
2607		var vt string
2608		if nt != nil {
2609			vt = w.nodeString(w.namelessType(nt))
2610		} else if ns != nil {
2611			typ, err := w.varValueType(ns, n)
2612			if err == nil {
2613				vt = typ
2614			}
2615		} else {
2616			typ := w.curPackage.findSelectorType(name)
2617			if typ != nil {
2618				vt = w.nodeString(w.namelessType(typ))
2619			}
2620		}
2621		if strings.HasPrefix(vt, "*") {
2622			vt = vt[1:]
2623		}
2624		if vt == "error" && sel == "Error" {
2625			return &TypeInfo{Kind: KindBuiltin, Name: "error.Error", Type: "()string"}, nil
2626		}
2627		if fn, ok := w.curPackage.functions[vt+"."+sel]; ok {
2628			return &TypeInfo{Kind: KindMethod, X: fn.ft, Name: name + "." + sel, T: fn.ft, Type: w.nodeString(w.namelessType(fn))}, nil
2629		}
2630	}
2631	if typ, ok := w.curPackage.structs[name]; ok {
2632		if fn, ok := w.curPackage.functions[name+"."+sel]; ok {
2633			return &TypeInfo{Kind: KindMethod, X: fn.ft, Name: name + "." + sel, T: fn.ft, Type: w.nodeString(w.namelessType(fn.ft))}, nil
2634		}
2635		if info, err := w.findStructFieldFunction(typ, sel); err == nil {
2636			return info, nil
2637		}
2638		// struct field is type function
2639		if ft := w.findStructFieldType(typ, sel); ft != nil {
2640			typ, err := w.varValueType(ft, 0)
2641			if err != nil {
2642				typ = w.nodeString(ft)
2643			}
2644			return &TypeInfo{Kind: KindField, X: ft, Name: name + "." + sel, T: ft, Type: typ}, nil
2645		}
2646	}
2647
2648	if ident, fn := w.curPackage.findMethod(name, sel); ident != nil && fn != nil {
2649		return &TypeInfo{Kind: KindMethod, X: fn, Name: name + "." + sel, T: ident, Type: w.nodeString(w.namelessType(fn))}, nil
2650	}
2651
2652	if p := w.findPackage(name); p != nil {
2653		fn := p.findCallFunc(sel)
2654		if fn != nil {
2655			return &TypeInfo{Kind: KindFunc, X: fn, Name: name + "." + sel, T: fn, Type: w.nodeString(w.namelessType(fn))}, nil
2656		}
2657		return nil, fmt.Errorf("not find pkg func0 %v.%v", p.name, sel)
2658	}
2659	return nil, fmt.Errorf("not lookup func %v.%v", name, sel)
2660}
2661
2662func (w *Walker) varFunctionType(name, sel string, index int) (string, error) {
2663	name = strings.TrimLeft(name, "*")
2664	pos := strings.Index(name, ".")
2665	if pos != -1 {
2666		pkg := name[:pos]
2667		typ := name[pos+1:]
2668
2669		if p := w.findPackage(pkg); p != nil {
2670			_, fn := p.findMethod(typ, sel)
2671			if fn != nil {
2672				ret := funcRetType(fn, index)
2673				if ret != nil {
2674					return w.pkgRetType(p.name, w.nodeString(w.namelessType(ret))), nil
2675				}
2676			}
2677		}
2678		return "", fmt.Errorf("unknown pkg type function pkg: %s.%s.%s", pkg, typ, sel)
2679	}
2680	//find local var
2681	if v, ok := w.localvar[name]; ok {
2682		vt := v.T
2683		if strings.HasPrefix(vt, "*") {
2684			vt = vt[1:]
2685		}
2686		if vt == "error" && sel == "Error" {
2687			return "string", nil
2688		}
2689		typ, err := w.varFunctionType(vt, sel, 0)
2690		if err == nil {
2691			return typ, nil
2692		}
2693	}
2694	//find global var.func()
2695	if ns, nt, n := w.resolveName(name); n >= 0 {
2696		var vt string
2697		if nt != nil {
2698			vt = w.nodeString(w.namelessType(nt))
2699		} else if ns != nil {
2700			typ, err := w.varValueType(ns, n)
2701			if err == nil {
2702				vt = typ
2703			}
2704		} else {
2705			typ := w.curPackage.findSelectorType(name)
2706			if typ != nil {
2707				vt = w.nodeString(w.namelessType(typ))
2708			}
2709		}
2710		if strings.HasPrefix(vt, "*") {
2711			vt = vt[1:]
2712		}
2713		if vt == "error" && sel == "Error" {
2714			return "string", nil
2715		}
2716		if fn, ok := w.curPackage.functions[vt+"."+sel]; ok {
2717			return w.nodeString(w.namelessType(funcRetType(fn.ft, index))), nil
2718		}
2719	}
2720	if typ, ok := w.curPackage.structs[name]; ok {
2721		if ft := w.findStructFieldType(typ, sel); ft != nil {
2722			return w.varValueType(ft, index)
2723		}
2724	}
2725	//find pkg.func()
2726	if p := w.findPackage(name); p != nil {
2727		typ := p.findCallType(sel, index)
2728		if typ != nil {
2729			return w.pkgRetType(p.name, w.nodeString(w.namelessType(typ))), nil
2730		}
2731		//log.Println("->", p.functions)
2732		return "", fmt.Errorf("not find pkg func1 %v . %v", p.name, sel)
2733	}
2734	return "", fmt.Errorf("not find func %v.%v", name, sel)
2735}
2736
2737func (w *Walker) lookupSelector(name string, sel string) (*TypeInfo, error) {
2738	name = strings.TrimLeft(name, "*")
2739	pos := strings.Index(name, ".")
2740	if pos != -1 {
2741		pkg := name[:pos]
2742		typ := name[pos+1:]
2743		if p := w.findPackage(pkg); p != nil {
2744			t := p.findType(typ)
2745			if t != nil {
2746				typ := w.findStructFieldType(t, sel)
2747				if typ != nil {
2748					return &TypeInfo{Kind: KindField, X: typ, Name: name + "." + sel, T: typ, Type: w.pkgRetType(p.name, w.nodeString(w.namelessType(typ)))}, nil
2749				}
2750			}
2751		}
2752		return nil, fmt.Errorf("lookup unknown pkg type selector pkg: %s.%s %s", pkg, typ, sel)
2753	}
2754
2755	if lv, ok := w.localvar[name]; ok {
2756		return w.lookupSelector(lv.T, sel)
2757	}
2758
2759	vs, vt, n := w.resolveName(name)
2760	if n >= 0 {
2761		var typ string
2762		if vt != nil {
2763			typ = w.nodeString(w.namelessType(vt))
2764		} else {
2765			typ, _ = w.varValueType(vs, n)
2766		}
2767		if strings.HasPrefix(typ, "*") {
2768			typ = typ[1:]
2769		}
2770		//typ is type, find real type
2771		for k, v := range w.curPackage.types {
2772			if k == typ {
2773				typ = w.nodeString(w.namelessType(v))
2774			}
2775		}
2776		pos := strings.Index(typ, ".")
2777		if pos == -1 {
2778			t := w.curPackage.findType(typ)
2779			if t != nil {
2780				typ := w.findStructFieldType(t, sel)
2781				if typ != nil {
2782					return &TypeInfo{Kind: KindField, X: typ, Name: name + "." + sel, T: typ, Type: w.nodeString(w.namelessType(typ))}, nil
2783				}
2784			}
2785		} else {
2786			name := typ[:pos]
2787			typ = typ[pos+1:]
2788			if p := w.findPackage(name); p != nil {
2789				t := p.findType(typ)
2790				if t != nil {
2791					typ := w.findStructFieldType(t, sel)
2792					if typ != nil {
2793						return &TypeInfo{Kind: KindField, X: typ, Name: name + "." + sel, T: typ, Type: w.nodeString(w.namelessType(typ))}, nil
2794					}
2795				}
2796			}
2797		}
2798	}
2799	if p := w.findPackage(name); p != nil {
2800		typ := p.findSelectorType(sel)
2801		if typ != nil {
2802			return &TypeInfo{Kind: KindType, X: typ, Name: name + "." + sel, T: typ, Type: w.pkgRetType(p.name, w.nodeString(w.namelessType(typ)))}, nil
2803		}
2804	}
2805	t := w.curPackage.findType(name)
2806	if t != nil {
2807		typ := w.findStructFieldType(t, sel)
2808		if typ != nil {
2809			return &TypeInfo{Kind: KindField, X: typ, Name: name + "." + sel, T: typ, Type: w.nodeString(w.namelessType(typ))}, nil
2810		}
2811	}
2812	if t, ok := w.curPackage.types[name]; ok {
2813		return w.lookupSelector(w.nodeString(t), sel)
2814	}
2815	return nil, fmt.Errorf("unknown selector expr ident: %s.%s", name, sel)
2816}
2817
2818func (w *Walker) varSelectorType(name string, sel string) (string, error) {
2819	name = strings.TrimLeft(name, "*")
2820	pos := strings.Index(name, ".")
2821	if pos != -1 {
2822		pkg := name[:pos]
2823		typ := name[pos+1:]
2824		if p := w.findPackage(pkg); p != nil {
2825			t := p.findType(typ)
2826			if t != nil {
2827				typ := w.findStructFieldType(t, sel)
2828				if typ != nil {
2829					return w.pkgRetType(pkg, w.nodeString(w.namelessType(typ))), nil
2830				}
2831			}
2832		}
2833		return "", fmt.Errorf("unknown pkg type selector pkg: %s.%s.%s", pkg, typ, sel)
2834	}
2835	//check local
2836	if lv, ok := w.localvar[name]; ok {
2837		return w.varSelectorType(lv.T, sel)
2838	}
2839	//check struct
2840	if t := w.curPackage.findType(name); t != nil {
2841		typ := w.findStructFieldType(t, sel)
2842		if typ != nil {
2843			return w.nodeString(w.namelessType(typ)), nil
2844		}
2845	}
2846	//check var
2847	vs, vt, n := w.resolveName(name)
2848	if n >= 0 {
2849		var typ string
2850		if vt != nil {
2851			typ = w.nodeString(w.namelessType(vt))
2852		} else {
2853			typ, _ = w.varValueType(vs, n)
2854		}
2855		if strings.HasPrefix(typ, "*") {
2856			typ = typ[1:]
2857		}
2858		//typ is type, find real type
2859		for k, v := range w.curPackage.types {
2860			if k == typ {
2861				typ = w.nodeString(w.namelessType(v))
2862			}
2863		}
2864		pos := strings.Index(typ, ".")
2865		if pos == -1 {
2866			t := w.curPackage.findType(typ)
2867			if t != nil {
2868				typ := w.findStructFieldType(t, sel)
2869				if typ != nil {
2870					return w.nodeString(w.namelessType(typ)), nil
2871				}
2872			}
2873		} else {
2874			name := typ[:pos]
2875			typ = typ[pos+1:]
2876			if p := w.findPackage(name); p != nil {
2877				t := p.findType(typ)
2878				if t != nil {
2879					typ := w.findStructFieldType(t, sel)
2880					if typ != nil {
2881						return w.nodeString(w.namelessType(typ)), nil
2882					}
2883				}
2884			}
2885		}
2886	}
2887
2888	if p := w.findPackage(name); p != nil {
2889		typ := p.findSelectorType(sel)
2890		if typ != nil {
2891			return w.pkgRetType(p.name, w.nodeString(w.namelessType(typ))), nil
2892		}
2893	}
2894	return "", fmt.Errorf("unknown var selector expr ident: %s.%s", name, sel)
2895}
2896
2897func (w *Walker) varValueType(vi ast.Expr, index int) (string, error) {
2898	if vi == nil {
2899		return "", nil
2900	}
2901	switch v := vi.(type) {
2902	case *ast.BasicLit:
2903		litType, ok := varType[v.Kind]
2904		if !ok {
2905			return "", fmt.Errorf("unknown basic literal kind %#v", v)
2906		}
2907		return litType, nil
2908	case *ast.CompositeLit:
2909		return w.nodeString(v.Type), nil
2910	case *ast.FuncLit:
2911		return w.nodeString(w.namelessType(v.Type)), nil
2912	case *ast.InterfaceType:
2913		return w.nodeString(v), nil
2914	case *ast.Ellipsis:
2915		typ, err := w.varValueType(v.Elt, index)
2916		if err != nil {
2917			return "", err
2918		}
2919		return "[]" + typ, nil
2920	case *ast.StarExpr:
2921		typ, err := w.varValueType(v.X, index)
2922		if err != nil {
2923			return "", err
2924		}
2925		return "*" + typ, err
2926	case *ast.UnaryExpr:
2927		if v.Op == token.AND {
2928			typ, err := w.varValueType(v.X, index)
2929			return "*" + typ, err
2930		}
2931		return "", fmt.Errorf("unknown unary expr: %#v", v)
2932	case *ast.SelectorExpr:
2933		switch st := v.X.(type) {
2934		case *ast.Ident:
2935			return w.varSelectorType(st.Name, v.Sel.Name)
2936		case *ast.CallExpr:
2937			typ, err := w.varValueType(v.X, index)
2938			if err == nil {
2939				if strings.HasPrefix(typ, "*") {
2940					typ = typ[1:]
2941				}
2942				t := w.curPackage.findType(typ)
2943				if st, ok := t.(*ast.StructType); ok {
2944					for _, fi := range st.Fields.List {
2945						for _, n := range fi.Names {
2946							if n.Name == v.Sel.Name {
2947								return w.varValueType(fi.Type, index)
2948							}
2949						}
2950					}
2951				}
2952			}
2953		case *ast.SelectorExpr:
2954			typ, err := w.varValueType(v.X, index)
2955			if err == nil {
2956				return w.varSelectorType(typ, v.Sel.Name)
2957			}
2958		case *ast.IndexExpr:
2959			typ, err := w.varValueType(st.X, index)
2960			if err == nil {
2961				if strings.HasPrefix(typ, "[]") {
2962					return w.varSelectorType(typ[2:], v.Sel.Name)
2963				}
2964			}
2965		case *ast.CompositeLit:
2966			typ, err := w.varValueType(st.Type, 0)
2967			if err == nil {
2968				//log.Println(typ, v.Sel.Name)
2969				t, err := w.varSelectorType(typ, v.Sel.Name)
2970				if err == nil {
2971					return t, nil
2972				}
2973			}
2974		}
2975		return "", fmt.Errorf("var unknown selector expr: %T %s.%s", v.X, w.nodeString(v.X), v.Sel)
2976	case *ast.Ident:
2977		if v.Name == "true" || v.Name == "false" {
2978			return "bool", nil
2979		}
2980		if isBuiltinType(v.Name) {
2981			return v.Name, nil
2982		}
2983		if lv, ok := w.localvar[v.Name]; ok {
2984			return lv.T, nil
2985		}
2986		vt := w.curPackage.findType(v.Name)
2987		if vt != nil {
2988			if _, ok := vt.(*ast.StructType); ok {
2989				return v.Name, nil
2990			}
2991			return w.nodeString(vt), nil
2992		}
2993		vs, _, n := w.resolveName(v.Name)
2994		if n >= 0 {
2995			return w.varValueType(vs, n)
2996		}
2997		return "", fmt.Errorf("unresolved identifier: %q", v.Name)
2998	case *ast.BinaryExpr:
2999		//== > < ! != >= <=
3000		if v.Op == token.EQL || v.Op == token.LSS || v.Op == token.GTR || v.Op == token.NOT ||
3001			v.Op == token.NEQ || v.Op == token.LEQ || v.Op == token.GEQ {
3002			return "bool", nil
3003		}
3004		left, err := w.varValueType(v.X, index)
3005		if err != nil {
3006			return "", err
3007		}
3008		right, err := w.varValueType(v.Y, index)
3009		if err != nil {
3010			return "", err
3011		}
3012		if left != right {
3013			return "", fmt.Errorf("in BinaryExpr, unhandled type mismatch; left=%q, right=%q", left, right)
3014		}
3015		return left, nil
3016	case *ast.ParenExpr:
3017		return w.varValueType(v.X, index)
3018	case *ast.CallExpr:
3019		switch ft := v.Fun.(type) {
3020		case *ast.ArrayType:
3021			return w.nodeString(v.Fun), nil
3022		case *ast.Ident:
3023			switch ft.Name {
3024			case "make":
3025				return w.nodeString(w.namelessType(v.Args[0])), nil
3026			case "new":
3027				return "*" + w.nodeString(w.namelessType(v.Args[0])), nil
3028			case "append":
3029				return w.varValueType(v.Args[0], 0)
3030			case "recover":
3031				return "interface{}", nil
3032			case "len", "cap", "copy":
3033				return "int", nil
3034			case "complex":
3035				return "complex128", nil
3036			case "real":
3037				return "float64", nil
3038			case "imag":
3039				return "float64", nil
3040			}
3041			if isBuiltinType(ft.Name) {
3042				return ft.Name, nil
3043			}
3044			typ := w.curPackage.findCallType(ft.Name, index)
3045			if typ != nil {
3046				return w.nodeString(w.namelessType(typ)), nil
3047			}
3048			//if local var type
3049			if fn, ok := w.localvar[ft.Name]; ok {
3050				typ := fn.T
3051				if strings.HasPrefix(typ, "func(") {
3052					expr, err := parser.ParseExpr(typ + "{}")
3053					if err == nil {
3054						if fl, ok := expr.(*ast.FuncLit); ok {
3055							retType := funcRetType(fl.Type, index)
3056							if retType != nil {
3057								return w.nodeString(w.namelessType(retType)), nil
3058							}
3059						}
3060					}
3061				}
3062			}
3063			//if var is func() type
3064			vs, _, n := w.resolveName(ft.Name)
3065			if n >= 0 {
3066				if vs != nil {
3067					typ, err := w.varValueType(vs, n)
3068					if err == nil {
3069						if strings.HasPrefix(typ, "func(") {
3070							expr, err := parser.ParseExpr(typ + "{}")
3071							if err == nil {
3072								if fl, ok := expr.(*ast.FuncLit); ok {
3073									retType := funcRetType(fl.Type, index)
3074									if retType != nil {
3075										return w.nodeString(w.namelessType(retType)), nil
3076									}
3077								}
3078							}
3079						}
3080					}
3081				}
3082			}
3083			return "", fmt.Errorf("unknown funcion %s %s", w.curPackageName, ft.Name)
3084		case *ast.SelectorExpr:
3085			typ, err := w.varValueType(ft.X, index)
3086			if err == nil {
3087				if strings.HasPrefix(typ, "*") {
3088					typ = typ[1:]
3089				}
3090				retType := w.curPackage.findCallType(typ+"."+ft.Sel.Name, index)
3091				if retType != nil {
3092					return w.nodeString(w.namelessType(retType)), nil
3093				}
3094			}
3095			switch st := ft.X.(type) {
3096			case *ast.Ident:
3097				return w.varFunctionType(st.Name, ft.Sel.Name, index)
3098			case *ast.CallExpr:
3099				typ, err := w.varValueType(st, 0)
3100				if err != nil {
3101					return "", err
3102				}
3103				return w.varFunctionType(typ, ft.Sel.Name, index)
3104			case *ast.SelectorExpr:
3105				typ, err := w.varValueType(st, index)
3106				if err == nil {
3107					return w.varFunctionType(typ, ft.Sel.Name, index)
3108				}
3109			case *ast.IndexExpr:
3110				typ, err := w.varValueType(st.X, index)
3111				if err == nil {
3112					if strings.HasPrefix(typ, "[]") {
3113						return w.varFunctionType(typ[2:], ft.Sel.Name, index)
3114					}
3115				}
3116			case *ast.TypeAssertExpr:
3117				typ := w.nodeString(w.namelessType(st.Type))
3118				typ = strings.TrimLeft(typ, "*")
3119				return w.varFunctionType(typ, ft.Sel.Name, index)
3120			}
3121			return "", fmt.Errorf("unknown var function selector %v %T", w.nodeString(ft.X), ft.X)
3122		case *ast.FuncLit:
3123			retType := funcRetType(ft.Type, index)
3124			if retType != nil {
3125				return w.nodeString(w.namelessType(retType)), nil
3126			}
3127		case *ast.CallExpr:
3128			typ, err := w.varValueType(v.Fun, 0)
3129			if err == nil && strings.HasPrefix(typ, "func(") {
3130				expr, err := parser.ParseExpr(typ + "{}")
3131				if err == nil {
3132					if fl, ok := expr.(*ast.FuncLit); ok {
3133						retType := funcRetType(fl.Type, index)
3134						if retType != nil {
3135							return w.nodeString(w.namelessType(retType)), nil
3136						}
3137					}
3138				}
3139			}
3140		}
3141		return "", fmt.Errorf("not a known function %T %v", v.Fun, w.nodeString(v.Fun))
3142	case *ast.MapType:
3143		return fmt.Sprintf("map[%s](%s)", w.nodeString(w.namelessType(v.Key)), w.nodeString(w.namelessType(v.Value))), nil
3144	case *ast.ArrayType:
3145		return fmt.Sprintf("[]%s", w.nodeString(w.namelessType(v.Elt))), nil
3146	case *ast.FuncType:
3147		return w.nodeString(w.namelessType(v)), nil
3148	case *ast.IndexExpr:
3149		typ, err := w.varValueType(v.X, index)
3150		typ = strings.TrimLeft(typ, "*")
3151		if err == nil {
3152			if index == 0 {
3153				return typ, nil
3154			} else if index == 1 {
3155				return "bool", nil
3156			}
3157			if strings.HasPrefix(typ, "[]") {
3158				return typ[2:], nil
3159			} else if strings.HasPrefix(typ, "map[") {
3160				node, err := parser.ParseExpr(typ + "{}")
3161				if err == nil {
3162					if cl, ok := node.(*ast.CompositeLit); ok {
3163						if m, ok := cl.Type.(*ast.MapType); ok {
3164							return w.nodeString(w.namelessType(m.Value)), nil
3165						}
3166					}
3167				}
3168			}
3169		}
3170		return "", fmt.Errorf("unknown index %v %v %v %v", typ, v.X, index, err)
3171	case *ast.SliceExpr:
3172		return w.varValueType(v.X, index)
3173	case *ast.ChanType:
3174		typ, err := w.varValueType(v.Value, index)
3175		if err == nil {
3176			if v.Dir == ast.RECV {
3177				return "<-chan " + typ, nil
3178			} else if v.Dir == ast.SEND {
3179				return "chan<- " + typ, nil
3180			}
3181			return "chan " + typ, nil
3182		}
3183	case *ast.TypeAssertExpr:
3184		if index == 1 {
3185			return "bool", nil
3186		}
3187		return w.nodeString(w.namelessType(v.Type)), nil
3188	default:
3189		return "", fmt.Errorf("unknown value type %v %T", w.nodeString(vi), vi)
3190	}
3191	//panic("unreachable")
3192	return "", fmt.Errorf("unreachable value type %v %T", vi, vi)
3193}
3194
3195// resolveName finds a top-level node named name and returns the node
3196// v and its type t, if known.
3197func (w *Walker) resolveName(name string) (v ast.Expr, t interface{}, n int) {
3198	for _, file := range w.curPackage.apkg.Files {
3199		for _, di := range file.Decls {
3200			switch d := di.(type) {
3201			case *ast.GenDecl:
3202				switch d.Tok {
3203				case token.VAR:
3204					for _, sp := range d.Specs {
3205						vs := sp.(*ast.ValueSpec)
3206						for i, vname := range vs.Names {
3207							if vname.Name == name {
3208								if len(vs.Values) == 1 {
3209									return vs.Values[0], vs.Type, i
3210								}
3211								return nil, vs.Type, i
3212							}
3213						}
3214					}
3215				}
3216			}
3217		}
3218	}
3219	return nil, nil, -1
3220}
3221
3222// constDepPrefix is a magic prefix that is used by constValueType
3223// and walkConst to signal that a type isn't known yet. These are
3224// resolved at the end of walking of a package's files.
3225const constDepPrefix = "const-dependency:"
3226
3227func (w *Walker) walkConst(vs *ast.ValueSpec) {
3228	for _, ident := range vs.Names {
3229		if !w.isExtract(ident.Name) {
3230			continue
3231		}
3232		litType := ""
3233		if vs.Type != nil {
3234			litType = w.nodeString(vs.Type)
3235		} else {
3236			litType = w.lastConstType
3237			if vs.Values != nil {
3238				if len(vs.Values) != 1 {
3239					log.Fatalf("const %q, values: %#v", ident.Name, vs.Values)
3240				}
3241				var err error
3242				litType, err = w.constValueType(vs.Values[0])
3243				if err != nil {
3244					if apiVerbose {
3245						log.Printf("unknown kind in const %q (%T): %v", ident.Name, vs.Values[0], err)
3246					}
3247					litType = "unknown-type"
3248				}
3249			}
3250		}
3251		if strings.HasPrefix(litType, constDepPrefix) {
3252			dep := litType[len(constDepPrefix):]
3253			w.constDep[ident.Name] = &ExprType{T: dep, X: ident}
3254			continue
3255		}
3256		if litType == "" {
3257			if apiVerbose {
3258				log.Printf("unknown kind in const %q", ident.Name)
3259			}
3260			continue
3261		}
3262		w.lastConstType = litType
3263
3264		w.curPackage.consts[ident.Name] = &ExprType{T: litType, X: ident}
3265
3266		if isExtract(ident.Name) {
3267			w.emitFeature(fmt.Sprintf("const %s %s", ident, litType), ident.Pos())
3268		}
3269	}
3270}
3271
3272func (w *Walker) resolveConstantDeps() {
3273	var findConstType func(string) string
3274	findConstType = func(ident string) string {
3275		if dep, ok := w.constDep[ident]; ok {
3276			return findConstType(dep.T)
3277		}
3278		if t, ok := w.curPackage.consts[ident]; ok {
3279			return t.T
3280		}
3281		return ""
3282	}
3283	for ident, info := range w.constDep {
3284		if !isExtract(ident) {
3285			continue
3286		}
3287		t := findConstType(ident)
3288		if t == "" {
3289			if apiVerbose {
3290				log.Printf("failed to resolve constant %q", ident)
3291			}
3292			continue
3293		}
3294		w.curPackage.consts[ident] = &ExprType{T: t, X: info.X}
3295		w.emitFeature(fmt.Sprintf("const %s %s", ident, t), info.X.Pos())
3296	}
3297}
3298
3299func (w *Walker) walkVar(vs *ast.ValueSpec) {
3300	if vs.Type != nil {
3301		typ := w.nodeString(vs.Type)
3302		for _, ident := range vs.Names {
3303			w.curPackage.vars[ident.Name] = &ExprType{T: typ, X: ident}
3304			if isExtract(ident.Name) {
3305				w.emitFeature(fmt.Sprintf("var %s %s", ident, typ), ident.Pos())
3306			}
3307		}
3308	} else if len(vs.Names) == len(vs.Values) {
3309		for n, ident := range vs.Names {
3310			if !w.isExtract(ident.Name) {
3311				continue
3312			}
3313			typ, err := w.varValueType(vs.Values[n], n)
3314			if err != nil {
3315				if apiVerbose {
3316					log.Printf("unknown type of variable0 %q, type %T, error = %v, pos=%s",
3317						ident.Name, vs.Values[n], err, w.fset.Position(vs.Pos()))
3318				}
3319				typ = "unknown-type"
3320			}
3321			w.curPackage.vars[ident.Name] = &ExprType{T: typ, X: ident}
3322			if isExtract(ident.Name) {
3323				w.emitFeature(fmt.Sprintf("var %s %s", ident, typ), ident.Pos())
3324			}
3325		}
3326	} else if len(vs.Values) == 1 {
3327		for n, ident := range vs.Names {
3328			if !w.isExtract(ident.Name) {
3329				continue
3330			}
3331			typ, err := w.varValueType(vs.Values[0], n)
3332			if err != nil {
3333				if apiVerbose {
3334					log.Printf("unknown type of variable1 %q, type %T, error = %v, pos=%s",
3335						ident.Name, vs.Values[0], err, w.fset.Position(vs.Pos()))
3336				}
3337				typ = "unknown-type"
3338			}
3339			w.curPackage.vars[ident.Name] = &ExprType{T: typ, X: ident}
3340			if isExtract(ident.Name) {
3341				w.emitFeature(fmt.Sprintf("var %s %s", ident, typ), ident.Pos())
3342			}
3343		}
3344	}
3345}
3346
3347func (w *Walker) nodeString(node interface{}) string {
3348	if node == nil {
3349		return ""
3350	}
3351	var b bytes.Buffer
3352	printer.Fprint(&b, w.fset, node)
3353	return b.String()
3354}
3355
3356func (w *Walker) nodeDebug(node interface{}) string {
3357	if node == nil {
3358		return ""
3359	}
3360	var b bytes.Buffer
3361	ast.Fprint(&b, w.fset, node, nil)
3362	return b.String()
3363}
3364
3365func (w *Walker) noteInterface(name string, it *ast.InterfaceType) {
3366	w.interfaces[pkgSymbol{w.curPackageName, name}] = it
3367}
3368
3369func (w *Walker) walkTypeSpec(ts *ast.TypeSpec) {
3370	name := ts.Name.Name
3371	if !isExtract(name) {
3372		return
3373	}
3374	switch t := ts.Type.(type) {
3375	case *ast.StructType:
3376		w.walkStructType(name, t)
3377	case *ast.InterfaceType:
3378		w.walkInterfaceType(name, t)
3379	default:
3380		w.emitFeature(fmt.Sprintf("type %s %s", name, w.nodeString(ts.Type)), t.Pos()-token.Pos(len(name)+1))
3381	}
3382}
3383
3384func (w *Walker) walkStructType(name string, t *ast.StructType) {
3385	typeStruct := fmt.Sprintf("type %s struct", name)
3386	w.emitFeature(typeStruct, t.Pos()-token.Pos(len(name)+1))
3387	pop := w.pushScope(typeStruct)
3388	defer pop()
3389	for _, f := range t.Fields.List {
3390		typ := f.Type
3391		for _, name := range f.Names {
3392			if isExtract(name.Name) {
3393				w.emitFeature(fmt.Sprintf("%s %s", name, w.nodeString(w.namelessType(typ))), name.Pos())
3394			}
3395		}
3396		if f.Names == nil {
3397			switch v := typ.(type) {
3398			case *ast.Ident:
3399				if isExtract(v.Name) {
3400					w.emitFeature(fmt.Sprintf("embedded %s", v.Name), v.Pos())
3401				}
3402			case *ast.StarExpr:
3403				switch vv := v.X.(type) {
3404				case *ast.Ident:
3405					if isExtract(vv.Name) {
3406						w.emitFeature(fmt.Sprintf("embedded *%s", vv.Name), vv.Pos())
3407					}
3408				case *ast.SelectorExpr:
3409					w.emitFeature(fmt.Sprintf("embedded %s", w.nodeString(typ)), v.Pos())
3410				default:
3411					log.Fatalf("unable to handle embedded starexpr before %T", typ)
3412				}
3413			case *ast.SelectorExpr:
3414				w.emitFeature(fmt.Sprintf("embedded %s", w.nodeString(typ)), v.Pos())
3415			default:
3416				if apiVerbose {
3417					log.Printf("unable to handle embedded %T", typ)
3418				}
3419			}
3420		}
3421	}
3422}
3423
3424// typeMethod is a method of an interface.
3425type typeMethod struct {
3426	name string // "Read"
3427	sig  string // "([]byte) (int, error)", from funcSigString
3428	ft   *ast.FuncType
3429	pos  token.Pos
3430	recv ast.Expr
3431}
3432
3433// interfaceMethods returns the expanded list of exported methods for an interface.
3434// The boolean complete reports whether the list contains all methods (that is, the
3435// interface has no unexported methods).
3436// pkg is the complete package name ("net/http")
3437// iname is the interface name.
3438func (w *Walker) interfaceMethods(pkg, iname string) (methods []typeMethod, complete bool) {
3439	t, ok := w.interfaces[pkgSymbol{pkg, iname}]
3440	if !ok {
3441		if apiVerbose {
3442			log.Printf("failed to find interface %s.%s", pkg, iname)
3443		}
3444		return
3445	}
3446
3447	complete = true
3448	for _, f := range t.Methods.List {
3449		typ := f.Type
3450		switch tv := typ.(type) {
3451		case *ast.FuncType:
3452			for _, mname := range f.Names {
3453				if isExtract(mname.Name) {
3454					ft := typ.(*ast.FuncType)
3455					methods = append(methods, typeMethod{
3456						name: mname.Name,
3457						sig:  w.funcSigString(ft),
3458						ft:   ft,
3459						pos:  f.Pos(),
3460					})
3461				} else {
3462					complete = false
3463				}
3464			}
3465		case *ast.Ident:
3466			embedded := typ.(*ast.Ident).Name
3467			if embedded == "error" {
3468				methods = append(methods, typeMethod{
3469					name: "Error",
3470					sig:  "() string",
3471					ft: &ast.FuncType{
3472						Params: nil,
3473						Results: &ast.FieldList{
3474							List: []*ast.Field{
3475								&ast.Field{
3476									Type: &ast.Ident{
3477										Name: "string",
3478									},
3479								},
3480							},
3481						},
3482					},
3483					pos: f.Pos(),
3484				})
3485				continue
3486			}
3487			if !isExtract(embedded) {
3488				log.Fatalf("unexported embedded interface %q in exported interface %s.%s; confused",
3489					embedded, pkg, iname)
3490			}
3491			m, c := w.interfaceMethods(pkg, embedded)
3492			methods = append(methods, m...)
3493			complete = complete && c
3494		case *ast.SelectorExpr:
3495			lhs := w.nodeString(tv.X)
3496			rhs := w.nodeString(tv.Sel)
3497			fpkg, ok := w.selectorFullPkg[lhs]
3498			if !ok {
3499				log.Fatalf("can't resolve selector %q in interface %s.%s", lhs, pkg, iname)
3500			}
3501			m, c := w.interfaceMethods(fpkg, rhs)
3502			methods = append(methods, m...)
3503			complete = complete && c
3504		default:
3505			log.Fatalf("unknown type %T in interface field", typ)
3506		}
3507	}
3508	return
3509}
3510
3511func (w *Walker) walkInterfaceType(name string, t *ast.InterfaceType) {
3512	methNames := []string{}
3513	pop := w.pushScope("type " + name + " interface")
3514	methods, complete := w.interfaceMethods(w.curPackageName, name)
3515	w.packageMap[w.curPackageName].interfaceMethods[name] = methods
3516	for _, m := range methods {
3517		methNames = append(methNames, m.name)
3518		w.emitFeature(fmt.Sprintf("%s%s", m.name, m.sig), m.pos)
3519	}
3520	if !complete {
3521		// The method set has unexported methods, so all the
3522		// implementations are provided by the same package,
3523		// so the method set can be extended. Instead of recording
3524		// the full set of names (below), record only that there were
3525		// unexported methods. (If the interface shrinks, we will notice
3526		// because a method signature emitted during the last loop,
3527		// will disappear.)
3528		w.emitFeature("unexported methods", 0)
3529	}
3530	pop()
3531
3532	if !complete {
3533		return
3534	}
3535
3536	sort.Strings(methNames)
3537	if len(methNames) == 0 {
3538		w.emitFeature(fmt.Sprintf("type %s interface {}", name), t.Pos()-token.Pos(len(name)+1))
3539	} else {
3540		w.emitFeature(fmt.Sprintf("type %s interface { %s }", name, strings.Join(methNames, ", ")), t.Pos()-token.Pos(len(name)+1))
3541	}
3542}
3543
3544func baseTypeName(x ast.Expr) (name string, imported bool) {
3545	switch t := x.(type) {
3546	case *ast.Ident:
3547		return t.Name, false
3548	case *ast.SelectorExpr:
3549		if _, ok := t.X.(*ast.Ident); ok {
3550			// only possible for qualified type names;
3551			// assume type is imported
3552			return t.Sel.Name, true
3553		}
3554	case *ast.StarExpr:
3555		return baseTypeName(t.X)
3556	}
3557	return
3558}
3559
3560func (w *Walker) peekFuncDecl(f *ast.FuncDecl) {
3561	var fname = f.Name.Name
3562	var recv ast.Expr
3563	if f.Recv != nil {
3564		recvTypeName, imp := baseTypeName(f.Recv.List[0].Type)
3565		if imp {
3566			return
3567		}
3568		fname = recvTypeName + "." + f.Name.Name
3569		recv = f.Recv.List[0].Type
3570	}
3571	// Record return type for later use.
3572	//if f.Type.Results != nil && len(f.Type.Results.List) >= 1 {
3573	// record all function
3574	w.curPackage.functions[fname] = typeMethod{
3575		name: fname,
3576		sig:  w.funcSigString(f.Type),
3577		ft:   f.Type,
3578		pos:  f.Pos(),
3579		recv: recv,
3580	}
3581	//}
3582}
3583
3584func (w *Walker) walkFuncDecl(f *ast.FuncDecl) {
3585	if !w.isExtract(f.Name.Name) {
3586		return
3587	}
3588	if f.Recv != nil {
3589		// Method.
3590		recvType := w.nodeString(f.Recv.List[0].Type)
3591		keep := isExtract(recvType) ||
3592			(strings.HasPrefix(recvType, "*") &&
3593				isExtract(recvType[1:]))
3594		if !keep {
3595			return
3596		}
3597		w.emitFeature(fmt.Sprintf("method (%s) %s%s", recvType, f.Name.Name, w.funcSigString(f.Type)), f.Name.Pos())
3598		return
3599	}
3600	// Else, a function
3601	w.emitFeature(fmt.Sprintf("func %s%s", f.Name.Name, w.funcSigString(f.Type)), f.Name.Pos())
3602}
3603
3604func (w *Walker) funcSigString(ft *ast.FuncType) string {
3605	var b bytes.Buffer
3606	writeField := func(b *bytes.Buffer, f *ast.Field) {
3607		if n := len(f.Names); n > 1 {
3608			for i := 0; i < n; i++ {
3609				if i > 0 {
3610					b.WriteString(", ")
3611				}
3612				b.WriteString(w.nodeString(w.namelessType(f.Type)))
3613			}
3614		} else {
3615			b.WriteString(w.nodeString(w.namelessType(f.Type)))
3616		}
3617	}
3618	b.WriteByte('(')
3619	if ft.Params != nil {
3620		for i, f := range ft.Params.List {
3621			if i > 0 {
3622				b.WriteString(", ")
3623			}
3624			writeField(&b, f)
3625		}
3626	}
3627	b.WriteByte(')')
3628	if ft.Results != nil {
3629		nr := 0
3630		for _, f := range ft.Results.List {
3631			if n := len(f.Names); n > 1 {
3632				nr += n
3633			} else {
3634				nr++
3635			}
3636		}
3637		if nr > 0 {
3638			b.WriteByte(' ')
3639			if nr > 1 {
3640				b.WriteByte('(')
3641			}
3642			for i, f := range ft.Results.List {
3643				if i > 0 {
3644					b.WriteString(", ")
3645				}
3646				writeField(&b, f)
3647			}
3648			if nr > 1 {
3649				b.WriteByte(')')
3650			}
3651		}
3652	}
3653	return b.String()
3654}
3655
3656// namelessType returns a type node that lacks any variable names.
3657func (w *Walker) namelessType(t interface{}) interface{} {
3658	ft, ok := t.(*ast.FuncType)
3659	if !ok {
3660		return t
3661	}
3662	return &ast.FuncType{
3663		Params:  w.namelessFieldList(ft.Params),
3664		Results: w.namelessFieldList(ft.Results),
3665	}
3666}
3667
3668// namelessFieldList returns a deep clone of fl, with the cloned fields
3669// lacking names.
3670func (w *Walker) namelessFieldList(fl *ast.FieldList) *ast.FieldList {
3671	fl2 := &ast.FieldList{}
3672	if fl != nil {
3673		for _, f := range fl.List {
3674			n := len(f.Names)
3675			if n >= 1 {
3676				for i := 0; i < n; i++ {
3677					fl2.List = append(fl2.List, w.namelessField(f))
3678				}
3679			} else {
3680				fl2.List = append(fl2.List, w.namelessField(f))
3681			}
3682		}
3683	}
3684	return fl2
3685}
3686
3687// namelessField clones f, but not preserving the names of fields.
3688// (comments and tags are also ignored)
3689func (w *Walker) namelessField(f *ast.Field) *ast.Field {
3690	return &ast.Field{
3691		Type: f.Type,
3692	}
3693}
3694
3695func (w *Walker) emitFeature(feature string, pos token.Pos) {
3696	if !w.wantedPkg[w.curPackage.name] {
3697		return
3698	}
3699	more := strings.Index(feature, "\n")
3700	if more != -1 {
3701		if len(feature) <= 1024 {
3702			feature = strings.Replace(feature, "\n", " ", 1)
3703			feature = strings.Replace(feature, "\n", ";", -1)
3704			feature = strings.Replace(feature, "\t", " ", -1)
3705		} else {
3706			feature = feature[:more] + " ...more"
3707			if apiVerbose {
3708				log.Printf("feature contains newlines: %v, %s", feature, w.fset.Position(pos))
3709			}
3710		}
3711	}
3712	f := strings.Join(w.scope, w.sep) + w.sep + feature
3713
3714	if _, dup := w.curPackage.features[f]; dup {
3715		return
3716	}
3717	w.curPackage.features[f] = pos
3718}
3719
3720func strListContains(l []string, s string) bool {
3721	for _, v := range l {
3722		if v == s {
3723			return true
3724		}
3725	}
3726	return false
3727}
3728
3729const goosList = "darwin freebsd linux netbsd openbsd plan9 windows "
3730const goarchList = "386 amd64 arm "
3731
3732// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
3733// suffix which does not match the current system.
3734// The recognized name formats are:
3735//
3736//     name_$(GOOS).*
3737//     name_$(GOARCH).*
3738//     name_$(GOOS)_$(GOARCH).*
3739//     name_$(GOOS)_test.*
3740//     name_$(GOARCH)_test.*
3741//     name_$(GOOS)_$(GOARCH)_test.*
3742//
3743func isOSArchFile(ctxt *build.Context, name string) bool {
3744	if dot := strings.Index(name, "."); dot != -1 {
3745		name = name[:dot]
3746	}
3747	l := strings.Split(name, "_")
3748	if n := len(l); n > 0 && l[n-1] == "test" {
3749		l = l[:n-1]
3750	}
3751	n := len(l)
3752	if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
3753		return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH
3754	}
3755	if n >= 1 && knownOS[l[n-1]] {
3756		return l[n-1] == ctxt.GOOS
3757	}
3758	if n >= 1 && knownArch[l[n-1]] {
3759		return l[n-1] == ctxt.GOARCH
3760	}
3761	return false
3762}
3763
3764var knownOS = make(map[string]bool)
3765var knownArch = make(map[string]bool)
3766
3767func init() {
3768	for _, v := range strings.Fields(goosList) {
3769		knownOS[v] = true
3770	}
3771	for _, v := range strings.Fields(goarchList) {
3772		knownArch[v] = true
3773	}
3774}
3775