This is an automated email from the ASF dual-hosted git repository.

AlexStocks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new 115af01da fix(openapi): generate enum components and map value schemas 
(#3609)
115af01da is described below

commit 115af01da805090d153f68cfd4974dc41e69fdcc
Author: XiaoFei <[email protected]>
AuthorDate: Sat Aug 8 18:31:04 2026 +0800

    fix(openapi): generate enum components and map value schemas (#3609)
    
    * fix(openapi): generate enum components and map value schemas
    
    * fix(openapi): cover map reference values and error schema collisions
---
 .../protoc-gen-triple-openapi/example/greet.proto  |   4 +
 .../example/greet.triple.openapi.json              |  69 +++++++++++++-
 .../example/greet.triple.openapi.yaml              |  48 ++++++++++
 .../internal/converter/components.go               |  11 ++-
 .../internal/converter/convert.go                  |  11 ++-
 .../internal/converter/convert_test.go             | 105 +++++++++++++++++++++
 .../internal/converter/schema/schema.go            |  40 +++++---
 .../internal/converter/schema/util.go              |  23 ++++-
 8 files changed, 289 insertions(+), 22 deletions(-)

diff --git a/tools/protoc-gen-triple-openapi/example/greet.proto 
b/tools/protoc-gen-triple-openapi/example/greet.proto
index 3db26d2d7..897fe6630 100644
--- a/tools/protoc-gen-triple-openapi/example/greet.proto
+++ b/tools/protoc-gen-triple-openapi/example/greet.proto
@@ -32,6 +32,10 @@ message GreetRequest {
   map<string, string> metadata = 3;
   GreetingType type = 4;
   GreetProfile profile = 5;
+  repeated GreetingType types = 6;
+  repeated GreetProfile profiles = 7;
+  map<string, GreetProfile> profile_metadata = 8;
+  map<string, GreetingType> type_metadata = 9;
 }
 
 message GreetProfile {
diff --git a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json 
b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json
index 8a322723f..289675c87 100644
--- a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json
+++ b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json
@@ -141,7 +141,10 @@
           },
           "metadata": {
             "type": "object",
-            "title": "metadata"
+            "title": "metadata",
+            "additionalProperties": {
+              "type": "string"
+            }
           },
           "type": {
             "title": "type",
@@ -150,6 +153,34 @@
           "profile": {
             "title": "profile",
             "$ref": "#/components/schemas/greet.GreetProfile"
+          },
+          "types": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/greet.GreetingType"
+            },
+            "title": "types"
+          },
+          "profiles": {
+            "type": "array",
+            "items": {
+              "$ref": "#/components/schemas/greet.GreetProfile"
+            },
+            "title": "profiles"
+          },
+          "profileMetadata": {
+            "type": "object",
+            "title": "profile_metadata",
+            "additionalProperties": {
+              "$ref": "#/components/schemas/greet.GreetProfile"
+            }
+          },
+          "typeMetadata": {
+            "type": "object",
+            "title": "type_metadata",
+            "additionalProperties": {
+              "$ref": "#/components/schemas/greet.GreetingType"
+            }
           }
         },
         "title": "GreetRequest"
@@ -168,6 +199,34 @@
         },
         "title": "MetadataEntry"
       },
+      "greet.GreetRequest.ProfileMetadataEntry": {
+        "type": "object",
+        "properties": {
+          "key": {
+            "type": "string",
+            "title": "key"
+          },
+          "value": {
+            "title": "value",
+            "$ref": "#/components/schemas/greet.GreetProfile"
+          }
+        },
+        "title": "ProfileMetadataEntry"
+      },
+      "greet.GreetRequest.TypeMetadataEntry": {
+        "type": "object",
+        "properties": {
+          "key": {
+            "type": "string",
+            "title": "key"
+          },
+          "value": {
+            "title": "value",
+            "$ref": "#/components/schemas/greet.GreetingType"
+          }
+        },
+        "title": "TypeMetadataEntry"
+      },
       "greet.GreetResponse": {
         "type": "object",
         "properties": {
@@ -198,6 +257,14 @@
         },
         "title": "GreetUserResponse"
       },
