Skip to content

Commit

Permalink
Merge pull request #383 from swagger-api/dotnet
Browse files Browse the repository at this point in the history
fix csharp client
  • Loading branch information
frantuma committed May 16, 2019
2 parents 2b08178 + a888a7b commit 68e0a68
Show file tree
Hide file tree
Showing 10 changed files with 364 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ private static String getTypeOfSchema(Schema schema) {
if(SchemaTypeUtil.INTEGER64_FORMAT.equals(schema.getFormat())) {
return "long";
} else {
return schema.getType();
return "integer";
}
} else if (schema instanceof MapSchema) {
return "map";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package io.swagger.codegen.v3.generators.dotnet;

import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Lambda;
import com.google.common.collect.ImmutableMap;
import com.samskivert.mustache.Mustache;
import io.swagger.codegen.v3.CodegenConstants;
import io.swagger.codegen.v3.CodegenModel;
import io.swagger.codegen.v3.CodegenOperation;
import io.swagger.codegen.v3.CodegenProperty;
import io.swagger.codegen.v3.generators.DefaultCodegenConfig;
import io.swagger.codegen.v3.generators.handlebars.csharp.CsharpHelper;
import io.swagger.codegen.v3.generators.handlebars.lambda.CamelCaseLambda;
import io.swagger.codegen.v3.generators.handlebars.lambda.IndentedLambda;
import io.swagger.codegen.v3.generators.handlebars.lambda.LowercaseLambda;
import io.swagger.codegen.v3.generators.handlebars.lambda.TitlecaseLambda;
import io.swagger.codegen.v3.generators.handlebars.lambda.UppercaseLambda;
import io.swagger.codegen.v3.utils.ModelUtils;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
Expand Down Expand Up @@ -158,10 +165,12 @@ public AbstractCSharpCodegen() {
typeMapping.put("bytearray", "byte[]");
typeMapping.put("boolean", "bool?");
typeMapping.put("integer", "int?");
typeMapping.put("int", "int?");
typeMapping.put("float", "float?");
typeMapping.put("long", "long?");
typeMapping.put("double", "double?");
typeMapping.put("number", "decimal?");
typeMapping.put("BigDecimal", "decimal?");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
typeMapping.put("file", "System.IO.Stream");
Expand Down Expand Up @@ -328,13 +337,13 @@ public void processOpts() {
// This either updates additionalProperties with the above fixes, or sets the default if the option was not specified.
additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix);

//addMustacheLambdas(additionalProperties);
addHandlebarsLambdas(additionalProperties);
}

/** todo: write with OAS3 classes.
private void addMustacheLambdas(Map<String, Object> objs) {
private void addHandlebarsLambdas(Map<String, Object> objs) {

Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>()

Map<String, Lambda> lambdas = new ImmutableMap.Builder<String, Lambda>()
.put("lowercase", new LowercaseLambda().generator(this))
.put("uppercase", new UppercaseLambda())
.put("titlecase", new TitlecaseLambda())
Expand All @@ -346,6 +355,7 @@ private void addMustacheLambdas(Map<String, Object> objs) {
.put("indented_16", new IndentedLambda(16, " "))
.build();


if (objs.containsKey("lambda")) {
LOGGER.warn("An property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " +
"You'll likely need to use a custom template, " +
Expand All @@ -355,7 +365,6 @@ private void addMustacheLambdas(Map<String, Object> objs) {
objs.put("lambda", lambdas);
}
}
*/

@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
Expand Down Expand Up @@ -494,7 +503,7 @@ public void updateCodegenPropertyEnum(CodegenProperty var) {
var.vendorExtensions = new HashMap<>();
}

ModelUtils.updateCodegenPropertyEnum(var);
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 (getBooleanValue(var, CodegenConstants.IS_ENUM_EXT_NAME)) {
Expand Down Expand Up @@ -1029,4 +1038,22 @@ public String escapeUnsafeCharacters(String input) {

return intermediate;
}

@Override
public void addHandlebarHelpers(Handlebars handlebars) {
super.addHandlebarHelpers(handlebars);
handlebars.registerHelpers(new CsharpHelper());
}

/*
TODO: uncomment if/when switching to stream for file upload
@Override
public void postProcessParameter(CodegenParameter parameter) {
if (parameter.getIsBinary()) {
parameter.dataType = "System.IO.Stream";
}
super.postProcessParameter(parameter);
}
*/

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.swagger.codegen.v3.generators.handlebars.csharp;

public class CsharpHelper {

public CharSequence backslash() {
return "\\";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.swagger.codegen.v3.generators.handlebars.lambda;

import com.github.jknack.handlebars.Lambda;
import io.swagger.codegen.v3.CodegenConfig;
import io.swagger.codegen.v3.generators.DefaultCodegenConfig;

import java.io.IOException;

/**
* Converts text in a fragment to camelCase.
*
* Register:
* <pre>
* additionalProperties.put("camelcase", new CamelCaseLambda());
* </pre>
*
* Use:
* <pre>
* {{#camelcase}}{{name}}{{/camelcase}}
* </pre>
*/
public class CamelCaseLambda implements Lambda {

private CodegenConfig generator = null;
private Boolean escapeParam = false;

public CamelCaseLambda() {

}

public CamelCaseLambda generator(final CodegenConfig generator) {
this.generator = generator;
return this;
}

public CamelCaseLambda escapeAsParamName(final Boolean escape) {
this.escapeParam = escape;
return this;
}
@Override
public Object apply(Object o, com.github.jknack.handlebars.Template template) throws IOException {
String executed = template.apply(o);
String text = DefaultCodegenConfig.camelize(executed, true);
if (generator != null) {
text = generator.sanitizeName(text);
if (generator.reservedWords().contains(text)) {
// Escaping must be done *after* camelize, because generators may escape using characters removed by camelize function.
text = generator.escapeReservedWord(text);
}

if (escapeParam) {
// NOTE: many generators call escapeReservedWord in toParamName, but we can't assume that's always the case.
// Here, we'll have to accept that we may be duplicating some work.
text = generator.toParamName(text);
}
}
return text;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package io.swagger.codegen.v3.generators.handlebars.lambda;

import com.github.jknack.handlebars.Lambda;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;

/**
* This naively prepends indention to all lines of a fragment.
* <p>
* Generator authors may add helpers for explicitly adding prefixed spaces which fragments won't be aware of.
* <p>
* Register:
* <pre>
* additionalProperties.put("indent4", new IndentedLambda(4));
* additionalProperties.put("indent8", new IndentedLambda(8));
* </pre>
* <p>
* Use:
* <pre>{@code
* {{#indent4}}{{>template}}{{/indent4}}
* {{#indent8}}{{>other_template}}{{/indent8}}
* }</pre>
*/
public class IndentedLambda implements Lambda {
private final int prefixSpaceCount;
private int spaceCode;

/**
* Constructs a new instance of {@link io.swagger.codegen.mustache.IndentedLambda}, with an indent count of 4 spaces
*/
public IndentedLambda() {
this(4, " ");
}

/**
* Constructs a new instance of {@link io.swagger.codegen.mustache.IndentedLambda}, with customized indent count and intention character
*
* @param prefixSpaceCount The number of indented characters to apply as a prefix to a fragment.
* @param indentionCharacter String representation of the character used in the indent (e.g. " ", "\t", ".").
*/
public IndentedLambda(int prefixSpaceCount, String indentionCharacter) {
this(prefixSpaceCount, Character.codePointAt(indentionCharacter, 0));
}

/**
* Constructs a new instance of {@link io.swagger.codegen.mustache.IndentedLambda}
*
* @param prefixSpaceCount The number of indented characters to apply as a prefix to a fragment.
*/
private IndentedLambda(int prefixSpaceCount, int indentionCodePoint) {
if (prefixSpaceCount <= 0) {
throw new IllegalArgumentException("prefixSpaceCount must be greater than 0");
}

if (!Character.isValidCodePoint(indentionCodePoint)) {
throw new IllegalArgumentException("indentionCodePoint is an invalid code point ");
}

this.prefixSpaceCount = prefixSpaceCount;
this.spaceCode = indentionCodePoint;
}

@Override
public Object apply(Object o, com.github.jknack.handlebars.Template template) throws IOException {
String text = template.apply(o);
if (text == null || text.length() == 0) {
return text;
}

String prefixedIndention = StringUtils.repeat(new String(Character.toChars(spaceCode)), prefixSpaceCount);
StringBuilder sb = new StringBuilder();
String[] lines = text.split(System.lineSeparator());
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
// Mustache will apply correct indentation to the first line of a template (to match declaration location).
// So, we want to skip the first line.
if (i > 0) {
sb.append(prefixedIndention);
}

sb.append(line);

// We've split on the system's line separator. We don't want to add an additional trailing line.
if (i < lines.length - 1) {
sb.append(System.lineSeparator());
}
}
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.swagger.codegen.v3.generators.handlebars.lambda;

import com.github.jknack.handlebars.Lambda;
import io.swagger.codegen.v3.CodegenConfig;

import java.io.IOException;

/**
* Converts text in a fragment to lowercase.
*
* Register:
* <pre>
* additionalProperties.put("lowercase", new LowercaseLambda());
* </pre>
*
* Use:
* <pre>
* {{#lowercase}}{{httpMethod}}{{/lowercase}}
* </pre>
*/
public class LowercaseLambda implements Lambda {
private CodegenConfig generator = null;

public LowercaseLambda() {

}

public LowercaseLambda generator(final CodegenConfig generator) {
this.generator = generator;
return this;
}

@Override
public Object apply(Object o, com.github.jknack.handlebars.Template template) throws IOException {
String text = template.apply(o);
if (text == null || text.length() == 0) {
return text;
}
text = text.toLowerCase();
if (generator != null && generator.reservedWords().contains(text)) {
text = generator.escapeReservedWord(text);
}

return text;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.swagger.codegen.v3.generators.handlebars.lambda;

import com.github.jknack.handlebars.Lambda;

import java.io.IOException;

/**
* Converts text in a fragment to title case.
*
* Register:
* <pre>
* additionalProperties.put("titlecase", new TitlecaseLambda());
* </pre>
*
* Use:
* <pre>
* {{#titlecase}}{{classname}}{{/titlecase}}
* </pre>
*/
public class TitlecaseLambda implements Lambda {
private String delimiter;

/**
* Constructs a new instance of {@link io.swagger.codegen.mustache.TitlecaseLambda}, which will convert all text
* in a space delimited string to title-case.
*/
public TitlecaseLambda() {
this(" ");
}

/**
* Constructs a new instance of {@link io.swagger.codegen.mustache.TitlecaseLambda}, splitting on the specified
* delimiter and converting each word to title-case.
* <p>
* NOTE: passing {@code null} results in a title-casing the first word only.
*
* @param delimiter Provided to allow an override for the default space delimiter.
*/
public TitlecaseLambda(String delimiter) {
this.delimiter = delimiter;
}

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

@Override
public Object apply(Object o, com.github.jknack.handlebars.Template template) throws IOException {
String text = template.apply(o);
if (text == null || text.length() == 0) {
return text;
}
if (delimiter == null) {
return titleCase(text);
}

// Split accepts regex. \Q and \E wrap the delimiter to create a literal regex,
// so things like "." and "|" aren't treated as their regex equivalents.
StringBuffer sb = new StringBuffer();
String[] parts = text.split("\\Q" + delimiter + "\\E");
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
sb.append(titleCase(part));
if (i != parts.length - 1) {
sb.append(delimiter);
}
}
return sb.toString();
}
}
Loading

0 comments on commit 68e0a68

Please sign in to comment.