This commit is contained in:
wing328 2018-01-07 19:11:40 +08:00
commit b7f4f3e058
11 changed files with 156 additions and 88 deletions

View File

@ -405,28 +405,28 @@ public class CodeGenMojo extends AbstractMojo {
// Set generation options
if (null != generateApis && generateApis) {
System.setProperty("apis", "");
System.setProperty(CodegenConstants.APIS, "");
} else {
System.clearProperty("apis");
System.clearProperty(CodegenConstants.APIS);
}
if (null != generateModels && generateModels) {
System.setProperty("models", modelsToGenerate);
System.setProperty(CodegenConstants.MODELS, modelsToGenerate);
} else {
System.clearProperty("models");
System.clearProperty(CodegenConstants.MODELS);
}
if (null != generateSupportingFiles && generateSupportingFiles) {
System.setProperty("supportingFiles", supportingFilesToGenerate);
System.setProperty(CodegenConstants.SUPPORTING_FILES, supportingFilesToGenerate);
} else {
System.clearProperty("supportingFiles");
System.clearProperty(CodegenConstants.SUPPORTING_FILES);
}
System.setProperty("modelTests", generateModelTests.toString());
System.setProperty("modelDocs", generateModelDocumentation.toString());
System.setProperty("apiTests", generateApiTests.toString());
System.setProperty("apiDocs", generateApiDocumentation.toString());
System.setProperty("withXml", withXml.toString());
System.setProperty(CodegenConstants.MODEL_TESTS, generateModelTests.toString());
System.setProperty(CodegenConstants.MODEL_DOCS, generateModelDocumentation.toString());
System.setProperty(CodegenConstants.API_TESTS, generateApiTests.toString());
System.setProperty(CodegenConstants.API_DOCS, generateApiDocumentation.toString());
System.setProperty(CodegenConstants.WITH_XML, withXml.toString());
if (configOptions != null) {
// Retained for backwards-compataibility with configOptions -> instantiation-types

View File

@ -4,6 +4,8 @@ package io.swagger.codegen;
* A class for storing constants that are used throughout the project.
*/
public class CodegenConstants {
/* System Properties */
// NOTE: We may want to move these to a separate class to avoid confusion or modification.
public static final String APIS = "apis";
public static final String MODELS = "models";
public static final String SUPPORTING_FILES = "supportingFiles";
@ -11,6 +13,8 @@ public class CodegenConstants {
public static final String MODEL_DOCS = "modelDocs";
public static final String API_TESTS = "apiTests";
public static final String API_DOCS = "apiDocs";
public static final String WITH_XML = "withXml";
/* /end System Properties */
public static final String API_PACKAGE = "apiPackage";
public static final String API_PACKAGE_DESC = "package for generated api classes";

View File

@ -1930,6 +1930,8 @@ public class DefaultCodegen {
if (property.defaultValue != null) {
property.defaultValue = property.defaultValue.replace(baseItem.baseType, toEnumName(baseItem));
}
updateCodegenPropertyEnum(property);
}
}

View File

@ -551,7 +551,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return;
}
Set<String> supportingFilesToGenerate = null;
String supportingFiles = System.getProperty("supportingFiles");
String supportingFiles = System.getProperty(CodegenConstants.SUPPORTING_FILES);
if (supportingFiles != null && !supportingFiles.isEmpty()) {
supportingFilesToGenerate = new HashSet<String>(Arrays.asList(supportingFiles.split(",")));
}

View File

@ -352,6 +352,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
* those vars referencing RefModel'd enums to work the same as inlined enums rather than as objects.
* @param models
*/
@SuppressWarnings({ "unchecked" })
private void postProcessEnumRefs(final Map<String, Object> models) {
Map<String, CodegenModel> enumRefs = new HashMap<String, CodegenModel>();
for (Map.Entry<String, Object> entry : models.entrySet()) {
@ -372,11 +373,57 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
// while enums in many other languages are true objects.
CodegenModel refModel = enumRefs.get(var.datatype);
var.allowableValues = refModel.allowableValues;
var.isEnum = true;
updateCodegenPropertyEnum(var);
// We do these after updateCodegenPropertyEnum to avoid generalities that don't mesh with C#.
var.isPrimitiveType = true;
var.isEnum = true;
}
}
// We're looping all models here.
if (model.isEnum) {
// We now need to make allowableValues.enumVars look like the context of CodegenProperty
Boolean isString = false;
Boolean isInteger = false;
Boolean isLong = false;
Boolean isByte = false;
if (model.dataType.startsWith("byte")) {
// C# Actually supports byte and short enums, swagger spec only supports byte.
isByte = true;
model.vendorExtensions.put("x-enum-byte", true);
} else if (model.dataType.startsWith("int32")) {
isInteger = true;
model.vendorExtensions.put("x-enum-integer", true);
} else if (model.dataType.startsWith("int64")) {
isLong = true;
model.vendorExtensions.put("x-enum-long", true);
} else {
// C# doesn't support non-integral enums, so we need to treat everything else as strings (e.g. to not lose precision or data integrity)
isString = true;
model.vendorExtensions.put("x-enum-string", true);
}
// Since we iterate enumVars for modelnnerEnum and enumClass templates, and CodegenModel is missing some of CodegenProperty's properties,
// we can take advantage of Mustache's contextual lookup to add the same "properties" to the model's enumVars scope rather than CodegenProperty's scope.
List<Map<String, String>> enumVars = (ArrayList<Map<String, String>>)model.allowableValues.get("enumVars");
List<Map<String, Object>> newEnumVars = new ArrayList<Map<String, Object>>();
for (Map<String, String> enumVar : enumVars) {
Map<String, Object> mixedVars = new HashMap<String, Object>();
mixedVars.putAll(enumVar);
mixedVars.put("isString", isString);
mixedVars.put("isLong", isLong);
mixedVars.put("isInteger", isInteger);
mixedVars.put("isByte", isByte);
newEnumVars.add(mixedVars);
}
if (!newEnumVars.isEmpty()) {
model.allowableValues.put("enumVars", newEnumVars);
}
}
} else {
@ -385,6 +432,42 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
}
}
/**
* Update codegen property's enum by adding "enumVars" (with name and value)
*
* @param var list of CodegenProperty
*/
@Override
public void updateCodegenPropertyEnum(CodegenProperty var) {
if (var.vendorExtensions == null) {
var.vendorExtensions = new HashMap<>();
}
super.updateCodegenPropertyEnum(var);
// Because C# uses nullable primitives for datatype, and datatype is used in DefaultCodegen for determining enum-ness, guard against weirdness here.
if (var.isEnum) {
if ("byte".equals(var.dataFormat)) {// C# Actually supports byte and short enums.
var.vendorExtensions.put("x-enum-byte", true);
var.isString = false;
var.isLong = false;
var.isInteger = false;
} else if ("int32".equals(var.dataFormat)) {
var.isInteger = true;
var.isString = false;
var.isLong = false;
} else if ("int64".equals(var.dataFormat)) {
var.isLong = true;
var.isString = false;
var.isInteger = false;
} else {// C# doesn't support non-integral enums, so we need to treat everything else as strings (e.g. to not lose precision or data integrity)
var.isString = true;
var.isInteger = false;
var.isLong = false;
}
}
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
super.postProcessOperations(objs);
@ -769,6 +852,19 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
this.interfacePrefix = interfacePrefix;
}
@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.
// Per: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/enum
// The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.
// but we're not supporting unsigned integral types or shorts.
if(datatype.startsWith("int") || datatype.startsWith("long") || datatype.startsWith("byte")) {
return value;
}
return escapeText(value);
}
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
@ -799,32 +895,6 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
return sanitizeName(camelize(property.name)) + "Enum";
}
/*
@Override
public String toEnumName(CodegenProperty property) {
String enumName = sanitizeName(property.name);
if (!StringUtils.isEmpty(modelNamePrefix)) {
enumName = modelNamePrefix + "_" + enumName;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
enumName = enumName + "_" + modelNameSuffix;
}
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(enumName)) {
LOGGER.warn(enumName + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + enumName));
enumName = "model_" + enumName; // e.g. return => ModelReturn (after camelize)
}
if (enumName.matches("\\d.*")) { // starts with number
return "_" + enumName;
} else {
return enumName;
}
}
*/
public String testPackageName() {
return this.packageName + ".Test";
}
@ -839,5 +909,4 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*").replace("--", "- -");
}
}

