goast/goast.go

125 lines
2.7 KiB
Go

package goast
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
)
type Parser struct {
source *os.File
debug bool
}
type Defines struct {
packageName string
variable map[string]struct{}
constant map[string]struct{}
function map[string]struct{}
method map[string]struct{}
imports map[string]struct{}
types map[string]struct{}
}
// NewParser get new parser
func NewParser(file string) (*Parser, error) {
source, err := os.OpenFile(file, os.O_RDONLY, 0400)
if err != nil {
return nil, err
}
return &Parser{source: source}, nil
}
// Parse parse go file
func (ps *Parser) Parse() (*Defines, error) {
tokenSet := token.NewFileSet()
astFile, err := parser.ParseFile(tokenSet, "", ps.source, 0)
if err != nil {
return nil, err
}
if ps.debug {
_ = ast.Print(tokenSet, astFile)
}
var defines = &Defines{
variable: make(map[string]struct{}),
constant: make(map[string]struct{}),
function: make(map[string]struct{}),
method: make(map[string]struct{}),
imports: make(map[string]struct{}),
types: make(map[string]struct{}),
}
// get package name
defines.packageName = astFile.Name.Name
for _, decl := range astFile.Decls {
switch decl.(type) {
case *ast.GenDecl:
gen := decl.(*ast.GenDecl)
switch gen.Tok {
case token.IMPORT:
_, pkg := getKVFromImportSpec(gen.Specs[0].(*ast.ImportSpec))
defines.imports[pkg] = struct{}{}
case token.VAR:
key, _ := getKVFromValueSpec(gen.Specs[0].(*ast.ValueSpec))
defines.variable[key] = struct{}{}
case token.CONST:
key, _ := getKVFromValueSpec(gen.Specs[0].(*ast.ValueSpec))
defines.constant[key] = struct{}{}
case token.TYPE:
key, _ := getKVFromTypeSpec(gen.Specs[0].(*ast.TypeSpec))
defines.types[key] = struct{}{}
}
case *ast.FuncDecl:
funcDecl := decl.(*ast.FuncDecl)
if funcDecl.Recv == nil {
defines.function[funcDecl.Name.Name] = struct{}{}
} else {
methodType, _ := getMethodNameFromReceiveField(funcDecl.Recv)
name := fmt.Sprintf("%s.%s", methodType, funcDecl.Name.Name)
defines.method[name] = struct{}{}
}
}
}
return defines, nil
}
func (ps *Parser) Debug() {
ps.debug = true
}
func (d *Defines) ExistVariable(name string) bool {
_, exist := d.variable[name]
return exist
}
func (d *Defines) ExistConstant(name string) bool {
_, exist := d.constant[name]
return exist
}
func (d *Defines) ExistFunction(name string) bool {
_, exist := d.function[name]
return exist
}
func (d *Defines) ExistMethod(name string) bool {
_, exist := d.method[name]
return exist
}
func (d *Defines) ExistImport(name string) bool {
_, exist := d.imports[name]
return exist
}
func (d *Defines) ExistType(name string) bool {
_, exist := d.types[name]
return exist
}