mirror of
				https://github.com/beego/bee.git
				synced 2025-10-31 12:33:21 +00:00 
			
		
		
		
	Merge pull request #784 from y4h2/parse-config
Parse-Config | supports field formatter
This commit is contained in:
		| @@ -10,6 +10,11 @@ import ( | ||||
| 	"go/types" | ||||
| ) | ||||
|  | ||||
| // FieldFormatter transfers the field value to expected format | ||||
| type FieldFormatter interface { | ||||
| 	Format(field *StructField) string | ||||
| } | ||||
|  | ||||
| // StructField defines struct field | ||||
| type StructField struct { | ||||
| 	Name       string | ||||
| @@ -18,6 +23,7 @@ type StructField struct { | ||||
| 	Comment    string | ||||
| 	Doc        string | ||||
| 	Tag        string | ||||
| 	FormatFunc func(field *StructField) string | ||||
| } | ||||
|  | ||||
| // Key returns the key of the field | ||||
| @@ -32,7 +38,7 @@ func (sf *StructField) Value() interface{} { | ||||
| 		return sf.NestedType.ToKV() | ||||
| 	} | ||||
|  | ||||
| 	return "" | ||||
| 	return sf.FormatFunc(sf) | ||||
| } | ||||
|  | ||||
| // StructNode defines struct node | ||||
| @@ -52,15 +58,16 @@ func (sn *StructNode) ToKV() map[string]interface{} { | ||||
|  | ||||
| // StructParser parses structs in given file or string | ||||
| type StructParser struct { | ||||
| 	MainStruct *StructNode | ||||
| 	Info       types.Info | ||||
| 	MainStruct     *StructNode | ||||
| 	Info           types.Info | ||||
| 	FieldFormatter FieldFormatter | ||||
| } | ||||
|  | ||||
| // NewStructParser is the constructor of StructParser | ||||
| // 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. | ||||
| // 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() | ||||
| 	f, err := parser.ParseFile(fset, filePath, src, parser.ParseComments) | ||||
| 	if err != nil { | ||||
| @@ -80,8 +87,9 @@ func NewStructParser(filePath string, src interface{}, rootStruct string) (*Stru | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	cg := &StructParser{ | ||||
| 		Info: info, | ||||
| 	sp := &StructParser{ | ||||
| 		FieldFormatter: formatter, | ||||
| 		Info:           info, | ||||
| 	} | ||||
|  | ||||
| 	ast.Inspect(f, func(n ast.Node) bool { | ||||
| @@ -101,27 +109,27 @@ func NewStructParser(filePath string, src interface{}, rootStruct string) (*Stru | ||||
| 			return true | ||||
| 		} | ||||
|  | ||||
| 		cg.MainStruct = cg.ParseStruct(structName, s) | ||||
| 		sp.MainStruct = sp.ParseStruct(structName, s) | ||||
| 		return false | ||||
| 	}) | ||||
|  | ||||
| 	if cg.MainStruct == nil { | ||||
| 	if sp.MainStruct == nil { | ||||
| 		return nil, errors.New("non-exist root struct") | ||||
| 	} | ||||
|  | ||||
| 	return cg, nil | ||||
| 	return sp, nil | ||||
| } | ||||
|  | ||||
| func (cg *StructParser) ToJSON() ([]byte, error) { | ||||
| 	value := cg.MainStruct.ToKV() | ||||
| func (sp *StructParser) ToJSON() ([]byte, error) { | ||||
| 	value := sp.MainStruct.ToKV() | ||||
| 	return json.MarshalIndent(value, "", "  ") | ||||
| } | ||||
|  | ||||
| // 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) | ||||
| 	fieldName := field.Names[0].Name | ||||
| 	fieldType := cg.Info.TypeOf(field.Type) | ||||
| 	fieldType := sp.Info.TypeOf(field.Type) | ||||
|  | ||||
| 	fieldTag := "" | ||||
| 	if field.Tag != nil { | ||||
| @@ -138,7 +146,7 @@ func (cg *StructParser) ParseField(field *ast.Field) *StructField { | ||||
|  | ||||
| 	var nestedStruct *StructNode | ||||
| 	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 { | ||||
| @@ -151,7 +159,7 @@ func (cg *StructParser) ParseField(field *ast.Field) *StructField { | ||||
| 		if !ok { | ||||
| 			return nil | ||||
| 		} | ||||
| 		nestedStruct = cg.ParseStruct(ts.Name.Name, s) | ||||
| 		nestedStruct = sp.ParseStruct(ts.Name.Name, s) | ||||
| 	} | ||||
| 	// fieldType.(*types.Basic) // basic type | ||||
| 	// *ast.ArrayType: | ||||
| @@ -165,14 +173,15 @@ func (cg *StructParser) ParseField(field *ast.Field) *StructField { | ||||
| 		Comment:    fieldComment, | ||||
| 		Doc:        fieldDoc, | ||||
| 		NestedType: nestedStruct, | ||||
| 		FormatFunc: sp.FieldFormatter.Format, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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{} | ||||
| 	for _, field := range s.Fields.List { | ||||
| 		parsedField := cg.ParseField(field) | ||||
| 		parsedField := sp.ParseField(field) | ||||
| 		if parsedField != nil { | ||||
| 			fields = append(fields, parsedField) | ||||
| 		} | ||||
|   | ||||
| @@ -5,6 +5,13 @@ import ( | ||||
| 	"log" | ||||
| ) | ||||
|  | ||||
| type sampleFormatter struct { | ||||
| } | ||||
|  | ||||
| func (f *sampleFormatter) Format(field *StructField) string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func ExampleStructParser() { | ||||
| 	const src = ` | ||||
| package p | ||||
| @@ -28,14 +35,15 @@ type StructA struct { | ||||
| 	Field6 func(int) | ||||
| 	Field7 StructB | ||||
| } | ||||
|  | ||||
| ` | ||||
| 	cg, err := NewStructParser("src.go", src, "StructA") | ||||
| 	formatter := &sampleFormatter{} | ||||
|  | ||||
| 	sp, err := NewStructParser("src.go", src, "StructA", formatter) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	b, err := cg.ToJSON() | ||||
| 	b, err := sp.ToJSON() | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ming Deng
					Ming Deng