java-decompiler: extra casts on method calls omitted
(loosely based on https://github.com/JetBrains/intellij-community/pull/217)
This commit is contained in:
@@ -53,6 +53,8 @@ public class InvocationExprent extends Exprent {
|
|||||||
public static final int CONSTRUCTOR_THIS = 1;
|
public static final int CONSTRUCTOR_THIS = 1;
|
||||||
public static final int CONSTRUCTOR_SUPER = 2;
|
public static final int CONSTRUCTOR_SUPER = 2;
|
||||||
|
|
||||||
|
private static final BitSet EMPTY_BIT_SET = new BitSet(0);
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private String classname;
|
private String classname;
|
||||||
@@ -321,7 +323,7 @@ public class InvocationExprent extends Exprent {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case TYP_CLINIT:
|
case TYP_CLINIT:
|
||||||
throw new RuntimeException("Explicite invocation of <clinit>");
|
throw new RuntimeException("Explicit invocation of <clinit>");
|
||||||
case TYP_INIT:
|
case TYP_INIT:
|
||||||
if (super_qualifier != null) {
|
if (super_qualifier != null) {
|
||||||
buf.append("super(");
|
buf.append("super(");
|
||||||
@@ -355,7 +357,7 @@ public class InvocationExprent extends Exprent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<Integer> setAmbiguousParameters = getAmbiguousParameters();
|
BitSet setAmbiguousParameters = getAmbiguousParameters();
|
||||||
|
|
||||||
boolean firstParameter = true;
|
boolean firstParameter = true;
|
||||||
int start = isEnum ? 2 : 0;
|
int start = isEnum ? 2 : 0;
|
||||||
@@ -366,7 +368,7 @@ public class InvocationExprent extends Exprent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextBuffer buff = new TextBuffer();
|
TextBuffer buff = new TextBuffer();
|
||||||
boolean ambiguous = setAmbiguousParameters.contains(i);
|
boolean ambiguous = setAmbiguousParameters.get(i);
|
||||||
ExprProcessor.getCastedExprent(lstParameters.get(i), descriptor.params[i], buff, indent, true, ambiguous, tracer);
|
ExprProcessor.getCastedExprent(lstParameters.get(i), descriptor.params[i], buff, indent, true, ambiguous, tracer);
|
||||||
buf.append(buff);
|
buf.append(buff);
|
||||||
|
|
||||||
@@ -379,47 +381,56 @@ public class InvocationExprent extends Exprent {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<Integer> getAmbiguousParameters() {
|
private BitSet getAmbiguousParameters() {
|
||||||
|
StructClass cl = DecompilerContext.getStructContext().getClass(classname);
|
||||||
|
if (cl == null) return EMPTY_BIT_SET;
|
||||||
|
|
||||||
Set<Integer> ret = new HashSet<Integer>();
|
// check number of matches
|
||||||
|
List<MethodDescriptor> matches = new ArrayList<MethodDescriptor>();
|
||||||
StructClass cstr = DecompilerContext.getStructContext().getClass(classname);
|
nextMethod:
|
||||||
if (cstr != null) {
|
for (StructMethod mt : cl.getMethods()) {
|
||||||
List<MethodDescriptor> lstMethods = new ArrayList<MethodDescriptor>();
|
if (name.equals(mt.getName())) {
|
||||||
for (StructMethod meth : cstr.getMethods()) {
|
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
|
||||||
if (name.equals(meth.getName())) {
|
if (md.params.length == descriptor.params.length) {
|
||||||
MethodDescriptor md = MethodDescriptor.parseDescriptor(meth.getDescriptor());
|
for (int i = 0; i < md.params.length; i++) {
|
||||||
if (md.params.length == descriptor.params.length) {
|
if (md.params[i].type_family != descriptor.params[i].type_family) {
|
||||||
boolean equals = true;
|
continue nextMethod;
|
||||||
for (int i = 0; i < md.params.length; i++) {
|
|
||||||
if (md.params[i].type_family != descriptor.params[i].type_family) {
|
|
||||||
equals = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (equals) {
|
|
||||||
lstMethods.add(md);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lstMethods.size() > 1) {
|
|
||||||
for (int i = 0; i < descriptor.params.length; i++) {
|
|
||||||
VarType partype = descriptor.params[i];
|
|
||||||
|
|
||||||
for (MethodDescriptor md : lstMethods) {
|
|
||||||
if (!partype.equals(md.params[i])) {
|
|
||||||
ret.add(i);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
matches.add(md);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (matches.size() == 1) return EMPTY_BIT_SET;
|
||||||
|
|
||||||
return ret;
|
// check if a call is unambiguous
|
||||||
|
StructMethod mt = cl.getMethod(InterpreterUtil.makeUniqueKey(name, stringDescriptor));
|
||||||
|
if (mt != null) {
|
||||||
|
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
|
||||||
|
if (md.params.length == lstParameters.size()) {
|
||||||
|
boolean exact = true;
|
||||||
|
for (int i = 0; i < md.params.length; i++) {
|
||||||
|
if (!md.params[i].equals(lstParameters.get(i).getExprType())) {
|
||||||
|
exact = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exact) return EMPTY_BIT_SET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark parameters
|
||||||
|
BitSet ambiguous = new BitSet(descriptor.params.length);
|
||||||
|
for (int i = 0; i < descriptor.params.length; i++) {
|
||||||
|
VarType paramType = descriptor.params[i];
|
||||||
|
for (MethodDescriptor md : matches) {
|
||||||
|
if (!paramType.equals(md.params[i])) {
|
||||||
|
ambiguous.set(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ambiguous;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class StructLocalVariableTableAttribute extends StructGeneralAttribute {
|
public class StructLocalVariableTableAttribute extends StructGeneralAttribute {
|
||||||
|
|
||||||
private Map<Integer, String> mapVarNames = new HashMap<Integer, String>();
|
private Map<Integer, String> mapVarNames = Collections.emptyMap();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initContent(ConstantPool pool) throws IOException {
|
public void initContent(ConstantPool pool) throws IOException {
|
||||||
|
|||||||
@@ -37,4 +37,6 @@ public class SingleClassesTest extends SingleClassesTestBase {
|
|||||||
@Test public void testInnerClassConstructor() { doTest("pkg/TestInnerClassConstructor"); }
|
@Test public void testInnerClassConstructor() { doTest("pkg/TestInnerClassConstructor"); }
|
||||||
@Test public void testInnerClassConstructor11() { doTest("v11/TestInnerClassConstructor"); }
|
@Test public void testInnerClassConstructor11() { doTest("v11/TestInnerClassConstructor"); }
|
||||||
@Test public void testTryCatchFinally() { doTest("pkg/TestTryCatchFinally"); }
|
@Test public void testTryCatchFinally() { doTest("pkg/TestTryCatchFinally"); }
|
||||||
|
@Test public void testAmbiguousCall() { doTest("pkg/TestAmbiguousCall"); }
|
||||||
|
@Test public void testAmbiguousCallWithDebugInfo() { doTest("pkg/TestAmbiguousCallWithDebugInfo"); }
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
testData/classes/pkg/TestAmbiguousCall.class
Normal file
BIN
testData/classes/pkg/TestAmbiguousCall.class
Normal file
Binary file not shown.
BIN
testData/classes/pkg/TestAmbiguousCallWithDebugInfo.class
Normal file
BIN
testData/classes/pkg/TestAmbiguousCallWithDebugInfo.class
Normal file
Binary file not shown.
18
testData/results/TestAmbiguousCall.dec
Normal file
18
testData/results/TestAmbiguousCall.dec
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package pkg;
|
||||||
|
|
||||||
|
class TestAmbiguousCall {
|
||||||
|
void m1(RuntimeException var1, String var2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void m1(IllegalArgumentException var1, String var2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
IllegalArgumentException var1 = new IllegalArgumentException();
|
||||||
|
this.m1((RuntimeException)var1, "RE");
|
||||||
|
this.m1(var1, "IAE");
|
||||||
|
IllegalArgumentException var2 = new IllegalArgumentException();
|
||||||
|
this.m1((RuntimeException)var2, "RE");
|
||||||
|
this.m1((IllegalArgumentException)var2, "IAE");
|
||||||
|
}
|
||||||
|
}
|
||||||
18
testData/results/TestAmbiguousCallWithDebugInfo.dec
Normal file
18
testData/results/TestAmbiguousCallWithDebugInfo.dec
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package pkg;
|
||||||
|
|
||||||
|
class TestAmbiguousCall {
|
||||||
|
void m1(RuntimeException e, String s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void m1(IllegalArgumentException e, String s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
IllegalArgumentException iae = new IllegalArgumentException();
|
||||||
|
this.m1((RuntimeException)iae, "RE");
|
||||||
|
this.m1(iae, "IAE");
|
||||||
|
IllegalArgumentException re = new IllegalArgumentException();
|
||||||
|
this.m1((RuntimeException)re, "RE");
|
||||||
|
this.m1((IllegalArgumentException)re, "IAE");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ public enum TestEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TestEnum() {
|
private TestEnum() {
|
||||||
this((String)"?");
|
this("?");
|
||||||
}
|
}
|
||||||
|
|
||||||
private TestEnum(@Deprecated String var3) {
|
private TestEnum(@Deprecated String var3) {
|
||||||
|
|||||||
16
testData/src/pkg/TestAmbiguousCall.java
Normal file
16
testData/src/pkg/TestAmbiguousCall.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package pkg;
|
||||||
|
|
||||||
|
class TestAmbiguousCall {
|
||||||
|
void m1(RuntimeException e, String s) { }
|
||||||
|
void m1(IllegalArgumentException e, String s) { }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
IllegalArgumentException iae = new IllegalArgumentException();
|
||||||
|
m1((RuntimeException)iae, "RE");
|
||||||
|
m1(iae, "IAE");
|
||||||
|
|
||||||
|
RuntimeException re = new IllegalArgumentException();
|
||||||
|
m1(re, "RE");
|
||||||
|
m1((IllegalArgumentException)re, "IAE");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user