github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/internal/code/imports.go (about)

     1  package code
     2  
     3  import (
     4  	"go/build"
     5  	"go/parser"
     6  	"go/token"
     7  	"io/ioutil"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  )
    12  
    13  var gopaths []string
    14  
    15  func init() {
    16  	gopaths = filepath.SplitList(build.Default.GOPATH)
    17  	for i, p := range gopaths {
    18  		gopaths[i] = filepath.ToSlash(filepath.Join(p, "src"))
    19  	}
    20  }
    21  
    22  // NameForDir manually looks for package stanzas in files located in the given directory. This can be
    23  // much faster than having to consult go list, because we already know exactly where to look.
    24  func NameForDir(dir string) string {
    25  	dir, err := filepath.Abs(dir)
    26  	if err != nil {
    27  		return SanitizePackageName(filepath.Base(dir))
    28  	}
    29  	files, err := ioutil.ReadDir(dir)
    30  	if err != nil {
    31  		return SanitizePackageName(filepath.Base(dir))
    32  	}
    33  	fset := token.NewFileSet()
    34  	for _, file := range files {
    35  		if !strings.HasSuffix(strings.ToLower(file.Name()), ".go") {
    36  			continue
    37  		}
    38  
    39  		filename := filepath.Join(dir, file.Name())
    40  		if src, err := parser.ParseFile(fset, filename, nil, parser.PackageClauseOnly); err == nil {
    41  			return src.Name.Name
    42  		}
    43  	}
    44  
    45  	return SanitizePackageName(filepath.Base(dir))
    46  }
    47  
    48  // goModuleRoot returns the root of the current go module if there is a go.mod file in the directory tree
    49  // If not, it returns false
    50  func goModuleRoot(dir string) (string, bool) {
    51  	dir, err := filepath.Abs(dir)
    52  	if err != nil {
    53  		panic(err)
    54  	}
    55  	dir = filepath.ToSlash(dir)
    56  	modDir := dir
    57  	assumedPart := ""
    58  	for {
    59  		f, err := ioutil.ReadFile(filepath.Join(modDir, "go.mod"))
    60  		if err == nil {
    61  			// found it, stop searching
    62  			return string(modregex.FindSubmatch(f)[1]) + assumedPart, true
    63  		}
    64  
    65  		assumedPart = "/" + filepath.Base(modDir) + assumedPart
    66  		parentDir, err := filepath.Abs(filepath.Join(modDir, ".."))
    67  		if err != nil {
    68  			panic(err)
    69  		}
    70  
    71  		if parentDir == modDir {
    72  			// Walked all the way to the root and didnt find anything :'(
    73  			break
    74  		}
    75  		modDir = parentDir
    76  	}
    77  	return "", false
    78  }
    79  
    80  // ImportPathForDir takes a path and returns a golang import path for the package
    81  func ImportPathForDir(dir string) (res string) {
    82  	dir, err := filepath.Abs(dir)
    83  
    84  	if err != nil {
    85  		panic(err)
    86  	}
    87  	dir = filepath.ToSlash(dir)
    88  
    89  	modDir, ok := goModuleRoot(dir)
    90  	if ok {
    91  		return modDir
    92  	}
    93  
    94  	for _, gopath := range gopaths {
    95  		if len(gopath) < len(dir) && strings.EqualFold(gopath, dir[0:len(gopath)]) {
    96  			return dir[len(gopath)+1:]
    97  		}
    98  	}
    99  
   100  	return ""
   101  }
   102  
   103  var modregex = regexp.MustCompile(`module ([^\s]*)`)