Created
March 16, 2023 08:10
-
-
Save abiiranathan/6bafd426f748677b8dfcc79cb130f023 to your computer and use it in GitHub Desktop.
Parsing AST in go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package schemagen | |
import ( | |
"fmt" | |
"go/ast" | |
"go/parser" | |
"go/token" | |
"strings" | |
) | |
// getStructsWithBuildTag retrieves all the structs in a Go source file that have a doc string containing a certain build tag. | |
func GetStructsWithBuildTag(filename, buildTag string) ([]string, error) { | |
var result []string | |
// Parse the file and generate an AST | |
fset := token.NewFileSet() | |
node, err := parser.ParseFile(fset, filename, nil, parser.AllErrors|parser.ParseComments) | |
if err != nil { | |
return nil, err | |
} | |
// Iterate through all the declarations in the file | |
for _, decl := range node.Decls { | |
// Check if the declaration is a type declaration | |
if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.TYPE { | |
// Doc comment on type declaration | |
var typeMatchesTag = strings.Contains(genDecl.Doc.Text(), buildTag) | |
// Iterate through all the specs in the type declaration | |
for _, spec := range genDecl.Specs { | |
if typeSpec, ok := spec.(*ast.TypeSpec); ok { | |
// Check if the type is a struct and has a doc string containing the build tag | |
if stype, ok := typeSpec.Type.(*ast.StructType); ok { | |
// Print struct fields | |
for _, field := range stype.Fields.List { | |
if i, ok := field.Type.(*ast.Ident); ok { | |
fieldType := i.Name | |
for _, name := range field.Names { | |
fmt.Printf("\tField: name=%s type=%s\n", name.Name, fieldType) | |
} | |
} | |
} | |
if typeMatchesTag { | |
result = append(result, typeSpec.Name.Name) | |
continue | |
} | |
// type on struct name | |
if typeSpec.Doc != nil && strings.Contains(typeSpec.Doc.Text(), buildTag) { | |
result = append(result, typeSpec.Name.Name) | |
} | |
} | |
} | |
} | |
} | |
} | |
return result, nil | |
} | |
/* | |
print struct field | |
structType := typeSpec.Type.(*ast.StructType) | |
for _, field := range structType.Fields.List { | |
i := field.Type.(*ast.Ident) | |
fieldType := i.Name | |
for _, name := range field.Names { | |
fmt.Printf("\tField: name=%s type=%s\n", name.Name, fieldType) | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment