From 9d6a282dd12db39ae76235d029caa0c8083cd551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Thu, 30 May 2024 23:12:59 +0800 Subject: [PATCH] add deprecated tag (#1) * fix: 2024-05-25 15:45:21 * add tag query and parameter --- .../tests/deprecated/message.openapi.yaml | 41 ++++++ examples/tests/deprecated/message.proto | 45 +++++++ .../openapiv3annotations/message.openapi.yaml | 8 ++ .../tests/openapiv3annotations/message.proto | 126 ++++++++++-------- generator/generator.go | 39 ++++++ 5 files changed, 205 insertions(+), 54 deletions(-) create mode 100644 examples/tests/deprecated/message.openapi.yaml create mode 100644 examples/tests/deprecated/message.proto diff --git a/examples/tests/deprecated/message.openapi.yaml b/examples/tests/deprecated/message.openapi.yaml new file mode 100644 index 0000000..35c20e8 --- /dev/null +++ b/examples/tests/deprecated/message.openapi.yaml @@ -0,0 +1,41 @@ +# Generated with protoc-gen-openapi +# https://github.com/pubgo/protoc-gen-openapi + +openapi: 3.0.3 +info: + title: openapi examples + version: 0.0.1 +paths: + /v1/messages:deprecated: + put: + tags: + - Messaging1 + operationId: Messaging1_UpdateMessage + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Messagedeprecated' + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Messagedeprecated' +components: + schemas: + Messagedeprecated: + type: object + properties: + id: + type: string + label: + deprecated: true + type: string + label1: + deprecated: true + type: string +tags: + - name: Messaging1 diff --git a/examples/tests/deprecated/message.proto b/examples/tests/deprecated/message.proto new file mode 100644 index 0000000..486837a --- /dev/null +++ b/examples/tests/deprecated/message.proto @@ -0,0 +1,45 @@ +// Copyright 2021 Google LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +package tests.deprecated.message.v1; + +import "google/api/annotations.proto"; +import "openapiv3/annotations.proto"; + +option go_package = "github.com/google/gnostic/apps/protoc-gen-openapi/examples/tests/noannotations/message/v1;message"; + +service Messaging1 { + rpc UpdateMessage (Messagedeprecated) returns (Messagedeprecated) { + option (google.api.http) = { + put: "/v1/messages:deprecated" + body: "*" + }; + } +} + +message Messagedeprecated { + int64 id = 1; + string label = 2 [ + (openapi.v3.property) = { + deprecated: true + } + ]; + + string label1 = 3 [ + deprecated = true + ]; +} diff --git a/examples/tests/openapiv3annotations/message.openapi.yaml b/examples/tests/openapiv3annotations/message.openapi.yaml index 80294df..02a6ee0 100644 --- a/examples/tests/openapiv3annotations/message.openapi.yaml +++ b/examples/tests/openapiv3annotations/message.openapi.yaml @@ -25,6 +25,12 @@ paths: required: true schema: type: string + - name: Authorization + in: header + description: jwt token + required: true + schema: + type: string requestBody: content: application/json: @@ -40,6 +46,8 @@ paths: $ref: '#/components/schemas/Message' security: - BasicAuth: [] + x-operation-id: updateMessage + abc: def components: schemas: Message: diff --git a/examples/tests/openapiv3annotations/message.proto b/examples/tests/openapiv3annotations/message.proto index 39e95b5..8b13368 100644 --- a/examples/tests/openapiv3annotations/message.proto +++ b/examples/tests/openapiv3annotations/message.proto @@ -23,72 +23,90 @@ import "openapiv3/annotations.proto"; option go_package = "github.com/google/gnostic/apps/protoc-gen-openapi/examples/tests/openapiv3annotations/message/v1;message"; option (openapi.v3.document) = { - info: { - title: "Title from annotation"; - version: "Version from annotation"; - description: "Description from annotation"; - contact: { - name: "Contact Name"; - url: "https://github.com/google/gnostic"; - email: "gnostic@google.com"; - } - license: { - name: "Apache License"; - url: "https://github.com/google/gnostic/blob/master/LICENSE"; + info: { + title: "Title from annotation"; + version: "Version from annotation"; + description: "Description from annotation"; + contact: { + name: "Contact Name"; + url: "https://github.com/google/gnostic"; + email: "gnostic@google.com"; + } + license: { + name: "Apache License"; + url: "https://github.com/google/gnostic/blob/master/LICENSE"; + } } - } - components: { - security_schemes: { - additional_properties: [ - { - name: "BasicAuth"; - value: { - security_scheme: { - type: "http"; - scheme: "basic"; - } - } + components: { + security_schemes: { + additional_properties: [ + { + name: "BasicAuth"; + value: { + security_scheme: { + type: "http"; + scheme: "basic"; + } + } + } + ] } - ] } - } }; service Messaging1 { - rpc UpdateMessage(Message) returns(Message) { - option(google.api.http) = { - patch: "/v1/messages/{message_id}" - body: "*" - }; - option(openapi.v3.operation) = { - security: [ - { - additional_properties: [ - { - name: "BasicAuth"; - value: {} - } + rpc UpdateMessage (Message) returns (Message) { + option (google.api.http) = { + patch: "/v1/messages/{message_id}" + body: "*" + }; + + option (openapi.v3.operation) = { + tags: ["abc=def"], + specification_extension: [ + { + name: "x-operation-id"; + value: { + yaml: "updateMessage" + }; + } + ], + parameters: [{ + parameter: { + description: "jwt token", + in: "header", + name: "Authorization", + required: true, + }, + }], + security: [ + { + additional_properties: [ + { + name: "BasicAuth"; + value: {} + } + ] + } ] - } - ] - }; - } + }; + } } service Messaging2 { - rpc UpdateMessage(Message) returns (Message) {} + rpc UpdateMessage (Message) returns (Message) {} } message Message { - option (openapi.v3.schema) = { - title: "This is an overridden message schema title"; - }; + option (openapi.v3.schema) = { + title: "This is an overridden message schema title"; + }; - int64 id = 1; - string label = 2 [ - (openapi.v3.property) = { - title: "this is an overriden field schema title"; - max_length: 255; - } - ]; + int64 id = 1; + string label = 2 [ + (openapi.v3.property) = { + title: "this is an overriden field schema title"; + max_length: 255; + } + ]; } diff --git a/generator/generator.go b/generator/generator.go index 592e602..848fcca 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -29,6 +29,7 @@ import ( "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" any_pb "google.golang.org/protobuf/types/known/anypb" wk "github.com/pubgo/protoc-gen-openapi/generator/wellknown" @@ -763,6 +764,39 @@ func (g *OpenAPIv3Generator) addPathsToDocumentV3(d *v3.Document, services []*pr proto.Merge(op, extOperation.(*v3.Operation)) } + for _, v := range op.Parameters { + if v.Oneof == nil { + continue + } + + switch v1 := v.Oneof.(type) { + case *v3.ParameterOrReference_Parameter: + p := v1.Parameter + if p.In == "header" { + if p.Schema == nil { + p.Schema = wk.NewStringSchema() + } + } + } + } + + var tags []string + for _, v := range op.Tags { + if strings.Contains(v, "=") { + tagNames := strings.SplitN(v, "=", 2) + op.SpecificationExtension = append(op.SpecificationExtension, &v3.NamedAny{ + Name: strings.TrimSpace(tagNames[0]), + Value: &v3.Any{ + Yaml: strings.TrimSpace(tagNames[1]), + }, + }) + continue + } + + tags = append(tags, v) + } + + op.Tags = tags g.addOperationToDocumentV3(d, op, path2, methodName) } } @@ -871,6 +905,11 @@ func (g *OpenAPIv3Generator) addSchemasForMessagesToDocumentV3(d *v3.Document, m } schema.Schema.ReadOnly = outputOnly schema.Schema.WriteOnly = inputOnly + if opt, ok := field.Desc.Options().(*descriptorpb.FieldOptions); ok && opt != nil { + if opt.Deprecated != nil && *opt.Deprecated { + schema.Schema.Deprecated = *opt.Deprecated + } + } // Merge any `Property` annotations with the current extProperty := proto.GetExtension(field.Desc.Options(), v3.E_Property)