Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions cmd/protoc-gen-openapi/examples/tests/openapiv3enum/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# OpenAPI Enumeration Feature Improvements

## Overview

We have improved the enumeration support in the `protoc-gen-openapi` tool to correctly generate OpenAPI documentation containing enumeration values, with support for handling naming conflicts in nested enumerations.

## Major Improvements

1. **Unified Enumeration Value Generation**: Enumeration values are generated regardless of what `enum_type` is set to
2. **Field Name Usage**: Enumeration values use the field names defined in proto, rather than numeric values
3. **Type Unification**: Changed the default type from "integer" to "string" since we're using enumeration field names
4. **Backward Compatibility**: Still supports the `enum_type` parameter to control behavior
5. **Nested Enumeration Support**: Correctly handles enumerations nested within messages, avoiding naming conflicts
6. **Naming Conflict Resolution**: Nested enumerations use the `ParentMessage_EnumName` format to avoid conflicts

## Nested Enumeration Handling

### Naming Rules

- **File-level enumerations**: `EnumName` (e.g., `UserStatus`)
- **Nested enumerations**: `ParentMessage_EnumName` (e.g., `User_Status`)

### Example

```protobuf
message User {
enum Status { // Nested enumeration
UNKNOWN = 0;
ACTIVE = 1;
INACTIVE = 2;
}
Status status = 1;
}

enum UserRole { // File-level enumeration
ADMIN = 0;
USER = 1;
}
```

Generated OpenAPI Schema:

```yaml
components:
schemas:
User_Status: # Nested enumeration, using concatenated name
type: string
format: enum
enum:
- UNKNOWN
- ACTIVE
- INACTIVE

UserRole: # File-level enumeration, using original name
type: string
format: enum
enum:
- ADMIN
- USER

User:
type: object
properties:
status:
$ref: '#/components/schemas/User_Status' # Reference to nested enumeration
```

## Important Notes

1. Enumeration values use the field names defined in proto, not numeric values
2. This ensures the generated OpenAPI documentation is clearer and more readable
3. Maintains compatibility with existing code
4. Nested enumerations automatically handle naming conflicts using the `ParentMessage_EnumName` format
5. All enumeration types are defined in `components/schemas`, with fields referencing them via `$ref`
109 changes: 109 additions & 0 deletions cmd/protoc-gen-openapi/examples/tests/openapiv3enum/message.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2024 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.openapiv3enum.message.v1;

import "google/api/annotations.proto";

option go_package = "github.com/google/gnostic/apps/protoc-gen-openapi/examples/tests/openapiv3enum/message/v1;message";

// User management service
service UserService {
rpc CreateUser(User) returns (User) {
option (google.api.http) = {
post : "/v1/users"
body : "*"
};
}

rpc GetUser(GetUserRequest) returns (User) {
option (google.api.http) = {
get : "/v1/users/{user_id}"
};
}

rpc UpdateUserStatus(UpdateUserStatusRequest) returns (User) {
option (google.api.http) = {
patch : "/v1/users/{user_id}/status"
body : "*"
};
}
}

// File-level enumeration for user roles
enum UserRole {
USER_ROLE_UNSPECIFIED = 0;
USER_ROLE_ADMIN = 1;
USER_ROLE_USER = 2;
USER_ROLE_MODERATOR = 3;
}

// File-level enumeration for account types
enum AccountType {
ACCOUNT_TYPE_UNSPECIFIED = 0;
ACCOUNT_TYPE_PERSONAL = 1;
ACCOUNT_TYPE_BUSINESS = 2;
ACCOUNT_TYPE_ENTERPRISE = 3;
}

message User {
string user_id = 1;
string name = 2;
string email = 3;

// Nested enumeration for user status
enum Status {
STATUS_UNSPECIFIED = 0;
STATUS_ACTIVE = 1;
STATUS_INACTIVE = 2;
STATUS_SUSPENDED = 3;
STATUS_DELETED = 4;
}

// Nested enumeration for verification status
enum VerificationStatus {
VERIFICATION_UNSPECIFIED = 0;
VERIFICATION_PENDING = 1;
VERIFICATION_VERIFIED = 2;
VERIFICATION_FAILED = 3;
}

Status status = 4;
VerificationStatus verification_status = 5;
UserRole role = 6;
AccountType account_type = 7;

// Nested enumeration for notification preferences
enum NotificationPreference {
NOTIFICATION_UNSPECIFIED = 0;
NOTIFICATION_EMAIL = 1;
NOTIFICATION_SMS = 2;
NOTIFICATION_PUSH = 3;
NOTIFICATION_NONE = 4;
}

NotificationPreference notification_preference = 8;
}

message GetUserRequest {
string user_id = 1;
}

message UpdateUserStatusRequest {
string user_id = 1;
User.Status status = 2;
}
Loading