Skip to content

Commit 3726d6a

Browse files
authored
Merge pull request #2136 from uc4w6c/fix_javadoc_for_record_class_v2
Fixed a bug that javadoc of record class parameters was not recognize…
2 parents da6a42f + d25f9dd commit 3726d6a

File tree

9 files changed

+228
-18
lines changed

9 files changed

+228
-18
lines changed

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/JavadocPropertyCustomizer.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* *
44
* * *
55
* * * *
6-
* * * * * Copyright 2019-2022 the original author or authors.
6+
* * * * * Copyright 2019-2023 the original author or authors.
77
* * * * *
88
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
99
* * * * * you may not use this file except in compliance with the License.
@@ -105,7 +105,16 @@ private void setJavadocDescription(Class<?> cls, List<Field> fields, Schema exis
105105
existingSchema.setDescription(javadocProvider.getClassJavadoc(cls));
106106
}
107107
Map<String, Schema> properties = existingSchema.getProperties();
108-
if (!CollectionUtils.isEmpty(properties))
108+
if (!CollectionUtils.isEmpty(properties)) {
109+
if (cls.getSuperclass() != null && cls.isRecord()) {
110+
Map<String, String> recordParamMap = javadocProvider.getRecordClassParamJavadoc(cls);
111+
properties.entrySet().stream()
112+
.filter(stringSchemaEntry -> StringUtils.isBlank(stringSchemaEntry.getValue().getDescription()))
113+
.forEach(stringSchemaEntry -> {
114+
if (recordParamMap.containsKey(stringSchemaEntry.getKey()))
115+
stringSchemaEntry.getValue().setDescription(recordParamMap.get(stringSchemaEntry.getKey()));
116+
});
117+
}
109118
properties.entrySet().stream()
110119
.filter(stringSchemaEntry -> StringUtils.isBlank(stringSchemaEntry.getValue().getDescription()))
111120
.forEach(stringSchemaEntry -> {
@@ -116,7 +125,7 @@ private void setJavadocDescription(Class<?> cls, List<Field> fields, Schema exis
116125
stringSchemaEntry.getValue().setDescription(fieldJavadoc);
117126
});
118127
});
119-
128+
}
120129
}
121130
}
122131
}

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/providers/JavadocProvider.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* *
44
* * *
55
* * * *
6-
* * * * * Copyright 2019-2022 the original author or authors.
6+
* * * * * Copyright 2019-2023 the original author or authors.
77
* * * * *
88
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
99
* * * * * you may not use this file except in compliance with the License.
@@ -42,6 +42,14 @@ public interface JavadocProvider {
4242
*/
4343
String getClassJavadoc(Class<?> cl);
4444

45+
/**
46+
* Gets param descripton of record class.
47+
*
48+
* @param cl the class
49+
* @return map of field and param descriptions
50+
*/
51+
Map<String, String> getRecordClassParamJavadoc(Class<?> cl);
52+
4553
/**
4654
* Gets method description.
4755
*
@@ -91,4 +99,3 @@ public interface JavadocProvider {
9199
*/
92100
String getFirstSentence(String text);
93101
}
94-

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/providers/SpringDocJavadocProvider.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* *
44
* * *
55
* * * *
6-
* * * * * Copyright 2019-2022 the original author or authors.
6+
* * * * * Copyright 2019-2023 the original author or authors.
77
* * * * *
88
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
99
* * * * * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
2828
import java.lang.reflect.Method;
2929
import java.util.List;
3030
import java.util.Map;
31+
import java.util.stream.Collectors;
3132

3233
import com.github.therapi.runtimejavadoc.ClassJavadoc;
3334
import com.github.therapi.runtimejavadoc.CommentFormatter;
@@ -65,6 +66,19 @@ public String getClassJavadoc(Class<?> cl) {
6566
return formatter.format(classJavadoc.getComment());
6667
}
6768

