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  }