Skip to content
Open
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 @@ -977,6 +977,16 @@ public void preprocessOpenAPI(OpenAPI openAPI) {

@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
// A model named `Tag` collides with io.swagger.v3.oas.annotations.tags.Tag. When this file
// imports the model, importing the annotation too is a duplicate single-type-import, which
// javac rejects outright. Reference the annotation by its fully qualified name instead and
// skip its import -- only for the files that actually hit the clash.
final String tagModelImport = modelPackage() + ".Tag";
if (objs.getImports() != null
&& objs.getImports().stream().anyMatch(imp -> tagModelImport.equals(imp.get("import")))) {
objs.put("qualifySwaggerTagAnnotation", true);
}

final OperationMap operations = objs.getOperations();
if (operations != null) {
final List<CodegenOperation> ops = operations.getOperation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
{{^qualifySwaggerTagAnnotation}}
import io.swagger.v3.oas.annotations.tags.Tag;
{{/qualifySwaggerTagAnnotation}}
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.ExampleObject;
{{/swagger2AnnotationLibrary}}
Expand Down Expand Up @@ -106,7 +108,7 @@ import {{javaxPackage}}.annotation.Generated;
{{/useResponseEntity}}
{{/useSpringController}}
{{#swagger2AnnotationLibrary}}
@Tag(name = "{{{tagName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{tagName}}} API"{{/tagDescription}})
{{#qualifySwaggerTagAnnotation}}@io.swagger.v3.oas.annotations.tags.Tag{{/qualifySwaggerTagAnnotation}}{{^qualifySwaggerTagAnnotation}}@Tag{{/qualifySwaggerTagAnnotation}}(name = "{{{tagName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{tagName}}} API"{{/tagDescription}})
{{/swagger2AnnotationLibrary}}
{{#swagger1AnnotationLibrary}}
@Api(value = "{{{tagName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{tagName}}} API"{{/tagDescription}})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
{{^qualifySwaggerTagAnnotation}}
import io.swagger.v3.oas.annotations.tags.Tag;
{{/qualifySwaggerTagAnnotation}}
{{/swagger2AnnotationLibrary}}
{{#swagger1AnnotationLibrary}}
import io.swagger.annotations.*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,35 @@ public void shouldGenerateExclusiveMinMaxForOAS31() throws IOException {
}


@Test
public void modelNamedTagDoesNotClashWithSwaggerTagAnnotation() throws IOException {
// A model named `Tag` collides with io.swagger.v3.oas.annotations.tags.Tag. Importing both
// is a duplicate single-type-import, which javac rejects outright, so the generated api
// must fall back to the fully qualified annotation name and skip the import.
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();

OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/3_0/spring/model-named-tag.yaml", null, new ParseOptions())
.getOpenAPI();
SpringCodegen codegen = new SpringCodegen();
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(INTERFACE_ONLY, "true");

ClientOptInput input = new ClientOptInput().openAPI(openAPI).config(codegen);
DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);

Map<String, File> files = generator.opts(input).generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));

Path api = files.get("TagApi.java").toPath();
assertFileNotContains(api, "import io.swagger.v3.oas.annotations.tags.Tag;");
assertFileContains(api, "@io.swagger.v3.oas.annotations.tags.Tag(name = \"pets\"");
// the model import must still be there -- that is the type actually used in signatures
assertFileContains(api, "import org.openapitools.model.Tag;");
}

@Test
public void shouldUseTagsForClassname() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
openapi: 3.0.3
info:
title: model named Tag
version: 1.0.0
tags:
- name: pets
paths:
/tag:
get:
tags:
- pets
operationId: getTag
responses:
"200":
description: ok
content:
application/json:
schema:
$ref: "#/components/schemas/Tag"
components:
schemas:
Tag:
properties:
id:
type: string