Skip to content

Commit

Permalink
Merge pull request #968 from linwumingshi/refactor/request-example-ge…
Browse files Browse the repository at this point in the history
…neration

refactor: improve request example generation for API documentation
  • Loading branch information
shalousun authored Nov 27, 2024
2 parents 29678d3 + 3f57e89 commit fe0532f
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 132 deletions.
41 changes: 1 addition & 40 deletions .github/workflows/build-and-run-example-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -337,43 +337,4 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: error-log-${{ runner.os }}-grpc-api-doc
path: logs

write-comment:
if: ${{ always() }}
name: write comment to pr
needs: [build, maven-plugin-build, generate-api-docs, generate-grpc-api-doc]
runs-on: ubuntu-latest
permissions:
pull-requests: write
timeout-minutes: 5
steps:
- name: Set status message
id: set-status
run: |
job_status=""
# Set the job status message
if [ ${{ needs.build.result }} == 'success' ] && [ ${{ needs.maven-plugin-build.result }} == 'success' ] && [ ${{ needs.generate-api-docs.result }} == 'success' ] && [ ${{ needs.generate-grpc-api-doc.result }} == 'success' ]; then
job_status=":green_heart: All jobs completed successfully! :tada:"
else
job_status=":x: Some jobs failed. Please check the details."
fi
echo "job_status=$job_status" >> $GITHUB_ENV
- name: Comment on the pull request
uses: peter-evans/create-or-update-comment@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
issue-number: ${{ github.event.number }}
body: |
Pull requests [#${{ github.event.number }}](https://github.com/${{ github.repository }}/pull/${{ github.event.number }}) report:
${{ env.job_status }}
[DETAILS](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- ${{ needs.build.result == 'success' && '✅' || '❌' }} - build: ${{ needs.build.result }}
- ${{ needs.maven-plugin-build.result == 'success' && '✅' || '❌' }} - maven-plugin-build: ${{ needs.maven-plugin-build.result }}
- ${{ needs.generate-api-docs.result == 'success' && '✅' || '❌' }} - generate-api-docs(rest, dubbo, javadoc, websocket): ${{ needs.generate-api-docs.result }}
- ${{ needs.generate-grpc-api-doc.result == 'success' && '✅' || '❌' }} - generate-grpc-api-doc(ubuntu-latest, macos-latest, windows-latest): ${{ needs.generate-grpc-api-doc.result }}
path: logs
10 changes: 7 additions & 3 deletions src/main/java/com/ly/doc/model/request/ApiRequestExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
*/
package com.ly.doc.model.request;

import java.util.List;

import com.ly.doc.model.FormData;
import com.power.common.util.StringUtil;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* @author yu 2019/12/22.
*/
Expand Down Expand Up @@ -88,6 +89,9 @@ public ApiRequestExample setUrl(String url) {
}

public List<FormData> getFormDataList() {
if (Objects.isNull(formDataList)) {
return new ArrayList<>();
}
return formDataList;
}

Expand Down
30 changes: 18 additions & 12 deletions src/main/java/com/ly/doc/template/IRestDocTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -1341,12 +1341,14 @@ default ApiRequestExample buildReqJson(DocJavaMethod javaMethod, ApiMethodDoc ap
apiMethodDoc.getPathParams()
.stream()
.filter(Objects::nonNull)
.filter(p -> StringUtil.isNotEmpty(p.getValue()) || p.isConfigParam())
// filter out null value params Fix String Param value is ""
.filter(p -> Objects.nonNull(p.getValue()) || p.isConfigParam())
.forEach(param -> pathParamsMap.put(param.getSourceField(), param.getValue()));
apiMethodDoc.getQueryParams()
.stream()
.filter(Objects::nonNull)
.filter(p -> StringUtil.isNotEmpty(p.getValue()) || p.isConfigParam())
// filter out null value params Fix String Param value is ""
.filter(param -> Objects.nonNull(param.getValue()) || param.isConfigParam())
.forEach(param -> queryParamsMap.put(param.getSourceField(), param.getValue()));
List<JavaAnnotation> methodAnnotations = method.getAnnotations();
Map<String, MappingAnnotation> mappingAnnotationMap = frameworkAnnotations.getMappingAnnotations();
Expand All @@ -1360,18 +1362,20 @@ default ApiRequestExample buildReqJson(DocJavaMethod javaMethod, ApiMethodDoc ap
}
String params = StringUtil.removeQuotes(paramsObjects.toString());
if (!params.startsWith("[")) {
mappingParamProcess(paramsObjects.toString(), queryParamsMap);
this.mappingParamProcess(paramsObjects.toString(), queryParamsMap);
continue;
}
@SuppressWarnings("unchecked")
List<String> headers = (LinkedList<String>) paramsObjects;
for (String str : headers) {
mappingParamProcess(str, queryParamsMap);
this.mappingParamProcess(str, queryParamsMap);
}
}
}
List<DocJavaParameter> parameterList = getJavaParameterList(configBuilder, javaMethod, frameworkAnnotations);
List<DocJavaParameter> parameterList = this.getJavaParameterList(configBuilder, javaMethod,
frameworkAnnotations);
List<ApiReqParam> reqHeaderList = apiMethodDoc.getRequestHeaders();
// if no parameter, return curl request
if (parameterList.isEmpty()) {
String path = apiMethodDoc.getPath().split(";")[0];
path = DocUtil.formatAndRemove(path, pathParamsMap);
Expand Down Expand Up @@ -1430,7 +1434,8 @@ default ApiRequestExample buildReqJson(DocJavaMethod javaMethod, ApiMethodDoc ap
if (Objects.nonNull(annotationDefaultVal)) {
mockValue = DocUtil.resolveAnnotationValue(classLoader, annotationDefaultVal);
}
paramName = getParamName(classLoader, paramName, annotation);
paramName = this.getParamName(classLoader, paramName, annotation);
// RequestBody annotation
if (frameworkAnnotations.getRequestBodyAnnotation().getAnnotationName().equals(annotationName)) {
// priority use mapping annotation's consumer value
if (apiMethodDoc.getContentType().equals(MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
Expand Down Expand Up @@ -1463,6 +1468,7 @@ default ApiRequestExample buildReqJson(DocJavaMethod javaMethod, ApiMethodDoc ap
queryParamsMap.remove(paramName);
paramAdded = true;
}
// PathVariable annotation
else if (frameworkAnnotations.getPathVariableAnnotation()
.getAnnotationName()
.contains(annotationName)) {
Expand All @@ -1476,6 +1482,7 @@ else if (frameworkAnnotations.getPathVariableAnnotation()
pathParamsMap.put(paramName, mockValue);
paramAdded = true;
}
// RequestParam annotation
else if (frameworkAnnotations.getRequestParamAnnotation()
.getAnnotationName()
.contains(annotationName)) {
Expand All @@ -1497,6 +1504,7 @@ else if (frameworkAnnotations.getRequestParamAnnotation()
requestParam = true;
paramAdded = true;
}
// RequestPart annotation
else if (frameworkAnnotations.getRequestPartAnnotation().getAnnotationName().contains(annotationName)) {
if (!JavaClassValidateUtil.isFile(gicTypeName)) {
apiMethodDoc.setContentType(MediaType.MULTIPART_FORM_DATA);
Expand Down Expand Up @@ -1532,6 +1540,7 @@ else if (frameworkAnnotations.getRequestPartAnnotation().getAnnotationName().con
formData.setSrc(new ArrayList<>(0));
formDataList.add(formData);
}
// primitive type
else if (JavaClassValidateUtil.isPrimitive(fullyQualifiedName) && !requestParam) {
FormData formData = new FormData();
formData.setKey(paramName);
Expand All @@ -1540,6 +1549,7 @@ else if (JavaClassValidateUtil.isPrimitive(fullyQualifiedName) && !requestParam)
formData.setValue(mockValue);
formDataList.add(formData);
}
// array or collection
else if (JavaClassValidateUtil.isArray(fullyQualifiedName)
|| JavaClassValidateUtil.isCollection(fullyQualifiedName)) {
String gicName = globGicName[0];
Expand Down Expand Up @@ -1569,6 +1579,7 @@ else if (JavaClassValidateUtil.isArray(fullyQualifiedName)
formData.setValue(value);
formDataList.add(formData);
}
// enum type
else if (javaClass.isEnum()) {
// do nothing
Object value = JavaClassUtil.getEnumValue(javaClass, configBuilder, Boolean.TRUE);
Expand All @@ -1594,13 +1605,8 @@ else if (javaClass.isEnum()) {
apiMethodDoc.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
}
requestExample.setFormDataList(formDataList);
// curl send file to convert
final Map<String, String> formDataToMap = DocUtil.formDataToMap(formDataList);
// formData add to params '--data'
queryParamsMap.putAll(formDataToMap);
// set example body
RequestExampleUtil.setExampleBody(apiMethodDoc, requestExample, formDataList, pathParamsMap, queryParamsMap);
return requestExample;
return RequestExampleUtil.setExampleBody(apiMethodDoc, requestExample, pathParamsMap, queryParamsMap);
}

/**
Expand Down
64 changes: 55 additions & 9 deletions src/main/java/com/ly/doc/template/JAXRSDocBuildTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,72 @@
package com.ly.doc.template;

import com.ly.doc.builder.ProjectDocConfigBuilder;
import com.ly.doc.constants.*;
import com.ly.doc.handler.*;
import com.ly.doc.constants.DocAnnotationConstants;
import com.ly.doc.constants.DocGlobalConstants;
import com.ly.doc.constants.DocTags;
import com.ly.doc.constants.FrameworkEnum;
import com.ly.doc.constants.JAXRSAnnotations;
import com.ly.doc.constants.JakartaJaxrsAnnotations;
import com.ly.doc.constants.MediaType;
import com.ly.doc.constants.ParamTypeConstants;
import com.ly.doc.handler.DefaultWebSocketRequestHandler;
import com.ly.doc.handler.IHeaderHandler;
import com.ly.doc.handler.IRequestMappingHandler;
import com.ly.doc.handler.JaxrsHeaderHandler;
import com.ly.doc.handler.JaxrsPathHandler;
import com.ly.doc.handler.SpringMVCRequestHeaderHandler;
import com.ly.doc.handler.SpringMVCRequestMappingHandler;
import com.ly.doc.helper.FormDataBuildHelper;
import com.ly.doc.helper.JsonBuildHelper;
import com.ly.doc.helper.ParamsBuildHelper;
import com.ly.doc.model.*;
import com.ly.doc.model.ApiConfig;
import com.ly.doc.model.ApiDoc;
import com.ly.doc.model.ApiExceptionStatus;
import com.ly.doc.model.ApiMethodDoc;
import com.ly.doc.model.ApiMethodReqParam;
import com.ly.doc.model.ApiParam;
import com.ly.doc.model.ApiReqParam;
import com.ly.doc.model.ApiSchema;
import com.ly.doc.model.DocJavaMethod;
import com.ly.doc.model.DocJavaParameter;
import com.ly.doc.model.ExceptionAdviceMethod;
import com.ly.doc.model.FormData;
import com.ly.doc.model.WebSocketDoc;
import com.ly.doc.model.annotation.EntryAnnotation;
import com.ly.doc.model.annotation.FrameworkAnnotations;
import com.ly.doc.model.annotation.HeaderAnnotation;
import com.ly.doc.model.request.ApiRequestExample;
import com.ly.doc.model.request.CurlRequest;
import com.ly.doc.model.request.JaxrsPathMapping;
import com.ly.doc.model.request.RequestMapping;
import com.ly.doc.utils.*;
import com.ly.doc.utils.ApiParamTreeUtil;
import com.ly.doc.utils.CurlUtil;
import com.ly.doc.utils.DocClassUtil;
import com.ly.doc.utils.DocPathUtil;
import com.ly.doc.utils.DocUtil;
import com.ly.doc.utils.JavaClassUtil;
import com.ly.doc.utils.JavaClassValidateUtil;
import com.ly.doc.utils.JavaFieldUtil;
import com.ly.doc.utils.JsonUtil;
import com.ly.doc.utils.RequestExampleUtil;
import com.ly.doc.utils.TornaUtil;
import com.power.common.util.CollectionUtil;
import com.power.common.util.RandomUtil;
import com.power.common.util.StringUtil;
import com.thoughtworks.qdox.model.*;

import java.util.*;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -696,8 +742,8 @@ else if (javaClass.isEnum()) {
}
}
requestExample.setFormDataList(formDataList);
RequestExampleUtil.setExampleBody(apiMethodDoc, requestExample, formDataList, pathParamsMap, pathParamsMap);
return requestExample;
// set example body
return RequestExampleUtil.setExampleBody(apiMethodDoc, requestExample, pathParamsMap, pathParamsMap);
}

/**
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/ly/doc/utils/ParamUtil.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
/*
* smart-doc
*
* Copyright (C) 2018-2024 smart-doc
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package com.ly.doc.utils;

import com.ly.doc.builder.ProjectDocConfigBuilder;
Expand Down
Loading

0 comments on commit fe0532f

Please sign in to comment.