Skip to content

Commit 681b199

Browse files
committed
sync setMirror from jb
1 parent bf1086d commit 681b199

9 files changed

Lines changed: 184 additions & 25 deletions

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsBinaryExpressionImpl.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package com.intellij.java.language.impl.psi.impl.compiled;
1717

18-
import com.intellij.java.language.impl.psi.impl.source.tree.JavaElementType;
1918
import com.intellij.java.language.psi.*;
2019
import consulo.annotation.access.RequiredReadAction;
2120
import consulo.language.ast.IElementType;
@@ -44,7 +43,7 @@ public void appendMirrorText(int indentLevel, StringBuilder buffer) {
4443

4544
@Override
4645
public void setMirror(TreeElement element) throws InvalidMirrorException {
47-
setMirrorCheckingType(element, JavaElementType.BINARY_EXPRESSION);
46+
setMirrorCheckingType(element, null);
4847
}
4948

5049
@Override

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsClassImpl.java‎

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.intellij.java.language.impl.psi.impl.source.PsiClassImpl;
1717
import com.intellij.java.language.impl.psi.impl.source.PsiExtensibleClass;
1818
import com.intellij.java.language.impl.psi.scope.processor.MethodsProcessor;
19+
import com.intellij.java.language.impl.psi.util.JavaPsiRecordUtil;
1920
import com.intellij.java.language.psi.*;
2021
import com.intellij.java.language.psi.util.PsiUtil;
2122
import consulo.annotation.access.RequiredReadAction;
@@ -36,6 +37,8 @@
3637
import org.jspecify.annotations.Nullable;
3738

3839
import java.util.*;
40+
import java.util.function.Predicate;
41+
import java.util.stream.Collectors;
3942

4043
import static consulo.util.lang.ObjectUtil.assertNotNull;
4144
import static java.util.Arrays.asList;
@@ -431,24 +434,100 @@ public void setMirror(TreeElement element) throws InvalidMirrorException {
431434
setMirrorIfPresent(getDocComment(), mirror.getDocComment());
432435

433436
PsiModifierList modifierList = getModifierList();
434-
if (modifierList != null) {
437+
if (modifierList != null && mirror.getModifierList() != null) {
435438
setMirror(modifierList, mirror.getModifierList());
436439
}
437-
setMirror(getNameIdentifier(), mirror.getNameIdentifier());
438-
setMirror(getTypeParameterList(), mirror.getTypeParameterList());
439-
setMirror(getExtendsList(), mirror.getExtendsList());
440-
setMirror(getImplementsList(), mirror.getImplementsList());
440+
if (mirror.getNameIdentifier() != null) {
441+
setMirrorChecked(getNameIdentifier(), mirror.getNameIdentifier());
442+
}
443+
if (mirror.getTypeParameterList() != null) {
444+
setMirrorChecked(getTypeParameterList(), mirror.getTypeParameterList());
445+
}
446+
if (mirror.getExtendsList() != null) {
447+
setMirrorChecked(getExtendsList(), mirror.getExtendsList());
448+
}
449+
if (mirror.getImplementsList() != null) {
450+
setMirrorChecked(getImplementsList(), mirror.getImplementsList());
451+
}
441452

442453
if (mirror instanceof PsiExtensibleClass extMirror) {
443-
setMirrors(getOwnFields(), extMirror.getOwnFields());
444-
setMirrors(getOwnMethods(), extMirror.getOwnMethods());
445-
setMirrors(getOwnInnerClasses(), extMirror.getOwnInnerClasses());
454+
setMirrorsChecked(getOwnFields(), extMirror.getOwnFields());
455+
setMethodMirrorsChecked(getOwnMethods(), extMirror.getOwnMethods());
456+
//inner classes are sorted by decompiler by method lines, so it is necessary to resort
457+
setSortedMirrorsChecked(getOwnInnerClasses(), extMirror.getOwnInnerClasses(), Comparator.comparing(PsiClass::getName));
446458
}
447459
else {
448-
setMirrors(getOwnFields(), asList(mirror.getFields()));
449-
setMirrors(getOwnMethods(), asList(mirror.getMethods()));
450-
setMirrors(getOwnInnerClasses(), asList(mirror.getInnerClasses()));
460+
setMirrorsChecked(getOwnFields(), asList(mirror.getFields()));
461+
setMethodMirrorsChecked(getOwnMethods(), asList(mirror.getMethods()));
462+
//inner classes are sorted by decompiler by method lines, so it is necessary to resort
463+
setSortedMirrorsChecked(getOwnInnerClasses(), asList(mirror.getInnerClasses()), Comparator.comparing(PsiClass::getName));
464+
}
465+
}
466+
467+
private static <T extends PsiElement> void setMirrorChecked(T stub, T mirror) {
468+
setMirror(stub, mirror);
469+
}
470+
471+
private static <T extends PsiElement> void setMirrorsChecked(List<T> stubs, List<T> mirrors) {
472+
if (stubs.size() == mirrors.size()) {
473+
setMirrors(stubs, mirrors);
474+
}
475+
}
476+
477+
private static void setMethodMirrorsChecked(List<PsiMethod> stubs, List<PsiMethod> mirrors) {
478+
if (stubs.size() == mirrors.size()) {
479+
setMirrors(stubs, mirrors);
480+
}
481+
482+
// If the count of stubs and mirrors doesn't match,
483+
// it's probably because the default constructor (present in stubs) isn't present in the decompiled code (mirrors),
484+
// because it was removed by Fernflower's "high readability" mode.
485+
486+
// If after removing all constructors from both stubs and mirrors, the count is still different, then we cannot help.
487+
final long nonConstructorStubCount = stubs.stream().filter(method -> !method.isConstructor()).count();
488+
final long nonConstructorMirrorCount = mirrors.stream().filter(method -> !method.isConstructor()).count();
489+
if (nonConstructorStubCount != nonConstructorMirrorCount) {
490+
return;
451491
}
492+
493+
if (stubs.size() - 1 == mirrors.size()) {
494+
Predicate<PsiMethod> isSyntheticConstructor = (PsiMethod stubMethod) -> {
495+
final PsiClass containingClass = stubMethod.getContainingClass();
496+
if (containingClass == null) {
497+
return false;
498+
}
499+
500+
if (containingClass.isRecord()) {
501+
return JavaPsiRecordUtil.isCanonicalConstructor(stubMethod);
502+
}
503+
else {
504+
return isDefaultConstructor(stubMethod);
505+
}
506+
};
507+
508+
final List<PsiMethod> stubsWithoutSyntheticConstructor = stubs.stream()
509+
.filter(isSyntheticConstructor.negate())
510+
.collect(Collectors.toList());
511+
512+
setMirrors(stubsWithoutSyntheticConstructor, mirrors);
513+
}
514+
}
515+
516+
private static boolean isDefaultConstructor(PsiMethod stubMethod) {
517+
if (!stubMethod.isConstructor()) {
518+
return false;
519+
}
520+
if (!stubMethod.getParameterList().isEmpty()) {
521+
return false;
522+
}
523+
return true;
524+
}
525+
526+
private static <T extends PsiElement> void setSortedMirrorsChecked(List<T> stub,
527+
List<T> mirror,
528+
Comparator<? super T> comparator) {
529+
setMirrorsChecked(stub.stream().sorted(comparator).collect(Collectors.toList()),
530+
mirror.stream().sorted(comparator).collect(Collectors.toList()));
452531
}
453532

454533
@Override

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import consulo.document.util.TextRange;
2525
import consulo.language.impl.ast.TreeElement;
2626
import consulo.language.impl.psi.ResolveScopeManager;
27+
import consulo.language.impl.psi.SourceTreeToPsiMap;
2728
import consulo.language.psi.*;
2829
import consulo.language.psi.resolve.PsiScopeProcessor;
2930
import consulo.language.psi.resolve.ResolveCache;
@@ -333,6 +334,12 @@ public void appendMirrorText(final int indentLevel, final StringBuilder buffer)
333334
@Override
334335
public void setMirror(TreeElement element) throws InvalidMirrorException {
335336
setMirrorCheckingType(element, JavaElementType.JAVA_CODE_REFERENCE);
337+
338+
PsiJavaCodeReferenceElement mirror = SourceTreeToPsiMap.treeToPsiNotNull(element);
339+
PsiReferenceParameterList list = getParameterList();
340+
if (list != null) {
341+
setMirror(list, mirror.getParameterList());
342+
}
336343
}
337344

338345
@Override

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsLiteralExpressionImpl.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package com.intellij.java.language.impl.psi.impl.compiled;
1717

18-
import com.intellij.java.language.impl.psi.impl.source.tree.JavaElementType;
1918
import com.intellij.java.language.psi.JavaElementVisitor;
2019
import com.intellij.java.language.psi.PsiLiteralExpression;
2120
import com.intellij.java.language.psi.PsiType;
@@ -62,7 +61,7 @@ public void appendMirrorText(int indentLevel, StringBuilder buffer) {
6261

6362
@Override
6463
public void setMirror(TreeElement element) throws InvalidMirrorException {
65-
setMirrorCheckingType(element, JavaElementType.LITERAL_EXPRESSION);
64+
setMirrorCheckingType(element, null);
6665
}
6766

6867
@Override

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsModifierListImpl.java‎

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
import consulo.language.psi.PsiElement;
2828
import consulo.language.psi.PsiElementVisitor;
2929
import consulo.language.util.IncorrectOperationException;
30+
import consulo.project.DumbService;
31+
import consulo.util.collection.ContainerUtil;
32+
import org.jspecify.annotations.Nullable;
33+
34+
import java.util.HashMap;
35+
import java.util.Map;
3036

3137

3238
public class ClsModifierListImpl extends ClsRepositoryPsiElement<PsiModifierListStub> implements PsiModifierList {
@@ -158,7 +164,54 @@ public void appendMirrorText(int indentLevel, StringBuilder buffer) {
158164
@Override
159165
public void setMirror(TreeElement element) throws InvalidMirrorException {
160166
setMirrorCheckingType(element, JavaElementType.MODIFIER_LIST);
161-
setMirrors(getAnnotations(), SourceTreeToPsiMap.<PsiModifierList>treeToPsiNotNull(element).getAnnotations());
167+
PsiAnnotation[] annotations = getAnnotations();
168+
PsiAnnotation[] mirrorAnnotations = SourceTreeToPsiMap.<PsiModifierList>treeToPsiNotNull(element).getAnnotations();
169+
// Annotations could be inconsistent, as in stubs all type annotations are attached to the types
170+
// not to modifier list
171+
Map<String, PsiAnnotation> annotationByShortName = getAnnotationByShortName(annotations);
172+
Map<String, PsiAnnotation> mirrorAnnotationByShortName = getAnnotationByShortName(mirrorAnnotations);
173+
if (!annotationByShortName.containsKey(null) &&
174+
!mirrorAnnotationByShortName.containsKey(null) &&
175+
annotationByShortName.size() == annotations.length &&
176+
mirrorAnnotationByShortName.size() == mirrorAnnotations.length) {
177+
//it is possible to work with short name without resolving
178+
for (Map.Entry<String, PsiAnnotation> annotationEntry : annotationByShortName.entrySet()) {
179+
String key = annotationEntry.getKey();
180+
PsiAnnotation mirror = mirrorAnnotationByShortName.get(key);
181+
if (mirror != null) {
182+
PsiAnnotation annotation = annotationEntry.getValue();
183+
setMirror(annotation, mirror);
184+
}
185+
}
186+
return;
187+
}
188+
DumbService.getInstance(getProject()).runWithAlternativeResolveEnabled(() -> {
189+
//necessary to use AlternativeResolver, because of getQualifiedName()
190+
for (PsiAnnotation annotation : annotations) {
191+
String qualifiedName = annotation.getQualifiedName();
192+
if (qualifiedName != null) {
193+
PsiAnnotation mirror = ContainerUtil.find(mirrorAnnotations, m -> qualifiedName.equals(m.getQualifiedName()));
194+
if (mirror != null) {
195+
setMirror(annotation, mirror);
196+
}
197+
}
198+
}
199+
});
200+
}
201+
202+
private static Map<String, PsiAnnotation> getAnnotationByShortName(PsiAnnotation[] annotations) {
203+
HashMap<String, PsiAnnotation> result = new HashMap<>();
204+
for (PsiAnnotation annotation : annotations) {
205+
result.put(getAnnotationReferenceShortName(annotation), annotation);
206+
}
207+
return result;
208+
}
209+
210+
@Nullable
211+
private static String getAnnotationReferenceShortName(PsiAnnotation annotation) {
212+
PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement();
213+
if (referenceElement == null) return null;
214+
return referenceElement.getReferenceName();
162215
}
163216

164217
@Override

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsPrefixExpressionImpl.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package com.intellij.java.language.impl.psi.impl.compiled;
1717

18-
import com.intellij.java.language.impl.psi.impl.source.tree.JavaElementType;
1918
import com.intellij.java.language.psi.*;
2019
import consulo.language.ast.IElementType;
2120
import consulo.language.impl.ast.TreeElement;
@@ -79,7 +78,7 @@ public void appendMirrorText(int indentLevel, StringBuilder buffer) {
7978

8079
@Override
8180
public void setMirror(TreeElement element) throws InvalidMirrorException {
82-
setMirrorCheckingType(element, JavaElementType.PREFIX_EXPRESSION);
81+
setMirrorCheckingType(element, null);
8382
}
8483

8584
@Override

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsReferenceListImpl.java‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@ public void appendMirrorText(int indentLevel, StringBuilder buffer) {
100100
@Override
101101
public void setMirror(TreeElement element) throws InvalidMirrorException {
102102
setMirrorCheckingType(element, null);
103-
setMirrors(getReferenceElements(), SourceTreeToPsiMap.<PsiReferenceList>treeToPsiNotNull(element).getReferenceElements());
103+
PsiJavaCodeReferenceElement[] mirrorRefs = SourceTreeToPsiMap.<PsiReferenceList>treeToPsiNotNull(element).getReferenceElements();
104+
PsiJavaCodeReferenceElement[] stubRefs = getReferenceElements();
105+
if (mirrorRefs.length == 0 && stubRefs.length == 1 && CommonClassNames.JAVA_LANG_OBJECT.equals(stubRefs[0].getQualifiedName())) {
106+
// annotated Object type is supported in stubs but not supported in decompiler yet
107+
return;
108+
}
109+
setMirrors(stubRefs, mirrorRefs);
104110
}
105111

106112
@Override

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsReferenceParameterListImpl.java‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717

1818
import consulo.util.lang.StringUtil;
1919
import consulo.language.psi.PsiElement;
20+
import consulo.language.psi.util.PsiTreeUtil;
2021
import com.intellij.java.language.psi.PsiReferenceParameterList;
2122
import com.intellij.java.language.psi.PsiType;
2223
import com.intellij.java.language.psi.PsiTypeElement;
2324
import com.intellij.java.language.impl.psi.impl.cache.TypeAnnotationContainer;
25+
import com.intellij.java.language.impl.psi.impl.source.tree.JavaElementType;
2426
import consulo.language.impl.ast.TreeElement;
27+
import consulo.language.impl.psi.SourceTreeToPsiMap;
2528

2629
import java.util.regex.Matcher;
2730
import java.util.regex.Pattern;
@@ -46,7 +49,7 @@ public ClsReferenceParameterListImpl(PsiElement parent,
4649

4750
for(int i = 0; i < length; i++)
4851
{
49-
String s = classParameters[length - i - 1];
52+
String s = classParameters[i];
5053
char variance = ClsTypeElementImpl.VARIANCE_NONE;
5154
final Matcher extendsMatcher = EXTENDS_PREFIX.matcher(s);
5255
if(extendsMatcher.find())
@@ -69,7 +72,7 @@ else if(StringUtil.startsWithChar(s, '?'))
6972
}
7073
}
7174

72-
myTypeParameters[i] = new ClsTypeElementImpl(this, s, variance, annotations.forTypeArgument(length - i - 1));
75+
myTypeParameters[i] = new ClsTypeElementImpl(this, s, variance, annotations.forTypeArgument(i));
7376
}
7477
}
7578

@@ -81,6 +84,14 @@ public void appendMirrorText(int indentLevel, StringBuilder buffer)
8184
@Override
8285
public void setMirror(TreeElement element) throws InvalidMirrorException
8386
{
87+
setMirrorCheckingType(element, JavaElementType.REFERENCE_PARAMETER_LIST);
88+
89+
PsiReferenceParameterList mirror = SourceTreeToPsiMap.treeToPsiNotNull(element);
90+
PsiTypeElement[] children = PsiTreeUtil.getChildrenOfType(mirror, PsiTypeElement.class);
91+
if(children != null)
92+
{
93+
setMirrors(myTypeParameters, children);
94+
}
8495
}
8596

8697
@Override
@@ -98,7 +109,7 @@ public PsiType[] getTypeArguments()
98109
cachedTypes = PsiType.createArray(myTypeParameters.length);
99110
for(int i = 0; i < cachedTypes.length; i++)
100111
{
101-
cachedTypes[cachedTypes.length - i - 1] = myTypeParameters[i].getType();
112+
cachedTypes[i] = myTypeParameters[i].getType();
102113
}
103114
myTypeParametersCachedTypes = cachedTypes;
104115
}

‎java-language-impl/src/main/java/com/intellij/java/language/impl/psi/impl/compiled/ClsTypeElementImpl.java‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
import consulo.application.util.NotNullLazyValue;
1515
import consulo.application.util.NullableLazyValue;
1616
import consulo.language.impl.ast.TreeElement;
17+
import consulo.language.impl.psi.SourceTreeToPsiMap;
1718
import consulo.language.psi.PsiElement;
1819
import consulo.language.psi.PsiElementVisitor;
20+
import consulo.language.psi.util.PsiTreeUtil;
1921
import one.util.streamex.StreamEx;
2022

2123
import org.jspecify.annotations.Nullable;
@@ -111,9 +113,13 @@ public void appendMirrorText(int indentLevel, StringBuilder buffer) {
111113
public void setMirror(TreeElement element) throws InvalidMirrorException {
112114
setMirrorCheckingType(element, JavaElementType.TYPE);
113115

114-
ClsElementImpl child = myChild.getValue();
115-
if (child != null) {
116-
child.setMirror(element.getFirstChildNode());
116+
PsiTypeElement mirror = SourceTreeToPsiMap.treeToPsiNotNull(element);
117+
ClsElementImpl childValue = myChild.getValue();
118+
if (childValue instanceof ClsTypeElementImpl) {
119+
setMirror(childValue, PsiTreeUtil.getChildOfType(mirror, PsiTypeElement.class));
120+
}
121+
else if (childValue instanceof ClsJavaCodeReferenceElementImpl) {
122+
setMirror(childValue, PsiTreeUtil.getChildOfType(mirror, PsiJavaCodeReferenceElement.class));
117123
}
118124
}
119125

0 commit comments

Comments
 (0)