fix yaml format bug and generate file

This commit is contained in:
LinXiaoYi 2021-06-29 01:05:17 +08:00
parent 076856f2c7
commit 1ee9f1326b
4 changed files with 85 additions and 23 deletions

1
go.mod
View File

@ -19,6 +19,7 @@ require (
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/talos-systems/talos/pkg/machinery v0.0.0-20210625144407-2060ceaa0b16 github.com/talos-systems/talos/pkg/machinery v0.0.0-20210625144407-2060ceaa0b16
golang.org/x/mod v0.4.2 // indirect golang.org/x/mod v0.4.2 // indirect
golang.org/x/text v0.3.6
golang.org/x/tools v0.1.3 golang.org/x/tools v0.1.3
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
honnef.co/go/tools v0.1.4 // indirect honnef.co/go/tools v0.1.4 // indirect

View File

@ -2,6 +2,7 @@ package beeParser
import ( import (
"fmt" "fmt"
"go/types"
"strconv" "strconv"
"strings" "strings"
) )
@ -33,7 +34,7 @@ func handleTailWhitespace(s string) string {
return s[0:i] return s[0:i]
} }
//handle value to remove head and tail space. // Handle value to remove head and tail space.
func handleWhitespaceValues(values []string) []interface{} { func handleWhitespaceValues(values []string) []interface{} {
res := make([]interface{}, 0) res := make([]interface{}, 0)
for _, v := range values { for _, v := range values {
@ -44,7 +45,7 @@ func handleWhitespaceValues(values []string) []interface{} {
return res return res
} }
//try to transfer string to original type // Transfer string to original type
func transferType(str string) interface{} { func transferType(str string) interface{} {
if res, err := strconv.Atoi(str); err == nil { if res, err := strconv.Atoi(str); err == nil {
return res return res
@ -55,8 +56,8 @@ func transferType(str string) interface{} {
return str return str
} }
//parse annotation to generate array with key and values // Parse annotation to generate array with key and values
//start with "@" as a key-value pair,key and values are separated by a space,wrap to distinguish values. // start with "@" as a key-value pair,key and values are separated by a space,wrap to distinguish values.
func (a *Annotation) Annotate(annotation string) map[string]interface{} { func (a *Annotation) Annotate(annotation string) map[string]interface{} {
results := make(map[string]interface{}) results := make(map[string]interface{})
//split annotation with '@' //split annotation with '@'
@ -75,20 +76,54 @@ func (a *Annotation) Annotate(annotation string) map[string]interface{} {
return results return results
} }
//create new annotation // Create new annotation,parse "Key","Default","Description" by annotation.
//parse "Key","Default","Description" by annotation // If key and default value is empty by annotaion, set default key and value
//the type of "Key" and "Description" is string, "Default" is interface{} // by params, default value according defaultType to generate
func NewAnnotation(annotation string) *Annotation { func NewAnnotation(annotation, defaultKey string, defaultType types.Type) *Annotation {
a := &Annotation{} a := &Annotation{}
kvs := a.Annotate(annotation) kvs := a.Annotate(annotation)
if v, ok := kvs["Key"]; ok { if v, ok := kvs["Key"]; ok {
a.Key = fmt.Sprintf("%v", v) a.Key = fmt.Sprintf("%v", v)
} }
if v, ok := kvs["Description"]; ok { if v, ok := kvs["Description"]; ok {
a.Description = fmt.Sprintf("%v", v) if ss, ok := v.([]interface{}); ok {
for i, s := range ss {
if i == 0 {
a.Description += s.(string)
continue
}
a.Description += "\n" + s.(string)
}
} else {
a.Description = fmt.Sprintf("%v", v)
}
} }
if v, ok := kvs["Default"]; ok { if v, ok := kvs["Default"]; ok {
a.Default = v a.Default = v
} }
if a.Key == "" {
//if key by parse is empty, set a default key
a.Key = defaultKey
}
if a.Default == nil {
//if default value is nil, set the default value according to the defaultType
a.Default = getDefaultValue(defaultType)
}
return a return a
} }
// Get the default value according to the t, process bool/string/int
func getDefaultValue(t types.Type) interface{} {
switch tys := t.(type) {
case *types.Basic:
switch tys.Kind() {
case types.Bool:
return false
case types.Int, types.Int16, types.Int8, types.Int32, types.Int64, types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64, types.Uintptr, types.Float32, types.Float64:
return 0
case types.String:
return ""
}
}
return nil
}

View File

@ -2,6 +2,8 @@ package beeParser
import ( import (
"encoding/json" "encoding/json"
"io/ioutil"
"strings"
"github.com/talos-systems/talos/pkg/machinery/config/encoder" "github.com/talos-systems/talos/pkg/machinery/config/encoder"
) )
@ -10,10 +12,7 @@ type JsonFormatter struct {
} }
func (f *JsonFormatter) FieldFormatFunc(field *StructField) ([]byte, error) { func (f *JsonFormatter) FieldFormatFunc(field *StructField) ([]byte, error) {
annotation := NewAnnotation(field.Doc + field.Comment) annotation := NewAnnotation(field.Doc+field.Comment, field.Name, field.Type)
if annotation.Key == "" {
annotation.Key = field.Name
}
res := map[string]interface{}{} res := map[string]interface{}{}
if field.NestedType != nil { if field.NestedType != nil {
res[annotation.Key] = field.NestedType res[annotation.Key] = field.NestedType
@ -41,24 +40,34 @@ type Result map[string]interface{}
func (c Result) Doc() *encoder.Doc { func (c Result) Doc() *encoder.Doc {
return &result return &result
} }
func (f *YamlFormatter) FieldFormatFunc(field *StructField) ([]byte, error) { func (f *YamlFormatter) FieldFormatFunc(field *StructField) ([]byte, error) {
annotation := NewAnnotation(field.Doc + field.Comment) annotation := NewAnnotation(field.Doc+field.Comment, field.Name, field.Type)
if annotation.Key == "" {
annotation.Key = field.Name
}
res := Result{} res := Result{}
// add head comment for this field // add head comment for this field
res.Doc().Comments[encoder.HeadComment] = annotation.Description res.Doc().Comments[encoder.HeadComment] = annotation.Description
if field.NestedType != nil { if field.NestedType != nil {
b, _ := field.NestedType.FormatFunc(field.NestedType) // nestedType format result as this field value
b, err := field.NestedType.FormatFunc(field.NestedType)
if err != nil {
return nil, err
}
res[annotation.Key] = string(b) res[annotation.Key] = string(b)
} else { } else {
res[annotation.Key] = annotation.Default res[annotation.Key] = annotation.Default
} }
encoder := encoder.NewEncoder(&res, []encoder.Option{ encoder := encoder.NewEncoder(&res, []encoder.Option{
encoder.WithComments(encoder.CommentsAll), encoder.WithComments(encoder.CommentsAll),
}...) }...)
return encoder.Encode() encodeByte, err := encoder.Encode()
if err != nil {
return nil, err
}
// when field.NestedType != nil, the key and nested value strings are encoded with "|"
// remove "|" by string replace
encodeByte = []byte(strings.Replace(string(encodeByte), annotation.Key+": |", annotation.Key+":", 1))
return encodeByte, nil
} }
func (f *YamlFormatter) StructFormatFunc(node *StructNode) ([]byte, error) { func (f *YamlFormatter) StructFormatFunc(node *StructNode) ([]byte, error) {
@ -71,5 +80,10 @@ func (f *YamlFormatter) StructFormatFunc(node *StructNode) ([]byte, error) {
} }
func (f *YamlFormatter) Marshal(node *StructNode) ([]byte, error) { func (f *YamlFormatter) Marshal(node *StructNode) ([]byte, error) {
return node.FormatFunc(node) res, err := node.FormatFunc(node)
if err != nil {
return nil, err
}
ioutil.WriteFile(node.Name+".yaml", res, 0667)
return res, nil
} }

View File

@ -25,6 +25,7 @@ type StructA struct {
// @Default https://github.com/beego/bee // @Default https://github.com/beego/bee
// https://github.com/beego // https://github.com/beego
// @Description comment of a of field2 // @Description comment of a of field2
// ssssss
a string a string
// @Key b // @Key b
// @Default https://github.com/beego/bee https://github.com/beego // @Default https://github.com/beego/bee https://github.com/beego
@ -38,6 +39,11 @@ type StructA struct {
// @Key NestField // @Key NestField
// @Description comment of NestField // @Description comment of NestField
NestField StructB NestField StructB
Field5 float32
Field6 bool
Field7 string
Field8 interface{}
Field9 *StructB
} }
` `
@ -105,16 +111,22 @@ func ExampleYamlFormatter() {
// # comment of field1 // # comment of field1
// Field1: test // Field1: test
// # comment of b of field2 // # comment of b of field2
// Field2: | // Field2:
// # comment of a of field2 // # comment of a of field2
// # ssssss
// a: // a:
// - https://github.com/beego/bee // - https://github.com/beego/bee
// - https://github.com/beego // - https://github.com/beego
// # comment of b of field2 // # comment of b of field2
// b: https://github.com/beego/bee https://github.com/beego // b: https://github.com/beego/bee https://github.com/beego
// # comment of field3 // # comment of field3
// Field3: null // Field3: 0
// Field4: false // Field4: false
// NestField: | // NestField:
// FieldB1: null // FieldB1: null
// Field5: 0
// Field6: false
// Field7: ""
// Field8: null
// Field9: null
} }