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 }