mirror of
https://github.com/alibaba/higress.git
synced 2026-03-17 00:40:48 +08:00
feat: Improve model parsing function of "hgctl plugin build" command (#966)
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user