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 }