Skip to content

Commit d63fc67

Browse files
authored
Properly walk the inheritance tree when checking for possibly ambiguous unboxing calls (#444)
1 parent ef138de commit d63fc67

File tree

4 files changed

+461
-20
lines changed

4 files changed

+461
-20
lines changed

src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler.exps;
33

4+
import org.jetbrains.annotations.Nullable;
45
import org.jetbrains.java.decompiler.code.CodeConstants;
56
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
67
import org.jetbrains.java.decompiler.main.DecompilerContext;
@@ -34,6 +35,7 @@
3435

3536
import java.lang.reflect.Method;
3637
import java.util.*;
38+
import java.util.function.Predicate;
3739
import java.util.stream.Collectors;
3840

3941
public class InvocationExprent extends Exprent {
@@ -992,32 +994,30 @@ public TextBuffer appendParamList(int indent) {
992994
VarType.VARTYPE_CHAR;
993995
}
994996

995-
// TODO: better way to select boxing? this doesn't seem to consider superclass implementations
996997
int count = 0;
997998
StructClass stClass = DecompilerContext.getStructContext().getClass(classname);
998999
if (stClass != null) {
999-
nextMethod:
1000-
for (StructMethod mt : stClass.getMethods()) {
1001-
if (name.equals(mt.getName()) && (currCls == null || canAccess(currCls.classStruct, mt))) {
1002-
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
1003-
if (md.params.length == descriptor.params.length) {
1004-
for (int x = 0; x < md.params.length; x++) {
1005-
if (md.params[x].typeFamily != descriptor.params[x].typeFamily &&
1006-
md.params[x].typeFamily != types[x].typeFamily
1007-
) {
1008-
continue nextMethod;
1009-
}
1000+
List<StructMethod> customMatchedDescriptors = getMatchedDescriptors((md) -> {
1001+
if (md.params.length == descriptor.params.length) {
1002+
for (int x = 0; x < md.params.length; x++) {
1003+
if (md.params[x].typeFamily != descriptor.params[x].typeFamily &&
1004+
md.params[x].typeFamily != types[x].typeFamily
1005+
) {
1006+
return false;
1007+
}
10101008

1011-
if (md.params[x].arrayDim != descriptor.params[x].arrayDim &&
1012-
md.params[x].arrayDim != types[x].arrayDim
1013-
) {
1014-
continue nextMethod;
1015-
}
1009+
if (md.params[x].arrayDim != descriptor.params[x].arrayDim &&
1010+
md.params[x].arrayDim != types[x].arrayDim
1011+
) {
1012+
return false;
10161013
}
1017-
count++;
10181014
}
1015+
return true;
10191016
}
1020-
}
1017+
1018+
return false;
1019+
});
1020+
count = customMatchedDescriptors.size();
10211021
}
10221022

10231023
if (count != matches.size()) { //We become more ambiguous? Lets keep the explicit boxing
@@ -1286,6 +1286,9 @@ public boolean shouldForceUnboxing() {
12861286
}
12871287

12881288
private List<StructMethod> getMatchedDescriptors() {
1289+
return getMatchedDescriptors(null);
1290+
}
1291+
private List<StructMethod> getMatchedDescriptors(@Nullable Predicate<MethodDescriptor> customParamMatcher) {
12891292
List<StructMethod> matches = new ArrayList<>();
12901293
ClassNode currCls = DecompilerContext.getContextProperty(DecompilerContext.CURRENT_CLASS_NODE);
12911294
StructClass cl = DecompilerContext.getStructContext().getClass(classname);
@@ -1303,7 +1306,13 @@ private List<StructMethod> getMatchedDescriptors() {
13031306
for (StructMethod mt : cls.getMethods()) {
13041307
if (name.equals(mt.getName())) {
13051308
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
1306-
if (matches(md.params, descriptor.params) && (currCls == null || canAccess(currCls.classStruct, mt))) {
1309+
boolean matchedParams;
1310+
if (customParamMatcher == null) {
1311+
matchedParams = matches(md.params, descriptor.params);
1312+
} else {
1313+
matchedParams = customParamMatcher.test(md);
1314+
}
1315+
if (matchedParams && (currCls == null || canAccess(currCls.classStruct, mt))) {
13071316
matches.add(mt);
13081317
}
13091318
}

test/org/jetbrains/java/decompiler/SingleClassesTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ private void registerDefault() {
710710
register(JAVA_8, "TestAnonymousClassToLambda");
711711
// TODO: broken stack processing, deleted ternary!
712712
register(JAVA_17, "TestPatternMatchingLoops");
713+
register(JAVA_8, "TestBoxingSuperclass");
713714
}
714715

715716
private void registerEntireClassPath() {

0 commit comments

Comments
 (0)