Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
package main
import (
"fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"os"
"path/filepath"
"strings"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"github.com/spikeekips/mitum/cmd"
)
var (
log zerolog.Logger
packageCache map[string]string
basePackageName string
)
var rootCmd = &cobra.Command{
Use: "mitum-codegen-hinted [<key> ...]",
Short: "generate code for hinted",
PersistentPreRun: func(c *cobra.Command, args []string) {
if l, err := cmd.LoadLogging(); err != nil {
c.Println("Error:", err.Error())
os.Exit(1)
} else {
log = l
}
log.Debug().
RawJSON("flags", cmd.PrintFlagsJSON(c)).
Msg("parsed flags")
packageCache = map[string]string{}
},
Run: func(c *cobra.Command, args []string) {
dir, err := os.Getwd()
if err != nil {
c.Println("Error:", err.Error())
os.Exit(1)
}
/*
pkgs, err := listPackages(dir)
if err != nil {
c.Println("Error:", err.Error())
os.Exit(1)
}
log.Info().Msgf("found %d packages", len(pkgs))
for _, pkg := range pkgs {
for name, f := range pkg.Files {
log_ := log.With().Str("package", pkg.Name).Str("file", name).Logger()
log_.Debug().Msg("dig in package")
if f.Scope == nil {
continue
}
log_.Debug().Int("objects", len(f.Scope.Objects)).Msg("objects found")
for _, obj := range f.Scope.Objects {
if obj.Kind != ast.Typ {
continue
}
log_.Debug().Str("struct", obj.Name).Msg("struct found")
}
}
ast.Inspect(pkg, func(n ast.Node) bool {
log_ := log.With().Str("package", pkg.Name).Logger()
switch t := n.(type) {
// find variable declarations
case *ast.TypeSpec:
if t.Name.IsExported() {
switch t.Type.(type) {
case *ast.StructType:
log_.Debug().Str("struct", t.Name.Name).Msg("struct found")
if pkg.Scope == nil {
return true
}
fmt.Println("..", t.Name.Name, pkg.Scope == nil)
fmt.Println(">", pkg.Scope.Lookup(t.Name.Name))
}
}
}
return true
})
}
*/
listPackages(c, dir)
},
}
func listPackages(c *cobra.Command, dir string) (map[string]*ast.Package, error) {
/*
pkgs := map[string]*ast.Package{}
if fd, err := os.Open(dir); err != nil {
return nil, err
} else if list, err := fd.Readdir(-1); err != nil {
return nil, err
} else {
for _, fi := range list {
if !fi.IsDir() {
continue
} else if strings.HasPrefix(fi.Name(), ".") {
continue
}
ps, err := parser.ParseDir(token.NewFileSet(), fi.Name(), filter, 0)
if err != nil {
return nil, err
} else if len(ps) < 1 {
continue
}
for name, pkg := range ps {
pkgs[name] = pkg
log.Debug().Str("name", name).Int("files", len(pkg.Files)).Msg("found package")
}
}
}
return pkgs, nil
*/
fileSet := token.NewFileSet()
var pkgs []*ast.Package
if fd, err := os.Open(dir); err != nil {
return nil, err
} else if list, err := fd.Readdir(-1); err != nil {
return nil, err
} else {
for _, fi := range list {
if !fi.IsDir() {
continue
} else if strings.HasPrefix(fi.Name(), ".") {
continue
}
ps, err := parser.ParseDir(fileSet, filepath.Join(dir, fi.Name()), filter, 0)
if err != nil {
return nil, err
} else if len(ps) < 1 {
continue
}
for _, pkg := range ps {
pkgs = append(pkgs, pkg)
}
}
}
var files []*ast.File
for _, pkg := range pkgs {
for _, f := range pkg.Files {
files = append(files, f)
}
}
for _, pkg := range pkgs {
var pkgPath string
for name, _ := range pkg.Files {
pkgPath = filepath.Dir(name)
break
}
if err := parsePackage(c, pkgPath, fileSet, pkg, files); err != nil {
return nil, err
}
}
return nil, nil
}
func parsePackage(c *cobra.Command, dir string, fileSet *token.FileSet, pkg *ast.Package, _ []*ast.File) error {
var files []*ast.File
for _, f := range pkg.Files {
files = append(files, f)
}
fmt.Println(">", dir, pkg.Name)
config := &types.Config{
Error: func(err error) {
log.Error().Err(err).Msg("problem found in types.Config()")
},
Importer: importer.Default(),
}
pg, err := config.Check(dir, fileSet, files, nil)
if err != nil {
return err
}
fmt.Println("<", pg.Name())
return nil
}
func filter(info os.FileInfo) bool {
name := info.Name()
if info.IsDir() {
return false
}
if filepath.Ext(name) != ".go" {
return false
}
if strings.HasSuffix(name, "_test.go") {
return false
}
return true
}
func main() {
rootCmd.PersistentFlags().Var(&cmd.FlagLogLevel, "log-level", "log level: {debug error warn info crit}")
rootCmd.PersistentFlags().StringVar(&cmd.FlagLogOut, "log", cmd.FlagLogOut, "log output directory")
rootCmd.PersistentFlags().Var(&cmd.FlagLogFormat, "log-format", "log format: {json terminal}")
if err := rootCmd.Execute(); err != nil {
rootCmd.Println("Error:", err.Error())
os.Exit(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment