github.com/please-build/puku@v1.7.3-0.20240516143641-f7d7f4941f57/generate/import.go (about) 1 package generate 2 3 import ( 4 "go/parser" 5 "go/token" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/please-build/puku/kinds" 11 ) 12 13 // GoFile represents a single Go file in a package 14 type GoFile struct { 15 // Name is the name from the package clause of this file 16 Name, FileName string 17 // Imports are the imports of this file 18 Imports []string 19 } 20 21 // ImportDir does _some_ of what the go/build ImportDir does but is more permissive. 22 func ImportDir(dir string) (map[string]*GoFile, error) { 23 files, err := os.ReadDir(dir) 24 if err != nil { 25 return nil, err 26 } 27 28 ret := make(map[string]*GoFile, len(files)) 29 for _, info := range files { 30 if !info.Type().IsRegular() { 31 continue 32 } 33 34 if filepath.Ext(info.Name()) != ".go" { 35 continue 36 } 37 38 f, err := importFile(dir, info.Name()) 39 if err != nil { 40 return nil, err 41 } 42 ret[info.Name()] = f 43 } 44 45 return ret, nil 46 } 47 48 func importFile(dir, src string) (*GoFile, error) { 49 f, err := parser.ParseFile(token.NewFileSet(), filepath.Join(dir, src), nil, parser.ImportsOnly|parser.ParseComments) 50 if err != nil { 51 return nil, err 52 } 53 imports := make([]string, 0, len(f.Imports)) 54 for _, i := range f.Imports { 55 path := i.Path.Value 56 path = strings.Trim(path, `"`) 57 imports = append(imports, path) 58 } 59 60 return &GoFile{ 61 Name: f.Name.Name, 62 FileName: src, 63 Imports: imports, 64 }, nil 65 } 66 67 // IsExternal returns whether the test is external 68 func (f *GoFile) IsExternal(pkgName string) bool { 69 return f.Name == filepath.Base(pkgName)+"_test" && f.IsTest() 70 } 71 72 func (f *GoFile) IsTest() bool { 73 return strings.HasSuffix(f.FileName, "_test.go") 74 } 75 76 func (f *GoFile) IsCmd() bool { 77 return f.Name == "main" 78 } 79 80 func (f *GoFile) kindType() kinds.Type { 81 if f.IsTest() { 82 return kinds.Test 83 } 84 if f.IsCmd() { 85 return kinds.Bin 86 } 87 return kinds.Lib 88 }