Fix issue 12341 (#15234)

* if method return type is void then no return

* build the project

* fix build the project

* fix build the project

* fix return

* fix build the project

* fix build the project

* fix build the project

---------

Co-authored-by: Rodrigo Maciel de Almeida <rodrigo.almeida@wefin.com.br>
This commit is contained in:
Rodrigo de Almeida - RMA3 2023-04-18 17:56:12 -03:00 committed by GitHub
parent f5b4490bc9
commit 9b2917f3a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 337 additions and 38 deletions

View File

@ -101,6 +101,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
public boolean hasChildren;
public boolean isMap;
public boolean isNull;
public boolean isVoid = false;
/**
* Indicates the OAS schema specifies "deprecated: true".
*/
@ -880,6 +881,16 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getAdditionalPropertiesIsAnyType() {
return additionalPropertiesIsAnyType;

View File

@ -26,7 +26,7 @@ public class CodegenOperation {
public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>();
public boolean hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams, hasRequiredParams,
returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart,
isArray, isMultipart, isVoid = false,
hasVersionHeaders = false, hasVersionQueryParams = false,
isResponseBinary = false, isResponseFile = false, isResponseOptional = false, hasReference = false, defaultReturnType = false,
isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
@ -329,6 +329,7 @@ public class CodegenOperation {
sb.append(", returnProperty=").append(returnProperty);
sb.append(", isArray=").append(isArray);
sb.append(", isMultipart=").append(isMultipart);
sb.append(", isVoid=").append(isVoid);
sb.append(", isResponseBinary=").append(isResponseBinary);
sb.append(", isResponseFile=").append(isResponseFile);
sb.append(", isResponseFile=").append(isResponseOptional);
@ -406,6 +407,7 @@ public class CodegenOperation {
isMap == that.isMap &&
isArray == that.isArray &&
isMultipart == that.isMultipart &&
isVoid == that.isVoid &&
isResponseBinary == that.isResponseBinary &&
isResponseFile == that.isResponseFile &&
isResponseOptional == that.isResponseOptional &&
@ -471,7 +473,7 @@ public class CodegenOperation {
return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
hasRequiredParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart, isResponseBinary, isResponseFile, isResponseOptional, hasReference,
isArray, isMultipart, isVoid, isResponseBinary, isResponseFile, isResponseOptional, hasReference,
hasDefaultResponse, isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
isRestful, isDeprecated, isCallbackRequest, uniqueItems, path, operationId, returnType, httpMethod,
returnBaseType, returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse,

View File

@ -107,6 +107,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
private Integer maxProperties;
private Integer minProperties;
public boolean isNull;
public boolean isVoid = false;
private boolean hasRequired;
private boolean hasDiscriminatorWithNonEmptyMapping;
private CodegenComposedSchemas composedSchemas;
@ -165,6 +166,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
output.pattern = this.pattern;
output.additionalProperties = this.additionalProperties;
output.isNull = this.isNull;
output.isVoid = this.isVoid;
output.setAdditionalPropertiesIsAnyType(this.getAdditionalPropertiesIsAnyType());
output.setHasVars(this.hasVars);
output.setHasRequired(this.hasRequired);
@ -245,7 +247,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
@Override
public int hashCode() {
return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, isContainer, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumDefaultValue, enumName, style, isDeepObject, isAllowEmptyValue, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isPassword, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, isDeprecated, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf, isNull, additionalPropertiesIsAnyType, hasVars, hasRequired, isShort, isUnboundedInteger, hasDiscriminatorWithNonEmptyMapping, composedSchemas, hasMultipleTypes, schema, content, requiredVarsMap, ref, uniqueItemsBoolean, schemaIsFromAdditionalProperties);
return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, isContainer, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumDefaultValue, enumName, style, isDeepObject, isAllowEmptyValue, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isPassword, isFreeFormObject, isAnyType, isArray, isMap, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, isDeprecated, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), contentType, multipleOf, isNull, isVoid, additionalPropertiesIsAnyType, hasVars, hasRequired, isShort, isUnboundedInteger, hasDiscriminatorWithNonEmptyMapping, composedSchemas, hasMultipleTypes, schema, content, requiredVarsMap, ref, uniqueItemsBoolean, schemaIsFromAdditionalProperties);
}
@Override
@ -294,6 +296,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
isDeprecated == that.isDeprecated &&
required == that.required &&
isNull == that.isNull &&
isVoid == that.isVoid &&
hasDiscriminatorWithNonEmptyMapping == that.getHasDiscriminatorWithNonEmptyMapping() &&
getAdditionalPropertiesIsAnyType() == that.getAdditionalPropertiesIsAnyType() &&
hasMultipleTypes == that.getHasMultipleTypes() &&
@ -431,6 +434,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
sb.append(", contentType=").append(contentType);
sb.append(", multipleOf=").append(multipleOf);
sb.append(", isNull=").append(isNull);
sb.append(", isVoid=").append(isVoid);
sb.append(", getAdditionalPropertiesIsAnyType=").append(additionalPropertiesIsAnyType);
sb.append(", getHasVars=").append(hasVars);
sb.append(", getHasRequired=").append(hasRequired);
@ -784,6 +788,16 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getHasValidation() {
return hasValidation;

View File

@ -136,6 +136,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
public boolean isEmail;
public boolean isPassword;
public boolean isNull;
public boolean isVoid = false;
/**
* The type is a free-form object, i.e. it is a map of string to values with no declared properties.
* A OAS free-form schema may include the 'additionalProperties' attribute, which puts a constraint
@ -875,6 +876,16 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getHasValidation() {
return hasValidation;
@ -1096,6 +1107,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
sb.append(", xmlNamespace='").append(xmlNamespace).append('\'');
sb.append(", isXmlWrapped=").append(isXmlWrapped);
sb.append(", isNull=").append(isNull);
sb.append(", isVoid=").append(isVoid);
sb.append(", getAdditionalPropertiesIsAnyType=").append(getAdditionalPropertiesIsAnyType());
sb.append(", getHasVars=").append(getHasVars());
sb.append(", getHasRequired=").append(getHasRequired());
@ -1167,6 +1179,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
isXmlAttribute == that.isXmlAttribute &&
isXmlWrapped == that.isXmlWrapped &&
isNull == that.isNull &&
isVoid == that.isVoid &&
hasMultipleTypes == that.getHasMultipleTypes() &&
hasDiscriminatorWithNonEmptyMapping == that.hasDiscriminatorWithNonEmptyMapping &&
isBooleanSchemaTrue == that.getIsBooleanSchemaTrue() &&
@ -1243,7 +1256,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars,
vendorExtensions, hasValidation, isInherited, discriminatorValue, nameInCamelCase,
nameInSnakeCase, enumName, maxItems, minItems, isXmlAttribute, xmlPrefix, xmlName,
xmlNamespace, isXmlWrapped, isNull, additionalPropertiesIsAnyType, hasVars, hasRequired,
xmlNamespace, isXmlWrapped, isNull, isVoid, additionalPropertiesIsAnyType, hasVars, hasRequired,
hasDiscriminatorWithNonEmptyMapping, composedSchemas, hasMultipleTypes, requiredVarsMap,
ref, uniqueItemsBoolean, schemaIsFromAdditionalProperties, isBooleanSchemaTrue, isBooleanSchemaFalse,
format, dependentRequired, contains);

View File

@ -62,6 +62,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
public boolean isBinary = false;
public boolean isFile = false;
public boolean isNull;
public boolean isVoid = false;
public Object schema;
public String jsonSchema;
public Map<String, Object> vendorExtensions = new HashMap<String, Object>();
@ -101,7 +102,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBoolean, isDate,
isDateTime, isUuid, isEmail, isPassword, isModel, isFreeFormObject, isAnyType, isDefault, simpleType, primitiveType,
isMap, isArray, isBinary, isFile, schema, jsonSchema, vendorExtensions, items, additionalProperties,
vars, requiredVars, isNull, hasValidation, isShort, isUnboundedInteger,
vars, requiredVars, isNull, isVoid, hasValidation, isShort, isUnboundedInteger,
getMaxProperties(), getMinProperties(), uniqueItems, getMaxItems(), getMinItems(), getMaxLength(),
getMinLength(), exclusiveMinimum, exclusiveMaximum, getMinimum(), getMaximum(), getPattern(),
is1xx, is2xx, is3xx, is4xx, is5xx, additionalPropertiesIsAnyType, hasVars, hasRequired,
@ -145,6 +146,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
items == that.items &&
additionalProperties == that.additionalProperties &&
isNull == that.isNull &&
isVoid == that.isVoid &&
hasValidation == that.hasValidation &&
is1xx == that.is1xx &&
is2xx == that.is2xx &&
@ -603,6 +605,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
sb.append(", vars='").append(vars).append('\'');
sb.append(", requiredVars='").append(requiredVars).append('\'');
sb.append(", isNull='").append(isNull);
sb.append(", isVoid='").append(isVoid);
sb.append(", hasValidation='").append(hasValidation);
sb.append(", getAdditionalPropertiesIsAnyType=").append(additionalPropertiesIsAnyType);
sb.append(", getHasVars=").append(hasVars);
@ -646,6 +649,16 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
this.isNull = isNull;
}
@Override
public boolean getIsVoid() {
return isVoid;
}
@Override
public void setIsVoid(boolean isVoid) {
this.isVoid = isVoid;
}
@Override
public boolean getHasValidation() {
return hasValidation;

View File

@ -151,6 +151,10 @@ public interface IJsonSchemaValidationProperties {
void setIsNull(boolean isNull);
boolean getIsVoid();
void setIsVoid(boolean isVoid);
boolean getHasValidation();
void setHasValidation(boolean hasValidation);

View File

@ -812,6 +812,11 @@ public class SpringCodegen extends AbstractJavaCodegen
public void setReturnContainer(final String returnContainer) {
resp.containerType = returnContainer;
}
@Override
public void setIsVoid(boolean isVoid) {
resp.isVoid = isVoid;
}
});
}
}
@ -827,6 +832,11 @@ public class SpringCodegen extends AbstractJavaCodegen
public void setReturnContainer(final String returnContainer) {
operation.returnContainer = returnContainer;
}
@Override
public void setIsVoid(boolean isVoid) {
operation.isVoid = isVoid;
}
});
prepareVersioningParameters(ops);
@ -848,6 +858,8 @@ public class SpringCodegen extends AbstractJavaCodegen
void setReturnType(String returnType);
void setReturnContainer(String returnContainer);
void setIsVoid(boolean isVoid);
}
/**
@ -859,6 +871,7 @@ public class SpringCodegen extends AbstractJavaCodegen
final String rt = returnType;
if (rt == null) {
dataTypeAssigner.setReturnType("Void");
dataTypeAssigner.setIsVoid(true);
} else if (rt.startsWith("List") || rt.startsWith("java.util.List")) {
final int start = rt.indexOf("<");
final int end = rt.lastIndexOf(">");

View File

@ -237,7 +237,7 @@ public interface {{classname}} {
{{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore {{/springFoxDocumentationProvider}}{{#springDocDocumentationProvider}}@ParameterObject {{/springDocDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}
){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} {
{{#delegate-method}}
return {{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
{{^isVoid}}return {{/isVoid}}{{#isVoid}}{{#useResponseEntity}}return {{/useResponseEntity}}{{^useResponseEntity}}{{#reactive}}return {{/reactive}}{{/useResponseEntity}}{{/isVoid}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
}
// Override this method
@ -247,7 +247,7 @@ public interface {{classname}} {
{{>methodBody}}
{{/isDelegate}}
{{#isDelegate}}
return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
{{^isVoid}}return {{/isVoid}}{{#isVoid}}{{#useResponseEntity}}return {{/useResponseEntity}}{{^useResponseEntity}}{{#reactive}}return {{/reactive}}{{/useResponseEntity}}{{/isVoid}}getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
{{/isDelegate}}
}{{/jdk8-default-interface}}

View File

@ -130,7 +130,7 @@ public class {{classname}}Controller implements {{classname}} {
{{/async}}
{{/isDelegate}}
{{#isDelegate}}
return delegate.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
{{^isVoid}}return {{/isVoid}}{{#isVoid}}{{#useResponseEntity}}return {{/useResponseEntity}}{{^useResponseEntity}}{{#reactive}}return {{/reactive}}{{/useResponseEntity}}{{/isVoid}}delegate.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}});
{{/isDelegate}}
}

View File

@ -1 +1 @@
{{#isMap}}Map<String, {{{returnType}}}>{{/isMap}}{{#isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}{{{returnContainer}}}{{/reactive}}<{{{returnType}}}>{{/isArray}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}}
{{#isMap}}Map<String, {{{returnType}}}>{{/isMap}}{{#isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}{{{returnContainer}}}{{/reactive}}<{{{returnType}}}>{{/isArray}}{{^returnContainer}}{{#useResponseEntity}}{{{returnType}}}{{/useResponseEntity}}{{^useResponseEntity}}{{#isDelegate}}{{#isVoid}}void{{/isVoid}}{{^isVoid}}{{{returnType}}}{{/isVoid}}{{/isDelegate}}{{^isDelegate}}{{#async}}{{{returnType}}}{{/async}}{{^async}}{{#isVoid}}void{{/isVoid}}{{^isVoid}}{{{returnType}}}{{/isVoid}}{{/async}}{{/isDelegate}}{{/useResponseEntity}}{{/returnContainer}}

View File

@ -71,6 +71,23 @@ public class MethodAssert extends AbstractAssert<MethodAssert, MethodDeclaration
return this;
}
public MethodAssert bodyNotContainsLines(final String... lines) {
Assertions.assertThat(isWithImplementation())
.withFailMessage("Method %s is abstract", methodSignature)
.isTrue();
final String actualBody = actual.getTokenRange()
.orElseThrow(() -> new IllegalStateException("Not-abstract method doesn't have body"))
.toString();
Assertions.assertThat(actualBody)
.withFailMessage(
"Method's %s body shouldn't contains lines\n====\n%s\n====\nbut actually was\n====\n%s\n====",
methodSignature, Arrays.stream(lines).collect(Collectors.joining(System.lineSeparator())), actualBody
)
.doesNotContain(lines);
return this;
}
public MethodAssert doesNotHaveImplementation() {
Assertions.assertThat(isWithImplementation())
.withFailMessage("Method %s should be abstract", methodSignature)

View File

@ -2281,4 +2281,165 @@ public class SpringCodegenTest {
.assertMethodAnnotations()
.containsWithNameAndAttributes("JsonProperty", ImmutableMap.of("value", "\"property name with spaces\""));
}
@Test
public void testReturnTypeVoidWithResponseEntity_issue12341() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/issue12341.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(SpringCodegen.DATE_LIBRARY, "java8-localdatetime");
codegen.additionalProperties().put(INTERFACE_ONLY, "true");
codegen.additionalProperties().put(USE_RESPONSE_ENTITY, "true");
codegen.additionalProperties().put(DELEGATE_PATTERN, "true");
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));
JavaFileAssert javaFileAssert = JavaFileAssert.assertThat(files.get("TestApi.java"));
javaFileAssert
.assertMethod("_postToTest", "ObjTest")
.hasReturnType("ResponseEntity<ObjTest>")
.bodyContainsLines("return postToTest(objToTest);");
javaFileAssert
.assertMethod("postToTest", "ObjTest")
.hasReturnType("ResponseEntity<ObjTest>")
.bodyContainsLines("return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);");
javaFileAssert
.assertMethod("_putToTest", "ObjTest")
.hasReturnType("ResponseEntity<Void>")
.bodyContainsLines("return putToTest(objToTest);");
javaFileAssert
.assertMethod("putToTest", "ObjTest")
.hasReturnType("ResponseEntity<Void>")
.bodyContainsLines("return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);");
}
@Test
public void testReturnTypeVoidWithoutResponseEntityWithDelegate_issue12341() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/issue12341.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(SpringCodegen.DATE_LIBRARY, "java8-localdatetime");
codegen.additionalProperties().put(INTERFACE_ONLY, "true");
codegen.additionalProperties().put(USE_RESPONSE_ENTITY, "false");
codegen.additionalProperties().put(DELEGATE_PATTERN, "true");
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));
JavaFileAssert javaFileAssert = JavaFileAssert.assertThat(files.get("TestApi.java"));
javaFileAssert
.assertMethod("_postToTest", "ObjTest")
.hasReturnType("ObjTest")
.bodyContainsLines("return postToTest(objToTest);");
javaFileAssert
.assertMethod("postToTest", "ObjTest")
.hasReturnType("ObjTest")
.bodyContainsLines("throw new IllegalArgumentException(\"Not implemented\");");
javaFileAssert
.assertMethod("_putToTest", "ObjTest")
.hasReturnType("void")
.bodyContainsLines("putToTest(objToTest);")
.bodyNotContainsLines("return putToTest(objToTest);");
javaFileAssert
.assertMethod("putToTest", "ObjTest")
.hasReturnType("void")
.bodyContainsLines("throw new IllegalArgumentException(\"Not implemented\");");
}
@Test
public void testReturnTypeVoidWithoutResponseEntityWithoutDelegateWithAsync_issue12341() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/issue12341.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(SpringCodegen.DATE_LIBRARY, "java8-localdatetime");
codegen.additionalProperties().put(INTERFACE_ONLY, "true");
codegen.additionalProperties().put(USE_RESPONSE_ENTITY, "false");
codegen.additionalProperties().put(DELEGATE_PATTERN, "false");
codegen.additionalProperties().put(ASYNC, "true");
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));
JavaFileAssert javaFileAssert = JavaFileAssert.assertThat(files.get("TestApi.java"));
javaFileAssert
.assertMethod("postToTest", "ObjTest")
.hasReturnType("CompletableFuture<ObjTest>")
.bodyContainsLines("return CompletableFuture.supplyAsync(()-> {")
.bodyContainsLines("throw new IllegalArgumentException(\"Not implemented\");");
javaFileAssert
.assertMethod("putToTest", "ObjTest")
.hasReturnType("CompletableFuture<Void>")
.bodyContainsLines("throw new IllegalArgumentException(\"Not implemented\");");
}
@Test
public void testReturnTypeVoidWithoutResponseEntityWithoutDelegateWithoutAsync_issue12341() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/2_0/issue12341.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(SpringCodegen.DATE_LIBRARY, "java8-localdatetime");
codegen.additionalProperties().put(INTERFACE_ONLY, "true");
codegen.additionalProperties().put(USE_RESPONSE_ENTITY, "false");
codegen.additionalProperties().put(DELEGATE_PATTERN, "false");
codegen.additionalProperties().put(ASYNC, "false");
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));
JavaFileAssert javaFileAssert = JavaFileAssert.assertThat(files.get("TestApi.java"));
javaFileAssert
.assertMethod("postToTest", "ObjTest")
.hasReturnType("ObjTest")
.bodyContainsLines("throw new IllegalArgumentException(\"Not implemented\");");
javaFileAssert
.assertMethod("putToTest", "ObjTest")
.hasReturnType("void")
.bodyContainsLines("throw new IllegalArgumentException(\"Not implemented\");");
}
}

View File

@ -0,0 +1,51 @@
swagger: '2.0'
info:
description: 'blah'
version: 1.0.0
title: sample spec
host: fake.site.com
tags:
- name: Test
schemes:
- https
paths:
/test:
post:
summary: Post to test
description: ''
operationId: postToTest
consumes:
- application/json
produces:
- application/json
parameters:
- in: body
name: Obj to test
schema:
$ref: '#/definitions/ObjTest'
responses:
'201':
description: successful operation
schema:
$ref: '#/definitions/ObjTest'
put:
summary: Put to test
operationId: putToTest
parameters:
- in: body
name: Obj to test
schema:
$ref: '#/definitions/ObjTest'
responses:
'204':
description: successful operation
definitions:
ObjTest:
description: A model to return
type: object
properties:
field1:
type: integer
format: int64
field2:
type: string

View File

@ -539,10 +539,10 @@ public interface PathHandlerInterface {
* <p><b>Response headers</b>: [CodegenProperty{openApiType='integer', baseName='X-Rate-Limit', complexType='null', getter='getxRateLimit', setter='setxRateLimit', description='calls per hour allowed by the user', dataType='Integer', datatypeWithEnum='Integer', dataFormat='int32', name='xRateLimit', min='null', max='null', defaultValue='null', defaultValueWithParam=' = data.X-Rate-Limit;', baseType='Integer', containerType='null', title='null', unescapedDescription='calls per hour allowed by the user', maxLength=null, minLength=null, pattern='null', example='null', jsonSchema='{
"type" : "integer",
"format" : "int32"
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=true, isModel=false, isContainer=false, isString=false, isNumeric=true, isInteger=true, isShort=true, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=false, isUuid=false, isUri=false, isEmail=false, isPassword=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isInnerEnum=false, isEnumRef=false, isAnyType=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, isNew=false, isOverridden=null, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XRateLimit', nameInSnakeCase='X_RATE_LIMIT', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, uniqueItemsBoolean=null, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false, requiredVarsMap=null, ref=null, schemaIsFromAdditionalProperties=false, isBooleanSchemaTrue=false, isBooleanSchemaFalse=false, format=int32, dependentRequired=null, contains=null}, CodegenProperty{openApiType='string', baseName='X-Expires-After', complexType='Date', getter='getxExpiresAfter', setter='setxExpiresAfter', description='date in UTC when token expires', dataType='Date', datatypeWithEnum='Date', dataFormat='date-time', name='xExpiresAfter', min='null', max='null', defaultValue='null', defaultValueWithParam=' = data.X-Expires-After;', baseType='Date', containerType='null', title='null', unescapedDescription='date in UTC when token expires', maxLength=null, minLength=null, pattern='null', example='null', jsonSchema='{
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=true, isModel=false, isContainer=false, isString=false, isNumeric=true, isInteger=true, isShort=true, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=false, isUuid=false, isUri=false, isEmail=false, isPassword=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isInnerEnum=false, isEnumRef=false, isAnyType=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, isNew=false, isOverridden=null, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XRateLimit', nameInSnakeCase='X_RATE_LIMIT', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, uniqueItemsBoolean=null, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, isVoid=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false, requiredVarsMap=null, ref=null, schemaIsFromAdditionalProperties=false, isBooleanSchemaTrue=false, isBooleanSchemaFalse=false, format=int32, dependentRequired=null, contains=null}, CodegenProperty{openApiType='string', baseName='X-Expires-After', complexType='Date', getter='getxExpiresAfter', setter='setxExpiresAfter', description='date in UTC when token expires', dataType='Date', datatypeWithEnum='Date', dataFormat='date-time', name='xExpiresAfter', min='null', max='null', defaultValue='null', defaultValueWithParam=' = data.X-Expires-After;', baseType='Date', containerType='null', title='null', unescapedDescription='date in UTC when token expires', maxLength=null, minLength=null, pattern='null', example='null', jsonSchema='{
"type" : "string",
"format" : "date-time"
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=false, isModel=false, isContainer=false, isString=false, isNumeric=false, isInteger=false, isShort=false, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=true, isUuid=false, isUri=false, isEmail=false, isPassword=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isInnerEnum=false, isEnumRef=false, isAnyType=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, isNew=false, isOverridden=null, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XExpiresAfter', nameInSnakeCase='X_EXPIRES_AFTER', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, uniqueItemsBoolean=null, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false, requiredVarsMap=null, ref=null, schemaIsFromAdditionalProperties=false, isBooleanSchemaTrue=false, isBooleanSchemaFalse=false, format=date-time, dependentRequired=null, contains=null}]</p>
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=false, isModel=false, isContainer=false, isString=false, isNumeric=false, isInteger=false, isShort=false, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=true, isUuid=false, isUri=false, isEmail=false, isPassword=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isInnerEnum=false, isEnumRef=false, isAnyType=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, isNew=false, isOverridden=null, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XExpiresAfter', nameInSnakeCase='X_EXPIRES_AFTER', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, uniqueItemsBoolean=null, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, isVoid=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false, requiredVarsMap=null, ref=null, schemaIsFromAdditionalProperties=false, isBooleanSchemaTrue=false, isBooleanSchemaFalse=false, format=date-time, dependentRequired=null, contains=null}]</p>
*
* <p><b>Produces</b>: [{mediaType=application/xml}, {mediaType=application/json}]</p>
* <p><b>Returns</b>: {@link String}</p>

View File

@ -95,11 +95,11 @@ public interface PetApi {
value = "/pet/{petId}"
)
@ResponseStatus(HttpStatus.BAD_REQUEST)
default Void deletePet(
default void deletePet(
@ApiParam(value = "Pet id to delete", required = true) @PathVariable("petId") Long petId,
@ApiParam(value = "") @RequestHeader(value = "api_key", required = false) String apiKey
) {
return getDelegate().deletePet(petId, apiKey);
getDelegate().deletePet(petId, apiKey);
}
@ -293,12 +293,12 @@ public interface PetApi {
consumes = { "application/x-www-form-urlencoded" }
)
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
default Void updatePetWithForm(
default void updatePetWithForm(
@ApiParam(value = "ID of pet that needs to be updated", required = true) @PathVariable("petId") Long petId,
@ApiParam(value = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) String name,
@ApiParam(value = "Updated status of the pet") @Valid @RequestParam(value = "status", required = false) String status
) {
return getDelegate().updatePetWithForm(petId, name, status);
getDelegate().updatePetWithForm(petId, name, status);
}

View File

@ -60,7 +60,7 @@ public interface PetApiDelegate {
* @return Invalid pet value (status code 400)
* @see PetApi#deletePet
*/
default Void deletePet(Long petId,
default void deletePet(Long petId,
String apiKey) {
throw new IllegalArgumentException("Not implemented");
@ -195,7 +195,7 @@ public interface PetApiDelegate {
* @return Invalid input (status code 405)
* @see PetApi#updatePetWithForm
*/
default Void updatePetWithForm(Long petId,
default void updatePetWithForm(Long petId,
String name,
String status) {
throw new IllegalArgumentException("Not implemented");

View File

@ -51,10 +51,10 @@ public interface StoreApi {
value = "/store/order/{orderId}"
)
@ResponseStatus(HttpStatus.BAD_REQUEST)
default Void deleteOrder(
default void deleteOrder(
@ApiParam(value = "ID of the order that needs to be deleted", required = true) @PathVariable("orderId") String orderId
) {
return getDelegate().deleteOrder(orderId);
getDelegate().deleteOrder(orderId);
}

View File

@ -32,7 +32,7 @@ public interface StoreApiDelegate {
* or Order not found (status code 404)
* @see StoreApi#deleteOrder
*/
default Void deleteOrder(String orderId) {
default void deleteOrder(String orderId) {
throw new IllegalArgumentException("Not implemented");
}

View File

@ -54,10 +54,10 @@ public interface UserApi {
consumes = { "application/json" }
)
@ResponseStatus(HttpStatus.OK)
default Void createUser(
default void createUser(
@ApiParam(value = "Created user object", required = true) @Valid @RequestBody User user
) {
return getDelegate().createUser(user);
getDelegate().createUser(user);
}
@ -86,10 +86,10 @@ public interface UserApi {
consumes = { "application/json" }
)
@ResponseStatus(HttpStatus.OK)
default Void createUsersWithArrayInput(
default void createUsersWithArrayInput(
@ApiParam(value = "List of user object", required = true) @Valid @RequestBody List<User> user
) {
return getDelegate().createUsersWithArrayInput(user);
getDelegate().createUsersWithArrayInput(user);
}
@ -118,10 +118,10 @@ public interface UserApi {
consumes = { "application/json" }
)
@ResponseStatus(HttpStatus.OK)
default Void createUsersWithListInput(
default void createUsersWithListInput(
@ApiParam(value = "List of user object", required = true) @Valid @RequestBody List<User> user
) {
return getDelegate().createUsersWithListInput(user);
getDelegate().createUsersWithListInput(user);
}
@ -151,10 +151,10 @@ public interface UserApi {
value = "/user/{username}"
)
@ResponseStatus(HttpStatus.BAD_REQUEST)
default Void deleteUser(
default void deleteUser(
@ApiParam(value = "The name that needs to be deleted", required = true) @PathVariable("username") String username
) {
return getDelegate().deleteUser(username);
getDelegate().deleteUser(username);
}
@ -249,10 +249,10 @@ public interface UserApi {
value = "/user/logout"
)
@ResponseStatus(HttpStatus.OK)
default Void logoutUser(
default void logoutUser(
) {
return getDelegate().logoutUser();
getDelegate().logoutUser();
}
@ -284,11 +284,11 @@ public interface UserApi {
consumes = { "application/json" }
)
@ResponseStatus(HttpStatus.BAD_REQUEST)
default Void updateUser(
default void updateUser(
@ApiParam(value = "name that need to be deleted", required = true) @PathVariable("username") String username,
@ApiParam(value = "Updated user object", required = true) @Valid @RequestBody User user
) {
return getDelegate().updateUser(username, user);
getDelegate().updateUser(username, user);
}
}

View File

@ -32,7 +32,7 @@ public interface UserApiDelegate {
* @return successful operation (status code 200)
* @see UserApi#createUser
*/
default Void createUser(User user) {
default void createUser(User user) {
throw new IllegalArgumentException("Not implemented");
}
@ -45,7 +45,7 @@ public interface UserApiDelegate {
* @return successful operation (status code 200)
* @see UserApi#createUsersWithArrayInput
*/
default Void createUsersWithArrayInput(List<User> user) {
default void createUsersWithArrayInput(List<User> user) {
throw new IllegalArgumentException("Not implemented");
}
@ -58,7 +58,7 @@ public interface UserApiDelegate {
* @return successful operation (status code 200)
* @see UserApi#createUsersWithListInput
*/
default Void createUsersWithListInput(List<User> user) {
default void createUsersWithListInput(List<User> user) {
throw new IllegalArgumentException("Not implemented");
}
@ -72,7 +72,7 @@ public interface UserApiDelegate {
* or User not found (status code 404)
* @see UserApi#deleteUser
*/
default Void deleteUser(String username) {
default void deleteUser(String username) {
throw new IllegalArgumentException("Not implemented");
}
@ -129,7 +129,7 @@ public interface UserApiDelegate {
* @return successful operation (status code 200)
* @see UserApi#logoutUser
*/
default Void logoutUser() {
default void logoutUser() {
throw new IllegalArgumentException("Not implemented");
}
@ -144,7 +144,7 @@ public interface UserApiDelegate {
* or User not found (status code 404)
* @see UserApi#updateUser
*/
default Void updateUser(String username,
default void updateUser(String username,
User user) {
throw new IllegalArgumentException("Not implemented");