github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgGoSource/kmgGoParser/Program.go (about)

     1  package kmgGoParser
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/bronze1man/kmg/kmgConfig"
     6  	"github.com/bronze1man/kmg/kmgFile"
     7  	"github.com/golang/groupcache/singleflight"
     8  	"path/filepath"
     9  	"strings"
    10  	"sync"
    11  )
    12  
    13  // 表示整个程序
    14  type Program struct {
    15  	PackageLookupPathList []string            // GOPATH, GOROOT
    16  	CachedPackageMap      map[string]*Package // pkgPath
    17  	groupCache            singleflight.Group
    18  	locker                sync.Mutex
    19  }
    20  
    21  func NewProgramFromDefault() *Program {
    22  	return &Program{
    23  		PackageLookupPathList: append(kmgConfig.DefaultEnv().GOPATH, kmgConfig.DefaultEnv().GetGOROOT()),
    24  		CachedPackageMap:      map[string]*Package{},
    25  	}
    26  }
    27  
    28  func NewProgram(lookupPathList []string) *Program {
    29  	return &Program{
    30  		PackageLookupPathList: lookupPathList,
    31  		CachedPackageMap:      map[string]*Package{},
    32  	}
    33  }
    34  
    35  func (prog *Program) GetPackage(pkgPath string) *Package {
    36  	pkg := prog.getCachedPackage(pkgPath)
    37  	if pkg != nil {
    38  		return pkg
    39  	}
    40  	_, err := prog.groupCache.Do(pkgPath, func() (interface{}, error) {
    41  		pkg = prog.mustParsePackage(pkgPath)
    42  		prog.setCachedPackage(pkg)
    43  		return nil, nil
    44  	})
    45  	if err != nil {
    46  		panic(err)
    47  	}
    48  	return prog.getCachedPackage(pkgPath)
    49  }
    50  
    51  func (prog *Program) GetNamedType(pkgPath string, name string) *NamedType {
    52  	return prog.GetPackage(pkgPath).LookupNamedType(name)
    53  }
    54  
    55  func (prog *Program) mustParsePackage(pkgPath string) *Package {
    56  	var dirPath string
    57  	var found bool
    58  	for _, lookupPath := range prog.PackageLookupPathList {
    59  		dirPath = filepath.Join(lookupPath, "src", pkgPath)
    60  		if kmgFile.MustFileExist(dirPath) {
    61  			found = true
    62  			break
    63  		}
    64  	}
    65  	if !found {
    66  		panic(fmt.Errorf("can not found pkgPath %s %#v", pkgPath, prog.PackageLookupPathList))
    67  	}
    68  
    69  	pkg := &Package{
    70  		ImportMap: map[string]bool{},
    71  		PkgPath:   pkgPath,
    72  	}
    73  	for _, path := range kmgFile.MustReadDirFileOneLevel(dirPath) {
    74  		if strings.HasSuffix(path, ".go") {
    75  			pkg.mustAddFile(filepath.Join(dirPath, path))
    76  		}
    77  	}
    78  	pkg.Program = prog
    79  	return pkg
    80  }
    81  
    82  func (prog *Program) getCachedPackage(pkgPath string) *Package {
    83  	prog.locker.Lock()
    84  	defer prog.locker.Unlock()
    85  	return prog.CachedPackageMap[pkgPath]
    86  }
    87  
    88  func (prog *Program) setCachedPackage(pkg *Package) {
    89  	prog.locker.Lock()
    90  	defer prog.locker.Unlock()
    91  	prog.CachedPackageMap[pkg.PkgPath] = pkg
    92  }