From ac4ed47c9fdbaa75a6f5ddf9852e6b2b039eb014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E4=B8=87=E7=A8=8B?= <1498425439@qq.com> Date: Tue, 15 Mar 2022 23:31:44 +0800 Subject: [PATCH] =?UTF-8?q?1.11=20Add=20json=20key=20jump=20to=20field=20|?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=20json=20=E8=B7=B3=E8=BD=AC=E5=88=B0?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 52 +++++++------- build.gradle | 42 ++++++----- .../linwancen/plugin/show/JsonJump.java | 72 +++++++++++++++++++ .../plugin/show/doc/JsonDocUtils.java | 72 +++---------------- .../plugin/show/doc/PsiClassUtils.java | 17 ++++- .../linwancen/plugin/show/json/JsonRef.java | 41 +++++++++++ .../linwancen/plugin/show/json/JsonUtils.java | 22 ++++++ src/main/resources/META-INF/plugin.xml | 14 ++-- 8 files changed, 220 insertions(+), 112 deletions(-) create mode 100644 src/main/java/io/github/linwancen/plugin/show/JsonJump.java create mode 100644 src/main/java/io/github/linwancen/plugin/show/json/JsonRef.java create mode 100644 src/main/java/io/github/linwancen/plugin/show/json/JsonUtils.java diff --git a/README.md b/README.md index acde7b6..c920095 100644 --- a/README.md +++ b/README.md @@ -5,41 +5,45 @@ https://plugins.jetbrains.com/plugin/18553-show-comment English Notes: Chinese Notes: English Change Notes: Chinese Change Notes: \ No newline at end of file diff --git a/build.gradle b/build.gradle index f905dad..09e857a 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'io.github.linwancen' -version '1.9.0.' + (new Date().format('yyyy.MM.dd_HH.mm')) +version '1.11.0.' + (new Date().format('yyyy.MM.dd_HH.mm')) apply plugin: 'java' @@ -39,28 +39,32 @@ patchPluginXml { changeNotes = """ English Change Notes: Chinese Change Notes: """ } diff --git a/src/main/java/io/github/linwancen/plugin/show/JsonJump.java b/src/main/java/io/github/linwancen/plugin/show/JsonJump.java new file mode 100644 index 0000000..be56091 --- /dev/null +++ b/src/main/java/io/github/linwancen/plugin/show/JsonJump.java @@ -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 psiFields = new ArrayList<>(); + List tips = new ArrayList<>(); + PsiClass[] psiClasses = PsiClassUtils.encClass(virtualFile, project); + List jsonPath = JsonUtils.jsonPath(jsonProp); + put(project, psiFields, tips, psiClasses, jsonPath, jsonPath.size() - 1); + + List 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 psiFields, List tips, + PsiClass[] psiClasses, List 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); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/io/github/linwancen/plugin/show/doc/JsonDocUtils.java b/src/main/java/io/github/linwancen/plugin/show/doc/JsonDocUtils.java index cf7acbc..9119b77 100644 --- a/src/main/java/io/github/linwancen/plugin/show/doc/JsonDocUtils.java +++ b/src/main/java/io/github/linwancen/plugin/show/doc/JsonDocUtils.java @@ -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 jsonPath = jsonPath(jsonProp); - return doc(psiClasses, element.getProject(), jsonPath, jsonPath.size() - 1); - } - - @NotNull - public static List jsonPath(JsonProperty jsonProp) { - ArrayList 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 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(); - } } diff --git a/src/main/java/io/github/linwancen/plugin/show/doc/PsiClassUtils.java b/src/main/java/io/github/linwancen/plugin/show/doc/PsiClassUtils.java index 46d823d..939b489 100644 --- a/src/main/java/io/github/linwancen/plugin/show/doc/PsiClassUtils.java +++ b/src/main/java/io/github/linwancen/plugin/show/doc/PsiClassUtils.java @@ -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; + } } diff --git a/src/main/java/io/github/linwancen/plugin/show/json/JsonRef.java b/src/main/java/io/github/linwancen/plugin/show/json/JsonRef.java new file mode 100644 index 0000000..7124ef7 --- /dev/null +++ b/src/main/java/io/github/linwancen/plugin/show/json/JsonRef.java @@ -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 implements PsiPolyVariantReference { + + final PsiField psiField; + final List tips; + + public JsonRef(@NotNull PsiElement element, @NotNull PsiField psiField, @NotNull List 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(); + } +} \ No newline at end of file diff --git a/src/main/java/io/github/linwancen/plugin/show/json/JsonUtils.java b/src/main/java/io/github/linwancen/plugin/show/json/JsonUtils.java new file mode 100644 index 0000000..dd4c5bc --- /dev/null +++ b/src/main/java/io/github/linwancen/plugin/show/json/JsonUtils.java @@ -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 jsonPath(JsonProperty jsonProp) { + ArrayList jsonPath = new ArrayList<>(); + do { + jsonPath.add(jsonProp.getName()); + } while ((jsonProp = PsiTreeUtil.getParentOfType(jsonProp, JsonProperty.class)) != null); + return jsonPath; + } +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index d8af239..2856689 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -6,16 +6,16 @@ -
  • Show javadoc comments at the Project view Tree structure. -
  • Show javadoc comments at the end-of-line. -
  • Show javadoc comments at "xx ClassNameOrSimpleName.json". +
  • Show javadoc comments at the Project view Tree structure +
  • Show javadoc comments at the end-of-line +
  • Show javadoc comments at "xx ClassNameOrSimpleName.json" and jump to field
  • Config: settings -> Tools -> Show Comment Global/Project Chinese Notes:
      -
    • 在结构树显示 文档注释。 -
    • 在行末尾显示 文档注释。 -
    • 支持 "xx 类全名或简名.json"。 +
    • 在结构树显示 文档注释 +
    • 在行末尾显示 文档注释 +
    • 支持 "xx 类全名或简名.json" 文档注释与跳转到字段
    • 修改配置:设置 -> 工具 -> Show Comment Global/Project
    ]]> @@ -40,6 +40,8 @@ Chinese Notes: id="io.github.linwancen.plugin.show.settings.ProjectSettingsConfigurable" displayName="Show Comment Project"/> + +