git.sr.ht/~sircmpwn/gqlgen@v0.0.0-20200522192042-c84d29a1c940/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 if err != nil { 84 panic(err) 85 } 86 dir = filepath.ToSlash(dir) 87 88 modDir, ok := goModuleRoot(dir) 89 if ok { 90 return modDir 91 } 92 93 for _, gopath := range gopaths { 94 if len(gopath) < len(dir) && strings.EqualFold(gopath, dir[0:len(gopath)]) { 95 return dir[len(gopath)+1:] 96 } 97 } 98 99 return "" 100 } 101 102 var modregex = regexp.MustCompile("module (.*)\n")