Skip to content

Commit

Permalink
Fix a few issues with the C generator (part 1 version 2) (#14434)
Browse files Browse the repository at this point in the history
* C: add a template for an empty any_type.h header

Some generated C apis fail to build because the source files get
'#include "any_type.h"' lines, but no such header gets generated. As a
simple fix, add a new template for an empty file with that name. This is
enough to fix the problem for us, because all the generic type stuff is
handled by object_t.

* C: fix enums

I'm guessing that enums have not been used much with the C generator
before, because they always seem to produce code that doesn't build, or
that tries to free them after use. This patch fixes all the problems
we've encountered so far, except for those that need checking the return
type. I'll come back to that later.

* C: fix confusion of 'classname'/'classFilename'

* C: fix issues with returned enums

Currently, the C templates never check if a function returns an enum
inside mustache, so when that happens the generated code has broken
return types and doesn't build. I originally tried to fix this by
extending CodegenOperation to implement a 'returnTypeIsEnum' check, but
William Cheng suggested[1] that I use the existing 'returnProperty'
instead:

  #14379 (comment)

So do that.

* C: update the samples

As required for a pull request, run the generate-samples.sh script and
commit the changes.

* update samples

---------

Co-authored-by: William Cheng <[email protected]>
  • Loading branch information
eafer and wing328 authored Nov 27, 2024
1 parent 8a94fc6 commit 47665aa
Show file tree
Hide file tree
Showing 12 changed files with 73 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ public void processOpts() {
// Object files in model folder
supportingFiles.add(new SupportingFile("object-body.mustache", "model", "object.c"));
supportingFiles.add(new SupportingFile("object-header.mustache", "model", "object.h"));
supportingFiles.add(new SupportingFile("any_type-header.mustache", "model", "any_type.h"));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ set(HDRS
include/keyValuePair.h
external/cJSON.h
model/object.h
model/any_type.h
{{#models}}
{{#model}}
model/{{classFilename}}.h
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* any_type.h
*
* A placeholder for now, this type isn't really needed.
*/
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ end:
// {{{.}}}
//
{{/notes}}
{{#returnType}}{{#returnTypeIsPrimitive}}{{#returnSimpleType}}{{{.}}}*{{/returnSimpleType}}{{^returnSimpleType}}{{#isArray}}{{{.}}}_t*{{/isArray}}{{#isMap}}{{{.}}}{{/isMap}}{{/returnSimpleType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{{.}}}_t*{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void{{/returnType}}
{{#returnType}}{{#returnTypeIsPrimitive}}{{#returnSimpleType}}{{{.}}}*{{/returnSimpleType}}{{^returnSimpleType}}{{#isArray}}{{{.}}}_t*{{/isArray}}{{#isMap}}{{{.}}}{{/isMap}}{{/returnSimpleType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{#returnProperty}}{{^isEnum}}{{{returnType}}}_t*{{/isEnum}}{{#isEnum}}{{projectName}}_{{{returnType}}}_{{returnEnumName}}_e{{/isEnum}}{{/returnProperty}}{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void{{/returnType}}
{{{classname}}}_{{{operationId}}}(apiClient_t *apiClient{{#allParams}}, {{#isPrimitiveType}}{{#isNumber}}{{{dataType}}} {{/isNumber}}{{#isLong}}{{{dataType}}} {{/isLong}}{{#isInteger}}{{{dataType}}} *{{/isInteger}}{{#isDouble}}{{{dataType}}} {{/isDouble}}{{#isFloat}}{{{dataType}}} {{/isFloat}}{{#isBoolean}}{{dataType}} *{{/isBoolean}}{{#isEnum}}{{#isString}}{{projectName}}_{{operationId}}_{{baseName}}_e {{/isString}}{{/isEnum}}{{^isEnum}}{{#isString}}{{{dataType}}} *{{/isString}}{{/isEnum}}{{#isByteArray}}{{{dataType}}} *{{/isByteArray}}{{#isDate}}{{{dataType}}} {{/isDate}}{{#isDateTime}}{{{dataType}}} {{/isDateTime}}{{#isFile}}{{{dataType}}} {{/isFile}}{{#isFreeFormObject}}{{dataType}}_t *{{/isFreeFormObject}}{{/isPrimitiveType}}{{^isArray}}{{^isPrimitiveType}}{{#isModel}}{{#isEnum}}{{datatypeWithEnum}}_e {{/isEnum}}{{^isEnum}}{{{dataType}}}_t *{{/isEnum}}{{/isModel}}{{^isModel}}{{#isEnum}}{{datatypeWithEnum}}_e {{/isEnum}}{{/isModel}}{{#isUuid}}{{dataType}} *{{/isUuid}}{{#isEmail}}{{dataType}} {{/isEmail}}{{/isPrimitiveType}}{{/isArray}}{{#isContainer}}{{#isArray}}{{dataType}}_t *{{/isArray}}{{#isMap}}{{dataType}} {{/isMap}}{{/isContainer}}{{{paramName}}}{{/allParams}})
{
list_t *localVarQueryParameters = {{#hasQueryParams}}list_createList();{{/hasQueryParams}}{{^hasQueryParams}}NULL;{{/hasQueryParams}}
Expand Down Expand Up @@ -263,7 +263,7 @@ end:
{{#isPrimitiveType}}{{#isNumber}}{{{dataType}}}{{/isNumber}}{{#isLong}}{{{dataType}}}{{/isLong}}{{#isInteger}}{{{dataType}}}{{/isInteger}}{{#isDouble}}{{{dataType}}}{{/isDouble}}{{#isFloat}}{{{dataType}}}{{/isFloat}}{{#isBoolean}}{{dataType}}{{/isBoolean}}{{#isEnum}}{{#isString}}{{projectName}}_{{operationId}}_{{baseName}}_e{{/isString}}{{/isEnum}}{{^isEnum}}{{#isString}}{{{dataType}}} *{{/isString}}{{/isEnum}}{{#isByteArray}}{{{dataType}}} *{{/isByteArray}}{{#isDate}}{{{dataType}}}{{/isDate}}{{#isDateTime}}{{{dataType}}}{{/isDateTime}}{{#isFile}}{{{dataType}}}{{/isFile}}{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isModel}}{{#isEnum}}{{datatypeWithEnum}}_e{{/isEnum}}{{^isEnum}}{{{dataType}}}_t *{{/isEnum}}{{/isModel}}{{^isModel}}{{#isEnum}}{{datatypeWithEnum}}_e{{/isEnum}}{{/isModel}}{{#isUuid}}{{dataType}} *{{/isUuid}}{{#isEmail}}{{dataType}}{{/isEmail}}{{/isPrimitiveType}} valueForm_{{paramName}} = 0;
keyValuePair_t *keyPairForm_{{paramName}} = 0;
{{/isFile}}
if ({{paramName}} != NULL)
if ({{paramName}} != {{^isEnum}}NULL{{/isEnum}}{{#isEnum}}0{{/isEnum}})
{
{{#isFile}}
keyForm_{{paramName}} = strdup("{{{baseName}}}");
Expand Down Expand Up @@ -399,9 +399,9 @@ end:
{{^returnContainer}}
//nonprimitive not container
cJSON *{{classname}}localVarJSON = cJSON_Parse(apiClient->dataReceived);
{{{returnBaseType}}}_t *elementToReturn = {{{returnBaseType}}}_parseFromJSON({{classname}}localVarJSON);
{{#returnProperty}}{{^isEnum}}{{{returnBaseType}}}_t *{{/isEnum}}{{#isEnum}}{{projectName}}_{{{returnType}}}_{{returnEnumName}}_e {{/isEnum}}{{/returnProperty}}elementToReturn = {{{returnBaseType}}}_parseFromJSON({{classname}}localVarJSON);
cJSON_Delete({{classname}}localVarJSON);
if(elementToReturn == NULL) {
if(elementToReturn == {{#returnProperty}}{{^isEnum}}NULL{{/isEnum}}{{#isEnum}}0{{/isEnum}}{{/returnProperty}}) {
// return 0;
}

Expand Down Expand Up @@ -524,8 +524,10 @@ end:
keyForm_{{{paramName}}} = NULL;
}
if (valueForm_{{{paramName}}}) {
{{^isEnum}}
free(valueForm_{{{paramName}}});
valueForm_{{{paramName}}} = NULL;
{{/isEnum}}
valueForm_{{{paramName}}} = {{^isEnum}}NULL{{/isEnum}}{{#isEnum}}0{{/isEnum}};
}
free(keyPairForm_{{paramName}});
{{/isString}}
Expand All @@ -541,7 +543,7 @@ end:
return elementToReturn;
end:
free(localVarPath);
return NULL;
return {{#returnProperty}}{{^isEnum}}NULL{{/isEnum}}{{#isEnum}}0{{/isEnum}}{{/returnProperty}};
{{/returnType}}
{{^returnType}}
//No return type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef enum { {{projectName}}_{{operationId}}_{{enumName}}_NULL = 0{{#enumVars
// {{{.}}}
//
{{/notes}}
{{#returnType}}{{#returnTypeIsPrimitive}}{{#returnSimpleType}}{{{.}}}*{{/returnSimpleType}}{{^returnSimpleType}}{{#isArray}}{{{.}}}_t*{{/isArray}}{{#isMap}}{{{.}}}{{/isMap}}{{/returnSimpleType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{{.}}}_t*{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void{{/returnType}}
{{#returnType}}{{#returnTypeIsPrimitive}}{{#returnSimpleType}}{{{.}}}*{{/returnSimpleType}}{{^returnSimpleType}}{{#isArray}}{{{.}}}_t*{{/isArray}}{{#isMap}}{{{.}}}{{/isMap}}{{/returnSimpleType}}{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{#returnProperty}}{{^isEnum}}{{{returnType}}}_t*{{/isEnum}}{{#isEnum}}{{projectName}}_{{{returnType}}}_{{returnEnumName}}_e{{/isEnum}}{{/returnProperty}}{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void{{/returnType}}
{{{classname}}}_{{{operationId}}}(apiClient_t *apiClient{{#allParams}}, {{#isPrimitiveType}}{{#isNumber}}{{{dataType}}} {{/isNumber}}{{#isLong}}{{{dataType}}} {{/isLong}}{{#isInteger}}{{{dataType}}} *{{/isInteger}}{{#isDouble}}{{{dataType}}} {{/isDouble}}{{#isFloat}}{{{dataType}}} {{/isFloat}}{{#isBoolean}}{{dataType}} *{{/isBoolean}}{{#isEnum}}{{#isString}}{{projectName}}_{{operationId}}_{{baseName}}_e {{/isString}}{{/isEnum}}{{^isEnum}}{{#isString}}{{{dataType}}} *{{/isString}}{{/isEnum}}{{#isByteArray}}{{{dataType}}} *{{/isByteArray}}{{#isDate}}{{{dataType}}} {{/isDate}}{{#isDateTime}}{{{dataType}}} {{/isDateTime}}{{#isFile}}{{{dataType}}} {{/isFile}}{{#isFreeFormObject}}{{dataType}}_t *{{/isFreeFormObject}}{{/isPrimitiveType}}{{^isArray}}{{^isPrimitiveType}}{{#isModel}}{{#isEnum}}{{datatypeWithEnum}}_e {{/isEnum}}{{^isEnum}}{{{dataType}}}_t *{{/isEnum}}{{/isModel}}{{^isModel}}{{#isEnum}}{{datatypeWithEnum}}_e {{/isEnum}}{{/isModel}}{{#isUuid}}{{dataType}} *{{/isUuid}}{{#isEmail}}{{dataType}} {{/isEmail}}{{/isPrimitiveType}}{{/isArray}}{{#isContainer}}{{#isArray}}{{dataType}}_t *{{/isArray}}{{#isMap}}{{dataType}} {{/isMap}}{{/isContainer}}{{{paramName}}}{{/allParams}});


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ char* {{classFilename}}_{{classname}}_ToString({{projectName}}_{{classVarName}}_
return 0;
}

cJSON *{{classFilename}}_{{classname}}_convertToJSON({{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}}) {
cJSON *{{classname}}_convertToJSON({{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}}) {
cJSON *item = cJSON_CreateObject();
{{#isString}}
if(cJSON_AddStringToObject(item, "{{{classname}}}", {{classFilename}}_{{{classname}}}_ToString({{{classname}}})) == NULL) {
Expand All @@ -48,7 +48,7 @@ fail:
return NULL;
}

{{projectName}}_{{classVarName}}_{{enumName}}_e {{classFilename}}_{{classname}}_parseFromJSON(cJSON *{{classname}}JSON) {
{{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}}_parseFromJSON(cJSON *{{classname}}JSON) {
{{projectName}}_{{classVarName}}_{{enumName}}_e *{{classname}} = NULL;
{{#isEnum}}
{{#isNumeric}}
Expand All @@ -75,6 +75,7 @@ end:
{{^isEnum}}
{{#vars}}
{{^isContainer}}
{{#isPrimitiveType}}
{{^isModel}}
{{#isEnum}}
char* {{classname}}_{{name}}_ToString({{projectName}}_{{classVarName}}_{{enumName}}_e {{name}}) {
Expand All @@ -96,6 +97,7 @@ char* {{classname}}_{{name}}_ToString({{projectName}}_{{classVarName}}_{{enumNam
}
{{/isEnum}}
{{/isModel}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#items}}
Expand Down Expand Up @@ -138,7 +140,12 @@ char* {{classname}}_{{name}}_ToString({{projectName}}_{{classVarName}}_{{enumNam
{{/isModel}}
{{^isModel}}
{{^isFreeFormObject}}
{{^isEnum}}
{{datatype}}_t *{{name}}{{^-last}},{{/-last}}
{{/isEnum}}
{{#isEnum}}
{{projectName}}_{{dataType}}_{{enumName}}_e {{name}}{{^-last}},{{/-last}}
{{/isEnum}}
{{/isFreeFormObject}}
{{/isModel}}
{{#isUuid}}
Expand Down Expand Up @@ -227,10 +234,12 @@ void {{classname}}_free({{classname}}_t *{{classname}}) {
{{/isModel}}
{{^isModel}}
{{^isFreeFormObject}}
{{^isEnum}}
if ({{{classname}}}->{{{name}}}) {
{{{complexType}}}_free({{{classname}}}->{{{name}}});
{{classname}}->{{name}} = NULL;
}
{{/isEnum}}
{{/isFreeFormObject}}
{{/isModel}}
{{#isUuid}}
Expand Down Expand Up @@ -337,7 +346,12 @@ cJSON *{{classname}}_convertToJSON({{classname}}_t *{{classname}}) {
}
{{/isEnum}}
{{#isEnum}}
{{#isPrimitiveType}}
if ({{projectName}}_{{classVarName}}_{{enumName}}_NULL == {{{classname}}}->{{{name}}}) {
{{/isPrimitiveType}}
{{^isPrimitiveType}}
if ({{projectName}}_{{dataType}}_{{enumName}}_NULL == {{{classname}}}->{{{name}}}) {
{{/isPrimitiveType}}
goto fail;
}
{{/isEnum}}
Expand All @@ -347,7 +361,12 @@ cJSON *{{classname}}_convertToJSON({{classname}}_t *{{classname}}) {
if({{{classname}}}->{{{name}}}) {
{{/isEnum}}
{{#isEnum}}
{{#isPrimitiveType}}
if({{{classname}}}->{{{name}}} != {{projectName}}_{{classVarName}}_{{enumName}}_NULL) {
{{/isPrimitiveType}}
{{^isPrimitiveType}}
if({{{classname}}}->{{{name}}} != {{projectName}}_{{dataType}}_{{enumName}}_NULL) {
{{/isPrimitiveType}}
{{/isEnum}}
{{/required}}
{{^isContainer}}
Expand Down Expand Up @@ -589,7 +608,12 @@ fail:
{{^isModel}}
{{^isFreeFormObject}}
// define the local variable for {{{classname}}}->{{{name}}}
{{^isEnum}}
{{complexType}}_t *{{name}}_local_nonprim = NULL;
{{/isEnum}}
{{#isEnum}}
{{projectName}}_{{dataType}}_{{enumName}}_e {{name}}_local_nonprim = 0;
{{/isEnum}}

{{/isFreeFormObject}}
{{/isModel}}
Expand Down Expand Up @@ -853,7 +877,7 @@ fail:
{{/isModel}}
{{^isModel}}
{{^isFreeFormObject}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}_local_nonprim{{^required}} : NULL{{/required}}{{^-last}},{{/-last}}
{{^required}}{{{name}}} ? {{/required}}{{{name}}}_local_nonprim{{^required}} : {{^isEnum}}NULL{{/isEnum}}{{#isEnum}}0{{/isEnum}}{{/required}}{{^-last}},{{/-last}}
{{/isFreeFormObject}}
{{/isModel}}
{{#isUuid}}
Expand Down Expand Up @@ -929,8 +953,10 @@ end:
{{^isModel}}
{{^isFreeFormObject}}
if ({{{name}}}_local_nonprim) {
{{^isEnum}}
{{complexType}}_free({{{name}}}_local_nonprim);
{{{name}}}_local_nonprim = NULL;
{{/isEnum}}
{{{name}}}_local_nonprim = {{^isEnum}}NULL{{/isEnum}}{{#isEnum}}0{{/isEnum}};
}
{{/isFreeFormObject}}
{{/isModel}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ char* {{classFilename}}_{{classname}}_ToString({{projectName}}_{{classVarName}}_

{{projectName}}_{{classVarName}}_{{enumName}}_e {{classFilename}}_{{classname}}_FromString(char* {{classname}});

//cJSON *{{classFilename}}_{{classname}}_convertToJSON({{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}});
cJSON *{{classname}}_convertToJSON({{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}});

//{{projectName}}_{{classVarName}}_{{enumName}}_e {{classFilename}}_{{classname}}_parseFromJSON(cJSON *{{classname}}JSON);
{{projectName}}_{{classVarName}}_{{enumName}}_e {{classname}}_parseFromJSON(cJSON *{{classname}}JSON);

{{/isEnum}}
{{^isEnum}}
{{#vars}}
{{^isContainer}}
{{#isPrimitiveType}}
{{^isModel}}
{{#isEnum}}
// Enum {{enumName}} for {{classVarName}}
Expand All @@ -52,6 +53,7 @@ char* {{classFilename}}_{{name}}_ToString({{projectName}}_{{classVarName}}_{{enu

{{/isEnum}}
{{/isModel}}
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{#items}}
Expand Down Expand Up @@ -88,7 +90,12 @@ typedef struct {{classname}}_t {
{{/isModel}}
{{^isModel}}
{{^isFreeFormObject}}
{{^isEnum}}
{{datatype}}_t *{{name}}; // custom
{{/isEnum}}
{{#isEnum}}
{{projectName}}_{{dataType}}_{{enumName}}_e {{name}}; //referenced enum
{{/isEnum}}
{{/isFreeFormObject}}
{{/isModel}}
{{#isUuid}}
Expand Down Expand Up @@ -163,7 +170,12 @@ typedef struct {{classname}}_t {
{{/isModel}}
{{^isModel}}
{{^isFreeFormObject}}
{{^isEnum}}
{{datatype}}_t *{{name}}{{^-last}},{{/-last}}
{{/isEnum}}
{{#isEnum}}
{{projectName}}_{{dataType}}_{{enumName}}_e {{name}}{{^-last}},{{/-last}}
{{/isEnum}}
{{/isFreeFormObject}}
{{/isModel}}
{{#isUuid}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ include/binary.h
include/keyValuePair.h
include/list.h
libcurl.licence
model/any_type.h
model/api_response.c
model/api_response.h
model/category.c
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ set(HDRS
include/keyValuePair.h
external/cJSON.h
model/object.h
model/any_type.h
model/mapped_model.h
model/api_response.h
model/category.h
Expand Down
5 changes: 5 additions & 0 deletions samples/client/petstore/c-useJsonUnformatted/model/any_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* any_type.h
*
* A placeholder for now, this type isn't really needed.
*/
1 change: 1 addition & 0 deletions samples/client/petstore/c/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ include/binary.h
include/keyValuePair.h
include/list.h
libcurl.licence
model/any_type.h
model/api_response.c
model/api_response.h
model/category.c
Expand Down
5 changes: 5 additions & 0 deletions samples/client/petstore/c/model/any_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* any_type.h
*
* A placeholder for now, this type isn't really needed.
*/

0 comments on commit 47665aa

Please sign in to comment.