From 795eecd6a77f3f555a1388dc771767bf27c0d7c1 Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Thu, 18 Apr 2024 18:14:29 +0200 Subject: [PATCH] [java-decompiler] IDEA-352102 support dumb mode in com.intellij.psi.impl.compiled.ClsModifierListImpl.setMirror GitOrigin-RevId: 3d2e0562124a3fcc75c6f681a475dba59c15d69d --- .../impl/compiled/ClsModifierListImpl.java | 55 ++++++++++++++++-- .../cls/mirror/FieldWithSimilarAnnotation.txt | 31 ++++++++++ .../pkg/FieldWithSimilarAnnotation.class | Bin 0 -> 3053 bytes .../src/pkg/FieldWithSimilarAnnotation.java | 24 ++++++++ .../java/psi/ClsMirrorBuildingTest.java | 36 +++++++++++- 5 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/psi/cls/mirror/FieldWithSimilarAnnotation.txt create mode 100644 java/java-tests/testData/psi/cls/mirror/pkg/FieldWithSimilarAnnotation.class create mode 100644 java/java-tests/testData/psi/cls/mirror/src/pkg/FieldWithSimilarAnnotation.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsModifierListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsModifierListImpl.java index 00321dcbe1ac..63f613f89d16 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsModifierListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsModifierListImpl.java @@ -1,6 +1,8 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.psi.impl.compiled; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.cache.ModifierFlags; @@ -12,6 +14,10 @@ import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; public class ClsModifierListImpl extends ClsRepositoryPsiElement implements PsiModifierList { public ClsModifierListImpl(PsiModifierListStub stub) { @@ -136,17 +142,54 @@ public class ClsModifierListImpl extends ClsRepositoryPsiElementtreeToPsiNotNull(element).getAnnotations(); - for (PsiAnnotation annotation : annotations) { - String qualifiedName = annotation.getQualifiedName(); - // Annotations could be inconsistent, as in stubs all type annotations are attached to the types - // not to modifier list - if (qualifiedName != null) { - PsiAnnotation mirror = ContainerUtil.find(mirrorAnnotations, m -> qualifiedName.equals(m.getQualifiedName())); + // Annotations could be inconsistent, as in stubs all type annotations are attached to the types + // not to modifier list + Map annotationByShortName = getAnnotationByShortName(annotations); + Map mirrorAnnotationByShortName = getAnnotationByShortName(mirrorAnnotations); + if (!annotationByShortName.containsKey(null) && + !mirrorAnnotationByShortName.containsKey(null) && + annotationByShortName.size() == annotations.length && + mirrorAnnotationByShortName.size() == mirrorAnnotations.length) { + //it is possible to work with short name without resolving + for (Map.Entry annotationEntry : annotationByShortName.entrySet()) { + String key = annotationEntry.getKey(); + PsiAnnotation mirror = mirrorAnnotationByShortName.get(key); if (mirror != null) { + PsiAnnotation annotation = annotationEntry.getValue(); setMirror(annotation, mirror); } } + return; } + DumbService.getInstance(getProject()).runWithAlternativeResolveEnabled(() -> { + //necessary to use AlternativeResolver, because of getQualifiedName() + for (PsiAnnotation annotation : annotations) { + String qualifiedName = annotation.getQualifiedName(); + if (qualifiedName != null) { + PsiAnnotation mirror = ContainerUtil.find(mirrorAnnotations, m -> qualifiedName.equals(m.getQualifiedName())); + if (mirror != null) { + setMirror(annotation, mirror); + } + } + } + }); + } + + @NotNull + private static Map getAnnotationByShortName(@NotNull PsiAnnotation @NotNull [] annotations) { + HashMap result = new HashMap<>(); + for (@NotNull PsiAnnotation annotation : annotations) { + result.put(getAnnotationReferenceShortName(annotation), annotation); + } + return result; + } + + private static @Nullable String getAnnotationReferenceShortName(@NotNull PsiAnnotation annotation) { + PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement(); + if (referenceElement == null) return null; + String name = referenceElement.getReferenceName(); + if (name == null) return null; + return StringUtil.getShortName(name); } @Override diff --git a/java/java-tests/testData/psi/cls/mirror/FieldWithSimilarAnnotation.txt b/java/java-tests/testData/psi/cls/mirror/FieldWithSimilarAnnotation.txt new file mode 100644 index 000000000000..7ee1679404ef --- /dev/null +++ b/java/java-tests/testData/psi/cls/mirror/FieldWithSimilarAnnotation.txt @@ -0,0 +1,31 @@ + + // IntelliJ API Decompiler stub source generated from a class file + // Implementation of methods is not available + +package com.demo; + +public class FieldWithSimilarAnnotation { + private static final long serialVersionUID = -1L; + @javax.validation.constraints.NotNull(groups = {com.demo.SupplierSubmit.class}) + @io.swagger.v3.oas.annotations.media.Schema(description = "desc") + @com.demo.NotNull + private java.lang.@javax.validation.constraints.NotNull(groups = {com.demo.SupplierSubmit.class}) Long id; + + protected FieldWithSimilarAnnotation(com.demo.FieldWithSimilarAnnotation.FieldWithSimilarAnnotationBuilder b) { /* compiled code */ } + + public static com.demo.FieldWithSimilarAnnotation.FieldWithSimilarAnnotationBuilder builder() { /* compiled code */ } + + public java.lang.Long getId() { /* compiled code */ } + + public void setId(java.lang.Long id) { /* compiled code */ } + + public java.lang.String toString() { /* compiled code */ } + + public boolean equals(java.lang.Object o) { /* compiled code */ } + + protected boolean canEqual(java.lang.Object other) { /* compiled code */ } + + public int hashCode() { /* compiled code */ } + + public FieldWithSimilarAnnotation() { /* compiled code */ } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/FieldWithSimilarAnnotation.class b/java/java-tests/testData/psi/cls/mirror/pkg/FieldWithSimilarAnnotation.class new file mode 100644 index 0000000000000000000000000000000000000000..2817d232b1a4b602a0b63f8013bbdaed62a877a4 GIT binary patch literal 3053 zcmb_eU3U{z6x}zOd^Ai$XlbEPsFi|k(lSNx15!{ZEe6tp1d0Vem?UE|IGKqvldAv1 zXMcdc@PKP+amiXPebKf2O)Bm?Gc*ZO=|i*H%)NKc*=O%_&$%~${`2!M0M6h+1~J4_ zP*fz46v#c$H+0R??S^)}`oO690?7r_HvJ0%@#&eh4AK}#A){gsRDq?M)6(ij%h8ri z!>Zpg{bt2%nU?Nev~9=Nebce0wtsc0V_J2?70Bqdn&Ej<^Yilp>(k|3fi2FIyK2gg z-6#$qi@ho2RP4i$z_A^K5r~;}=H+>)6!r_0b^!2l`K4Cd%3v6yat{s&i4 zg)xBxU6mEzHSI=})(j3Jp2oPq(e1Zj+N__KhDTLQ;1%w+-fkN<70*rgNDguP651E4 zm|vO2m)Wz_jRt{lH9@1T^d zk|}xEr-PMXI9T!Z+Gi_zJKD6wjhm&FC8F^NNV9{px*_3rSv3-S| zlpF-ql5HFAqNRJD!Q!0U-eK#OJpNJ}d6lGKvetL9NvAN$BQnMx0x=xIS)7AFF_
  • cke;ea1oa{Ui5GoOMIE+WSP$^{LeuQqtA2z3NN+y2vFkt3ZF9E zVE!>gzVH)LKVtBEF2r$_-x3N?agE=jp&`mx;fyX=#dW^F!Lb_H$(8pxy2+Iop$Bja zw>gr5CW$CN15Yr#E*@j#5htQANa(i4RbE>BmTnrKl0qW?0|uo_tjA?E;1$MBM7#v< z;DgBd9Id6eWWEro>h&J%QI*_Ml?<{hgYrg;aF&T8NsK?i!S%;DG<0|qNAjDP+{E#r zX^uCMf1X>29&#Js;>OD?!hA%`1Thy2`EQX>9u|H>_8TPP4-3B{yE04klfhJmS)JwA zIc4q->={#j$G-2N&W$OXcs;OC9ulT^yRw0>Ga>wzutlunE`yKYB<^twW6bdcKIB>) zd5qyBjud=MtPvzr>A#RoA^SH*Q;6{|%@bbU+Y$S-e9FuwByAbLH?d*-uw0&P3r!hS z#uxJXj$po~pF;16Tya4;A4na~6`K^A&K15xYHky6+&@45VuAV4H4+%dI6lFB0w>rx zI!7^ND5V+*l(LQ?_LPmIP?ivs1R { + assertSameLinesWithFile(txtPath, ClsFileImpl.decompile(file).toString()); + PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(file); + if (psiFile instanceof PsiCompiledElement compiledElement) { + PsiElement mirror = compiledElement.getMirror(); + assertNotNull(mirror); + } + }); + } public void testTextPsiMismatch() { CommonCodeStyleSettings.IndentOptions options = CodeStyle.getSettings(getProject()).getIndentOptions(JavaFileType.INSTANCE); @@ -187,7 +213,15 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase { private static void doTest(String name) { String testDir = getTestDataDir(); - doTest(testDir + "pkg/" + name + ".class", testDir + name + ".txt"); + doTest(getClsPath(name, testDir), getTxtPath(name, testDir)); + } + + private static @NotNull String getTxtPath(String name, String testDir) { + return testDir + name + ".txt"; + } + + private static @NotNull String getClsPath(String name, String testDir) { + return testDir + "pkg/" + name + ".class"; } private static void doTest(String clsPath, String txtPath) {