From a0836c0289c9737c5e45091e8875ba467ae32a81 Mon Sep 17 00:00:00 2001 From: Sasha Melentyev Date: Sat, 6 Apr 2024 00:59:14 +0300 Subject: [PATCH 1/2] fix: nested item Signed-off-by: Sasha Melentyev --- example/message.proto | 1 + example/openapi.yaml | 6 ++++++ internal/gen/generator.go | 13 ++++++++++--- internal/gen/schema.go | 9 +++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/example/message.proto b/example/message.proto index e492991..e1c8959 100644 --- a/example/message.proto +++ b/example/message.proto @@ -34,6 +34,7 @@ message GetItemsResponse { ItemType type = 2 [(google.api.field_behavior) = REQUIRED]; string name = 3 [(google.api.field_behavior) = REQUIRED]; google.protobuf.Timestamp created_at = 4 [(google.api.field_behavior) = REQUIRED]; + repeated NestedItem nested_item = 5; } repeated Item items = 1 [(google.api.field_behavior) = REQUIRED]; diff --git a/example/openapi.yaml b/example/openapi.yaml index 4ee548e..61ca7b4 100644 --- a/example/openapi.yaml +++ b/example/openapi.yaml @@ -173,6 +173,10 @@ components: createdAt: type: string format: date-time + nestedItem: + type: array + items: + $ref: '#/components/schemas/GetItemsResponse.NestedItem' required: - id - type @@ -202,6 +206,8 @@ components: enum: - ITEM_TYPE_UNSPECIFIED - ITEM_TYPE_BASIC + NestedEnum: + type: object NestedEnum.ItemType: type: string enum: diff --git a/internal/gen/generator.go b/internal/gen/generator.go index 45115cf..a45f098 100644 --- a/internal/gen/generator.go +++ b/internal/gen/generator.go @@ -70,6 +70,12 @@ func NewGenerator(files []*protogen.File, opts ...GeneratorOption) (*Generator, } } } + } + + for _, f := range files { + if !f.Generate { + continue + } for _, m := range f.Messages { name := descriptorName(m.Desc) @@ -93,9 +99,10 @@ func NewGenerator(files []*protogen.File, opts ...GeneratorOption) (*Generator, // Generator instance. type Generator struct { - spec *ogen.Spec - indent int - requests map[string]struct{} + spec *ogen.Spec + indent int + requests map[string]struct{} + lastDescriptorName string } // YAML returns OpenAPI specification bytes. diff --git a/internal/gen/schema.go b/internal/gen/schema.go index 2bb1336..117f0e6 100644 --- a/internal/gen/schema.go +++ b/internal/gen/schema.go @@ -59,6 +59,15 @@ func (g *Generator) mkSchema(msg *protogen.Message) error { } if field.Message != nil { + currentDescriptorName := descriptorName(field.Desc) + if g.lastDescriptorName == currentDescriptorName { + s.SetRef(descriptorRef(field.Message.Desc)) + + continue + } + + g.lastDescriptorName = currentDescriptorName + if err := g.mkSchema(field.Message); err != nil { return err } From 362a5f5f87bc3a0a44b58e5e055ad660cafd5af7 Mon Sep 17 00:00:00 2001 From: Sasha Melentyev Date: Sat, 6 Apr 2024 00:59:14 +0300 Subject: [PATCH 2/2] fix: nested item Signed-off-by: Sasha Melentyev --- example/message.proto | 1 + example/openapi.yaml | 6 ++++++ internal/gen/generator.go | 41 +++++++++++++++++++++++++++++++++------ internal/gen/schema.go | 9 +++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/example/message.proto b/example/message.proto index e492991..e1c8959 100644 --- a/example/message.proto +++ b/example/message.proto @@ -34,6 +34,7 @@ message GetItemsResponse { ItemType type = 2 [(google.api.field_behavior) = REQUIRED]; string name = 3 [(google.api.field_behavior) = REQUIRED]; google.protobuf.Timestamp created_at = 4 [(google.api.field_behavior) = REQUIRED]; + repeated NestedItem nested_item = 5; } repeated Item items = 1 [(google.api.field_behavior) = REQUIRED]; diff --git a/example/openapi.yaml b/example/openapi.yaml index 4ee548e..61ca7b4 100644 --- a/example/openapi.yaml +++ b/example/openapi.yaml @@ -173,6 +173,10 @@ components: createdAt: type: string format: date-time + nestedItem: + type: array + items: + $ref: '#/components/schemas/GetItemsResponse.NestedItem' required: - id - type @@ -202,6 +206,8 @@ components: enum: - ITEM_TYPE_UNSPECIFIED - ITEM_TYPE_BASIC + NestedEnum: + type: object NestedEnum.ItemType: type: string enum: diff --git a/internal/gen/generator.go b/internal/gen/generator.go index 45115cf..8488c8c 100644 --- a/internal/gen/generator.go +++ b/internal/gen/generator.go @@ -70,6 +70,12 @@ func NewGenerator(files []*protogen.File, opts ...GeneratorOption) (*Generator, } } } + } + + for _, f := range files { + if !f.Generate { + continue + } for _, m := range f.Messages { name := descriptorName(m.Desc) @@ -93,9 +99,10 @@ func NewGenerator(files []*protogen.File, opts ...GeneratorOption) (*Generator, // Generator instance. type Generator struct { - spec *ogen.Spec - indent int - requests map[string]struct{} + spec *ogen.Spec + indent int + requests map[string]struct{} + descriptorNames map[string]struct{} } // YAML returns OpenAPI specification bytes. @@ -121,6 +128,7 @@ func (g *Generator) init() { g.spec = ogen.NewSpec() g.spec.Init() g.requests = make(map[string]struct{}) + g.descriptorNames = make(map[string]struct{}) } func (g *Generator) mkMethod(rule HTTPRule, m *protogen.Method) (string, *ogen.Operation, error) { @@ -143,7 +151,7 @@ func (g *Generator) mkMethod(rule HTTPRule, m *protogen.Method) (string, *ogen.O func (g *Generator) mkInput(rule HTTPRule, m *protogen.Method, op *ogen.Operation) (string, error) { name := descriptorName(m.Input.Desc) - g.requests[name] = struct{}{} + g.setRequest(name) var ( fields = collectFields(m.Input) @@ -403,8 +411,29 @@ func (g *Generator) hasSchema(s string) bool { return ok } -func (g *Generator) hasRequest(r string) bool { - _, ok := g.requests[r] +func (g *Generator) setRequest(s string) { + if g.hasRequest(s) { + return + } + + g.requests[s] = struct{}{} +} + +func (g *Generator) hasRequest(s string) bool { + _, ok := g.requests[s] + return ok +} + +func (g *Generator) setDescriptorName(s string) { + if g.hasDescriptorName(s) { + return + } + + g.descriptorNames[s] = struct{}{} +} + +func (g *Generator) hasDescriptorName(s string) bool { + _, ok := g.descriptorNames[s] return ok } diff --git a/internal/gen/schema.go b/internal/gen/schema.go index 2bb1336..a699e91 100644 --- a/internal/gen/schema.go +++ b/internal/gen/schema.go @@ -59,6 +59,15 @@ func (g *Generator) mkSchema(msg *protogen.Message) error { } if field.Message != nil { + name := descriptorName(field.Desc) + if g.hasDescriptorName(name) { + s.SetRef(descriptorRef(field.Message.Desc)) + + continue + } + + g.setDescriptorName(name) + if err := g.mkSchema(field.Message); err != nil { return err }