From 8e98671ba6d87608b4ee9eb0d56fdca4f56b517c Mon Sep 17 00:00:00 2001 From: Kazuhiro Fujieda Date: Tue, 7 Nov 2023 11:52:10 +0900 Subject: [PATCH] [csharp] Introducing the `enumPropertyNaming` option to the C# Generator (#16981) * [csharp] Support the enumPropertyNaming option * Add a doc comment to adjustNamingStyle --- .../languages/AbstractCSharpCodegen.java | 55 ++++++++++++++++++- .../csharpnetcore/CSharpModelEnumTest.java | 54 ++++++++++++++++++ 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java index e9a7a50b8a09..871dd608322b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java @@ -45,6 +45,7 @@ import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER; import static org.openapitools.codegen.utils.StringUtils.camelize; +import static org.openapitools.codegen.utils.StringUtils.underscore; public abstract class AbstractCSharpCodegen extends DefaultCodegen implements CodegenConfig { @@ -84,6 +85,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co protected String sourceFolder = "src"; protected String invalidNamePrefix = "var"; + protected CodegenConstants.ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.PascalCase; // TODO: Add option for test folder output location. Nice to allow e.g. ./test instead of ./src. // This would require updating relative paths (e.g. path to main project file in test project file) @@ -391,6 +393,10 @@ public void processOpts() { setEnumValueSuffix(additionalProperties.get(CodegenConstants.ENUM_VALUE_SUFFIX).toString()); } + if (additionalProperties.containsKey(CodegenConstants.ENUM_PROPERTY_NAMING)) { + setEnumPropertyNaming((String) additionalProperties.get(CodegenConstants.ENUM_PROPERTY_NAMING)); + } + // This either updates additionalProperties with the above fixes, or sets the default if the option was not specified. additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix); @@ -1598,6 +1604,22 @@ public void setSupportNullable(final boolean supportNullable) { this.supportNullable = supportNullable; } + public CodegenConstants.ENUM_PROPERTY_NAMING_TYPE getEnumPropertyNaming() { + return this.enumPropertyNaming; + } + + public void setEnumPropertyNaming(final String enumPropertyNamingType) { + try { + this.enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.valueOf(enumPropertyNamingType); + } catch (IllegalArgumentException ex) { + StringBuilder sb = new StringBuilder(enumPropertyNamingType + " is an invalid enum property naming option. Please choose from:"); + for (CodegenConstants.ENUM_PROPERTY_NAMING_TYPE t : CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.values()) { + sb.append("\n ").append(t.name()); + } + throw new RuntimeException(sb.toString()); + } + } + @Override public String toEnumValue(String value, String datatype) { // C# only supports enums as literals for int, int?, long, long?, byte, and byte?. All else must be treated as strings. @@ -1622,12 +1644,12 @@ public String toEnumValue(String value, String datatype) { @Override public String toEnumVarName(String name, String datatype) { if (name.length() == 0) { - return "Empty"; + return adjustNamingStyle("Empty"); } // for symbol, e.g. $, # if (getSymbolName(name) != null) { - return camelize(getSymbolName(name)); + return adjustNamingStyle(getSymbolName(name)); } String enumName = sanitizeName(name); @@ -1635,7 +1657,7 @@ public String toEnumVarName(String name, String datatype) { enumName = enumName.replaceFirst("^_", ""); enumName = enumName.replaceFirst("_$", ""); - enumName = camelize(enumName) + this.enumValueSuffix; + enumName = adjustNamingStyle(enumName) + this.enumValueSuffix; if (enumName.matches("\\d.*")) { // starts with number return "_" + enumName; @@ -1644,6 +1666,33 @@ public String toEnumVarName(String name, String datatype) { } } + /** + * Adjust the naming style of a given name based on the enumPropertyNaming option. + * + * @param name The original name + * @return The adjusted name + */ + private String adjustNamingStyle(String name) + { + switch (getEnumPropertyNaming()) { + case original: + return name; + case camelCase: + // NOTE: Removes hyphens and underscores + return camelize(name, LOWERCASE_FIRST_LETTER); + case PascalCase: + // NOTE: Removes hyphens and underscores + return camelize(name); + case snake_case: + // NOTE: Removes hyphens + return underscore(name); + case UPPERCASE: + return underscore(name).toUpperCase(Locale.ROOT); + default: + return name; + } + } + @Override public String toEnumName(CodegenProperty property) { return sanitizeName(camelize(property.name)) + this.enumNameSuffix; diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpModelEnumTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpModelEnumTest.java index 718857168182..731c899ac5ee 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpModelEnumTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpModelEnumTest.java @@ -28,11 +28,15 @@ import org.openapitools.codegen.languages.CSharpClientCodegen; import org.testng.Assert; import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.openapitools.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE; +import static org.openapitools.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.*; + public class CSharpModelEnumTest { // TODO there's no parent/child method in ComposeSchema so we will need to revise the code // before we can re-enable the test case below @@ -148,4 +152,54 @@ public void useEmptyEnumSuffixes() { Assert.assertEquals(codegen.toEnumVarName("Aaaa", ""), "Aaaa"); } + @Test(description = "support enum naming style options", dataProvider = "enumVarName") + public void testToEnumVarName(String name, String expected, ENUM_PROPERTY_NAMING_TYPE naming) throws Exception { + final AspNetServerCodegen codegen = new AspNetServerCodegen(); + codegen.setEnumPropertyNaming(naming.name()); + codegen.setEnumValueSuffix(""); + + Assert.assertEquals(codegen.toEnumVarName(name, "string"), expected); + } + + @DataProvider(name = "enumVarName") + public Object[][] provideTestData() + { + return new Object[][] { + { "FooBar", "fooBar", camelCase }, + { "fooBar", "fooBar", camelCase }, + { "foo-bar", "fooBar", camelCase }, + { "foo_bar", "fooBar", camelCase }, + { "foo bar", "fooBar", camelCase }, + { "FOO-BAR", "fOOBAR", camelCase }, // camelize doesn't support uppercase + { "FOO_BAR", "fOOBAR", camelCase }, // ditto + { "FooBar", "FooBar", PascalCase }, + { "fooBar", "FooBar", PascalCase }, + { "foo-bar", "FooBar", PascalCase }, + { "foo_bar", "FooBar", PascalCase }, + { "foo bar", "FooBar", PascalCase }, + { "FOO-BAR", "FOOBAR", PascalCase }, // ditto + { "FOO_BAR", "FOOBAR", PascalCase }, // ditto + { "FooBar", "foo_bar", snake_case }, + { "fooBar", "foo_bar", snake_case }, + { "foo-bar", "foo_bar", snake_case }, + { "foo_bar", "foo_bar", snake_case }, + { "foo bar", "foo_bar", snake_case }, + { "FOO-BAR", "foo_bar", snake_case }, + { "FOO_BAR", "foo_bar", snake_case }, + { "FooBar", "FOO_BAR", UPPERCASE }, + { "fooBar", "FOO_BAR", UPPERCASE }, + { "foo-bar", "FOO_BAR", UPPERCASE }, + { "foo_bar", "FOO_BAR", UPPERCASE }, + { "foo bar", "FOO_BAR", UPPERCASE }, + { "FOO-BAR", "FOO_BAR", UPPERCASE }, + { "FOO_BAR", "FOO_BAR", UPPERCASE }, + { "FooBar", "FooBar", original }, + { "fooBar", "fooBar", original }, + { "foo-bar", "foo_bar", original }, + { "foo_bar", "foo_bar", original }, + { "foo bar", "foo_bar", original }, + { "FOO-BAR", "FOO_BAR", original }, + { "FOO_BAR", "FOO_BAR", original }, + }; + } }