1.11 Add json key jump to field | 增加 json 跳转到字段
This commit is contained in:
72
src/main/java/io/github/linwancen/plugin/show/JsonJump.java
Normal file
72
src/main/java/io/github/linwancen/plugin/show/JsonJump.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package io.github.linwancen.plugin.show;
|
||||
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.json.psi.JsonStringLiteral;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import io.github.linwancen.plugin.show.doc.PsiClassUtils;
|
||||
import io.github.linwancen.plugin.show.json.JsonRef;
|
||||
import io.github.linwancen.plugin.show.json.JsonUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class JsonJump extends PsiReferenceContributor {
|
||||
|
||||
@Override
|
||||
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
|
||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(JsonStringLiteral.class),
|
||||
new PsiReferenceProvider() {
|
||||
@Override
|
||||
public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element,
|
||||
@NotNull ProcessingContext context) {
|
||||
JsonProperty jsonProp = PsiTreeUtil.getParentOfType(element, JsonProperty.class, true);
|
||||
if (jsonProp == null) {
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
VirtualFile virtualFile = element.getContainingFile().getVirtualFile();
|
||||
if (virtualFile == null) {
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
Project project = element.getProject();
|
||||
List<PsiField> psiFields = new ArrayList<>();
|
||||
List<PsiField> tips = new ArrayList<>();
|
||||
PsiClass[] psiClasses = PsiClassUtils.encClass(virtualFile, project);
|
||||
List<String> jsonPath = JsonUtils.jsonPath(jsonProp);
|
||||
put(project, psiFields, tips, psiClasses, jsonPath, jsonPath.size() - 1);
|
||||
|
||||
List<PsiReference> list = new ArrayList<>();
|
||||
for (PsiField psiField : psiFields) {
|
||||
list.add(new JsonRef(element, psiField, tips));
|
||||
}
|
||||
return list.toArray(new PsiReference[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void put(Project project, List<PsiField> psiFields, List<PsiField> tips,
|
||||
PsiClass[] psiClasses, List<String> jsonPath, int level) {
|
||||
String name = jsonPath.get(level);
|
||||
for (PsiClass psiClass : psiClasses) {
|
||||
if (level == 1) {
|
||||
tips.addAll(Arrays.asList(psiClass.getAllFields()));
|
||||
}
|
||||
PsiField psiField = psiClass.findFieldByName(name, true);
|
||||
if (psiField == null) {
|
||||
continue;
|
||||
}
|
||||
if (level == 0) {
|
||||
psiFields.add(psiField);
|
||||
} else {
|
||||
String classFullName = PsiClassUtils.toClassFullName(psiField);
|
||||
PsiClass[] classes = PsiClassUtils.fullNameToClass(classFullName, project);
|
||||
put(project, psiFields, tips, classes, jsonPath, level - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +1,31 @@
|
||||
package io.github.linwancen.plugin.show.doc;
|
||||
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiDocCommentOwner;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class JsonDocUtils {
|
||||
|
||||
private JsonDocUtils() {}
|
||||
|
||||
/**
|
||||
* depend on JsonJump
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiDocComment jsonDoc(PsiElement element, int startOffset, int endOffset) {
|
||||
JsonProperty jsonProp = PsiTreeUtil.getParentOfType(element, JsonProperty.class, true, startOffset);
|
||||
if (jsonProp == null || jsonProp.getNameElement().getTextRange().getEndOffset() > endOffset) {
|
||||
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
|
||||
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 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) {
|
||||
continue;
|
||||
}
|
||||
if (level == 0) {
|
||||
PsiDocComment docComment = DocUtils.srcOrByteCodeDoc(psiField);
|
||||
if (docComment != null) {
|
||||
return docComment;
|
||||
}
|
||||
} else {
|
||||
String classFullName = toClassFullName(psiField);
|
||||
PsiClass[] classes = PsiClassUtils.fullNameToClass(classFullName, project);
|
||||
PsiDocComment docComment = doc(classes, project, jsonPath, level - 1);
|
||||
for (PsiReference reference : jsonProp.getNameElement().getReferences()) {
|
||||
PsiElement resolve = reference.resolve();
|
||||
if (resolve instanceof PsiDocCommentOwner) {
|
||||
PsiDocCommentOwner owner = (PsiDocCommentOwner) resolve;
|
||||
PsiDocComment docComment = DocUtils.srcOrByteCodeDoc(owner);
|
||||
if (docComment != null) {
|
||||
return docComment;
|
||||
}
|
||||
@@ -61,26 +33,4 @@ public class JsonDocUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String toClassFullName(PsiField psiField) {
|
||||
// <> only in .java
|
||||
PsiElement navElement = psiField.getNavigationElement();
|
||||
if (navElement instanceof PsiField) {
|
||||
psiField = (PsiField) navElement;
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@ 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.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -51,4 +50,18 @@ public class PsiClassUtils {
|
||||
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
|
||||
return javaPsiFacade.findClasses(className, GlobalSearchScope.allScope(project));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String toClassFullName(PsiField psiField) {
|
||||
// Array
|
||||
// use replace simpler than getDeepComponentType()
|
||||
String typeName = psiField.getType().getCanonicalText().replace("[]", "");
|
||||
// List
|
||||
// use substring() because clsFieldImpl.getInnermostComponentReferenceElement() == null
|
||||
int index = typeName.indexOf("<");
|
||||
if (index >= 0) {
|
||||
return typeName.substring(index + 1, typeName.length() - 1);
|
||||
}
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.github.linwancen.plugin.show.json;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class JsonRef extends PsiReferenceBase<PsiElement> implements PsiPolyVariantReference {
|
||||
|
||||
final PsiField psiField;
|
||||
final List<PsiField> tips;
|
||||
|
||||
public JsonRef(@NotNull PsiElement element, @NotNull PsiField psiField, @NotNull List<PsiField> tips) {
|
||||
super(element);
|
||||
this.psiField = psiField;
|
||||
this.tips = tips;
|
||||
}
|
||||
|
||||
/**
|
||||
* do not use it because PsiReference.resolveReference() is @Experimental
|
||||
*/
|
||||
@Override
|
||||
public ResolveResult @NotNull [] multiResolve(boolean incompleteCode) {
|
||||
return new ResolveResult[]{new PsiElementResolveResult(psiField)};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement resolve() {
|
||||
return psiField;
|
||||
}
|
||||
|
||||
/**
|
||||
* I don't know how to use it
|
||||
*/
|
||||
@Override
|
||||
public Object @NotNull [] getVariants() {
|
||||
return tips.toArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.github.linwancen.plugin.show.json;
|
||||
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class JsonUtils {
|
||||
|
||||
private JsonUtils() {}
|
||||
|
||||
@NotNull
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user