From 65d4342af5721f4267000cfcd5a02fb2f2b36203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Matheson=20Wergeland?= Date: Mon, 21 Mar 2022 22:43:00 +0100 Subject: [PATCH] protoc-gen-openapiv2: Use the canonical camelCase converter for protobuf (#2599) * Use the canonical camelCase converter for protobuf. Fixes issue #2363. * Revert change that should go in separate PR --- internal/casing/LICENSE.md | 2 +- internal/casing/README.md | 8 +++++--- internal/casing/camel.go | 18 ++++++++++++++++++ .../internal/genopenapi/template.go | 14 +++----------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/internal/casing/LICENSE.md b/internal/casing/LICENSE.md index 0f646931a46..ca708b0f8ab 100644 --- a/internal/casing/LICENSE.md +++ b/internal/casing/LICENSE.md @@ -1,4 +1,4 @@ -Copyright 2010 The Go Authors. All rights reserved. +Copyright 2010, 2019 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/internal/casing/README.md b/internal/casing/README.md index 88114463aa8..928e0c70d66 100644 --- a/internal/casing/README.md +++ b/internal/casing/README.md @@ -1,5 +1,7 @@ # Case conversion -This package contains a single function, copied from the -`github.com/golang/protobuf/protoc-gen-go/generator` package. That -modules LICENSE is referenced in its entirety in this package. +This package contains two functions: +- `Camel` copied from the `github.com/golang/protobuf/protoc-gen-go/generator` package. +- `JSONCamelCase` copied from the `github.com/protocolbuffers/protobuf-go/internal/strs` package. + +Both these modules are licensed by The Go Authors, as reflected in this package's [LICENSE.md]. diff --git a/internal/casing/camel.go b/internal/casing/camel.go index 8cfef4bf2a6..85e708ea1f4 100644 --- a/internal/casing/camel.go +++ b/internal/casing/camel.go @@ -50,6 +50,24 @@ func Camel(s string) string { return string(t) } +// JSONCamelCase converts a snake_case identifier to a camelCase identifier, +// according to the protobuf JSON specification. +func JSONCamelCase(s string) string { + var b []byte + var wasUnderscore bool + for i := 0; i < len(s); i++ { // proto identifiers are always ASCII + c := s[i] + if c != '_' { + if wasUnderscore && isASCIILower(c) { + c -= 'a' - 'A' // convert to uppercase + } + b = append(b, c) + } + wasUnderscore = c == '_' + } + return string(b) +} + // And now lots of helper functions. // Is c an ASCII lower-case letter? diff --git a/protoc-gen-openapiv2/internal/genopenapi/template.go b/protoc-gen-openapiv2/internal/genopenapi/template.go index df915d34a2b..6af43c04e81 100644 --- a/protoc-gen-openapiv2/internal/genopenapi/template.go +++ b/protoc-gen-openapiv2/internal/genopenapi/template.go @@ -2523,7 +2523,7 @@ func updateswaggerObjectFromJSONSchema(s *openapiSchemaObject, j *openapi_option if reg.GetUseJSONNamesForFields() { for i, r := range s.Required { // TODO(oyvindwe): Look up field and use field.GetJsonName()? - s.Required[i] = doCamelCase(r) + s.Required[i] = casing.JSONCamelCase(r) } } s.Enum = j.GetEnum() @@ -2707,7 +2707,7 @@ func lowerCamelCase(fieldName string, fields []*descriptor.Field, msgs []*descri fieldNames := strings.Split(fieldName, ".") fieldNamesWithCamelCase := make([]string, 0) for i := 0; i < len(fieldNames)-1; i++ { - fieldNamesWithCamelCase = append(fieldNamesWithCamelCase, doCamelCase(string(fieldNames[i]))) + fieldNamesWithCamelCase = append(fieldNamesWithCamelCase, casing.JSONCamelCase(string(fieldNames[i]))) } prefix := strings.Join(fieldNamesWithCamelCase, ".") reservedJSONName := getReservedJSONName(fieldName, messageNameToFieldsToJSONName, fieldNameToType) @@ -2715,15 +2715,7 @@ func lowerCamelCase(fieldName string, fields []*descriptor.Field, msgs []*descri return prefix + "." + reservedJSONName } } - return doCamelCase(fieldName) -} - -func doCamelCase(input string) string { - parameterString := casing.Camel(input) - builder := &strings.Builder{} - builder.WriteString(strings.ToLower(string(parameterString[0]))) - builder.WriteString(parameterString[1:]) - return builder.String() + return casing.JSONCamelCase(fieldName) } func getReservedJSONName(fieldName string, messageNameToFieldsToJSONName map[string]map[string]string, fieldNameToType map[string]string) string {