+      "greet.GreetingType": {
+        "type": "string",
+        "title": "GreetingType",
+        "enum": [
+          "GREETING_TYPE_UNSPECIFIED",
+          "GREETING_TYPE_FORMAL"
+        ]
+      },
       "ErrorResponse": {
         "type": "object",
         "properties": {
diff --git a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml 
b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml
index a56c7ccb9..975cf78a1 100644
--- a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml
+++ b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml
@@ -90,12 +90,34 @@ components:
         metadata:
           type: object
           title: metadata
+          additionalProperties:
+            type: string
         type:
           title: type
           $ref: '#/components/schemas/greet.GreetingType'
         profile:
           title: profile
           $ref: '#/components/schemas/greet.GreetProfile'
+        types:
+          type: array
+          items:
+            $ref: '#/components/schemas/greet.GreetingType'
+          title: types
+        profiles:
+          type: array
+          items:
+            $ref: '#/components/schemas/greet.GreetProfile'
+          title: profiles
+        profileMetadata:
+          type: object
+          title: profile_metadata
+          additionalProperties:
+            $ref: '#/components/schemas/greet.GreetProfile'
+        typeMetadata:
+          type: object
+          title: type_metadata
+          additionalProperties:
+            $ref: '#/components/schemas/greet.GreetingType'
       title: GreetRequest
     greet.GreetRequest.MetadataEntry:
       type: object
@@ -107,6 +129,26 @@ components:
           type: string
           title: value
       title: MetadataEntry
+    greet.GreetRequest.ProfileMetadataEntry:
+      type: object
+      properties:
+        key:
+          type: string
+          title: key
+        value:
+          title: value
+          $ref: '#/components/schemas/greet.GreetProfile'
+      title: ProfileMetadataEntry
+    greet.GreetRequest.TypeMetadataEntry:
+      type: object
+      properties:
+        key:
+          type: string
+          title: key
+        value:
+          title: value
+          $ref: '#/components/schemas/greet.GreetingType'
+      title: TypeMetadataEntry
     greet.GreetResponse:
       type: object
       properties:
@@ -128,6 +170,12 @@ components:
           type: string
           title: greeting
       title: GreetUserResponse
+    greet.GreetingType:
+      type: string
+      title: GreetingType
+      enum:
+        - GREETING_TYPE_UNSPECIFIED
+        - GREETING_TYPE_FORMAL
     ErrorResponse:
       type: object
       properties:
diff --git a/tools/protoc-gen-triple-openapi/internal/converter/components.go 
b/tools/protoc-gen-triple-openapi/internal/converter/components.go
index 2a2bca07c..a10256c11 100644
--- a/tools/protoc-gen-triple-openapi/internal/converter/components.go
+++ b/tools/protoc-gen-triple-openapi/internal/converter/components.go
@@ -29,12 +29,17 @@ import (
        
"dubbo.apache.org/dubbo-go/v3/tools/protoc-gen-triple-openapi/internal/converter/schema"
 )
 
-func generateComponents(fd protoreflect.FileDescriptor) 
(*openapimodel.Components, error) {
+func generateComponents(fd protoreflect.FileDescriptor) 
(*openapimodel.Components, string, error) {
        components := &openapimodel.Components{
                Schemas: schema.GenerateFileSchemas(fd),
        }
 
        // triple error component
+       errorResponseSchemaID := "ErrorResponse"
+       if components.Schemas.GetOrZero(errorResponseSchemaID) != nil {
+               // A hyphen cannot occur in a protobuf full name, so this ID 
cannot collide.
+               errorResponseSchemaID = "Triple-ErrorResponse"
+       }
        errorResponseProps := orderedmap.New[string, *base.SchemaProxy]()
        errorResponseProps.Set("status", base.CreateSchemaProxy(&base.Schema{
                Description: "The status code.",
@@ -44,12 +49,12 @@ func generateComponents(fd protoreflect.FileDescriptor) 
(*openapimodel.Component
                Description: "A developer-facing error message.",
                Type:        []string{"string"},
        }))
-       components.Schemas.Set("ErrorResponse", 
base.CreateSchemaProxy(&base.Schema{
+       components.Schemas.Set(errorResponseSchemaID, 
base.CreateSchemaProxy(&base.Schema{
                Title:       "ErrorResponse",
                Description: `Error type returned by triple: 
https://cn.dubbo.apache.org/zh-cn/overview/reference/protocols/triple-spec/`,
                Properties:  errorResponseProps,
                Type:        []string{"object"},
        }))
 
-       return components, nil
+       return components, errorResponseSchemaID, nil
 }
diff --git a/tools/protoc-gen-triple-openapi/internal/converter/convert.go 
b/tools/protoc-gen-triple-openapi/internal/converter/convert.go
index 7bb59b59a..f663eb682 100644
--- a/tools/protoc-gen-triple-openapi/internal/converter/convert.go
+++ b/tools/protoc-gen-triple-openapi/internal/converter/convert.go
@@ -116,7 +116,8 @@ func convert(req *pluginpb.CodeGeneratorRequest) 
(*pluginpb.CodeGeneratorRespons
                })
 
                // handle openapi components
-               doc.Components, err = generateComponents(fd)
+               errorResponseSchemaID := ""
+               doc.Components, errorResponseSchemaID, err = 
generateComponents(fd)
                if err != nil {
                        return nil, err
                }
@@ -166,10 +167,10 @@ func convert(req *pluginpb.CodeGeneratorRequest) 
(*pluginpb.CodeGeneratorRespons
                                })
 
                                // status code 400
-                               codeMap.Set(constant.StatusCode400, 
newErrorResponse(constant.StatusCode400Description))
+                               codeMap.Set(constant.StatusCode400, 
newErrorResponse(constant.StatusCode400Description, errorResponseSchemaID))
 
                                // status code 500
-                               codeMap.Set(constant.StatusCode500, 
newErrorResponse(constant.StatusCode500Description))
+                               codeMap.Set(constant.StatusCode500, 
newErrorResponse(constant.StatusCode500Description, errorResponseSchemaID))
 
                                operation.Responses = &openapimodel.Responses{
                                        Codes: codeMap,
@@ -225,8 +226,8 @@ func formatOpenapiDoc(opts options.Options, doc 
*openapimodel.Document) (string,
        }
 }
 
-func newErrorResponse(description string) *openapimodel.Response {
-       responseSchema := 
base.CreateSchemaProxyRef(constant.OpenAPIDocComponentsSchemaSuffix + 
"ErrorResponse")
+func newErrorResponse(description, schemaID string) *openapimodel.Response {
+       responseSchema := 
base.CreateSchemaProxyRef(constant.OpenAPIDocComponentsSchemaSuffix + schemaID)
        responseMediaType := makeMediaTypes(responseSchema)
        return &openapimodel.Response{
                Description: description,
diff --git a/tools/protoc-gen-triple-openapi/internal/converter/convert_test.go 
b/tools/protoc-gen-triple-openapi/internal/converter/convert_test.go
index 2278ac1f9..d2ba3f71a 100644
--- a/tools/protoc-gen-triple-openapi/internal/converter/convert_test.go
+++ b/tools/protoc-gen-triple-openapi/internal/converter/convert_test.go
@@ -122,6 +122,10 @@ func greetRequest(format string) 
*pluginpb.CodeGeneratorRequest {
                                                        field("metadata", 
"metadata", 3, descriptorpb.FieldDescriptorProto_LABEL_REPEATED, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, 
".greet.GreetRequest.MetadataEntry"),
                                                        field("type", "type", 
4, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_ENUM, ".greet.GreetingType"),
                                                        field("profile", 
"profile", 5, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, ".greet.GreetProfile"),
+                                                       field("types", "types", 
6, descriptorpb.FieldDescriptorProto_LABEL_REPEATED, 
descriptorpb.FieldDescriptorProto_TYPE_ENUM, ".greet.GreetingType"),
+                                                       field("profiles", 
"profiles", 7, descriptorpb.FieldDescriptorProto_LABEL_REPEATED, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, ".greet.GreetProfile"),
+                                                       
field("profile_metadata", "profileMetadata", 8, 
descriptorpb.FieldDescriptorProto_LABEL_REPEATED, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, 
".greet.GreetRequest.ProfileMetadataEntry"),
+                                                       field("type_metadata", 
"typeMetadata", 9, descriptorpb.FieldDescriptorProto_LABEL_REPEATED, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, 
".greet.GreetRequest.TypeMetadataEntry"),
                                                },
                                                NestedType: 
[]*descriptorpb.DescriptorProto{
                                                        {
@@ -132,6 +136,22 @@ func greetRequest(format string) 
*pluginpb.CodeGeneratorRequest {
                                                                },
                                                                Options: 
&descriptorpb.MessageOptions{MapEntry: proto.Bool(true)},
                                                        },
+                                                       {
+                                                               Name: 
proto.String("ProfileMetadataEntry"),
+                                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                                       
field("key", "key", 1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                                                       
field("value", "value", 2, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, ".greet.GreetProfile"),
+                                                               },
+                                                               Options: 
&descriptorpb.MessageOptions{MapEntry: proto.Bool(true)},
+                                                       },
+                                                       {
+                                                               Name: 
proto.String("TypeMetadataEntry"),
+                                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                                       
field("key", "key", 1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                                                       
field("value", "value", 2, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_ENUM, ".greet.GreetingType"),
+                                                               },
+                                                               Options: 
&descriptorpb.MessageOptions{MapEntry: proto.Bool(true)},
+                                                       },
                                                },
                                        },
                                        {
@@ -173,6 +193,91 @@ func greetRequest(format string) 
*pluginpb.CodeGeneratorRequest {
        }
 }
 
+func TestConvertErrorResponseEnumCollision(t *testing.T) {
+       request := &pluginpb.CodeGeneratorRequest{
+               FileToGenerate: []string{"collision.proto"},
+               Parameter:      proto.String("format=yaml"),
+               ProtoFile: []*descriptorpb.FileDescriptorProto{{
+                       Name:   proto.String("collision.proto"),
+                       Syntax: proto.String("proto3"),
+                       EnumType: []*descriptorpb.EnumDescriptorProto{{
+                               Name:  proto.String("ErrorResponse"),
+                               Value: 
[]*descriptorpb.EnumValueDescriptorProto{{Name: proto.String("UNKNOWN"), 
Number: proto.Int32(0)}},
+                       }},
+                       MessageType: []*descriptorpb.DescriptorProto{
+                               {Name: proto.String("Request"), Field: 
[]*descriptorpb.FieldDescriptorProto{field("state", "state", 1, 
descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_ENUM, ".ErrorResponse")}},
+                               {Name: proto.String("Response")},
+                       },
+                       Service: []*descriptorpb.ServiceDescriptorProto{{
+                               Name:   proto.String("Service"),
+                               Method: 
[]*descriptorpb.MethodDescriptorProto{{Name: proto.String("Call"), InputType: 
proto.String(".Request"), OutputType: proto.String(".Response")}},
+                       }},
+               }},
+       }
+
+       response, err := convert(request)
+       if err != nil {
+               t.Fatalf("convert() error = %v", err)
+       }
+       got := response.File[0].GetContent()
+       for _, want := range []string{
+               "state:\n          title: state\n          $ref: 
'#/components/schemas/ErrorResponse'",
+               "ErrorResponse:\n      type: string\n      title: 
ErrorResponse\n      enum:\n        - UNKNOWN",
+               "Triple-ErrorResponse:\n      type: object",
+               "$ref: '#/components/schemas/Triple-ErrorResponse'",
+       } {
+               if !strings.Contains(got, want) {
+                       t.Errorf("generated OpenAPI does not contain %q\n%s", 
want, got)
+               }
+       }
+}
+
+func TestConvertErrorResponseMessageCollision(t *testing.T) {
+       request := &pluginpb.CodeGeneratorRequest{
+               FileToGenerate: []string{"collision.proto"},
+               Parameter:      proto.String("format=yaml"),
+               ProtoFile: []*descriptorpb.FileDescriptorProto{{
+                       Name:   proto.String("collision.proto"),
+                       Syntax: proto.String("proto3"),
+                       MessageType: []*descriptorpb.DescriptorProto{
+                               {
+                                       Name: proto.String("ErrorResponse"),
+                                       Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                               field("detail", "detail", 1, 
descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                       },
+                               },
+                               {
+                                       Name: proto.String("Request"),
+                                       Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                               field("error", "error", 1, 
descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, ".ErrorResponse"),
+                                       },
+                               },
+                               {Name: proto.String("Response")},
+                       },
+                       Service: []*descriptorpb.ServiceDescriptorProto{{
+                               Name:   proto.String("Service"),
+                               Method: 
[]*descriptorpb.MethodDescriptorProto{{Name: proto.String("Call"), InputType: 
proto.String(".Request"), OutputType: proto.String(".Response")}},
+                       }},
+               }},
+       }
+
+       response, err := convert(request)
+       if err != nil {
+               t.Fatalf("convert() error = %v", err)
+       }
+       got := response.File[0].GetContent()
+       for _, want := range []string{
+               "error:\n          title: error\n          $ref: 
'#/components/schemas/ErrorResponse'",
+               "ErrorResponse:\n      type: object\n      properties:\n        
detail:",
+               "Triple-ErrorResponse:\n      type: object",
+               "$ref: '#/components/schemas/Triple-ErrorResponse'",
+       } {
+               if !strings.Contains(got, want) {
+                       t.Errorf("generated OpenAPI does not contain %q\n%s", 
want, got)
+               }
+       }
+}
+
 func field(name, jsonName string, number int32, label 
descriptorpb.FieldDescriptorProto_Label, kind 
descriptorpb.FieldDescriptorProto_Type, typeName string) 
*descriptorpb.FieldDescriptorProto {
        fd := &descriptorpb.FieldDescriptorProto{
                Name:     proto.String(name),
diff --git 
a/tools/protoc-gen-triple-openapi/internal/converter/schema/schema.go 
b/tools/protoc-gen-triple-openapi/internal/converter/schema/schema.go
index c7b5f9aee..22ee710e6 100644
--- a/tools/protoc-gen-triple-openapi/internal/converter/schema/schema.go
+++ b/tools/protoc-gen-triple-openapi/internal/converter/schema/schema.go
@@ -30,7 +30,8 @@ import (
 
 func GenerateFileSchemas(tt protoreflect.FileDescriptor) 
*orderedmap.Map[string, *base.SchemaProxy] {
        messages := make(map[protoreflect.MessageDescriptor]struct{})
-       collectMessages(tt, messages)
+       enums := make(map[protoreflect.EnumDescriptor]struct{})
+       collectMessages(tt, messages, enums)
 
        schemas := orderedmap.New[string, *base.SchemaProxy]()
 
@@ -51,27 +52,40 @@ func GenerateFileSchemas(tt protoreflect.FileDescriptor) 
*orderedmap.Map[string,
                }
        }
 
+       sortedEnums := make([]protoreflect.EnumDescriptor, 0, len(enums))
+       for enum := range enums {
+               sortedEnums = append(sortedEnums, enum)
+       }
+       sort.Slice(sortedEnums, func(i, j int) bool {
+               return sortedEnums[i].FullName() < sortedEnums[j].FullName()
+       })
+
+       for _, enum := range sortedEnums {
+               id, schema := enumToSchema(enum)
+               schemas.Set(id, base.CreateSchemaProxy(schema))
+       }
+
        return schemas
 }
 
-func collectMessages(fd protoreflect.FileDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}) {
+func collectMessages(fd protoreflect.FileDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}, enums 
map[protoreflect.EnumDescriptor]struct{}) {
        services := fd.Services()
        for i := 0; i < services.Len(); i++ {
                service := services.Get(i)
                methods := service.Methods()
                for j := 0; j < methods.Len(); j++ {
                        method := methods.Get(j)
-                       collectMethodMessages(method, messages)
+                       collectMethodMessages(method, messages, enums)
                }
        }
 }
 
-func collectMethodMessages(md protoreflect.MethodDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}) {
-       collectMessage(md.Input(), messages)
-       collectMessage(md.Output(), messages)
+func collectMethodMessages(md protoreflect.MethodDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}, enums 
map[protoreflect.EnumDescriptor]struct{}) {
+       collectMessage(md.Input(), messages, enums)
+       collectMessage(md.Output(), messages, enums)
 }
 
-func collectMessage(md protoreflect.MessageDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}) {
+func collectMessage(md protoreflect.MessageDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}, enums 
map[protoreflect.EnumDescriptor]struct{}) {
        if md == nil {
                return
        }
@@ -83,18 +97,22 @@ func collectMessage(md protoreflect.MessageDescriptor, 
messages map[protoreflect
 
        fields := md.Fields()
        for i := 0; i < fields.Len(); i++ {
-               collectField(fields.Get(i), messages)
+               collectField(fields.Get(i), messages, enums)
        }
 
        nestedMessages := md.Messages()
        for i := 0; i < nestedMessages.Len(); i++ {
-               collectMessage(nestedMessages.Get(i), messages)
+               collectMessage(nestedMessages.Get(i), messages, enums)
        }
 }
 
-func collectField(fd protoreflect.FieldDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}) {
+func collectField(fd protoreflect.FieldDescriptor, messages 
map[protoreflect.MessageDescriptor]struct{}, enums 
map[protoreflect.EnumDescriptor]struct{}) {
        if fd == nil {
                return
        }
-       collectMessage(fd.Message(), messages)
+       if fd.Kind() == protoreflect.EnumKind {
+               enums[fd.Enum()] = struct{}{}
+               return
+       }
+       collectMessage(fd.Message(), messages, enums)
 }
diff --git a/tools/protoc-gen-triple-openapi/internal/converter/schema/util.go 
b/tools/protoc-gen-triple-openapi/internal/converter/schema/util.go
index 21605d7b0..f51719762 100644
--- a/tools/protoc-gen-triple-openapi/internal/converter/schema/util.go
+++ b/tools/protoc-gen-triple-openapi/internal/converter/schema/util.go
@@ -55,11 +55,16 @@ func messageToSchema(tt protoreflect.MessageDescriptor) 
(string, *base.Schema) {
 
 func fieldToSchema(parent *base.SchemaProxy, tt protoreflect.FieldDescriptor) 
*base.SchemaProxy {
        if tt.IsMap() {
-               // Handle maps
                root := ScalarFieldToSchema(parent, tt, false)
                root.Title = string(tt.Name())
                root.Type = []string{"object"}
-               // TODO: todo
+               value := tt.MapValue()
+               switch value.Kind() {
+               case protoreflect.MessageKind, protoreflect.EnumKind:
+                       root.AdditionalProperties = 
&base.DynamicValue[*base.SchemaProxy, bool]{A: ReferenceFieldToSchema(parent, 
value)}
+               default:
+                       root.AdditionalProperties = 
&base.DynamicValue[*base.SchemaProxy, bool]{A: 
base.CreateSchemaProxy(ScalarFieldToSchema(parent, value, true))}
+               }
                root.Description = ""
                return base.CreateSchemaProxy(root)
        } else if tt.IsList() {
@@ -137,6 +142,20 @@ func ScalarFieldToSchema(parent *base.SchemaProxy, tt 
protoreflect.FieldDescript
        return s
 }
 
+func enumToSchema(tt protoreflect.EnumDescriptor) (string, *base.Schema) {
+       values := tt.Values()
+       enum := make([]*yaml.Node, 0, values.Len())
+       for i := 0; i < values.Len(); i++ {
+               enum = append(enum, 
CreateStringNode(string(values.Get(i).Name())))
+       }
+
+       return string(tt.FullName()), &base.Schema{
+               Title: string(tt.Name()),
+               Type:  []string{"string"},
+               Enum:  enum,
+       }
+}
+
 func ReferenceFieldToSchema(parent *base.SchemaProxy, tt 
protoreflect.FieldDescriptor) *base.SchemaProxy {
        switch tt.Kind() {
        case protoreflect.MessageKind:

Reply via email to