1.9 Add project-view-tree-comment for "xx ClassNameOrSimpleName.json" and SPI file | 增加 "xx 类全名或简名.json" 和 SPI 项目导航栏注释

This commit is contained in:
林万程
2022-03-09 03:28:12 +08:00
parent 9c177a2543
commit 1122637819
6 changed files with 124 additions and 60 deletions

View File

@@ -1,5 +1,6 @@
package io.github.linwancen.plugin.show.doc;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import org.jetbrains.annotations.Nullable;
@@ -36,12 +37,26 @@ public class DocUtils {
@Nullable
public static PsiDocComment fileDoc(PsiFile psiFile) {
if (!(psiFile instanceof PsiClassOwner)) {
// for SPI
PsiClass[] psiClasses = PsiClassUtils.nameToClass(psiFile.getName(), psiFile.getProject());
// for "xxx ClassName.xxx"
if (psiClasses.length == 0) {
VirtualFile virtualFile = psiFile.getVirtualFile();
psiClasses = PsiClassUtils.encClass(virtualFile, psiFile.getProject());
}
for (PsiClass psiClass : psiClasses) {
PsiDocComment docComment = srcOrByteCodeDoc(psiClass);
if (docComment != null) {
// Inaccurate when there are classes with the same name
return docComment;
}
}
return null;
}
PsiClassOwner psiClassOwner = (PsiClassOwner) psiFile;
if (PsiPackage.PACKAGE_INFO_FILE.equals(psiFile.getName())) {
return PackageDocUtils.fromPackageInfoFile(psiFile);
}
PsiClassOwner psiClassOwner = (PsiClassOwner) psiFile;
PsiClass[] classes = psiClassOwner.getClasses();
if (classes.length == 0) {
return null;

View File

@@ -2,22 +2,17 @@ package io.github.linwancen.plugin.show.doc;
import com.intellij.json.psi.JsonProperty;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.List;
public class JsonDocUtils {
private static final Pattern JSON_PATTERN = Pattern.compile("[\\w.]*+$");
private JsonDocUtils() {}
@@ -27,60 +22,56 @@ public class JsonDocUtils {
if (jsonProp == null || jsonProp.getNameElement().getTextRange().getEndOffset() > endOffset) {
return null;
}
String fileName = element.getContainingFile().getVirtualFile().getNameWithoutExtension();
Matcher matcher = JSON_PATTERN.matcher(fileName);
if (!matcher.find()) {
return null;
}
String className = matcher.group();
PsiClass[] psiClasses = classByName(className, element.getProject());
PsiField psiField = psiField(psiClasses, element.getProject(), jsonProp);
if (psiField != null) {
return DocUtils.srcOrByteCodeDoc(psiField);
}
return null;
VirtualFile virtualFile = element.getContainingFile().getVirtualFile();
PsiClass[] psiClasses = PsiClassUtils.encClass(virtualFile, element.getProject());
List<String> jsonPath = jsonPath(jsonProp);
return doc(psiClasses, element.getProject(), jsonPath, jsonPath.size() - 1);
}
@NotNull
private static PsiClass[] classByName(String className, @NotNull Project project) {
int i = className.indexOf('.');
if (i > 0) {
return classByFullName(className, project);
}
PsiShortNamesCache namesCache = PsiShortNamesCache.getInstance(project);
return namesCache.getClassesByName(className, GlobalSearchScope.allScope(project));
}
@NotNull
private static PsiClass[] classByFullName(String className, @NotNull Project project) {
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
return javaPsiFacade.findClasses(className, GlobalSearchScope.allScope(project));
public static List<String> jsonPath(JsonProperty jsonProp) {
ArrayList<String> jsonPath = new ArrayList<>();
do {
jsonPath.add(jsonProp.getName());
} while ((jsonProp = PsiTreeUtil.getParentOfType(jsonProp, JsonProperty.class)) != null);
return jsonPath;
}
@Nullable
private static PsiField psiField(PsiClass[] rootClasses, Project project, JsonProperty jsonProp) {
JsonProperty parentJsonProp = PsiTreeUtil.getParentOfType(jsonProp, JsonProperty.class);
if (parentJsonProp == null) {
for (PsiClass c : rootClasses) {
PsiField field = c.findFieldByName(jsonProp.getName(), true);
if (field != null) {
return field;
}
private static PsiDocComment doc(PsiClass[] psiClasses, Project project, List<String> jsonPath, int level) {
String name = jsonPath.get(level);
for (PsiClass psiClass : psiClasses) {
PsiField psiField = psiClass.findFieldByName(name, true);
if (psiField == null) {
return null;
}
return null;
}
PsiField psiField = psiField(rootClasses, project, parentJsonProp);
if (psiField == null) {
return null;
}
String classFullName = psiField.getType().getCanonicalText();
@NotNull PsiClass[] psiClasses = classByFullName(classFullName, project);
for (PsiClass c : psiClasses) {
PsiField field = c.findFieldByName(jsonProp.getName(), true);
if (field != null) {
return field;
if (level == 0) {
return DocUtils.srcOrByteCodeDoc(psiField);
}
String classFullName = toClassFullName(psiField);
PsiClass[] classes = PsiClassUtils.fullNameToClass(classFullName, project);
PsiDocComment docComment = doc(classes, project, jsonPath, level - 1);
if (docComment != null) {
return docComment;
}
}
return null;
}
@NotNull
private static String toClassFullName(PsiField psiField) {
PsiTypeElement typeElement = psiField.getTypeElement();
if (typeElement != null) {
PsiJavaCodeReferenceElement code = typeElement.getInnermostComponentReferenceElement();
if (code != null) {
PsiType[] types = code.getTypeParameters();
if (types.length > 0) {
// List
return types[types.length - 1].getCanonicalText();
}
}
}
// Array
return psiField.getType().getDeepComponentType().getCanonicalText();
}
}

View File

@@ -0,0 +1,54 @@
package io.github.linwancen.plugin.show.doc;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PsiClassUtils {
private PsiClassUtils() {}
private static final Pattern JSON_PATTERN = Pattern.compile("[\\w.]*+$");
@NotNull
public static PsiClass[] encClass(@NotNull VirtualFile virtualFile, @NotNull Project project) {
String fileName = virtualFile.getNameWithoutExtension();
Matcher matcher = JSON_PATTERN.matcher(fileName);
if (!matcher.find()) {
return new PsiClass[0];
}
String className = matcher.group();
return nameToClass(className, project);
}
@NotNull
public static PsiClass[] nameToClass(@Nullable String className, @NotNull Project project) {
if (className == null) {
return new PsiClass[0];
}
int i = className.indexOf('.');
return i > 0
? fullNameToClass(className, project)
: simpleNameToClass(className, project);
}
@NotNull
public static PsiClass[] simpleNameToClass(@NotNull String className, @NotNull Project project) {
PsiShortNamesCache namesCache = PsiShortNamesCache.getInstance(project);
return namesCache.getClassesByName(className, GlobalSearchScope.allScope(project));
}
@NotNull
public static PsiClass[] fullNameToClass(@NotNull String className, @NotNull Project project) {
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
return javaPsiFacade.findClasses(className, GlobalSearchScope.allScope(project));
}
}