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  }