Skip to content

Instantly share code, notes, and snippets.

@yanolab
Created February 17, 2019 12:12
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save yanolab/2b6cab3de3b21d91e8e5680715f5f50a to your computer and use it in GitHub Desktop.
go AST
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
)
func loadFuncDeclsM(out map[string]map[string]*ast.FuncDecl, f *ast.File) {
if _, ok := out[f.Name.Name]; !ok {
out[f.Name.Name] = make(map[string]*ast.FuncDecl)
}
for _, decl := range f.Decls {
if v, ok := decl.(*ast.FuncDecl); ok {
out[f.Name.Name][v.Name.Name] = v
}
}
}
func parse(fpath string) (*token.FileSet, map[string]map[string]*ast.FuncDecl) {
fset := token.NewFileSet()
b, err := ioutil.ReadFile(fpath)
if err != nil {
panic(err)
}
f, err := parser.ParseFile(fset, fpath, string(b), parser.ParseComments)
if err != nil {
panic(err)
}
m := make(map[string]map[string]*ast.FuncDecl)
loadFuncDeclsM(m, f)
paths := getSrcPaths()
findPackage := func(pkgname string) (string, error) {
for _, p := range paths {
pkgpath := filepath.Join(p, pkgname)
if _, err := os.Stat(pkgpath); err == nil {
return pkgpath, nil
}
}
return "", fmt.Errorf("could not find pkg: %s", pkgname)
}
for _, i := range f.Imports {
p, err := findPackage(strings.Trim(i.Path.Value, "\""))
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
continue
}
pkgs, err := parser.ParseDir(fset, p, func(fi os.FileInfo) bool { return true }, parser.ParseComments)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
continue
}
for _, pkg := range pkgs {
for _, f := range pkg.Files {
loadFuncDeclsM(m, f)
}
}
}
return fset, m
}
func getSrcPath(name string) string {
cmd := exec.Command("go", "env", name)
b, err := cmd.Output()
if err != nil {
panic(err)
}
return filepath.Join(strings.Trim(string(b), "\r\n"), "src")
}
func getSrcPaths() []string {
return []string{getSrcPath("GOROOT"), getSrcPath("GOPATH")}
}
func main() {
fset, m := parse("main.go")
results := m["exec"]["Command"].Type.Results.List
ast.Print(fset, results)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment