Skip to content

Commit

Permalink
Add config property "enumPropertyNaming" to TypeScript codegens.
Browse files Browse the repository at this point in the history
It allows overriding how enum member names are capitalised or
snake_cased in generated code.  It works very similarly to the Kotlin
generator property of the same name.
  • Loading branch information
src-cfl committed Feb 15, 2019
1 parent 4a9971d commit a4e5eb7
Show file tree
Hide file tree
Showing 17 changed files with 154 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,14 @@ public String snakeCase(String name) {
return (name.length() > 0) ? (Character.toLowerCase(name.charAt(0)) + name.substring(1)) : "";
}

/**
* Capitalise first character of string
*/
@SuppressWarnings("static-method")
public static String titleCase(final String input) {
return input.substring(0, 1).toUpperCase() + input.substring(1);
}

/**
* Capitalize the string
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.utils.EnumPropertyNamingUtils;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
Expand Down Expand Up @@ -218,15 +220,7 @@ public CodegenConstants.ENUM_PROPERTY_NAMING_TYPE getEnumPropertyNaming() {
* @param enumPropertyNamingType The string representation of the naming convention, as defined by {@link CodegenConstants.ENUM_PROPERTY_NAMING_TYPE}
*/
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());
}
this.enumPropertyNaming = EnumPropertyNamingUtils.parseEnumPropertyNaming(enumPropertyNamingType);
}

/**
Expand Down Expand Up @@ -376,28 +370,11 @@ public String toEnumVarName(String value, String datatype) {
modified = sanitizeKotlinSpecificNames(modified);
}

switch (getEnumPropertyNaming()) {
case original:
// NOTE: This is provided as a last-case allowance, but will still result in reserved words being escaped.
modified = value;
break;
case camelCase:
// NOTE: Removes hyphens and underscores
modified = camelize(modified, true);
break;
case PascalCase:
// NOTE: Removes hyphens and underscores
String result = camelize(modified);
modified = titleCase(result);
break;
case snake_case:
// NOTE: Removes hyphens
modified = underscore(modified);
break;
case UPPERCASE:
modified = modified.toUpperCase();
break;
if (getEnumPropertyNaming() == ENUM_PROPERTY_NAMING_TYPE.original) {
// NOTE: This is provided as a last-case allowance, but will still result in reserved words being escaped.
modified = value;
}
modified = EnumPropertyNamingUtils.applyEnumPropertyCapitalisation(modified, getEnumPropertyNaming());

if (reservedWords.contains(modified)) {
return escapeReservedWord(modified);
Expand Down Expand Up @@ -516,10 +493,6 @@ private String sanitizeKotlinSpecificNames(final String name) {
return word;
}

private String titleCase(final String input) {
return input.substring(0, 1).toUpperCase() + input.substring(1);
}

@Override
protected boolean isReservedWord(String word) {
// We want case-sensitive escaping, to avoid unnecessary backtick-escaping.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.utils.EnumPropertyNamingUtils;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.DateProperty;
Expand All @@ -31,6 +33,12 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
private static final String UNDEFINED_VALUE = "undefined";

protected String modelPropertyNaming= "camelCase";
/**
* Enum variables are PascalCase by default.
* ref: https://basarat.gitbooks.io/typescript/content/docs/enums.html
*/
protected ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming = ENUM_PROPERTY_NAMING_TYPE.PascalCase;

protected Boolean supportsES6 = true;
protected HashSet<String> languageGenericTypes;

Expand Down Expand Up @@ -101,6 +109,7 @@ public AbstractTypeScriptClientCodegen() {
typeMapping.put("Error", "Error");

cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));
cliOptions.add(new CliOption(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_DESC).defaultValue(enumPropertyNaming.name()));
cliOptions.add(new CliOption(CodegenConstants.SUPPORTS_ES6, CodegenConstants.SUPPORTS_ES6_DESC).defaultValue("false"));

}
Expand All @@ -112,6 +121,9 @@ public void processOpts() {
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
}
if (additionalProperties.containsKey(CodegenConstants.ENUM_PROPERTY_NAMING)) {
setEnumPropertyNaming((String) additionalProperties.get(CodegenConstants.ENUM_PROPERTY_NAMING));
}

