diff --git a/README.md b/README.md index da80250..b6b89f6 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ When you need to use smart-doc to generate more API document information, you ca "recursionLimit":7,// Set the number of recursive executions to avoid stack overflow, the default is 7 "responseFieldToUnderline":true,//convert response field to underline "allInOneDocFileName":"index.html",//Customize the output document name + "displayActualType":false,//display actual type of generic, "requestExample":"true",//Whether to display the request example in the document, the default value is true. "responseExample":"true",//Whether to display the response example in the document, the default is true. "ignoreRequestParams":[ //The request parameter object will be discarded when generating the document.@since 1.9.2 diff --git a/README_CN.md b/README_CN.md index fb56871..b117130 100644 --- a/README_CN.md +++ b/README_CN.md @@ -102,6 +102,7 @@ smart-doc官方目前已经开发完成[maven插件](https://gitee.com/smart-doc "allInOneDocFileName":"index.html",//自定义设置输出文档名称, @since 1.9.0 "requestExample":"true",//是否将请求示例展示在文档中,默认true,@since 1.9.0 "responseExample":"true",//是否将响应示例展示在文档中,默认为true,@since 1.9.0 + "displayActualType":false,//配置true会在注释栏自动显示泛型的真实类型短类名,@since 1.9.6 "ignoreRequestParams":[ //忽略请求参数对象,把不想生成文档的参数对象屏蔽掉,@since 1.9.2 "org.springframework.ui.ModelMap" ], diff --git a/src/main/java/com/power/doc/helper/FormDataBuildHelper.java b/src/main/java/com/power/doc/helper/FormDataBuildHelper.java index 769b116..ce67053 100644 --- a/src/main/java/com/power/doc/helper/FormDataBuildHelper.java +++ b/src/main/java/com/power/doc/helper/FormDataBuildHelper.java @@ -101,8 +101,8 @@ public class FormDataBuildHelper { for (DocJavaField docField : fields) { JavaField field = docField.getJavaField(); String fieldName = field.getName(); - String subTypeName = field.getType().getFullyQualifiedName(); - String fieldGicName = field.getType().getGenericCanonicalName(); + String subTypeName = docField.getFullyQualifiedName(); + String fieldGicName = docField.getGenericCanonicalName(); JavaClass javaClass = builder.getJavaProjectBuilder().getClassByName(subTypeName); if (field.isStatic() || "this$0".equals(fieldName) || JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) { diff --git a/src/main/java/com/power/doc/helper/JsonBuildHelper.java b/src/main/java/com/power/doc/helper/JsonBuildHelper.java index 57c7c9d..eb742ca 100644 --- a/src/main/java/com/power/doc/helper/JsonBuildHelper.java +++ b/src/main/java/com/power/doc/helper/JsonBuildHelper.java @@ -40,6 +40,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; + + /** * @author yu 2019/12/21. */ @@ -107,12 +109,7 @@ public class JsonBuildHelper { data0.append("{"); String[] globGicName = DocClassUtil.getSimpleGicName(genericCanonicalName); //添加泛型对应关系 - if (cls != null && null != cls.getTypeParameters()) { - List> variables = cls.getTypeParameters(); - for (int i = 0; i < cls.getTypeParameters().size() && i> variables = cls.getTypeParameters(); - for (int i = 0; i < cls.getTypeParameters().size() && i fields = JavaClassUtil.getFields(cls, 0, new HashSet<>()); if (JavaClassValidateUtil.isPrimitive(simpleName)) { String processedType = isShowJavaType ? simpleName : DocClassUtil.processTypeNameForParams(simpleName.toLowerCase()); @@ -106,15 +102,13 @@ public class ParamsBuildHelper { param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setRequired(false).setVersion(DocGlobalConstants.DEFAULT_VERSION); } paramList.add(param); - } - - else { + } else { boolean isGenerics = JavaFieldUtil.checkGenerics(fields); out: for (DocJavaField docField : fields) { JavaField field = docField.getJavaField(); String fieldName = field.getName(); - String subTypeName = field.getType().getFullyQualifiedName(); + String subTypeName = docField.getFullyQualifiedName(); if (field.isStatic() || "this$0".equals(fieldName) || JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) { continue; @@ -127,7 +121,7 @@ public class ParamsBuildHelper { fieldName = StringUtil.camelToUnderline(fieldName); } String typeSimpleName = field.getType().getSimpleName(); - String fieldGicName = field.getType().getGenericCanonicalName(); + String fieldGicName = docField.getGenericCanonicalName(); List javaAnnotations = docField.getAnnotations(); Map tagsMap = DocUtil.getFieldTagsValue(field, docField); @@ -249,6 +243,9 @@ public class ParamsBuildHelper { } param.setType(DocGlobalConstants.ENUM); } + if (typeSimpleName.length() == 1 && displayActualType) { + comment = comment + "(" + JavaClassUtil.getClassSimpleName(subTypeName) + ")"; + } //如果已经设置返回类型 不需要再次设置 if (param.getType() == null) { String processedType; @@ -289,12 +286,12 @@ public class ParamsBuildHelper { preBuilder.append(DocGlobalConstants.FIELD_SPACE); } preBuilder.append("└─"); - int fieldPid = paramList.size()+pid; + int fieldPid = paramList.size() + pid; if (JavaClassValidateUtil.isMap(subTypeName)) { String gNameTemp = field.getType().getGenericCanonicalName(); if (JavaClassValidateUtil.isMap(gNameTemp)) { ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object") - .setId(paramList.size()+1).setPid(fieldPid) + .setId(paramList.size() + 1).setPid(fieldPid) .setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION); paramList.add(param1); continue; @@ -339,8 +336,7 @@ public class ParamsBuildHelper { } } } - } else - if (subTypeName.length() == 1 || DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) { + } else if (subTypeName.length() == 1 || DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) { if (isGenerics && DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) { ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object") .setId(paramList.size()) diff --git a/src/main/java/com/power/doc/model/ApiConfig.java b/src/main/java/com/power/doc/model/ApiConfig.java index aee56e0..c840c02 100644 --- a/src/main/java/com/power/doc/model/ApiConfig.java +++ b/src/main/java/com/power/doc/model/ApiConfig.java @@ -240,6 +240,11 @@ public class ApiConfig { */ private List ignoreRequestParams; + /** + * display actual type of generic + * @since 1.9.6 + */ + private boolean displayActualType; public String getServerUrl() { return serverUrl; @@ -525,4 +530,12 @@ public class ApiConfig { public void setIgnoreRequestParams(List ignoreRequestParams) { this.ignoreRequestParams = ignoreRequestParams; } + + public boolean isDisplayActualType() { + return displayActualType; + } + + public void setDisplayActualType(boolean displayActualType) { + this.displayActualType = displayActualType; + } } \ No newline at end of file diff --git a/src/main/java/com/power/doc/model/DocJavaField.java b/src/main/java/com/power/doc/model/DocJavaField.java index 344bdbe..e417b68 100644 --- a/src/main/java/com/power/doc/model/DocJavaField.java +++ b/src/main/java/com/power/doc/model/DocJavaField.java @@ -54,6 +54,16 @@ public class DocJavaField { */ private List annotations; + /** + * field fullyQualifiedName + */ + private String fullyQualifiedName; + + /** + * field genericCanonicalName + */ + private String genericCanonicalName; + public static DocJavaField builder() { return new DocJavaField(); } @@ -76,6 +86,24 @@ public class DocJavaField { return this; } + public String getFullyQualifiedName() { + return fullyQualifiedName; + } + + public DocJavaField setFullyQualifiedName(String fullyQualifiedName) { + this.fullyQualifiedName = fullyQualifiedName; + return this; + } + + public String getGenericCanonicalName() { + return genericCanonicalName; + } + + public DocJavaField setGenericCanonicalName(String genericCanonicalName) { + this.genericCanonicalName = genericCanonicalName; + return this; + } + public List getDocletTags() { if (docletTags == null) { return new ArrayList<>(); diff --git a/src/main/java/com/power/doc/utils/JavaClassUtil.java b/src/main/java/com/power/doc/utils/JavaClassUtil.java index f821bca..da0dd1d 100644 --- a/src/main/java/com/power/doc/utils/JavaClassUtil.java +++ b/src/main/java/com/power/doc/utils/JavaClassUtil.java @@ -38,6 +38,8 @@ import com.thoughtworks.qdox.model.impl.DefaultJavaParameterizedType; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.*; /** @@ -105,14 +107,25 @@ public class JavaClassUtil { fieldList.addAll(getFields(javaClass, counter, addedFields)); } } + Map javaTypes = getActualTypesMap(cls1); List docJavaFields = new ArrayList<>(); + List> variables = cls1.getTypeParameters(); for (JavaField javaField : cls1.getFields()) { String fieldName = javaField.getName(); if (addedFields.contains(fieldName)) { continue; } + String gicName = javaField.getType().getGenericCanonicalName(); + String subTypeName = javaField.getType().getFullyQualifiedName(); + if (subTypeName.length() == 1) { + JavaType type = javaTypes.get(subTypeName); + subTypeName = type.getFullyQualifiedName(); + gicName = type.getGenericCanonicalName(); + } addedFields.add(fieldName); - docJavaFields.add(DocJavaField.builder().setComment(javaField.getComment()).setJavaField(javaField)); + docJavaFields.add(DocJavaField.builder().setComment(javaField.getComment()) + .setJavaField(javaField).setFullyQualifiedName(subTypeName) + .setGenericCanonicalName(gicName)); } fieldList.addAll(docJavaFields); } @@ -156,7 +169,6 @@ public class JavaClassUtil { } public static String getEnumParams(JavaClass javaClass) { - List javaFields = javaClass.getEnumConstants(); StringBuilder stringBuilder = new StringBuilder(); for (JavaField javaField : javaFields) { @@ -171,7 +183,6 @@ public class JavaClassUtil { stringBuilder.append(","); } } - stringBuilder.append(")"); } stringBuilder.append("
"); @@ -199,7 +210,7 @@ public class JavaClassUtil { public static String getClassSimpleName(String className) { if (className.contains(".")) { int index = className.lastIndexOf("."); - className = className.substring(index + 1, className.length()); + className = className.substring(index + 1); } if (className.contains("[")) { int index = className.indexOf("["); @@ -214,27 +225,47 @@ public class JavaClassUtil { * @param javaClass JavaClass * @return JavaClass */ - public static JavaClass getActualType(JavaClass javaClass) { + public static JavaType getActualType(JavaClass javaClass) { return getActualTypes(javaClass).get(0); } /** * get Actual type list * - * @param javaClass JavaClass + * @param javaType JavaClass * @return JavaClass */ - public static List getActualTypes(JavaClass javaClass) { - if (null == javaClass) { + public static List getActualTypes(JavaType javaType) { + if (null == javaType) { return new ArrayList<>(0); } - List javaClassList = new ArrayList<>(); - List actualTypes = ((DefaultJavaParameterizedType) javaClass).getActualTypeArguments(); - actualTypes.forEach(javaType -> { - JavaClass actualClass = (JavaClass) javaType; - javaClassList.add(actualClass); - }); - return javaClassList; + String typeName = javaType.getGenericFullyQualifiedName(); + if (typeName.contains("<")) { + return ((JavaParameterizedType) javaType).getActualTypeArguments(); + } + return new ArrayList<>(0); + + } + + /** + * get Actual type map + * + * @param javaClass JavaClass + * @return Map + */ + public static Map getActualTypesMap(JavaClass javaClass) { + Map genericMap = new HashMap<>(10); + List> variables = javaClass.getTypeParameters(); + if (variables.size() < 1) { + return genericMap; + } + List javaTypes = getActualTypes(javaClass); + for (int i = 0; i < variables.size(); i++) { + if (javaTypes.size() > 0) { + genericMap.put(variables.get(i).getName(), javaTypes.get(i)); + } + } + return genericMap; } /** @@ -372,4 +403,12 @@ public class JavaClassUtil { } return annotationValueList; } + public static void genericParamMap(Map genericMap, JavaClass cls, String[] globGicName) { + if (cls != null && null != cls.getTypeParameters()) { + List> variables = cls.getTypeParameters(); + for (int i = 0; i < cls.getTypeParameters().size() && i