Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support generating Deprecated annotations and docs #1788

Merged
merged 1 commit into from
Oct 10, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.IJsonSchemaValidationProperties;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.VendorExtension;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.languages.AbstractJavaCodegen;
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
Expand Down Expand Up @@ -148,7 +149,6 @@ public abstract class AbstractMicronautJavaCodegen<T extends GeneratorOptionsBui
public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json";
public static final String CONTENT_TYPE_MULTIPART_FORM_DATA = "multipart/form-data";
public static final String CONTENT_TYPE_ANY = "*/*";
public static final String EXT_CONTENT_TYPE = "x-content-type";

private static final String MONO_CLASS_NAME = "reactor.core.publisher.Mono";
private static final String FLUX_CLASS_NAME = "reactor.core.publisher.Flux";
Expand Down Expand Up @@ -282,7 +282,6 @@ protected AbstractMicronautJavaCodegen() {

var generateSwaggerAnnotationsOption = new CliOption(OPT_GENERATE_SWAGGER_ANNOTATIONS, "Specify if you want to generate swagger annotations and which version").defaultValue(generateSwaggerAnnotations);
var generateSwaggerAnnotationsOptionMap = new HashMap<String, String>();
generateSwaggerAnnotationsOptionMap.put(OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_1, "Use io.swagger:swagger-annotations for annotating operations and schemas");
generateSwaggerAnnotationsOptionMap.put(OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2, "Use io.swagger.core.v3:swagger-annotations for annotating operations and schemas");
generateSwaggerAnnotationsOptionMap.put(OPT_GENERATE_SWAGGER_ANNOTATIONS_TRUE, "Equivalent to \"" + OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2 + "\"");
generateSwaggerAnnotationsOptionMap.put(OPT_GENERATE_SWAGGER_ANNOTATIONS_FALSE, "Do not generate swagger annotations");
Expand Down Expand Up @@ -560,9 +559,7 @@ public void processOpts() {
}

maybeSetSwagger();
if (OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_1.equals(generateSwaggerAnnotations)) {
additionalProperties.put("generateSwagger1Annotations", true);
} else if (OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2.equals(generateSwaggerAnnotations)) {
if (OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2.equals(generateSwaggerAnnotations)) {
additionalProperties.put("generateSwagger2Annotations", true);
}

Expand Down Expand Up @@ -677,8 +674,7 @@ private void maybeSetSwagger() {
if (additionalProperties.containsKey(OPT_GENERATE_SWAGGER_ANNOTATIONS)) {
String value = String.valueOf(additionalProperties.get(OPT_GENERATE_SWAGGER_ANNOTATIONS));
switch (value) {
case OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_1 -> generateSwaggerAnnotations = OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_1;
case OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2, OPT_GENERATE_SWAGGER_ANNOTATIONS_TRUE -> generateSwaggerAnnotations = OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2;
case OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_1, OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2, OPT_GENERATE_SWAGGER_ANNOTATIONS_TRUE -> generateSwaggerAnnotations = OPT_GENERATE_SWAGGER_ANNOTATIONS_SWAGGER_2;
case OPT_GENERATE_SWAGGER_ANNOTATIONS_FALSE -> generateSwaggerAnnotations = OPT_GENERATE_SWAGGER_ANNOTATIONS_FALSE;
default -> throw new RuntimeException("Value \"" + value + "\" for the " + OPT_GENERATE_SWAGGER_ANNOTATIONS + " parameter is unsupported or misspelled");
}
Expand Down Expand Up @@ -1314,8 +1310,8 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
}

// Remove the "*/*" contentType from operations as it is ambiguous
if (CONTENT_TYPE_ANY.equals(op.vendorExtensions.get(EXT_CONTENT_TYPE))) {
op.vendorExtensions.put(EXT_CONTENT_TYPE, CONTENT_TYPE_APPLICATION_JSON);
if (CONTENT_TYPE_ANY.equals(op.vendorExtensions.get(VendorExtension.X_CONTENT_TYPE.getName()))) {
op.vendorExtensions.put(VendorExtension.X_CONTENT_TYPE.getName(), CONTENT_TYPE_APPLICATION_JSON);
}
op.consumes = op.consumes == null ? null : op.consumes.stream()
.filter(contentType -> !CONTENT_TYPE_ANY.equals(contentType.get("mediaType")))
Expand All @@ -1340,14 +1336,14 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
// Force form parameters are only set if the content-type is according
// formParams correspond to urlencoded type
// bodyParams correspond to multipart body
if (CONTENT_TYPE_APPLICATION_FORM_URLENCODED.equals(op.vendorExtensions.get(EXT_CONTENT_TYPE))) {
if (CONTENT_TYPE_APPLICATION_FORM_URLENCODED.equals(op.vendorExtensions.get(VendorExtension.X_CONTENT_TYPE.getName()))) {
op.formParams.addAll(op.bodyParams);
op.bodyParams.forEach(p -> {
p.isBodyParam = false;
p.isFormParam = true;
});
op.bodyParams.clear();
} else if (CONTENT_TYPE_MULTIPART_FORM_DATA.equals(op.vendorExtensions.get(EXT_CONTENT_TYPE))) {
} else if (CONTENT_TYPE_MULTIPART_FORM_DATA.equals(op.vendorExtensions.get(VendorExtension.X_CONTENT_TYPE.getName()))) {
op.bodyParams.addAll(op.formParams);
for (var param : op.allParams) {
if (param.isFormParam) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.IJsonSchemaValidationProperties;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.VendorExtension;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.languages.AbstractKotlinCodegen;
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
Expand Down Expand Up @@ -156,7 +157,6 @@ public abstract class AbstractMicronautKotlinCodegen<T extends GeneratorOptionsB
public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json";
public static final String CONTENT_TYPE_MULTIPART_FORM_DATA = "multipart/form-data";
public static final String CONTENT_TYPE_ANY = "*/*";
public static final String EXT_CONTENT_TYPE = "x-content-type";

private static final String MONO_CLASS_NAME = "reactor.core.publisher.Mono";
private static final String FLUX_CLASS_NAME = "reactor.core.publisher.Flux";
Expand Down Expand Up @@ -933,21 +933,21 @@ public void preprocessOpenAPI(OpenAPI openApi) {

if (openApi.getPaths() != null) {
for (Map.Entry<String, PathItem> openAPIGetPathsEntry : openApi.getPaths().entrySet()) {
String pathname = openAPIGetPathsEntry.getKey();
PathItem path = openAPIGetPathsEntry.getValue();
if (path.readOperations() == null) {
var ops = path.readOperations();
if (ops == null || ops.isEmpty()) {
continue;
}
for (Operation operation : path.readOperations()) {
for (Operation operation : ops) {
log.info("Processing operation {}", operation.getOperationId());
if (hasBodyParameter(operation) || hasFormParameter(operation)) {
var defaultContentType = hasFormParameter(operation) ? CONTENT_TYPE_APPLICATION_FORM_URLENCODED : CONTENT_TYPE_APPLICATION_JSON;
var consumes = new ArrayList<>(getConsumesInfo(openApi, operation));
String contentType = consumes.isEmpty() ? defaultContentType : consumes.get(0);
operation.addExtension(EXT_CONTENT_TYPE, contentType);
operation.addExtension(VendorExtension.X_CONTENT_TYPE.getName(), contentType);
}
String[] accepts = getAccepts(openAPI, operation);
operation.addExtension("x-accepts", accepts);
String[] accepts = getAccepts(openApi, operation);
operation.addExtension(VendorExtension.X_ACCEPTS.getName(), accepts);
}
}
}
Expand Down Expand Up @@ -1011,8 +1011,8 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
}

// Remove the "*/*" contentType from operations as it is ambiguous
if (CONTENT_TYPE_ANY.equals(op.vendorExtensions.get(EXT_CONTENT_TYPE))) {
op.vendorExtensions.put(EXT_CONTENT_TYPE, CONTENT_TYPE_APPLICATION_JSON);
if (CONTENT_TYPE_ANY.equals(op.vendorExtensions.get(VendorExtension.X_CONTENT_TYPE.getName()))) {
op.vendorExtensions.put(VendorExtension.X_CONTENT_TYPE.getName(), CONTENT_TYPE_APPLICATION_JSON);
}
op.consumes = op.consumes == null ? null : op.consumes.stream()
.filter(contentType -> !CONTENT_TYPE_ANY.equals(contentType.get("mediaType")))
Expand All @@ -1037,14 +1037,14 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
// Force form parameters are only set if the content-type is according
// formParams correspond to urlencoded type
// bodyParams correspond to multipart body
if (CONTENT_TYPE_APPLICATION_FORM_URLENCODED.equals(op.vendorExtensions.get(EXT_CONTENT_TYPE))) {
if (CONTENT_TYPE_APPLICATION_FORM_URLENCODED.equals(op.vendorExtensions.get(VendorExtension.X_CONTENT_TYPE.getName()))) {
op.formParams.addAll(op.bodyParams);
op.bodyParams.forEach(p -> {
p.isBodyParam = false;
p.isFormParam = true;
});
op.bodyParams.clear();
} else if (CONTENT_TYPE_MULTIPART_FORM_DATA.equals(op.vendorExtensions.get(EXT_CONTENT_TYPE))) {
} else if (CONTENT_TYPE_MULTIPART_FORM_DATA.equals(op.vendorExtensions.get(VendorExtension.X_CONTENT_TYPE.getName()))) {
op.bodyParams.addAll(op.formParams);
for (var param : op.allParams) {
if (param.isFormParam) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private static String genericAnnotations(CodegenProperty prop, boolean isGenerat
}

if (StringUtils.isNotEmpty(prop.pattern) && !prop.isDate && !prop.isDateTime) {
if ("email".equals(type)) {
if (prop.isEmail) {
result.append("@Email(regexp = \"");
} else {
result.append("@Pattern(regexp = \"");
Expand Down Expand Up @@ -274,7 +274,7 @@ private static boolean isPrimitive(String type) {
}
return switch (type) {
case "array", "char", "character", "string", "boolean", "byte", "short", "int", "integer", "long", "uri", "url", "uuid", "email", "float",
"double", "number", "partial-time", "date", "date-time", "bigdecimal", "biginteger" -> true;
"double", "number", "partial-time", "date", "date-time", "bigdecimal", "decimal", "biginteger" -> true;
default -> false;
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ import java.util.Map;
import {{javaxPackage}}.validation.Valid;
import {{javaxPackage}}.validation.constraints.*;
{{/useBeanValidation}}
{{#generateSwagger1Annotations}}
import io.swagger.annotations.*;
{{/generateSwagger1Annotations}}
{{#generateSwagger2Annotations}}
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{#isDeprecated}}@Deprecated{{/isDeprecated}}
{{^isDate}}{{^isDateTime}}{{{vendorExtensions.typeWithEnumWithGenericAnnotations}}}{{/isDateTime}}{{/isDate}}
{{#isDateTime}}{{#vendorExtensions.formatPattern}}@Format("{{{vendorExtensions.formatPattern}}}"){{/vendorExtensions.formatPattern}}{{^vendorExtensions.formatPattern}}{{#dateTimeFormat}}@Format("{{{dateTimeFormat}}}"){{/dateTimeFormat}}{{/vendorExtensions.formatPattern}} {{{vendorExtensions.baseType}}} {{/isDateTime}}
{{#isDate}}{{#vendorExtensions.formatPattern}}@Format("{{{vendorExtensions.formatPattern}}}"){{/vendorExtensions.formatPattern}}{{^vendorExtensions.formatPattern}}{{#dateFormat}}@Format("{{{dateFormat}}}"){{/dateFormat}}{{/vendorExtensions.formatPattern}} {{{vendorExtensions.baseType}}} {{/isDate}}
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
/**
* {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{.}}}{{/description}}
{{#isDeprecated}}
*
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
{{/isDeprecated}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
{{#withXml}}
@XmlType(name="{{datatypeWithEnum}}")
@XmlEnum({{vendorExtensions.baseType}}.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ import io.micronaut.core.annotation.Nullable;
{{#generatedAnnotation}}
import {{javaxPackage}}.annotation.Generated;
{{/generatedAnnotation}}
{{#generateSwagger1Annotations}}
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
{{/generateSwagger1Annotations}}
{{#generateSwagger2Annotations}}
import io.swagger.v3.oas.annotations.media.Schema;
{{/generateSwagger2Annotations}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{{#formatNoEmptyLines}}
/**
* {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}}
{{#isDeprecated}}
*
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
{{/isDeprecated}}
*/
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
{{#description}}
{{#generateSwagger1Annotations}}
@ApiModel(description = "{{{description}}}")
{{/generateSwagger1Annotations}}
{{#generateSwagger2Annotations}}
@Schema({{#name}}name = "{{name}}", {{/name}}description = "{{{description}}}")
@Schema({{#name}}name = "{{name}}", {{/name}}description = "{{{description}}}"{{#isDeprecated}}, deprecated = true{{/isDeprecated}})
{{/generateSwagger2Annotations}}
{{/description}}
{{#lombok}}
Expand Down Expand Up @@ -87,8 +91,22 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE
{{#description}}
/**
* {{description}}
{{#deprecated}}
*
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
{{/deprecated}}
*/
{{/description}}
{{^description}}
{{#deprecated}}
/**
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
*/
{{/deprecated}}
{{/description}}
{{#deprecated}}
@Deprecated
{{/deprecated}}
{{>common/params/validation}}
{{#withXml}}
{{#isXmlAttribute}}
Expand All @@ -111,11 +129,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE
{{/isContainer}}
{{/isXmlAttribute}}
{{/withXml}}
{{#generateSwagger1Annotations}}
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
{{/generateSwagger1Annotations}}
{{#generateSwagger2Annotations}}
@Schema(name = "{{{baseName}}}"{{#isReadOnly}}, accessMode = Schema.AccessMode.READ_ONLY{{/isReadOnly}}{{#example}}, example = "{{{.}}}"{{/example}}{{#description}}, description = "{{{.}}}"{{/description}}, requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}})
@Schema(name = "{{{baseName}}}"{{#isReadOnly}}, accessMode = Schema.AccessMode.READ_ONLY{{/isReadOnly}}{{#example}}, example = "{{{.}}}"{{/example}}{{#description}}, description = "{{{.}}}"{{/description}}, requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}{{#deprecated}}, deprecated = true{{/deprecated}})
{{/generateSwagger2Annotations}}
{{#vendorExtensions.x-is-jackson-optional-nullable}}
{{!Unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}
Expand Down Expand Up @@ -195,10 +210,17 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE
*
{{/description}}
* @return the {{name}} property value
{{#deprecated}}
*
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
{{/deprecated}}
*/
{{#vendorExtensions.x-extra-annotation}}
{{{.}}}
{{/vendorExtensions.x-extra-annotation}}
{{#deprecated}}
@Deprecated
{{/deprecated}}
{{#isDiscriminator}}
{{#parent}}
@Override
Expand Down Expand Up @@ -233,10 +255,17 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE
*
{{/description}}
* @return the {{name}} property value wrapped in an optional
{{#deprecated}}
*
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
{{/deprecated}}
*/
{{#jackson}}
@JsonIgnore
{{/jackson}}
{{#deprecated}}
@Deprecated
{{/deprecated}}
public Optional<{{{vendorExtensions.typeWithEnumWithGenericAnnotations}}}> {{getter}}Optional() {
{{^vendorExtensions.x-is-jackson-optional-nullable}}
return Optional.ofNullable({{name}});
Expand All @@ -251,10 +280,19 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE
{{^vendorExtensions.lombok}}
/**
* Set the {{name}} property value
*
* @param {{name}} property value to set
{{#deprecated}}
*
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
{{/deprecated}}
*/
{{#vendorExtensions.x-setter-extra-annotation}}
{{{.}}}
{{/vendorExtensions.x-setter-extra-annotation}}
{{#deprecated}}
@Deprecated
{{/deprecated}}
public void {{setter}}({{{vendorExtensions.typeWithEnumWithGenericAnnotations}}} {{name}}) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}} = JsonNullable.<{{{vendorExtensions.typeWithEnumWithGenericAnnotations}}}>of({{name}});
Expand Down Expand Up @@ -288,7 +326,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE
* Set {{name}} in a chainable fashion.
*
* @return The same instance of {{classname}} for chaining.
{{#deprecated}}
*
* @deprecated{{#vendorExtensions.x-deprecated-message}} {{{.}}}{{/vendorExtensions.x-deprecated-message}}
{{/deprecated}}
*/
{{#deprecated}}
@Deprecated
{{/deprecated}}
public {{classname}} {{name}}({{{vendorExtensions.typeWithEnumWithGenericAnnotations}}} {{name}}) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}} = JsonNullable.<{{{vendorExtensions.typeWithEnumWithGenericAnnotations}}}>of({{name}});
Expand Down
Loading
Loading