1
0
mirror of https://github.com/beego/bee.git synced 2024-11-21 23:50:54 +00:00

Merge pull request #784 from y4h2/parse-config

Parse-Config | supports field formatter
This commit is contained in:
Ming Deng 2021-05-24 21:13:42 +08:00 committed by GitHub
commit 864c8f999d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 20 deletions

View File

@ -10,6 +10,11 @@ import (
"go/types" "go/types"
) )
// FieldFormatter transfers the field value to expected format
type FieldFormatter interface {
Format(field *StructField) string
}
// StructField defines struct field // StructField defines struct field
type StructField struct { type StructField struct {
Name string Name string
@ -18,6 +23,7 @@ type StructField struct {
Comment string Comment string
Doc string Doc string
Tag string Tag string
FormatFunc func(field *StructField) string
} }
// Key returns the key of the field // Key returns the key of the field
@ -32,7 +38,7 @@ func (sf *StructField) Value() interface{} {
return sf.NestedType.ToKV() return sf.NestedType.ToKV()
} }
return "" return sf.FormatFunc(sf)
} }
// StructNode defines struct node // StructNode defines struct node
@ -52,15 +58,16 @@ func (sn *StructNode) ToKV() map[string]interface{} {
// StructParser parses structs in given file or string // StructParser parses structs in given file or string
type StructParser struct { type StructParser struct {
MainStruct *StructNode MainStruct *StructNode
Info types.Info Info types.Info
FieldFormatter FieldFormatter
} }
// NewStructParser is the constructor of StructParser // NewStructParser is the constructor of StructParser
// filePath and src follow the same rule with go/parser.ParseFile // filePath and src follow the same rule with go/parser.ParseFile
// If src != nil, ParseFile parses the source from src and the filename is only used when recording position information. The type of the argument for the src parameter must be string, []byte, or io.Reader. If src == nil, ParseFile parses the file specified by filename. // If src != nil, ParseFile parses the source from src and the filename is only used when recording position information. The type of the argument for the src parameter must be string, []byte, or io.Reader. If src == nil, ParseFile parses the file specified by filename.
// rootStruct is the root struct we want to use // rootStruct is the root struct we want to use
func NewStructParser(filePath string, src interface{}, rootStruct string) (*StructParser, error) { func NewStructParser(filePath string, src interface{}, rootStruct string, formatter FieldFormatter) (*StructParser, error) {
fset := token.NewFileSet() fset := token.NewFileSet()
f, err := parser.ParseFile(fset, filePath, src, parser.ParseComments) f, err := parser.ParseFile(fset, filePath, src, parser.ParseComments)
if err != nil { if err != nil {
@ -80,8 +87,9 @@ func NewStructParser(filePath string, src interface{}, rootStruct string) (*Stru
return nil, err return nil, err
} }
cg := &StructParser{ sp := &StructParser{
Info: info, FieldFormatter: formatter,
Info: info,
} }
ast.Inspect(f, func(n ast.Node) bool { ast.Inspect(f, func(n ast.Node) bool {
@ -101,27 +109,27 @@ func NewStructParser(filePath string, src interface{}, rootStruct string) (*Stru
return true return true
} }
cg.MainStruct = cg.ParseStruct(structName, s) sp.MainStruct = sp.ParseStruct(structName, s)
return false return false
}) })
if cg.MainStruct == nil { if sp.MainStruct == nil {
return nil, errors.New("non-exist root struct") return nil, errors.New("non-exist root struct")
} }
return cg, nil return sp, nil
} }
func (cg *StructParser) ToJSON() ([]byte, error) { func (sp *StructParser) ToJSON() ([]byte, error) {
value := cg.MainStruct.ToKV() value := sp.MainStruct.ToKV()
return json.MarshalIndent(value, "", " ") return json.MarshalIndent(value, "", " ")
} }
// ParseField parses struct field in nested way // ParseField parses struct field in nested way
func (cg *StructParser) ParseField(field *ast.Field) *StructField { func (sp *StructParser) ParseField(field *ast.Field) *StructField {
// ast.Print(nil, field) // ast.Print(nil, field)
fieldName := field.Names[0].Name fieldName := field.Names[0].Name
fieldType := cg.Info.TypeOf(field.Type) fieldType := sp.Info.TypeOf(field.Type)
fieldTag := "" fieldTag := ""
if field.Tag != nil { if field.Tag != nil {
@ -138,7 +146,7 @@ func (cg *StructParser) ParseField(field *ast.Field) *StructField {
var nestedStruct *StructNode var nestedStruct *StructNode
if s, isInlineStruct := field.Type.(*ast.StructType); isInlineStruct { if s, isInlineStruct := field.Type.(*ast.StructType); isInlineStruct {
nestedStruct = cg.ParseStruct("", s) nestedStruct = sp.ParseStruct("", s)
} }
if _, isNamedStructorBasic := field.Type.(*ast.Ident); isNamedStructorBasic && field.Type.(*ast.Ident).Obj != nil { if _, isNamedStructorBasic := field.Type.(*ast.Ident); isNamedStructorBasic && field.Type.(*ast.Ident).Obj != nil {
@ -151,7 +159,7 @@ func (cg *StructParser) ParseField(field *ast.Field) *StructField {
if !ok { if !ok {
return nil return nil
} }
nestedStruct = cg.ParseStruct(ts.Name.Name, s) nestedStruct = sp.ParseStruct(ts.Name.Name, s)
} }
// fieldType.(*types.Basic) // basic type // fieldType.(*types.Basic) // basic type
// *ast.ArrayType: // *ast.ArrayType:
@ -165,14 +173,15 @@ func (cg *StructParser) ParseField(field *ast.Field) *StructField {
Comment: fieldComment, Comment: fieldComment,
Doc: fieldDoc, Doc: fieldDoc,
NestedType: nestedStruct, NestedType: nestedStruct,
FormatFunc: sp.FieldFormatter.Format,
} }
} }
// ParseStruct parses struct in nested way // ParseStruct parses struct in nested way
func (cg *StructParser) ParseStruct(structName string, s *ast.StructType) *StructNode { func (sp *StructParser) ParseStruct(structName string, s *ast.StructType) *StructNode {
fields := []*StructField{} fields := []*StructField{}
for _, field := range s.Fields.List { for _, field := range s.Fields.List {
parsedField := cg.ParseField(field) parsedField := sp.ParseField(field)
if parsedField != nil { if parsedField != nil {
fields = append(fields, parsedField) fields = append(fields, parsedField)
} }

View File

@ -5,6 +5,13 @@ import (
"log" "log"
) )
type sampleFormatter struct {
}
func (f *sampleFormatter) Format(field *StructField) string {
return ""
}
func ExampleStructParser() { func ExampleStructParser() {
const src = ` const src = `
package p package p
@ -28,14 +35,15 @@ type StructA struct {
Field6 func(int) Field6 func(int)
Field7 StructB Field7 StructB
} }
` `
cg, err := NewStructParser("src.go", src, "StructA") formatter := &sampleFormatter{}
sp, err := NewStructParser("src.go", src, "StructA", formatter)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
b, err := cg.ToJSON() b, err := sp.ToJSON()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }