Support the empty string as an enumeration value (#4450)

When a string enumeration has the empty string as one of its available
values, the generated code for many languages is invalid because the
empty string can not be used as an identifier.  As with numbers and
symbols, provide a mapping to an English name which can be used as a
replacement.  In this case, "empty" for the empty string/empty value.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
This commit is contained in:
Kevin Locke 2017-01-06 04:30:47 -07:00 committed by wing328
parent 43ab14b200
commit df0c54d043
53 changed files with 160 additions and 29 deletions

View File

@ -303,6 +303,10 @@ public class DefaultCodegen {
* @return the sanitized variable name for enum
*/
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "EMPTY";
}
String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) {
return "_" + var;

View File

@ -615,6 +615,10 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "Empty";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(getSymbolName(name));

View File

@ -808,6 +808,10 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "EMPTY";
}
// for symbol, e.g. $, #
if (getSymbolName(value) != null) {
return getSymbolName(value).toUpperCase();

View File

@ -589,6 +589,10 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return (getSymbolName(name)).toUpperCase();

View File

@ -286,6 +286,10 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "Empty";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(getSymbolName(name));

View File

@ -494,6 +494,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "Empty";
}
// for symbol, e.g. $, #
if (getSymbolName(value) != null) {
return camelize(getSymbolName(value));

View File

@ -1021,6 +1021,10 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "empty";
}
// for symbol, e.g. $, #
if (getSymbolName(value) != null) {
return (getSymbolName(value)).toUpperCase();

View File

@ -292,6 +292,10 @@ public class NancyFXServerCodegen extends AbstractCSharpCodegen {
@Override
public String toEnumVarName(final String name, final String datatype) {
if (name.length() == 0) {
return "Empty";
}
final String enumName = camelize(
sanitizeName(name)
.replaceFirst("^_", "")

View File

@ -644,6 +644,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// number
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
String varName = name;

View File

@ -568,6 +568,10 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// number
if ("Integer".equals(datatype) || "Float".equals(datatype)) {
String varName = name;

View File

@ -513,6 +513,10 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "empty";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase()), true);

View File

@ -388,6 +388,10 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
@SuppressWarnings("static-method")
public String toSwiftyEnumName(String value) {
if (value.length() == 0) {
return "Empty";
}
if (value.matches("^-?\\d*\\.{0,1}\\d+.*")) { // starts with number
value = "Number" + value;
value = value.replaceAll("-", "Minus");

View File

@ -1067,6 +1067,7 @@ definitions:
enum:
- UPPER
- lower
- ''
enum_integer:
type: integer
format: int32

View File

@ -46,7 +46,13 @@ namespace IO.Swagger.Model
/// Enum Lower for "lower"
/// </summary>
[EnumMember(Value = "lower")]
Lower
Lower,
/// <summary>
/// Enum Empty for ""
/// </summary>
[EnumMember(Value = "")]
Empty
}
/// <summary>

View File

@ -49,7 +49,13 @@ namespace IO.Swagger.Model
/// Enum Lower for "lower"
/// </summary>
[EnumMember(Value = "lower")]
Lower
Lower,
/// <summary>
/// Enum Empty for ""
/// </summary>
[EnumMember(Value = "")]
Empty
}
/// <summary>

View File

@ -31,7 +31,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -16,6 +16,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -31,7 +31,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -15,6 +15,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -42,7 +42,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -16,6 +16,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -31,7 +31,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -16,6 +16,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -31,7 +31,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -15,6 +15,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -45,7 +45,10 @@ public class EnumTest implements Parcelable {
UPPER("UPPER"),
@SerializedName("lower")
LOWER("lower");
LOWER("lower"),
@SerializedName("")
EMPTY("");
private String value;

View File

@ -16,6 +16,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -32,7 +32,10 @@ public class EnumTest {
UPPER("UPPER"),
@SerializedName("lower")
LOWER("lower");
LOWER("lower"),
@SerializedName("")
EMPTY("");
private String value;

View File

@ -32,7 +32,10 @@ public class EnumTest {
UPPER("UPPER"),
@SerializedName("lower")
LOWER("lower");
LOWER("lower"),
@SerializedName("")
EMPTY("");
private String value;

View File

@ -16,6 +16,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -32,7 +32,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -16,6 +16,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -32,7 +32,10 @@ public class EnumTest {
UPPER("UPPER"),
@SerializedName("lower")
LOWER("lower");
LOWER("lower"),
@SerializedName("")
EMPTY("");
private String value;

View File

@ -16,6 +16,7 @@ Name | Value
---- | -----
UPPER | &quot;UPPER&quot;
LOWER | &quot;lower&quot;
EMPTY | &quot;&quot;
<a name="EnumIntegerEnum"></a>

View File

@ -32,7 +32,10 @@ public class EnumTest {
UPPER("UPPER"),
@SerializedName("lower")
LOWER("lower");
LOWER("lower"),
@SerializedName("")
EMPTY("");
private String value;

View File

@ -17,6 +17,8 @@ Name | Type | Description | Notes
* `lower` (value: `"lower"`)
* `empty` (value: `""`)

View File

@ -111,7 +111,12 @@
* value: "lower"
* @const
*/
"lower": "lower" };
"lower": "lower",
/**
* value: ""
* @const
*/
"empty": "" };
/**
* Allowed values for the <code>enum_integer</code> property.

View File

@ -17,6 +17,8 @@ Name | Type | Description | Notes
* `lower` (value: `"lower"`)
* `empty` (value: `""`)

View File

@ -111,7 +111,12 @@
* value: "lower"
* @const
*/
"lower": "lower" };
"lower": "lower",
/**
* value: ""
* @const
*/
"empty": "" };
/**
* Allowed values for the <code>enum_integer</code> property.

View File

@ -118,6 +118,7 @@ class EnumTest implements ArrayAccess
const ENUM_STRING_UPPER = 'UPPER';
const ENUM_STRING_LOWER = 'lower';
const ENUM_STRING_EMPTY = '';
const ENUM_INTEGER_1 = 1;
const ENUM_INTEGER_MINUS_1 = -1;
const ENUM_NUMBER_1_DOT_1 = 1.1;
@ -134,6 +135,7 @@ class EnumTest implements ArrayAccess
return [
self::ENUM_STRING_UPPER,
self::ENUM_STRING_LOWER,
self::ENUM_STRING_EMPTY,
];
}
@ -188,7 +190,7 @@ class EnumTest implements ArrayAccess
public function listInvalidProperties()
{
$invalid_properties = [];
$allowed_values = ["UPPER", "lower"];
$allowed_values = ["UPPER", "lower", ""];
if (!in_array($this->container['enum_string'], $allowed_values)) {
$invalid_properties[] = "invalid value for 'enum_string', must be one of #{allowed_values}.";
}
@ -214,7 +216,7 @@ class EnumTest implements ArrayAccess
*/
public function valid()
{
$allowed_values = ["UPPER", "lower"];
$allowed_values = ["UPPER", "lower", ""];
if (!in_array($this->container['enum_string'], $allowed_values)) {
return false;
}
@ -246,9 +248,9 @@ class EnumTest implements ArrayAccess
*/
public function setEnumString($enum_string)
{
$allowed_values = array('UPPER', 'lower');
$allowed_values = array('UPPER', 'lower', '');
if (!is_null($enum_string) && (!in_array($enum_string, $allowed_values))) {
throw new \InvalidArgumentException("Invalid value for 'enum_string', must be one of 'UPPER', 'lower'");
throw new \InvalidArgumentException("Invalid value for 'enum_string', must be one of 'UPPER', 'lower', ''");
}
$this->container['enum_string'] = $enum_string;

View File

@ -67,7 +67,7 @@ class EnumTest(object):
:param enum_string: The enum_string of this EnumTest.
:type: str
"""
allowed_values = ["UPPER", "lower"]
allowed_values = ["UPPER", "lower", ""]
if enum_string not in allowed_values:
raise ValueError(
"Invalid value for `enum_string` ({0}), must be one of {1}"

View File

@ -100,7 +100,7 @@ module Petstore
# Check to see if the all the properties in the model are valid
# @return true if the model is valid
def valid?
enum_string_validator = EnumAttributeValidator.new('String', ["UPPER", "lower"])
enum_string_validator = EnumAttributeValidator.new('String', ["UPPER", "lower", ""])
return false unless enum_string_validator.valid?(@enum_string)
enum_integer_validator = EnumAttributeValidator.new('Integer', ["1", "-1"])
return false unless enum_integer_validator.valid?(@enum_integer)
@ -112,7 +112,7 @@ module Petstore
# Custom attribute writer method checking allowed values (enum).
# @param [Object] enum_string Object to be assigned
def enum_string=(enum_string)
validator = EnumAttributeValidator.new('String', ["UPPER", "lower"])
validator = EnumAttributeValidator.new('String', ["UPPER", "lower", ""])
unless validator.valid?(enum_string)
fail ArgumentError, "invalid value for 'enum_string', must be one of #{validator.allowable_values}."
end

View File

@ -12,6 +12,7 @@ open class EnumTest: JSONEncodable {
public enum EnumString: String {
case upper = "UPPER"
case lower = "lower"
case empty = ""
}
public enum EnumInteger: Int32 {
case number1 = 1

View File

@ -12,6 +12,7 @@ open class EnumTest: JSONEncodable {
public enum EnumString: String {
case upper = "UPPER"
case lower = "lower"
case empty = ""
}
public enum EnumInteger: Int32 {
case number1 = 1

View File

@ -12,6 +12,7 @@ open class EnumTest: JSONEncodable {
public enum EnumString: String {
case upper = "UPPER"
case lower = "lower"
case empty = ""
}
public enum EnumInteger: Int32 {
case number1 = 1

View File

@ -19,7 +19,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -1100,6 +1100,7 @@ definitions:
enum:
- "UPPER"
- "lower"
- ""
enum_integer:
type: "integer"
format: "int32"

View File

@ -18,7 +18,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -31,7 +31,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -31,7 +31,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -18,7 +18,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -18,7 +18,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;

View File

@ -18,7 +18,9 @@ public class EnumTest {
public enum EnumStringEnum {
UPPER("UPPER"),
LOWER("lower");
LOWER("lower"),
EMPTY("");
private String value;