Skip to content

Commit

Permalink
feat(generate): 完善结构解析器: 更好的判断递归
Browse files Browse the repository at this point in the history
  • Loading branch information
gudqs7 committed Aug 4, 2022
1 parent dc9f92f commit ae7dc11
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
import org.apache.commons.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
Expand All @@ -41,7 +43,7 @@ public StructureAndCommentInfo resolveFromClass(PsiClassReferenceType psiClassRe
if (psiClassReferenceType == null) {
return null;
}
StructureAndCommentInfo root = resolveFromClass0(psiClassReferenceType, "", 1);
StructureAndCommentInfo root = resolveFromClass0(null, psiClassReferenceType, "", 1);
psiClassCache.clear();
earlyCache.clear();
return root;
Expand Down Expand Up @@ -134,7 +136,7 @@ public StructureAndCommentInfo resolveFromReturnVal(PsiTypeElement returnTypeEle
return structureAndCommentInfo;
}

private StructureAndCommentInfo resolveFromClass0(PsiClassReferenceType psiClassReferenceType, String fieldPrefix, int level) {
private StructureAndCommentInfo resolveFromClass0(StructureAndCommentInfo parent, PsiClassReferenceType psiClassReferenceType, String fieldPrefix, int level) {
if (psiClassReferenceType == null) {
return null;
}
Expand All @@ -146,14 +148,14 @@ private StructureAndCommentInfo resolveFromClass0(PsiClassReferenceType psiClass
psiClass = replacePsiClassIfFromJar(psiClass);
String qualifiedName = psiClass.getQualifiedName();
PsiTypeUtil.resolvePsiClassParameter(psiClassReferenceType);
if (qualifiedName != null) {
if (psiClassCache.containsKey(qualifiedName)) {
return null;
}
if (earlyCache.containsKey(qualifiedName)) {
return null;
}
}
// if (qualifiedName != null) {
// if (psiClassCache.containsKey(qualifiedName)) {
// return null;
// }
// if (earlyCache.containsKey(qualifiedName)) {
// return null;
// }
// }
String clazzTypeName = psiClass.getName();
if (BaseTypeUtil.isBaseTypeOrObject(psiClass)) {
return null;
Expand All @@ -165,6 +167,7 @@ private StructureAndCommentInfo resolveFromClass0(PsiClassReferenceType psiClass
return null;
}
StructureAndCommentInfo root = new StructureAndCommentInfo();
root.setParent(parent);
root.setFieldType(clazzTypeName);
root.setOriginalFieldType(clazzTypeName);
root.setFieldTypeCode(FieldType.POJO.getType());
Expand Down Expand Up @@ -248,11 +251,11 @@ private StructureAndCommentInfo resolveByPsiType(StructureAndCommentInfo parent,
return null;
}
}
return resolveByPsiType0(FieldType.BASE.getType(), fieldName, psiFieldType, commentInfo, "%s", fieldPrefix, level);
return resolveByPsiType0(parent, FieldType.BASE.getType(), fieldName, psiFieldType, commentInfo, "%s", fieldPrefix, level);
}

@SuppressWarnings("AlibabaMethodTooLong")
private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fieldName, PsiType psiFieldType, CommentInfo commentInfo, String typeNameFormat, String fieldPrefix, int level) {
private StructureAndCommentInfo resolveByPsiType0(StructureAndCommentInfo parent, int fieldTypeCode, String fieldName, PsiType psiFieldType, CommentInfo commentInfo, String typeNameFormat, String fieldPrefix, int level) {
boolean hidden = commentInfo.isHidden(false);
fieldName = commentInfo.getName(fieldName);
hidden = handleHidden(fieldName, psiFieldType, hidden);
Expand Down Expand Up @@ -283,7 +286,7 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
PsiArrayType psiArrayType = (PsiArrayType) psiFieldType;
PsiType componentType = psiArrayType.getComponentType();
String newTypeNameFormat = String.format(typeNameFormat, "%s[]");
return resolveByPsiType0(FieldType.ARRAY.getType(), fieldName, componentType, commentInfo, newTypeNameFormat, fieldPrefix, level);
return resolveByPsiType0(parent, FieldType.ARRAY.getType(), fieldName, componentType, commentInfo, newTypeNameFormat, fieldPrefix, level);
}

boolean isReferenceType = psiFieldType instanceof PsiClassReferenceType;
Expand Down Expand Up @@ -315,7 +318,7 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
PsiType realPsiType = PsiTypeUtil.getRealPsiType(psiFieldType, project, null);
if (realPsiType != null) {
String newTypeNameFormat = String.format(typeNameFormat, "%s");
return resolveByPsiType0(fieldTypeCode, fieldName, realPsiType, commentInfo, newTypeNameFormat, fieldPrefix, level);
return resolveByPsiType0(parent, fieldTypeCode, fieldName, realPsiType, commentInfo, newTypeNameFormat, fieldPrefix, level);
}

// 枚举
Expand All @@ -325,19 +328,19 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel

// List
if (PsiTypeUtil.isPsiTypeFromList(psiFieldType, project)) {
return getStructureAndCommentInfoByCollection(fieldName, commentInfo, typeNameFormat, fieldPrefix, level,
return getStructureAndCommentInfoByCollection(parent, fieldName, commentInfo, typeNameFormat, fieldPrefix, level,
structureAndCommentInfo, parameters, "List<%s>", FieldType.LIST);
}

// Set
if (PsiTypeUtil.isPsiTypeFromSet(psiFieldType, project)) {
return getStructureAndCommentInfoByCollection(fieldName, commentInfo, typeNameFormat, fieldPrefix, level,
return getStructureAndCommentInfoByCollection(parent, fieldName, commentInfo, typeNameFormat, fieldPrefix, level,
structureAndCommentInfo, parameters, "Set<%s>", FieldType.SET);
}

// Collection 放在后面判断, 优先级低一些
if (PsiTypeUtil.isPsiTypeFromCollection(psiFieldType, project)) {
return getStructureAndCommentInfoByCollection(fieldName, commentInfo, typeNameFormat, fieldPrefix, level,
return getStructureAndCommentInfoByCollection(parent, fieldName, commentInfo, typeNameFormat, fieldPrefix, level,
structureAndCommentInfo, parameters, "Collection<%s>", FieldType.COLLECTION);
}

Expand All @@ -358,7 +361,7 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
}
keyTypeName = keyType.getPresentableText();
String newTypeNameFormat = String.format(typeNameFormat, "Map<" + keyTypeName + ", %s>");
return resolveByPsiType0(FieldType.MAP.getType(), fieldName, valueType, commentInfo, newTypeNameFormat, fieldPrefix, level);
return resolveByPsiType0(parent, FieldType.MAP.getType(), fieldName, valueType, commentInfo, newTypeNameFormat, fieldPrefix, level);
} else {
return structureAndCommentInfo;
}
Expand All @@ -371,7 +374,15 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
if (MapKeyConstant.FIELD_PREFIX_INIT.equals(fieldPrefix)) {
fieldPrefix0 = "";
}
StructureAndCommentInfo structureAndCommentInfoChild = resolveFromClass0(psiClassReferenceType, fieldPrefix0, level + 1);

boolean hasRecursion = checkRecursion(parent);
if (hasRecursion) {
return null;
}

structureAndCommentInfo.setPsiClass(resolveClass);
structureAndCommentInfo.setParent(parent);
StructureAndCommentInfo structureAndCommentInfoChild = resolveFromClass0(structureAndCommentInfo, psiClassReferenceType, fieldPrefix0, level + 1);
if (structureAndCommentInfoChild != null && structureAndCommentInfoChild.getChildren().size() > 0) {
structureAndCommentInfo.setLeaf(false);
structureAndCommentInfo.copyChild(structureAndCommentInfoChild.getChildren());
Expand All @@ -388,27 +399,49 @@ private StructureAndCommentInfo resolveByPsiType0(int fieldTypeCode, String fiel
return structureAndCommentInfo;
}

private boolean handleHidden(String fieldName, PsiType psiFieldType, boolean oldVal) {
if (FieldJumpUtil.isFieldNameNeedJump(fieldName)) {
return true;
}
String typeQname = psiFieldType.getCanonicalText();
if (FieldJumpUtil.isFieldTypeNeedJump(typeQname)) {
return true;
private boolean checkRecursion(StructureAndCommentInfo parent) {
if (parent == null) {
return false;
}
return oldVal;
Set<String> uniqueNodeSet = new HashSet<>(32);
StructureAndCommentInfo current = parent;
do {
if (current.getFieldTypeCode().equals(FieldType.POJO.getType())) {
PsiClass psiClass = current.getPsiClass();
if (psiClass != null) {
String qualifiedName = psiClass.getQualifiedName();
if (uniqueNodeSet.contains(qualifiedName)) {
return true;
}
uniqueNodeSet.add(qualifiedName);
}
}
current = current.getParent();
} while (current != null);
return false;
}

private StructureAndCommentInfo getStructureAndCommentInfoByCollection(String fieldName, CommentInfo commentInfo, String typeNameFormat, String fieldPrefix, int level, StructureAndCommentInfo structureAndCommentInfo, PsiType[] parameters, String format, FieldType fieldType) {
private StructureAndCommentInfo getStructureAndCommentInfoByCollection(StructureAndCommentInfo parent, String fieldName, CommentInfo commentInfo, String typeNameFormat, String fieldPrefix, int level, StructureAndCommentInfo structureAndCommentInfo, PsiType[] parameters, String format, FieldType fieldType) {
if (parameters.length > 0) {
PsiType elementType = parameters[0];
String newTypeNameFormat = String.format(typeNameFormat, format);
return resolveByPsiType0(fieldType.getType(), fieldName, elementType, commentInfo, newTypeNameFormat, fieldPrefix, level);
return resolveByPsiType0(parent, fieldType.getType(), fieldName, elementType, commentInfo, newTypeNameFormat, fieldPrefix, level);
} else {
return structureAndCommentInfo;
}
}

private boolean handleHidden(String fieldName, PsiType psiFieldType, boolean oldVal) {
if (FieldJumpUtil.isFieldNameNeedJump(fieldName)) {
return true;
}
String typeQname = psiFieldType.getCanonicalText();
if (FieldJumpUtil.isFieldTypeNeedJump(typeQname)) {
return true;
}
return oldVal;
}

private boolean checkHiddenRequest(String fieldPrefix, String fieldName) {
String fieldKey = fieldPrefix + fieldName;
List<String> hiddenKeys = ResolverContextHolder.getData(ResolverContextHolder.HIDDEN_KEYS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public class FieldLevelInfo {
*/
private String clazzDesc;

/**
* 当前类全限定名
*/
private String clazzQname;

/**
* 当前层级下所有字段数据
*/
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/cn/gudqs7/plugins/savior/reader/Java2ApiReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import cn.gudqs7.plugins.common.util.StringTool;
import cn.gudqs7.plugins.savior.pojo.FieldLevelInfo;
import cn.gudqs7.plugins.savior.pojo.FieldMemoInfo;
import com.intellij.psi.PsiClass;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
Expand All @@ -22,7 +23,9 @@ public class Java2ApiReader extends AbstractReader<FieldMemoInfo, Map<String, Li
@Override
protected void beforeRead(StructureAndCommentInfo structureAndCommentInfo, Map<String, Object> data) {
Map<String, List<FieldLevelInfo>> levelMap = new TreeMap<>(Comparator.comparingInt(Integer::parseInt));
Set<String> qNameSet = new HashSet<>(32);
data.put("levelMap", levelMap);
data.put("qNameSet", qNameSet);
}

@Override
Expand All @@ -38,13 +41,18 @@ protected void beforeLoop(StructureAndCommentInfo structureAndCommentInfo, Map<S
CommentInfo commentInfo = structureAndCommentInfo.getCommentInfo();
String clazzDesc = "";
String clazzTypeName = "";
String classQname = "";
switch (StructureType.of(type)) {
case PSI_CLASS:
case PSI_FIELD:
case PSI_PARAM:
case PSI_RETURN:
clazzDesc = commentInfo.getValue("");
clazzTypeName = structureAndCommentInfo.getOriginalFieldType();
PsiClass psiClass = structureAndCommentInfo.getPsiClass();
if (psiClass != null) {
classQname = psiClass.getQualifiedName();
}
break;
case PSI_PARAM_LIST:
clazzTypeName = "Params";
Expand All @@ -59,6 +67,7 @@ protected void beforeLoop(StructureAndCommentInfo structureAndCommentInfo, Map<S
clazzDesc = StringTool.replaceMd(clazzDesc);
loopData.put("clazzTypeName", clazzTypeName);
loopData.put("clazzDesc", clazzDesc);
loopData.put("classQname", classQname);
}

@Override
Expand All @@ -78,15 +87,18 @@ protected void afterLoop(StructureAndCommentInfo structureAndCommentInfo, Map<St
List<FieldMemoInfo> fieldList = getFromData(loopData, "fieldList");
if (fieldList.size() > 0) {
Map<String, List<FieldLevelInfo>> levelMap = getFromData(data, "levelMap");
Set<String> qNameSet = getFromData(data, "qNameSet");
int level = (int) loopData.get("level");
String clazzDesc = getFromData(loopData, "clazzDesc");
String clazzTypeName = getFromData(loopData, "clazzTypeName");
String parentClazzTypeName = parentData.get("clazzTypeName", "");
String classQname = parentData.get("classQname", "");
FieldLevelInfo fieldLevelInfo = new FieldLevelInfo();
fieldLevelInfo.setLevel(level);
fieldLevelInfo.setParentClazzTypeName(parentClazzTypeName);
fieldLevelInfo.setClazzTypeName(clazzTypeName);
fieldLevelInfo.setClazzDesc(clazzDesc);
fieldLevelInfo.setClazzQname(classQname);
fieldLevelInfo.setFieldList(fieldList);
String levelStr = String.valueOf(level);
List<FieldLevelInfo> list = levelMap.computeIfAbsent(levelStr, integer -> new ArrayList<>());
Expand Down
9 changes: 7 additions & 2 deletions src/main/resources/template/ftl/rpc/field.ftl
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
<#if levelMap?? && (levelMap?size > 0)>
<#assign cnNumberMap = {"1": "一", "2": "二", "3": "三", "4": "四", "5": "五", "6": "六", "7": "七", "8": "八", "9": "九"}>
<#assign qNameSet = {}>
<#list levelMap?keys as level>
<#if (level?number > 0)>

### 第${cnNumberMap[level]!level}
<#assign levelList = levelMap[level]!>
<#list levelList as levelInfo>
<#assign qName = levelInfo.clazzQname>
<#if !(qNameSet[qName])??>
<#assign qNameSet += {qName: "0"}>
#### ${levelInfo.clazzTypeName}
${((levelInfo.clazzDesc)?? && levelInfo.clazzDesc != '')?string('> '+ levelInfo.clazzDesc, '')}

| **字段** | **类型** | **必填** | **含义** | **其他参考信息** |
| -------- | -------- | -------- | -------- | -------- |
<#list levelInfo.fieldList?sort_by("index") as field>
<#list levelInfo.fieldList?sort_by("index") as field>
| ${field.fieldName} | **${((field.fieldTypeCode)?? && field.originalFieldTypeCode == 2)?string('[' + field.fieldTypeName + '](#' + field.originalFieldTypeName + ')', field.fieldTypeName)}** | ${field.required?string('**是**','否')} | ${field.fieldDesc} | ${field.notes} |
</#list>
</#list>
</#if>
</#list>
</#if>
</#list>
Expand Down
18 changes: 14 additions & 4 deletions src/main/resources/template/ftl/rpc/method.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,25 @@ ${jsonExample}

<#assign cnNumberMap = {"1": "一", "2": "二", "3": "三", "4": "四", "5": "五", "6": "六", "7": "七", "8": "八", "9": "九"}>
<#if paramLevelMap?? && (paramLevelMap?size > 0)>
<#assign paramQNameSet = {}>
<#list paramLevelMap?keys as level>
<#if (level?number > 0)>

### 第${cnNumberMap[level]!level}
<#assign levelList = paramLevelMap[level]!>
<#list levelList as levelInfo>
<#assign qName = levelInfo.clazzQname>
<#if !(paramQNameSet[qName])??>
<#assign paramQNameSet += {qName: "0"}>
#### ${levelInfo.clazzTypeName}
${((levelInfo.clazzDesc)?? && levelInfo.clazzDesc != '')?string('> '+ levelInfo.clazzDesc, '')}

| **字段** | **类型** | **必填** | **含义** | **其他参考信息** |
| -------- | -------- | -------- | -------- | -------- |
<#list levelInfo.fieldList?sort_by("index") as field>
<#list levelInfo.fieldList?sort_by("index") as field>
| ${field.fieldName} | **${((field.fieldTypeCode)?? && field.originalFieldTypeCode == 2)?string('[' + field.fieldTypeName + '](#' + field.originalFieldTypeName + ')', field.fieldTypeName)}** | ${field.required?string('**是**','否')} | ${field.fieldDesc} | ${field.notes} |
</#list>
</#list>
</#if>
</#list>
</#if>
</#list>
Expand All @@ -48,20 +53,25 @@ ${returnJsonExample}
</#if>

<#if returnLevelMap?? && (returnLevelMap?size > 0)>
<#assign returnQNameSet = {}>
<#list returnLevelMap?keys as level>
<#if (level?number > 0)>

### 第${cnNumberMap[level]!level}
<#assign levelList = returnLevelMap[level]!>
<#list levelList as levelInfo>
<#assign qName = levelInfo.clazzQname>
<#if !(returnQNameSet[qName])??>
<#assign returnQNameSet += {qName: "0"}>
#### ${levelInfo.clazzTypeName}
${((levelInfo.clazzDesc)?? && levelInfo.clazzDesc != '')?string('> '+ levelInfo.clazzDesc, '')}

| **字段** | **类型** | **含义** | **其他参考信息** |
| -------- | -------- | -------- | -------- |
<#list levelInfo.fieldList?sort_by("index") as field>
<#list levelInfo.fieldList?sort_by("index") as field>
| ${field.fieldName} | **${((field.fieldTypeCode)?? && field.originalFieldTypeCode == 2)?string('[' + field.fieldTypeName + '](#' + field.originalFieldTypeName + ')', field.fieldTypeName)}** | ${field.fieldDesc} | ${field.notes} |
</#list>
</#list>
</#if>
</#list>
</#if>
</#list>
Expand Down

0 comments on commit ae7dc11

Please sign in to comment.