github.com/tcncloud/wollemi@v0.8.1/adapters/golang/importer.go (about) 1 package golang 2 3 import ( 4 "go/build" 5 "go/parser" 6 "go/token" 7 "os" 8 "path/filepath" 9 "runtime" 10 "sort" 11 "strings" 12 13 "golang.org/x/mod/modfile" 14 15 "github.com/tcncloud/wollemi/ports/golang" 16 ) 17 18 type Package = golang.Package 19 20 func init() { 21 os.Setenv("GO111MODULE", "OFF") 22 } 23 24 func NewImporter() *Importer { 25 osarch := strings.Join([]string{runtime.GOOS, runtime.GOARCH}, "_") 26 goroot := build.Default.GOROOT 27 28 return &Importer{ 29 gorootpkg: filepath.Join(goroot, "pkg", osarch), 30 gorootsrc: filepath.Join(goroot, "src"), 31 } 32 } 33 34 type Importer struct { 35 gorootpkg string 36 gorootsrc string 37 } 38 39 func (this *Importer) GOPATH() string { 40 return build.Default.GOPATH 41 } 42 43 func (this *Importer) GOROOT() string { 44 return build.Default.GOROOT 45 } 46 47 func (this *Importer) ModulePath(buf []byte) string { 48 return modfile.ModulePath(buf) 49 } 50 51 func (this *Importer) ImportDir(dir string, names []string) (*Package, error) { 52 out := &Package{ 53 GoFileImports: make(map[string][]string, len(names)), 54 } 55 56 fset := token.NewFileSet() 57 58 for _, name := range names { 59 match, err := build.Default.MatchFile(dir, name) 60 if err != nil { 61 return nil, err 62 } 63 64 if !match { 65 out.IgnoredGoFiles = append(out.IgnoredGoFiles, name) 66 continue 67 } 68 69 path := filepath.Join(dir, name) 70 file, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly) 71 if err != nil { 72 return nil, err 73 } 74 75 pkgname := file.Name.String() 76 77 var gofiles *[]string 78 var imports *[]string 79 80 if strings.HasSuffix(name, "_test.go") { 81 if strings.HasSuffix(pkgname, "_test") { 82 gofiles = &out.XTestGoFiles 83 imports = &out.XTestImports 84 if out.Name == "" { 85 out.Name = strings.TrimSuffix(pkgname, "_test") 86 } 87 } else { 88 gofiles = &out.TestGoFiles 89 imports = &out.TestImports 90 if out.Name == "" { 91 out.Name = pkgname 92 } 93 } 94 } else { 95 gofiles = &out.GoFiles 96 imports = &out.Imports 97 if out.Name == "" { 98 out.Name = pkgname 99 } 100 } 101 102 *gofiles = append(*gofiles, name) 103 104 out.GoFileImports[name] = nil 105 106 FileImports: 107 for _, spec := range file.Imports { 108 path := spec.Path.Value 109 path = path[1 : len(path)-1] 110 111 out.GoFileImports[name] = append(out.GoFileImports[name], path) 112 113 for _, have := range *imports { 114 if path == have { 115 continue FileImports 116 } 117 } 118 119 *imports = append(*imports, path) 120 } 121 } 122 123 sort.Strings(out.Imports) 124 sort.Strings(out.TestImports) 125 sort.Strings(out.XTestImports) 126 sort.Strings(out.GoFiles) 127 sort.Strings(out.TestGoFiles) 128 sort.Strings(out.XTestGoFiles) 129 130 out.Goroot = strings.HasPrefix(dir, this.gorootsrc+"/") 131 132 return out, nil 133 } 134 135 func (this *Importer) IsGoroot(path string) bool { 136 pkg := filepath.Join(this.gorootpkg, path+".a") 137 src := filepath.Join(this.gorootsrc, path) 138 139 for _, path := range []string{pkg, src} { 140 if _, err := os.Stat(path); err == nil { 141 return true 142 } 143 } 144 145 return false 146 } 147 148 func NewPackage(in *build.Package, err error) (*Package, error) { 149 if err != nil { 150 return nil, err 151 } 152 153 var out *Package 154 155 if in != nil { 156 out = &Package{ 157 Name: in.Name, 158 Goroot: in.Goroot, 159 Imports: in.Imports, 160 TestImports: in.TestImports, 161 XTestImports: in.XTestImports, 162 GoFiles: in.GoFiles, 163 TestGoFiles: in.TestGoFiles, 164 XTestGoFiles: in.XTestGoFiles, 165 IgnoredGoFiles: in.IgnoredGoFiles, 166 } 167 } 168 169 return out, nil 170 }