69+
/**
70+
* Gets param descripton of record class.
71+
*
72+
* @param cl the class
73+
* @return map of field and param descriptions
74+
*/
75+
@Override
76+
public Map<String, String> getRecordClassParamJavadoc(Class<?> cl) {
77+
ClassJavadoc classJavadoc = RuntimeJavadoc.getJavadoc(cl);
78+
return classJavadoc.getRecordComponents().stream()
79+
.collect(Collectors.toMap(ParamJavadoc::getName, record -> formatter.format(record.getComment())));
80+
}
81+
6882
/**
6983
* Gets method javadoc description.
7084
*

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericParameterService.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque
364364
Type type = ReturnTypeParser.getType(methodParameter);
365365
if (type instanceof Class && !((Class<?>) type).isEnum() && optionalWebConversionServiceProvider.isPresent()) {
366366
WebConversionServiceProvider webConversionServiceProvider = optionalWebConversionServiceProvider.get();
367-
if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && methodParameter.getParameterType().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) == null){
367+
if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && methodParameter.getParameterType().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) == null) {
368368
Class<?> springConvertedType = webConversionServiceProvider.getSpringConvertedType(methodParameter.getParameterType());
369369
if (!(String.class.equals(springConvertedType) && ((Class<?>) type).isEnum()))
370370
type = springConvertedType;
@@ -727,17 +727,28 @@ public boolean isRequestBodyPresent(ParameterInfo parameterInfo) {
727727
String getParamJavadoc(JavadocProvider javadocProvider, MethodParameter methodParameter) {
728728
String pName = methodParameter.getParameterName();
729729
DelegatingMethodParameter delegatingMethodParameter = (DelegatingMethodParameter) methodParameter;
730-
final String paramJavadocDescription;
731-
if (delegatingMethodParameter.isParameterObject()) {
732-
String fieldName;
733-
if (StringUtils.isNotEmpty(pName) && pName.contains(DOT))
734-
fieldName = StringUtils.substringAfterLast(pName, DOT);
735-
else fieldName = pName;
736-
Field field = FieldUtils.getDeclaredField(((DelegatingMethodParameter) methodParameter).getExecutable().getDeclaringClass(), fieldName, true);
737-
paramJavadocDescription = javadocProvider.getFieldJavadoc(field);
730+
if (!delegatingMethodParameter.isParameterObject()) {
731+
return javadocProvider.getParamJavadoc(methodParameter.getMethod(), pName);
732+
}
733+
String fieldName;
734+
if (StringUtils.isNotEmpty(pName) && pName.contains(DOT))
735+
fieldName = StringUtils.substringAfterLast(pName, DOT);
736+
else fieldName = pName;
737+
738+
String paramJavadocDescription = null;
739+
Class cls = ((DelegatingMethodParameter) methodParameter).getExecutable().getDeclaringClass();
740+
if (cls.getSuperclass() != null && cls.isRecord()) {
741+
Map<String, String> recordParamMap = javadocProvider.getRecordClassParamJavadoc(cls);
742+
if (recordParamMap.containsKey(fieldName)) {
743+
paramJavadocDescription = recordParamMap.get(fieldName);
744+
}
745+
}
746+
747+
Field field = FieldUtils.getDeclaredField(cls, fieldName, true);
748+
String fieldJavadoc = javadocProvider.getFieldJavadoc(field);
749+
if (StringUtils.isNotBlank(fieldJavadoc)) {
750+
paramJavadocDescription = fieldJavadoc;
738751
}
739-
else
740-
paramJavadocDescription = javadocProvider.getParamJavadoc(methodParameter.getMethod(), pName);
741752
return paramJavadocDescription;
742753
}
743-
}
754+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package test.org.springdoc.api.app169;
2+
3+
import org.springdoc.core.annotations.ParameterObject;
4+
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
@RestController
10+
@RequestMapping("record")
11+
public class RecordController {
12+
@GetMapping
13+
public SimpleOuterClass index(@ParameterObject SimpleOuterClass filter) {
14+
return null;
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package test.org.springdoc.api.app169;
2+
3+
/**
4+
* simple inner class
5+
*
6+
* @param name the boolean name
7+
* @param maxNumber the max number
8+
*/
9+
public record SimpleInnerClass(Boolean name, Integer maxNumber) {
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package test.org.springdoc.api.app169;
2+
3+
/**
4+
* simple outer class
5+
*
6+
* @param name the name of the outer class
7+
* @param simpleInnerClass the inner class
8+
*/
9+
public record SimpleOuterClass(String name, SimpleInnerClass simpleInnerClass) {
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
*
3+
* * Copyright 2019-2023 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app169;
20+
21+
import test.org.springdoc.api.AbstractSpringDocTest;
22+
23+
import org.springframework.boot.autoconfigure.SpringBootApplication;
24+
25+
/**
26+
* The type Spring doc app 169 test.
27+
*/
28+
public class SpringDocApp169Test extends AbstractSpringDocTest {
29+
30+
/**
31+
* The type Spring doc test app.
32+
*/
33+
@SpringBootApplication
34+
static class SpringDocTestApp {
35+
}
36+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"openapi": "3.0.1",
3+
"info": {
4+
"title": "OpenAPI definition",
5+
"version": "v0"
6+
},
7+
"servers": [
8+
{
9+
"url": "http://localhost",
10+
"description": "Generated server url"
11+
}
12+
],
13+
"paths": {
14+
"/record": {
15+
"get": {
16+
"tags": [
17+
"record-controller"
18+
],
19+
"operationId": "index",
20+
"parameters": [
21+
{
22+
"name": "name",
23+
"in": "query",
24+
"description": "the name of the outer class",
25+
"required": false,
26+
"schema": {
27+
"type": "string"
28+
}
29+
},
30+
{
31+
"name": "simpleInnerClass.name",
32+
"in": "query",
33+
"description": "the boolean name",
34+
"required": false,
35+
"schema": {
36+
"type": "boolean"
37+
}
38+
},
39+
{
40+
"name": "simpleInnerClass.maxNumber",
41+
"in": "query",
42+
"description": "the max number",
43+
"required": false,
44+
"schema": {
45+
"type": "integer",
46+
"format": "int32"
47+
}
48+
}
49+
],
50+
"responses": {
51+
"200": {
52+
"description": "OK",
53+
"content": {
54+
"*/*": {
55+
"schema": {
56+
"$ref": "#/components/schemas/SimpleOuterClass"
57+
}
58+
}
59+
}
60+
}
61+
}
62+
}
63+
}
64+
},
65+
"components": {
66+
"schemas": {
67+
"SimpleInnerClass": {
68+
"type": "object",
69+
"properties": {
70+
"name": {
71+
"type": "boolean",
72+
"description": "the boolean name"
73+
},
74+
"maxNumber": {
75+
"type": "integer",
76+
"description": "the max number",
77+
"format": "int32"
78+
}
79+
},
80+
"description": "simple inner class"
81+
},
82+
"SimpleOuterClass": {
83+
"type": "object",
84+
"properties": {
85+
"name": {
86+
"type": "string",
87+
"description": "the name of the outer class"
88+
},
89+
"simpleInnerClass": {
90+
"$ref": "#/components/schemas/SimpleInnerClass"
91+
}
92+
},
93+
"description": "simple outer class"
94+
}
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)