if (additionalProperties.containsKey(CodegenConstants.SUPPORTS_ES6)) {
setSupportsES6(Boolean.valueOf(additionalProperties.get(CodegenConstants.SUPPORTS_ES6).toString()));
Expand Down Expand Up @@ -409,10 +421,21 @@ public void setModelPropertyNaming(String naming) {
}
}

/**
* @param enumPropertyNamingType The string representation of the naming convention, as defined by {@link ENUM_PROPERTY_NAMING_TYPE}
*/
public void setEnumPropertyNaming(final String enumPropertyNamingType) {
enumPropertyNaming = EnumPropertyNamingUtils.parseEnumPropertyNaming(enumPropertyNamingType);
}

public String getModelPropertyNaming() {
return this.modelPropertyNaming;
}

public ENUM_PROPERTY_NAMING_TYPE getEnumPropertyNaming() {
return enumPropertyNaming;
}

public String getNameUsingModelPropertyNaming(String name) {
switch (CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.valueOf(getModelPropertyNaming())) {
case original: return name;
Expand Down Expand Up @@ -448,7 +471,7 @@ public String toEnumVarName(String name, String datatype) {

// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(getSymbolName(name));
return EnumPropertyNamingUtils.applyEnumPropertyCapitalisation(getSymbolName(name), enumPropertyNaming);
}

// number
Expand All @@ -466,9 +489,7 @@ public String toEnumVarName(String name, String datatype) {
enumName = enumName.replaceFirst("^_", "");
enumName = enumName.replaceFirst("_$", "");

// camelize the enum variable name
// ref: https://basarat.gitbooks.io/typescript/content/docs/enums.html
enumName = camelize(enumName);
enumName = EnumPropertyNamingUtils.applyEnumPropertyCapitalisation(enumName, enumPropertyNaming);

if (enumName.matches("\\d.*")) { // starts with number
return "_" + enumName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.swagger.codegen.utils;

import io.swagger.codegen.CodegenConstants.ENUM_PROPERTY_NAMING_TYPE;
import io.swagger.codegen.DefaultCodegen;

public final class EnumPropertyNamingUtils {

/** Apply the given {@link ENUM_PROPERTY_NAMING_TYPE} to get the correct capitalisation and underscore-usage for an enum name. */
public static String applyEnumPropertyCapitalisation(String value, final ENUM_PROPERTY_NAMING_TYPE enumPropertyNaming) {
switch (enumPropertyNaming) {
case original:
return value;
case camelCase:
// NOTE: Removes hyphens and underscores
return DefaultCodegen.camelize(value, true);
case PascalCase:
// NOTE: Removes hyphens and underscores
return DefaultCodegen.titleCase(DefaultCodegen.camelize(value));
case snake_case:
// NOTE: Removes hyphens
return DefaultCodegen.underscore(value);
case UPPERCASE:
return value.toUpperCase();
default:
return value;
}
}

public static ENUM_PROPERTY_NAMING_TYPE parseEnumPropertyNaming(final String enumPropertyNamingType) {
try {
return 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 (ENUM_PROPERTY_NAMING_TYPE t : ENUM_PROPERTY_NAMING_TYPE.values()) {
sb.append("\n ").append(t.name());
}
throw new RuntimeException(sb.toString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class TypeScriptAngularClientOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
public static final String ENUM_PROPERTY_NAMING_VALUE = "snake_case";
private static final String NMP_NAME = "npmName";
private static final String NMP_VERSION = "1.1.2";
private static final String NPM_REPOSITORY = "https://registry.npmjs.org";
Expand All @@ -30,6 +31,7 @@ public Map<String, String> createOptions() {
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.ENUM_PROPERTY_NAMING, ENUM_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.SUPPORTS_ES6, SUPPORTS_ES6_VALUE)
.put(TypeScriptAngularClientCodegen.NPM_NAME, NMP_NAME)
.put(TypeScriptAngularClientCodegen.NPM_VERSION, NMP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class TypeScriptAngularJsClientOptionsProvider implements OptionsProvider
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
public static final String ENUM_PROPERTY_NAMING_VALUE = "snake_case";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";

@Override
Expand All @@ -25,6 +26,7 @@ public Map<String, String> createOptions() {
.put(CodegenConstants.SUPPORTS_ES6, SUPPORTS_ES6_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.ENUM_PROPERTY_NAMING, ENUM_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class TypeScriptAureliaClientOptionsProvider implements OptionsProvider {
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final Boolean SUPPORTS_ES6_VALUE = false;
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
public static final String ENUM_PROPERTY_NAMING_VALUE = "snake_case";
private static final String NMP_NAME = "npmName";
private static final String NMP_VERSION = "1.0.0";
public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false";
Expand All @@ -27,6 +28,7 @@ public Map<String, String> createOptions() {
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.ENUM_PROPERTY_NAMING, ENUM_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.SUPPORTS_ES6, String.valueOf(SUPPORTS_ES6_VALUE))
.put(TypeScriptAureliaClientCodegen.NPM_NAME, NMP_NAME)
.put(TypeScriptAureliaClientCodegen.NPM_VERSION, NMP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class TypeScriptFetchClientOptionsProvider implements OptionsProvider {
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final Boolean SUPPORTS_ES6_VALUE = false;
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
public static final String ENUM_PROPERTY_NAMING_VALUE = "snake_case";
private static final String NMP_NAME = "npmName";
private static final String NMP_VERSION = "1.0.0";
private static final String NPM_REPOSITORY = "https://registry.npmjs.org";
Expand All @@ -28,6 +29,7 @@ public Map<String, String> createOptions() {
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.ENUM_PROPERTY_NAMING, ENUM_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.SUPPORTS_ES6, String.valueOf(SUPPORTS_ES6_VALUE))
.put(TypeScriptFetchClientCodegen.NPM_NAME, NMP_NAME)
.put(TypeScriptFetchClientCodegen.NPM_VERSION, NMP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class TypeScriptInversifyClientOptionsProvider implements OptionsProvider
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
public static final String ENUM_PROPERTY_NAMING_VALUE = "snake_case";
private static final String NMP_NAME = "npmName";
private static final String NMP_VERSION = "1.1.2";
private static final String NPM_REPOSITORY = "https://registry.npmjs.org";
Expand All @@ -31,6 +32,7 @@ public Map<String, String> createOptions() {
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.ENUM_PROPERTY_NAMING, ENUM_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.SUPPORTS_ES6, SUPPORTS_ES6_VALUE)
.put(TypeScriptInversifyClientCodegen.NPM_NAME, NMP_NAME)
.put(TypeScriptInversifyClientCodegen.NPM_VERSION, NMP_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class TypeScriptNodeClientOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String MODEL_PROPERTY_NAMING_VALUE = "camelCase";
public static final String ENUM_PROPERTY_NAMING_VALUE = "snake_case";

private static final String NMP_NAME = "npmName";
private static final String NMP_VERSION = "1.1.2";
Expand All @@ -32,6 +33,7 @@ public Map<String, String> createOptions() {
.put(CodegenConstants.SUPPORTS_ES6, SUPPORTS_ES6_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(CodegenConstants.MODEL_PROPERTY_NAMING, MODEL_PROPERTY_NAMING_VALUE)
.put(CodegenConstants.ENUM_PROPERTY_NAMING, ENUM_PROPERTY_NAMING_VALUE)
.put(TypeScriptAngularClientCodegen.NPM_NAME, NMP_NAME)
.put(TypeScriptAngularClientCodegen.NPM_VERSION, NMP_VERSION)
.put(TypeScriptAngularClientCodegen.SNAPSHOT, Boolean.FALSE.toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ protected void setExpectations() {
times = 1;
clientCodegen.setModelPropertyNaming(TypeScriptAureliaClientOptionsProvider.MODEL_PROPERTY_NAMING_VALUE);
times = 1;
clientCodegen.setEnumPropertyNaming(TypeScriptAureliaClientOptionsProvider.ENUM_PROPERTY_NAMING_VALUE);
times = 1;
clientCodegen.setSupportsES6(TypeScriptAureliaClientOptionsProvider.SUPPORTS_ES6_VALUE);
times = 1;
}};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ protected void setExpectations() {
times = 1;
clientCodegen.setModelPropertyNaming(TypeScriptFetchClientOptionsProvider.MODEL_PROPERTY_NAMING_VALUE);
times = 1;
clientCodegen.setEnumPropertyNaming(TypeScriptFetchClientOptionsProvider.ENUM_PROPERTY_NAMING_VALUE);
times = 1;
clientCodegen.setSupportsES6(TypeScriptFetchClientOptionsProvider.SUPPORTS_ES6_VALUE);
times = 1;
}};
Expand Down

0 comments on commit a4e5eb7

Please sign in to comment.