View File

@ -671,19 +671,6 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
return codegenModel;
}
@Override
public String toEnumValue(String value, String datatype) {
if ("int?".equalsIgnoreCase(datatype) || "long?".equalsIgnoreCase(datatype) ||
"double?".equalsIgnoreCase(datatype) || "float?".equalsIgnoreCase(datatype)) {
return value;
} else if ("float?".equalsIgnoreCase(datatype)) {
// for float in C#, append "f". e.g. 3.14 => 3.14f
return value + "f";
} else {
return "\"" + escapeText(value) + "\"";
}
}
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
@ -696,8 +683,8 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
}
// number
if ("int?".equals(datatype) || "long?".equals(datatype) ||
"double?".equals(datatype) || "float?".equals(datatype)) {
if(datatype.startsWith("int") || datatype.startsWith("long") ||
datatype.startsWith("double") || datatype.startsWith("float")) {
String varName = "NUMBER_" + value;
varName = varName.replaceAll("-", "MINUS_");
varName = varName.replaceAll("\\+", "PLUS_");

View File

@ -4,14 +4,16 @@
{{#description}}
/// <value>{{description}}</value>
{{/description}}
{{#allowableValues}}{{#enumVars}}{{#-first}}{{#isString}}
[JsonConverter(typeof(StringEnumConverter))]
{{>visibility}} enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}
{{/isString}}{{/-first}}{{/enumVars}}{{/allowableValues}}
{{>visibility}} enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}{{#vendorExtensions.x-enum-byte}}: byte{{/vendorExtensions.x-enum-byte}}
{
{{#allowableValues}}{{#enumVars}}
/// <summary>
/// Enum {{name}} for {{{value}}}
/// Enum {{name}} for value: {{{value}}}
/// </summary>
[EnumMember(Value = {{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}})]
{{name}}{{#isInteger}} = {{{value}}}{{/isInteger}}{{^isInteger}} = {{-index}}{{/isInteger}}{{^-last}},
{{#isString}}[EnumMember(Value = "{{{value}}}")]{{/isString}}
{{name}}{{^isString}} = {{{value}}}{{/isString}}{{#isString}} = {{-index}}{{/isString}}{{^-last}},
{{/-last}}{{/enumVars}}{{/allowableValues}}
}
}{{! NOTE: This model's enumVars is modified to look like CodegenProperty}}

View File

@ -1,19 +1,21 @@
{{^isContainer}}
/// <summary>
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
/// {{^description}}Defines {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
/// </summary>
{{#description}}
/// <value>{{description}}</value>
{{/description}}
{{#isString}}
[JsonConverter(typeof(StringEnumConverter))]
{{>visibility}} enum {{#datatypeWithEnum}}{{&.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}
{{/isString}}
{{>visibility}} enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}{{#vendorExtensions.x-enum-byte}}: byte{{/vendorExtensions.x-enum-byte}}
{
{{#allowableValues}}{{#enumVars}}
/// <summary>
/// Enum {{name}} for {{{value}}}
/// Enum {{name}} for value: {{{value}}}
/// </summary>
[EnumMember(Value = {{#isLong}}"{{/isLong}}{{#isInteger}}"{{/isInteger}}{{#isFloat}}"{{/isFloat}}{{#isDouble}}"{{/isDouble}}{{{value}}}{{#isLong}}"{{/isLong}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isFloat}}"{{/isFloat}})]
{{name}}{{#isLong}} = {{{value}}}{{/isLong}}{{#isInteger}} = {{{value}}}{{/isInteger}}{{^isInteger}} = {{-index}}{{/isInteger}}{{^-last}},
{{#isString}}[EnumMember(Value = "{{{value}}}")]{{/isString}}
{{name}}{{^isString}} = {{{value}}}{{/isString}}{{#isString}} = {{-index}}{{/isString}}{{^-last}},
{{/-last}}{{/enumVars}}{{/allowableValues}}
}
{{/isContainer}}

View File

@ -31,50 +31,50 @@ namespace IO.Swagger.Model
public partial class MyClassWithOptionalInlineEnum : IEquatable<MyClassWithOptionalInlineEnum>, IValidatableObject
{
/// <summary>
/// Gets or Sets Days
/// Defines Days
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum DaysEnum
{
/// <summary>
/// Enum Sun for "sun"
/// Enum Sun for value: sun
/// </summary>
[EnumMember(Value = "sun")]
Sun = 1,
/// <summary>
/// Enum Mon for "mon"
/// Enum Mon for value: mon
/// </summary>
[EnumMember(Value = "mon")]
Mon = 2,
/// <summary>
/// Enum Tue for "tue"
/// Enum Tue for value: tue
/// </summary>
[EnumMember(Value = "tue")]
Tue = 3,
/// <summary>
/// Enum Wed for "wed"
/// Enum Wed for value: wed
/// </summary>
[EnumMember(Value = "wed")]
Wed = 4,
/// <summary>
/// Enum Thu for "thu"
/// Enum Thu for value: thu
/// </summary>
[EnumMember(Value = "thu")]
Thu = 5,
/// <summary>
/// Enum Fri for "fri"
/// Enum Fri for value: fri
/// </summary>
[EnumMember(Value = "fri")]
Fri = 6,
/// <summary>
/// Enum Sat for "sat"
/// Enum Sat for value: sat
/// </summary>
[EnumMember(Value = "sat")]
Sat = 7

View File

@ -31,50 +31,50 @@ namespace IO.Swagger.Model
public partial class MyClassWithRequiredInlineEnum : IEquatable<MyClassWithRequiredInlineEnum>, IValidatableObject
{
/// <summary>
/// Gets or Sets Days
/// Defines Days
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum DaysEnum
{
/// <summary>
/// Enum Sun for "sun"
/// Enum Sun for value: sun
/// </summary>
[EnumMember(Value = "sun")]
Sun = 1,
/// <summary>
/// Enum Mon for "mon"
/// Enum Mon for value: mon
/// </summary>
[EnumMember(Value = "mon")]
Mon = 2,
/// <summary>
/// Enum Tue for "tue"
/// Enum Tue for value: tue
/// </summary>
[EnumMember(Value = "tue")]
Tue = 3,
/// <summary>
/// Enum Wed for "wed"
/// Enum Wed for value: wed
/// </summary>
[EnumMember(Value = "wed")]
Wed = 4,
/// <summary>
/// Enum Thu for "thu"
/// Enum Thu for value: thu
/// </summary>
[EnumMember(Value = "thu")]
Thu = 5,
/// <summary>
/// Enum Fri for "fri"
/// Enum Fri for value: fri
/// </summary>
[EnumMember(Value = "fri")]
Fri = 6,
/// <summary>
/// Enum Sat for "sat"
/// Enum Sat for value: sat
/// </summary>
[EnumMember(Value = "sat")]
Sat = 7

View File

@ -27,48 +27,50 @@ namespace IO.Swagger.Model
/// <summary>
/// Defines WeekDays
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum WeekDays
{
/// <summary>
/// Enum Sun for "sun"
/// Enum Sun for value: sun
/// </summary>
[EnumMember(Value = "sun")]
Sun = 1,
/// <summary>
/// Enum Mon for "mon"
/// Enum Mon for value: mon
/// </summary>
[EnumMember(Value = "mon")]
Mon = 2,
/// <summary>
/// Enum Tue for "tue"
/// Enum Tue for value: tue
/// </summary>
[EnumMember(Value = "tue")]
Tue = 3,
/// <summary>
/// Enum Wed for "wed"
/// Enum Wed for value: wed
/// </summary>
[EnumMember(Value = "wed")]
Wed = 4,
/// <summary>
/// Enum Thu for "thu"
/// Enum Thu for value: thu
/// </summary>
[EnumMember(Value = "thu")]
Thu = 5,
/// <summary>
/// Enum Fri for "fri"
/// Enum Fri for value: fri
/// </summary>
[EnumMember(Value = "fri")]
Fri = 6,
/// <summary>
/// Enum Sat for "sat"
/// Enum Sat for value: sat
/// </summary>
[EnumMember(Value = "sat")]
Sat = 7