Skip to content

Commit

Permalink
Fix generator for controller parameters with arrays and enums (#1677)
Browse files Browse the repository at this point in the history
  • Loading branch information
altro3 authored Aug 21, 2024
1 parent b63d62c commit f195379
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1583,4 +1583,8 @@ public void setDateTimeLibrary(String name) {
setDateLibrary(name);
}

@Override
public boolean getUseInlineModelResolver() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1801,4 +1801,9 @@ private String recurseOnEndOfTheWord(String word, String oldValue, String newVal
private String firstTitleCase(final String input) {
return input.substring(0, 1).toUpperCase(Locale.ROOT) + input.substring(1);
}

@Override
public boolean getUseInlineModelResolver() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void generate() {
input.config(codeGenerator);

// Generate
DefaultGenerator generator = new DefaultGenerator();
var generator = new DefaultGenerator();
for (OutputKind outputKind : OutputKind.values()) {
generator.setGeneratorPropertyDefault(outputKind.generatorProperty, "false");
}
Expand Down Expand Up @@ -459,7 +459,7 @@ public MicronautCodeGeneratorBuilder withOutputs(OutputKind... elements) {

@Override
public MicronautCodeGeneratorBuilder withOptions(Consumer<? super MicronautCodeGeneratorOptionsBuilder> optionsConfigurer) {
DefaultOptionsBuilder builder = new DefaultOptionsBuilder();
var builder = new DefaultOptionsBuilder();
optionsConfigurer.accept(builder);
options = builder.build();
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ public void setInlineSchemaOptions(Map inlineSchemaOptions) {
}
}

private void normalizeArraySchema(Schema schema) {
if (ModelUtils.isArraySchema(schema)) {
schema.setEnum(null);
}
}

public void flatten() {
if (this.openAPI.getComponents() == null) {
this.openAPI.setComponents(new Components());
Expand Down Expand Up @@ -220,6 +226,8 @@ private void flattenContent(Content content, String name) {
if (schema == null) {
continue;
}
normalizeArraySchema(schema);

String schemaName = resolveModelName(schema.getTitle(), name); // name example: testPost_request
// Recursively gather/make inline models within this schema if any
gatherInlineModels(schema, schemaName);
Expand Down Expand Up @@ -264,6 +272,8 @@ private void flattenParameters(String modelName, Operation operation) {
continue;
}

normalizeArraySchema(parameterSchema);

String schemaName = resolveModelName(parameterSchema.getTitle(),
(operation.getOperationId() == null ? modelName : operation.getOperationId()) + "_" + parameter.getName() + "_parameter");
// Recursively gather/make inline models within this schema if any
Expand Down Expand Up @@ -314,6 +324,9 @@ private void flattenPathItemParameters(String modelName, Operation operation, Pa
if (parameterSchema == null) {
continue;
}

normalizeArraySchema(parameterSchema);

String schemaName = resolveModelName(parameterSchema.getTitle(),
(operation.getOperationId() == null ? modelName : operation.getOperationId()) + "_" + parameter.getName() + "_parameter");
// Recursively gather/make inline models within this schema if any
Expand Down Expand Up @@ -369,6 +382,8 @@ private void gatherInlineModels(Schema schema, String modelPrefix) {
continue;
}

normalizeArraySchema(prop);

String schemaName = resolveModelName(prop.getTitle(), modelPrefix + "_" + propName);
// Recurse to create $refs for inner models
gatherInlineModels(prop, schemaName);
Expand Down Expand Up @@ -445,6 +460,9 @@ private void gatherInlineModels(Schema schema, String modelPrefix) {
if (inner == null) {
continue;
}

normalizeArraySchema((Schema) inner);

String schemaName = resolveModelName(((Schema) inner).getTitle(), modelPrefix + "_allOf");
// Recurse to create $refs for inner models
gatherInlineModels((Schema) inner, schemaName);
Expand Down Expand Up @@ -479,6 +497,8 @@ private void gatherInlineModels(Schema schema, String modelPrefix) {
if (inner == null) {
continue;
}

normalizeArraySchema((Schema) inner);
String schemaName = resolveModelName(((Schema) inner).getTitle(), modelPrefix + "_anyOf");
// Recurse to create $refs for inner models
gatherInlineModels((Schema) inner, schemaName);
Expand All @@ -497,6 +517,8 @@ private void gatherInlineModels(Schema schema, String modelPrefix) {
if (inner == null) {
continue;
}

normalizeArraySchema((Schema) inner);
String schemaName = resolveModelName(((Schema) inner).getTitle(), modelPrefix + "_oneOf");
// Recurse to create $refs for inner models
gatherInlineModels((Schema) inner, schemaName);
Expand Down Expand Up @@ -762,6 +784,7 @@ private void flattenComponents() {
if (model == null) {
continue;
}
normalizeArraySchema(model);
if (ModelUtils.isAnyOf(model)) { // contains anyOf only
gatherInlineModels(model, modelName);
} else if (ModelUtils.isOneOf(model)) { // contains oneOf only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,16 @@ void testReservedWords() {
"public void set_for(String _for) {");
}

@Test
void testControllerEnums2() {

var codegen = new JavaMicronautClientCodegen();
String outputPath = generateFiles(codegen, "src/test/resources/3_0/controller-enum2.yml", CodegenConstants.APIS, CodegenConstants.MODELS);
String modelPath = outputPath + "src/main/java/org/openapitools/api/";

assertFileContains(modelPath + "BusinessCardsApi.java", "@QueryValue(\"statusCodes\") @Nullable List<@NotNull String> statusCodes");
}

@Test
void testCommonPathParametersWithRef() {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package io.micronaut.openapi.generator;

import java.util.List;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.servers.Server;

import org.junit.jupiter.api.Test;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;

import java.util.List;

import static java.util.stream.Collectors.groupingBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand Down Expand Up @@ -145,33 +144,33 @@ void doGenerateRequiredPropertiesInConstructor() {
// Constructor should have properties
String modelPath = outputPath + "src/main/kotlin/org/openapitools/model/";
assertFileContains(modelPath + "Pet.kt",
"""
data class Pet(
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_NAME)
var name: String,
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_PHOTO_URLS)
var photoUrls: List<@NotNull String>,
@field:Nullable
@field:JsonProperty(JSON_PROPERTY_ID)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var id: Long? = null,
@field:Nullable
@field:Valid
@field:JsonProperty(JSON_PROPERTY_CATEGORY)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var category: Category? = null,
@field:Nullable
@field:JsonProperty(JSON_PROPERTY_TAGS)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var tags: List<@Valid Tag>? = null,
@field:Nullable
@field:JsonProperty(JSON_PROPERTY_STATUS)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var status: PetStatus? = null,
) {
""");
"""
data class Pet(
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_NAME)
var name: String,
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_PHOTO_URLS)
var photoUrls: List<@NotNull String>,
@field:Nullable
@field:JsonProperty(JSON_PROPERTY_ID)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var id: Long? = null,
@field:Nullable
@field:Valid
@field:JsonProperty(JSON_PROPERTY_CATEGORY)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var category: Category? = null,
@field:Nullable
@field:JsonProperty(JSON_PROPERTY_TAGS)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var tags: List<@Valid Tag>? = null,
@field:Nullable
@field:JsonProperty(JSON_PROPERTY_STATUS)
@field:JsonInclude(JsonInclude.Include.USE_DEFAULTS)
var status: PetStatus? = null,
) {
""");
}

@Test
Expand Down Expand Up @@ -363,9 +362,9 @@ void testAddValidAnnotations() {

assertFileContains(apiPath + "BooksContainer.kt",
"""
@field:JsonProperty(JSON_PROPERTY_BOOKS)
var books: List<@Valid Book>
""");
@field:JsonProperty(JSON_PROPERTY_BOOKS)
var books: List<@Valid Book>
""");
}

@Test
Expand All @@ -392,15 +391,15 @@ void testDiscriminatorConstructorBug() {
String apiPath = outputPath + "src/main/kotlin/org/openapitools/model/";

assertFileContains(apiPath + "BookInfo.kt",
"""
open class BookInfo(
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_NAME)
open var name: String,
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_TYPE)
open var type: BookInfoType? = null,
) {""");
"""
open class BookInfo(
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_NAME)
open var name: String,
@field:NotNull
@field:JsonProperty(JSON_PROPERTY_TYPE)
open var type: BookInfoType? = null,
) {""");
assertFileContains(apiPath + "BasicBookInfo.kt",
"""
open class BasicBookInfo(
Expand Down Expand Up @@ -484,6 +483,16 @@ void testReservedWords() {
"var `data`: String,");
}

@Test
void testControllerEnums2() {

var codegen = new KotlinMicronautClientCodegen();
String outputPath = generateFiles(codegen, "src/test/resources/3_0/controller-enum2.yml", CodegenConstants.APIS, CodegenConstants.MODELS);
String modelPath = outputPath + "src/main/kotlin/org/openapitools/api/";

assertFileContains(modelPath + "BusinessCardsApi.kt", "@QueryValue(\"statusCodes\") @Nullable statusCodes: List<@NotNull String>?");
}

@Test
void testCommonPathParametersWithRef() {

Expand All @@ -492,13 +501,13 @@ void testCommonPathParametersWithRef() {
String path = outputPath + "src/main/kotlin/org/openapitools/";

assertFileContains(path + "api/WeatherForecastApisApi.kt", "@Get(\"/v1/forecast/{id}\")",
"@PathVariable(\"id\") @NotNull id: String,",
"@QueryValue(\"hourly\") @Nullable hourly: List<V1ForecastIdGetHourlyParameterInner>?,");
"@PathVariable(\"id\") @NotNull id: String,",
"@QueryValue(\"hourly\") @Nullable hourly: List<V1ForecastIdGetHourlyParameterInner>?,");

assertFileContains(path + "model/V1ForecastIdGetHourlyParameterInner.kt",
"enum class V1ForecastIdGetHourlyParameterInner(",
"@JsonProperty(\"temperature_2m\")",
"TEMPERATURE_2M(\"temperature_2m\"),");
"enum class V1ForecastIdGetHourlyParameterInner(",
"@JsonProperty(\"temperature_2m\")",
"TEMPERATURE_2M(\"temperature_2m\"),");
}

@Test
Expand All @@ -509,23 +518,23 @@ void testExtraAnnotations() {
String path = outputPath + "src/main/kotlin/org/openapitools/";

assertFileContains(path + "api/BooksApi.kt",
"""
@Post("/add-book")
@NotBlank
fun addBook(
""");
"""
@Post("/add-book")
@NotBlank
fun addBook(
""");

assertFileContains(path + "model/Book.kt",
"""
@Serializable
data class Book(
@field:NotNull
@field:Size(max = 10)
@field:JsonProperty(JSON_PROPERTY_TITLE)
@field:jakarta.validation.constraints.NotBlank
@set:NotEmpty
var title: String,
""");
"""
@Serializable
data class Book(
@field:NotNull
@field:Size(max = 10)
@field:JsonProperty(JSON_PROPERTY_TITLE)
@field:jakarta.validation.constraints.NotBlank
@set:NotEmpty
var title: String,
""");
}

@Test
Expand Down
46 changes: 46 additions & 0 deletions openapi-generator/src/test/resources/3_0/controller-enum2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
swagger: '2.0'
info:
description: Документация FINTECH REST API
version: '1'
title: FINTECH
contact: { }
basePath: /fintech/api
paths:
/v1/business-cards:
get:
tags:
- BusinessCards
operationId: getBusinessCardsUsingGET
consumes:
- application/json
produces:
- '*/*'
parameters:
- name: Authorization
in: header
description: Access token
required: true
type: string
- name: statusCodes
in: query
description: Список статусов бизнес-карт
required: false
type: array
items:
type: string
collectionFormat: multi
enum:
- ACTIVE
- BLOCKED
- TO_BE_REISSUED
- TO_BE_BLOCKED
- NOT_DELIVERED
- name: page
in: query
description: Номер страницы (начиная с 1)
required: true
type: integer
format: int32
responses:
'200':
description: OK

0 comments on commit f195379

Please sign in to comment.