Skip to content

Commit

Permalink
cmd/gopdecl
Browse files Browse the repository at this point in the history
  • Loading branch information
xushiwei committed Apr 10, 2022
1 parent 41364f6 commit ad0d652
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 0 deletions.
14 changes: 14 additions & 0 deletions cmd/gopdecl/goenv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import (
"os"
"path/filepath"
"runtime"
)

func initGoEnv() {
val := os.Getenv("GOMODCACHE")
if val == "" {
os.Setenv("GOMODCACHE", filepath.Join(runtime.GOROOT(), "pkg/mod"))
}
}
96 changes: 96 additions & 0 deletions cmd/gopdecl/gopdecl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"flag"
"fmt"
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"io/fs"
"os"
"strings"
"unicode"
)

var (
internal = flag.Bool("i", false, "print internal declarations")
)

func usage() {
fmt.Fprintf(os.Stderr, "Usage: gopdecl [-i] [source.gop ...]\n")
flag.PrintDefaults()
}

func isDir(name string) bool {
if fi, err := os.Lstat(name); err == nil {
return fi.IsDir()
}
return false
}

func isPublic(name string) bool {
for _, c := range name {
return unicode.IsUpper(c)
}
return false
}

func main() {
flag.Parse()
if flag.NArg() < 1 {
usage()
return
}
initGoEnv()

var files []*ast.File

fset := token.NewFileSet()
if infile := flag.Arg(0); isDir(infile) {
pkgs, first := parser.ParseDir(fset, infile, func(fi fs.FileInfo) bool {
return !strings.HasSuffix(fi.Name(), "_test.go")
}, 0)
check(first)
for name, pkg := range pkgs {
if !strings.HasSuffix(name, "_test") {
for _, f := range pkg.Files {
files = append(files, f)
}
break
}
}
} else {
for i, n := 0, flag.NArg(); i < n; i++ {
f, err := parser.ParseFile(fset, flag.Arg(i), nil, 0)
check(err)
files = append(files, f)
}
}

imp := importer.ForCompiler(fset, "source", nil)
conf := types.Config{
Importer: imp,
IgnoreFuncBodies: true,
DisableUnusedImportCheck: true,
}

pkg, err := conf.Check("", fset, files, nil)
check(err)

scope := pkg.Scope()
names := scope.Names()
for _, name := range names {
if *internal || isPublic(name) {
fmt.Println(scope.Lookup(name))
}
}
}

func check(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

0 comments on commit ad0d652

Please sign in to comment.