github.com/mattn/anko@v0.1.10/cmd/anko-package-gen/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/parser"
     7  	"go/token"
     8  	"log"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"sort"
    13  	"strings"
    14  )
    15  
    16  func pkgName(f string) string {
    17  	file, err := parser.ParseFile(token.NewFileSet(), f, nil, parser.PackageClauseOnly)
    18  	if err != nil || file == nil {
    19  		return ""
    20  	}
    21  	return file.Name.Name
    22  }
    23  
    24  func isGoFile(dir os.FileInfo) bool {
    25  	return !dir.IsDir() &&
    26  		!strings.HasPrefix(dir.Name(), ".") && // ignore .files
    27  		filepath.Ext(dir.Name()) == ".go"
    28  }
    29  
    30  func isPkgFile(dir os.FileInfo) bool {
    31  	return isGoFile(dir) && !strings.HasSuffix(dir.Name(), "_test.go") // ignore test files
    32  }
    33  
    34  func parseDir(p string) (map[string]*ast.Package, error) {
    35  	isGoFile := func(d os.FileInfo) bool {
    36  		return !d.IsDir() && !strings.HasSuffix(d.Name(), "_test.go") && !strings.HasPrefix(d.Name(), "example_")
    37  	}
    38  
    39  	pkgs, err := parser.ParseDir(token.NewFileSet(), p, isGoFile, parser.ParseComments)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	return pkgs, nil
    44  }
    45  
    46  func main() {
    47  	pkg := "flag"
    48  	if len(os.Args) == 2 {
    49  		pkg = os.Args[1]
    50  	}
    51  	b, err := exec.Command("go", "env", "GOROOT").CombinedOutput()
    52  	if err != nil {
    53  		log.Fatal(err)
    54  	}
    55  	paths := []string{filepath.Join(strings.TrimSpace(string(b)), "src")}
    56  	b, err = exec.Command("go", "env", "GOPATH").CombinedOutput()
    57  	if err != nil {
    58  		log.Fatal(err)
    59  	}
    60  	for _, p := range strings.Split(strings.TrimSpace(string(b)), string(filepath.ListSeparator)) {
    61  		paths = append(paths, filepath.Join(p, "src"))
    62  	}
    63  	for _, p := range paths {
    64  		pp := filepath.Join(p, pkg)
    65  		pkgs, err := parseDir(pp)
    66  		if err != nil || len(pkgs) == 0 {
    67  			continue
    68  		}
    69  		names := map[string]bool{}
    70  		pn := pkg
    71  		for _, pp := range pkgs {
    72  			pn = pp.Name
    73  			for _, f := range pp.Files {
    74  				for _, d := range f.Decls {
    75  					switch decl := d.(type) {
    76  					case *ast.GenDecl:
    77  						for _, spec := range decl.Specs {
    78  							if vspec, ok := spec.(*ast.ValueSpec); ok {
    79  								for _, n := range vspec.Names {
    80  									c := n.Name[0]
    81  									if c < 'A' || c > 'Z' {
    82  										continue
    83  									}
    84  									names[n.Name] = true
    85  								}
    86  							}
    87  						}
    88  					case *ast.FuncDecl:
    89  						if decl.Recv != nil {
    90  							continue
    91  						}
    92  						c := decl.Name.Name[0]
    93  						if c < 'A' || c > 'Z' {
    94  							continue
    95  						}
    96  						names[decl.Name.Name] = true
    97  					}
    98  				}
    99  			}
   100  		}
   101  		keys := []string{}
   102  		for k := range names {
   103  			keys = append(keys, k)
   104  		}
   105  		sort.Strings(keys)
   106  		fmt.Printf(`// Package %s implements %s interface for anko script.
   107  package %s
   108  
   109  import (
   110  	"%s"
   111  )
   112  
   113  func init() {
   114  	Packages["%s"] = map[string]interface{}{
   115  `, pn, pkg, pn, pkg, pn)
   116  		for _, k := range keys {
   117  			fmt.Printf(`	"%s": %s.%s,`+"\n", k, pn, k)
   118  		}
   119  		fmt.Println(`	}
   120  }`)
   121  	}
   122  }