feat: Improve model parsing function of "hgctl plugin build" command (#966)

This commit is contained in:
Kent Dong
2024-05-16 14:38:46 +08:00
committed by GitHub
parent 42c9c3d824
commit 3119ec8e24
3 changed files with 56 additions and 19 deletions

View File

@@ -124,7 +124,7 @@ func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
func (s JSONSchemaPropsOrBool) MarshalYAML() (interface{}, error) {
if s.Schema != nil {
return yaml.Marshal(s.Schema)
return s.Schema, nil
}
if s.Schema == nil && !s.Allows {

View File

@@ -33,7 +33,7 @@ type WasmPluginMeta struct {
Spec WasmPluginSpec `json:"spec" yaml:"spec"`
}
func defaultWsamPluginMeta() *WasmPluginMeta {
func defaultWasmPluginMeta() *WasmPluginMeta {
return &WasmPluginMeta{
APIVersion: "1.0.0",
Info: WasmPluginInfo{
@@ -77,7 +77,7 @@ func ParseGoSrc(dir, model string) (*WasmPluginMeta, error) {
if err != nil {
return nil, err
}
meta := defaultWsamPluginMeta()
meta := defaultWasmPluginMeta()
meta.setByConfigModel(m)
return meta, nil
}
@@ -96,26 +96,33 @@ func recursiveSetSchema(model *Model, parent *JSONSchemaProps) (string, *JSONSch
}
newName := cur.HandleFieldTags(model.Tag, parent, model.Name)
if IsArray(model.Type) {
item := NewJSONSchemaProps()
item.Type = GetItemType(cur.Type)
cur.Type = "array"
if IsObject(item.Type) {
item.Properties = make(map[string]JSONSchemaProps)
for _, field := range model.Fields {
name, child := recursiveSetSchema(&field, cur)
item.Properties[name] = *child
}
}
cur.Items = &JSONSchemaPropsOrArray{Schema: item}
itemModel := &*model
itemModel.Type = GetItemType(model.Type)
_, itemSchema := recursiveSetSchema(itemModel, nil)
cur.Items = &JSONSchemaPropsOrArray{Schema: itemSchema}
} else if IsMap(model.Type) {
cur.Type = "object"
valueModel := &*model
valueModel.Type = GetValueType(model.Type)
valueModel.Tag = ""
valueModel.Doc = ""
_, valueSchema := recursiveSetSchema(valueModel, nil)
cur.AdditionalProperties = &JSONSchemaPropsOrBool{Schema: valueSchema}
} else if IsObject(model.Type) { // type may be `array of object`, and it is handled in the first branch
for _, field := range model.Fields {
name, child := recursiveSetSchema(&field, cur)
cur.Properties[name] = *child
}
cur.Properties = make(map[string]JSONSchemaProps)
recursiveObjectProperties(cur, model)
}
return newName, cur
}
func recursiveObjectProperties(parent *JSONSchemaProps, model *Model) {
for _, field := range model.Fields {
name, child := recursiveSetSchema(&field, parent)
parent.Properties[name] = *child
}
}
func (meta *WasmPluginMeta) setModelAnnotations(comment string) {
as := GetAnnotations(comment)
for _, a := range as {

View File

@@ -30,6 +30,7 @@ import (
const (
ArrayPrefix = "array of "
MapPrefix = "map of "
ObjectSuffix = "object"
)
@@ -40,7 +41,23 @@ func IsArray(typ string) bool {
// GetItemType returns the item type of array, e.g.: array of int -> int
func GetItemType(typ string) string {
return strings.TrimPrefix(typ, ArrayPrefix)
if !IsArray(typ) {
return typ
}
return typ[len(ArrayPrefix):]
}
// IsMap returns true if the given type is a `map of <type>`
func IsMap(typ string) bool {
return strings.HasPrefix(typ, MapPrefix)
}
// GetValueType returns the value type of map, e.g.: map of int -> int
func GetValueType(typ string) string {
if !IsMap(typ) {
return typ
}
return typ[len(MapPrefix):]
}
// IsObject returns true if the given type is an `object` or an `array of object`
@@ -259,7 +276,7 @@ func (p *ModelParser) parseModelFields(model string) (fields []Model, err error)
return nil, errors.Wrapf(err, "failed to parse type %q of the field %q", field.Type, fd.Name)
}
if IsObject(fd.Type) {
subModel, err := p.getModelName(field.Type)
subModel, err := p.doGetModelName(pkgName, field.Type)
if err != nil {
return nil, errors.Wrapf(err, "failed to get the sub-model name of the field %q with type %q", fd.Name, field.Type)
}
@@ -313,6 +330,8 @@ func (p *ModelParser) doGetModelName(pkgName string, typ ast.Expr) (string, erro
return p.doGetModelName(pkgName, t.X)
case *ast.ArrayType: // slice or array
return p.doGetModelName(pkgName, t.Elt)
case *ast.MapType:
return p.doGetModelName(pkgName, t.Value)
case *ast.SelectorExpr: // <pkg_name>.<field_name>
pkg, ok := t.X.(*ast.Ident)
if !ok {
@@ -339,6 +358,16 @@ func (p *ModelParser) parseFieldType(pkgName string, typ ast.Expr) (string, erro
return "", err
}
return ArrayPrefix + ret, nil
case *ast.MapType:
if keyIdent, ok := t.Key.(*ast.Ident); !ok {
return "", ErrInvalidFieldType
} else if keyIdent.Name != "string" {
return "", ErrInvalidFieldType
} else if ret, err := p.parseFieldType(pkgName, t.Value); err != nil {
return "", err
} else {
return MapPrefix + ret, nil
}
case *ast.SelectorExpr: // <pkg_name>.<field_name>
pkg, ok := t.X.(*ast.Ident)
if !ok {
@@ -388,4 +417,5 @@ const (
JsonTypeString JsonType = "string"
JsonTypeObject JsonType = "object"
JsonTypeArray JsonType = "array"
JsonTypeMap JsonType = "map"
)