Skip to content
This repository was archived by the owner on Dec 4, 2025. It is now read-only.

Commit db189b9

Browse files
authored
Merge pull request #891 from linwumingshi/refactor/generic-javadoc-doc-template
enhance `IJavadocDocTemplate` with generics for method documentation
2 parents fc7b8fb + 985db45 commit db189b9

File tree

5 files changed

+110
-102
lines changed

5 files changed

+110
-102
lines changed

src/main/java/com/ly/doc/template/GRpcDocBuildTemplate.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
/*
2+
* Copyright (C) 2018-2024 smart-doc
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
121
package com.ly.doc.template;
222

323
import com.google.gson.Gson;
@@ -36,8 +56,9 @@
3656
* gRPC Doc build template.
3757
*
3858
* @author linwumingshi
59+
* @since 3.0.7
3960
*/
40-
public class GRpcDocBuildTemplate implements IDocBuildTemplate<GrpcApiDoc>, IRpcDocTemplate {
61+
public class GRpcDocBuildTemplate implements IDocBuildTemplate<GrpcApiDoc>, IJavadocDocTemplate<GrpcJavaMethod> {
4162

4263
/**
4364
* Logger for the class.
@@ -69,6 +90,11 @@ public boolean addMethodModifiers() {
6990
return false;
7091
}
7192

93+
@Override
94+
public GrpcJavaMethod createEmptyJavadocJavaMethod() {
95+
return new GrpcJavaMethod();
96+
}
97+
7298
@Override
7399
public boolean ignoreReturnObject(String typeName, List<String> ignoreParams) {
74100
return false;

src/main/java/com/ly/doc/template/IJavadocDocTemplate.java

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -39,25 +39,37 @@
3939
import static com.ly.doc.constants.DocTags.DEPRECATED;
4040
import static com.ly.doc.constants.DocTags.IGNORE;
4141

42-
public interface IJavadocDocTemplate extends IBaseDocBuildTemplate {
42+
/**
43+
* java doc template
44+
*
45+
* @param <T> extends JavadocJavaMethod
46+
* @author shalousun
47+
* @since 3.0.5
48+
*/
49+
public interface IJavadocDocTemplate<T extends JavadocJavaMethod> extends IBaseDocBuildTemplate {
4350

4451
/**
4552
* Add method modifiers
4653
* @return boolean
4754
*/
4855
boolean addMethodModifiers();
4956

57+
/**
58+
* Create empty JavadocJavaMethod.
59+
* @return empty JavadocJavaMethod
60+
*/
61+
T createEmptyJavadocJavaMethod();
62+
5063
/**
5164
* Convert JavaMethod to JavadocJavaMethod
5265
* @param apiConfig ApiConfig
5366
* @param method JavaMethod
5467
* @param actualTypesMap Map
5568
* @return JavadocJavaMethod
5669
*/
57-
default JavadocJavaMethod convertToJavadocJavaMethod(ApiConfig apiConfig, JavaMethod method,
58-
Map<String, JavaType> actualTypesMap) {
70+
default T convertToJavadocJavaMethod(ApiConfig apiConfig, JavaMethod method, Map<String, JavaType> actualTypesMap) {
5971
JavaClass cls = method.getDeclaringClass();
60-
JavadocJavaMethod javadocJavaMethod = new JavadocJavaMethod();
72+
T javadocJavaMethod = this.createEmptyJavadocJavaMethod();
6173
javadocJavaMethod.setJavaMethod(method);
6274
javadocJavaMethod.setName(method.getName());
6375
javadocJavaMethod.setActualTypesMap(actualTypesMap);
@@ -108,7 +120,7 @@ default String methodDefinition(JavaMethod method, Map<String, JavaType> actualT
108120
// append method modifiers
109121
method.getModifiers().forEach(item -> methodBuilder.append(item).append(" "));
110122
}
111-
String returnType = getMethodReturnType(method, actualTypesMap);
123+
String returnType = this.getMethodReturnType(method, actualTypesMap);
112124
// append method return type
113125
methodBuilder.append(returnType).append(" ");
114126
List<String> params = new ArrayList<>();
@@ -122,47 +134,54 @@ default String methodDefinition(JavaMethod method, Map<String, JavaType> actualT
122134
}
123135

124136
/**
125-
* Get parent class methods
126-
* @param apiConfig ApiConfig
137+
* Processes methods of a given class and its parent or interfaces.
127138
* @param cls JavaClass
128-
* @return List
139+
* @param methodProcessor Function to process methods from a class
140+
* @return List of documented Java methods
129141
*/
130-
default List<? extends JavadocJavaMethod> getParentsClassMethods(ApiConfig apiConfig, JavaClass cls) {
131-
List<JavadocJavaMethod> docJavaMethods = new ArrayList<>();
132-
JavaClass parentClass = cls.getSuperJavaClass();
133-
// if parent class is not null and not Object
134-
if (Objects.nonNull(parentClass) && !JavaTypeConstants.OBJECT_SIMPLE_NAME.equals(parentClass.getSimpleName())) {
135-
Map<String, JavaType> actualTypesMap = JavaClassUtil.getActualTypesMap(parentClass);
136-
List<JavaMethod> parentMethodList = parentClass.getMethods();
137-
for (JavaMethod method : parentMethodList) {
138-
docJavaMethods.add(this.convertToJavadocJavaMethod(apiConfig, method, actualTypesMap));
142+
default List<T> processClassHierarchy(JavaClass cls, Function<JavaClass, List<T>> methodProcessor) {
143+
List<T> docJavaMethods = new ArrayList<>();
144+
Set<JavaClass> classesToProcess = new LinkedHashSet<>();
145+
classesToProcess.add(cls);
146+
147+
while (!classesToProcess.isEmpty()) {
148+
JavaClass currentClass = classesToProcess.iterator().next();
149+
classesToProcess.remove(currentClass);
150+
151+
// Process methods
152+
docJavaMethods.addAll(methodProcessor.apply(currentClass));
153+
154+
// Add parent class if not Object
155+
JavaClass parentClass = currentClass.getSuperJavaClass();
156+
if (Objects.nonNull(parentClass)
157+
&& !JavaTypeConstants.OBJECT_SIMPLE_NAME.equals(parentClass.getSimpleName())) {
158+
classesToProcess.add(parentClass);
139159
}
140-
// add interface methods
141-
docJavaMethods.addAll(this.getInterfaceMethods(apiConfig, parentClass));
142-
// add parent class methods
143-
docJavaMethods.addAll(this.getParentsClassMethods(apiConfig, parentClass));
160+
161+
// Add interfaces
162+
classesToProcess.addAll(currentClass.getInterfaces());
144163
}
164+
145165
return docJavaMethods;
146166
}
147167

148168
/**
149-
* Get interface methods
169+
* Get parent class and interface methods
150170
* @param apiConfig ApiConfig
151171
* @param cls JavaClass
152172
* @return List
153173
*/
154-
default List<? extends JavadocJavaMethod> getInterfaceMethods(ApiConfig apiConfig, JavaClass cls) {
155-
List<JavadocJavaMethod> docJavaMethods = new ArrayList<>();
156-
for (JavaClass javaInterface : cls.getInterfaces()) {
157-
Map<String, JavaType> actualTypesMap = JavaClassUtil.getActualTypesMap(javaInterface);
158-
List<JavaMethod> interfaceMethodList = javaInterface.getMethods();
159-
for (JavaMethod method : interfaceMethodList) {
174+
default List<T> getParentsClassAndInterfaceMethods(ApiConfig apiConfig, JavaClass cls) {
175+
return this.processClassHierarchy(cls, currentClass -> {
176+
List<T> docJavaMethods = new ArrayList<>();
177+
Map<String, JavaType> actualTypesMap = JavaClassUtil.getActualTypesMap(currentClass);
178+
List<JavaMethod> methodList = currentClass.getMethods();
179+
for (JavaMethod method : methodList) {
160180
docJavaMethods.add(this.convertToJavadocJavaMethod(apiConfig, method, actualTypesMap));
161181
}
162-
// add interface methods
163-
docJavaMethods.addAll(this.getInterfaceMethods(apiConfig, javaInterface));
164-
}
165-
return docJavaMethods;
182+
return docJavaMethods;
183+
});
184+
166185
}
167186

168187
/**
@@ -301,11 +320,11 @@ else if (javaClass.isEnum()) {
301320
* @return A list containing documented methods represented as JavadocJavaMethod
302321
* objects.
303322
*/
304-
default List<? extends JavadocJavaMethod> buildServiceMethod(final JavaClass cls, ApiConfig apiConfig,
323+
default List<T> buildServiceMethod(final JavaClass cls, ApiConfig apiConfig,
305324
ProjectDocConfigBuilder projectBuilder) {
306325
String clsCanonicalName = cls.getCanonicalName();
307326
List<JavaMethod> methods = cls.getMethods();
308-
List<JavadocJavaMethod> methodDocList = new ArrayList<>(methods.size());
327+
List<T> methodDocList = new ArrayList<>(methods.size());
309328

310329
Set<String> filterMethods = DocUtil.findFilterMethods(clsCanonicalName);
311330
boolean needAllMethods = filterMethods.contains(DocGlobalConstants.DEFAULT_FILTER_METHOD);
@@ -322,21 +341,19 @@ default List<? extends JavadocJavaMethod> buildServiceMethod(final JavaClass cls
322341
"Unable to find comment for method " + method.getName() + " in " + cls.getCanonicalName());
323342
}
324343
if (needAllMethods || filterMethods.contains(method.getName())) {
325-
JavadocJavaMethod apiMethodDoc = this.convertToJavadocJavaMethod(apiConfig, method, null);
344+
T apiMethodDoc = this.convertToJavadocJavaMethod(apiConfig, method, null);
326345
methodDocList.add(apiMethodDoc);
327346
}
328347

329348
}
330-
// Add parent class methods
331-
methodDocList.addAll(this.getParentsClassMethods(apiConfig, cls));
332-
// Add interface methods
333-
methodDocList.addAll(this.getInterfaceMethods(apiConfig, cls));
349+
// Add parent class And interface methods
350+
methodDocList.addAll(this.getParentsClassAndInterfaceMethods(apiConfig, cls));
334351

335-
Map<JavadocJavaMethod, List<ApiParam>> methodRequestParams = new HashMap<>(16);
336-
Map<JavadocJavaMethod, List<ApiParam>> methodResponseParams = new HashMap<>(16);
352+
Map<T, List<ApiParam>> methodRequestParams = new HashMap<>(16);
353+
Map<T, List<ApiParam>> methodResponseParams = new HashMap<>(16);
337354

338355
// Construct the method map
339-
Map<String, JavadocJavaMethod> methodMap = methodDocList.stream().collect(Collectors.toMap(method -> {
356+
Map<String, T> methodMap = methodDocList.stream().collect(Collectors.toMap(method -> {
340357
// Build request params
341358
List<ApiParam> requestParams = this.requestParams(method.getJavaMethod(), projectBuilder,
342359
new AtomicInteger(0), method.getActualTypesMap());
@@ -357,8 +374,8 @@ default List<? extends JavadocJavaMethod> buildServiceMethod(final JavaClass cls
357374
Function.identity(), this::mergeJavadocMethods, LinkedHashMap::new));
358375

359376
int methodOrder = 0;
360-
List<JavadocJavaMethod> javadocJavaMethods = new ArrayList<>(methodMap.values().size());
361-
for (JavadocJavaMethod method : methodMap.values()) {
377+
List<T> javadocJavaMethods = new ArrayList<>(methodMap.values().size());
378+
for (T method : methodMap.values()) {
362379
methodOrder++;
363380
method.setOrder(methodOrder);
364381
String methodUid = DocUtil.generateId(clsCanonicalName + method.getName() + methodOrder);
@@ -389,7 +406,7 @@ default List<? extends JavadocJavaMethod> buildServiceMethod(final JavaClass cls
389406
* @return The merged JavadocJavaMethod object, with details filled in from the
390407
* replacement method if necessary.
391408
*/
392-
default JavadocJavaMethod mergeJavadocMethods(JavadocJavaMethod existing, JavadocJavaMethod replacement) {
409+
default T mergeJavadocMethods(T existing, T replacement) {
393410
// if existing info is empty and replacement info has desc,replace the info
394411
if (StringUtil.isEmpty(existing.getDesc()) && StringUtil.isNotEmpty(replacement.getDesc())) {
395412
existing.setDesc(replacement.getDesc());

src/main/java/com/ly/doc/template/IRpcDocTemplate.java

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/main/java/com/ly/doc/template/JavadocDocBuildTemplate.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ public boolean addMethodModifiers() {
6565
return true;
6666
}
6767

68+
@Override
69+
public JavadocJavaMethod createEmptyJavadocJavaMethod() {
70+
return new JavadocJavaMethod();
71+
}
72+
6873
@Override
6974
@SuppressWarnings("unchecked")
7075
public ApiSchema<JavadocApiDoc> renderApi(ProjectDocConfigBuilder projectBuilder,

src/main/java/com/ly/doc/template/RpcDocBuildTemplate.java

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,20 @@
2424
import com.ly.doc.constants.DocTags;
2525
import com.ly.doc.constants.DubboAnnotationConstants;
2626
import com.ly.doc.constants.FrameworkEnum;
27-
import com.ly.doc.model.*;
27+
import com.ly.doc.model.ApiConfig;
28+
import com.ly.doc.model.ApiSchema;
29+
import com.ly.doc.model.RpcJavaMethod;
30+
import com.ly.doc.model.WebSocketDoc;
2831
import com.ly.doc.model.annotation.FrameworkAnnotations;
2932
import com.ly.doc.model.rpc.RpcApiDoc;
3033
import com.ly.doc.utils.DocUtil;
3134
import com.ly.doc.utils.JavaClassUtil;
3235
import com.power.common.util.StringUtil;
3336
import com.power.common.util.ValidateUtil;
34-
import com.thoughtworks.qdox.model.*;
37+
import com.thoughtworks.qdox.model.DocletTag;
38+
import com.thoughtworks.qdox.model.JavaAnnotation;
39+
import com.thoughtworks.qdox.model.JavaClass;
40+
import com.thoughtworks.qdox.model.JavaType;
3541
import com.thoughtworks.qdox.model.expression.AnnotationValue;
3642

3743
import java.util.*;
@@ -43,8 +49,8 @@
4349
*
4450
* @author yu 2020/1/29.
4551
*/
46-
public class RpcDocBuildTemplate
47-
implements IDocBuildTemplate<RpcApiDoc>, IWebSocketDocBuildTemplate<WebSocketDoc>, IRpcDocTemplate {
52+
public class RpcDocBuildTemplate implements IDocBuildTemplate<RpcApiDoc>, IWebSocketDocBuildTemplate<WebSocketDoc>,
53+
IJavadocDocTemplate<RpcJavaMethod> {
4854

4955
/**
5056
* api index
@@ -62,7 +68,11 @@ public boolean addMethodModifiers() {
6268
}
6369

6470
@Override
65-
@SuppressWarnings("unchecked")
71+
public RpcJavaMethod createEmptyJavadocJavaMethod() {
72+
return new RpcJavaMethod();
73+
}
74+
75+
@Override
6676
public ApiSchema<RpcApiDoc> renderApi(ProjectDocConfigBuilder projectBuilder,
6777
Collection<JavaClass> candidateClasses) {
6878
ApiConfig apiConfig = projectBuilder.getApiConfig();
@@ -81,8 +91,7 @@ public ApiSchema<RpcApiDoc> renderApi(ProjectDocConfigBuilder projectBuilder,
8191
setCustomOrder = true;
8292
maxOrder = Math.max(maxOrder, order);
8393
}
84-
List<RpcJavaMethod> apiMethodDocs = (List<RpcJavaMethod>) this.buildServiceMethod(cls, apiConfig,
85-
projectBuilder);
94+
List<RpcJavaMethod> apiMethodDocs = this.buildServiceMethod(cls, apiConfig, projectBuilder);
8695
this.handleJavaApiDoc(cls, apiDocList, apiMethodDocs, order, projectBuilder);
8796
}
8897
ApiSchema<RpcApiDoc> apiSchema = new ApiSchema<>();
@@ -222,25 +231,4 @@ private void handleJavaApiDoc(JavaClass cls, List<RpcApiDoc> apiDocList, List<Rp
222231
apiDocList.add(apiDoc);
223232
}
224233

225-
@Override
226-
public JavadocJavaMethod convertToJavadocJavaMethod(ApiConfig apiConfig, JavaMethod method,
227-
Map<String, JavaType> actualTypesMap) {
228-
JavadocJavaMethod javaMethod = IRpcDocTemplate.super.convertToJavadocJavaMethod(apiConfig, method,
229-
actualTypesMap);
230-
return new RpcJavaMethod().setDetail(javaMethod.getDetail())
231-
.setAuthor(javaMethod.getAuthor())
232-
.setMethodDefinition(javaMethod.getMethodDefinition())
233-
.setOrder(javaMethod.getOrder())
234-
.setRequestParams(javaMethod.getRequestParams())
235-
.setResponseParams(javaMethod.getResponseParams())
236-
.setDeprecated((javaMethod.isDeprecated()))
237-
.setVersion((javaMethod.getVersion()))
238-
.setActualTypesMap(javaMethod.getActualTypesMap())
239-
.setName(javaMethod.getName())
240-
.setEscapeMethodDefinition(javaMethod.getEscapeMethodDefinition())
241-
.setMethodId(javaMethod.getMethodId())
242-
.setJavaMethod(javaMethod.getJavaMethod())
243-
.setReturnClassInfo(javaMethod.getReturnClassInfo());
244-
}
245-
246234
}

0 commit comments

Comments
 (0)