Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions modules/openapi-generator/src/main/resources/r/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
{{#items}}
{{#isEnum}}
# validate enum values
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -346,7 +346,7 @@
{{#isEnum}}
# validate enum values
for (query_item in `{{{paramName}}}`) {
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -370,7 +370,7 @@
{{#items}}
{{#isEnum}}
# validate enum values
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -392,7 +392,7 @@
{{#isEnum}}
# validate enum values
for (query_item in `{{{paramName}}}`) {
if (!(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(query_item) && !(query_item %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand All @@ -412,7 +412,7 @@
{{/isArray}}
{{^isArray}}
{{#isEnum}}
if (!(`{{paramName}}` %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
if (!is.null(`{{paramName}}`) && !(`{{paramName}}` %in% c({{#_enum}}"{{{.}}}"{{^-last}}, {{/-last}}{{/_enum}}))) {
{{#useDefaultExceptionHandling}}
stop("Invalid value for {{{paramName}}} when calling {{classname}}${{operationId}}. Must be {{_enum}}.")
{{/useDefaultExceptionHandling}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,21 @@

package org.openapitools.codegen.r;

import io.swagger.v3.oas.models.OpenAPI;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.languages.RClientCodegen;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Pattern;

public class RClientCodegenTest {

@Test
Expand Down Expand Up @@ -53,4 +63,35 @@ public void testAdditionalPropertiesPutForConfigValues() throws Exception {
Assert.assertEquals(codegen.isHideGenerationTimestamp(), false);
}

@Test
public void testNullCheckOnEnumValues() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final DefaultGenerator defaultGenerator = new DefaultGenerator();

RClientCodegen rClientCodegen = new RClientCodegen();
rClientCodegen.setOutputDir(output.getAbsolutePath());

final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/bugs/issue_18016.yaml");
final ClientOptInput clientOptInput = new ClientOptInput();
clientOptInput.openAPI(openAPI);
clientOptInput.config(rClientCodegen);
defaultGenerator.opts(clientOptInput);

var petsApi = defaultGenerator.generate().stream()
.filter(file -> "pets_api.R".equals(file.getName())).findFirst();
if (petsApi.isEmpty()) {
Assert.fail("`pets_api.R` have not been generated");
}
var isIfCondition = Pattern.compile("^\\s*(?!<#)\\s*if.*\\s%in%\\s.*").asPredicate();
var containsNullCheck = Pattern.compile("![(\\s]*is\\.null").asPredicate();
var hit = false;
for (var line: Files.readAllLines(Paths.get(petsApi.get().getAbsolutePath()))) {
if (isIfCondition.test(line)) {
hit = true;
Assert.assertTrue(containsNullCheck.test(line), "Null check is missing in line: " + line);
}
}
Assert.assertTrue(hit, "No if statement for enum found");
}
}
27 changes: 27 additions & 0 deletions modules/openapi-generator/src/test/resources/bugs/issue_18016.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
openapi: "3.0.0"
info:
version: 1.0.0
description: Specification to generate null check for enums in R client
title: RClientNullCheck
paths:
/exists:
get:
tags:
- pets
parameters:
- name: type
in: query
description: Type of pet
required: false
schema:
enum:
- cat
- dog
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: boolean
2 changes: 1 addition & 1 deletion samples/client/echo_api/r/R/query_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ QueryApi <- R6::R6Class(



if (!(`enum_nonref_string_query` %in% c("success", "failure", "unclassified"))) {
if (!is.null(`enum_nonref_string_query`) && !(`enum_nonref_string_query` %in% c("success", "failure", "unclassified"))) {
stop("Invalid value for enum_nonref_string_query when calling QueryApi$TestEnumRefString. Must be [success, failure, unclassified].")
}
query_params[["enum_nonref_string_query"]] <- `enum_nonref_string_query`
Expand Down
2 changes: 1 addition & 1 deletion samples/client/petstore/R-httr2-wrapper/R/pet_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$find_pets_by_status. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,
Expand Down
2 changes: 1 addition & 1 deletion samples/client/petstore/R-httr2/R/pet_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$find_pets_by_status. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,
Expand Down
2 changes: 1 addition & 1 deletion samples/client/petstore/R/R/pet_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ PetApi <- R6::R6Class(
# explore
for (query_item in `status`) {
# validate enum values
if (!(query_item %in% c("available", "pending", "sold"))) {
if (!is.null(query_item) && !(query_item %in% c("available", "pending", "sold"))) {
rlang::abort(message = "Invalid value for `status` when calling PetApi$FindPetsByStatus. Must be [available, pending, sold].",
.subclass = "ApiException",
ApiException = ApiException$new(status = 0,
Expand Down