From 020f5c404b22085c94dde14d8888fc5257e17148 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 4 Nov 2014 11:30:23 +0100 Subject: [PATCH] java-decompiler: extra casts on method calls omitted (loosely based on https://github.com/JetBrains/intellij-community/pull/217) --- .../decompiler/exps/InvocationExprent.java | 81 ++++++++++-------- .../StructLocalVariableTableAttribute.java | 2 +- .../java/decompiler/SingleClassesTest.java | 2 + testData/classes/pkg/TestAmbiguousCall.class | Bin 0 -> 606 bytes .../pkg/TestAmbiguousCallWithDebugInfo.class | Bin 0 -> 902 bytes testData/results/TestAmbiguousCall.dec | 18 ++++ .../TestAmbiguousCallWithDebugInfo.dec | 18 ++++ testData/results/TestEnum.dec | 2 +- testData/src/pkg/TestAmbiguousCall.java | 16 ++++ 9 files changed, 102 insertions(+), 37 deletions(-) create mode 100644 testData/classes/pkg/TestAmbiguousCall.class create mode 100644 testData/classes/pkg/TestAmbiguousCallWithDebugInfo.class create mode 100644 testData/results/TestAmbiguousCall.dec create mode 100644 testData/results/TestAmbiguousCallWithDebugInfo.dec create mode 100644 testData/src/pkg/TestAmbiguousCall.java diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java index b80b745..d7d2d76 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -53,6 +53,8 @@ public class InvocationExprent extends Exprent { public static final int CONSTRUCTOR_THIS = 1; public static final int CONSTRUCTOR_SUPER = 2; + private static final BitSet EMPTY_BIT_SET = new BitSet(0); + private String name; private String classname; @@ -321,7 +323,7 @@ public class InvocationExprent extends Exprent { break; case TYP_CLINIT: - throw new RuntimeException("Explicite invocation of "); + throw new RuntimeException("Explicit invocation of "); case TYP_INIT: if (super_qualifier != null) { buf.append("super("); @@ -355,7 +357,7 @@ public class InvocationExprent extends Exprent { } } - Set setAmbiguousParameters = getAmbiguousParameters(); + BitSet setAmbiguousParameters = getAmbiguousParameters(); boolean firstParameter = true; int start = isEnum ? 2 : 0; @@ -366,7 +368,7 @@ public class InvocationExprent extends Exprent { } 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); buf.append(buff); @@ -379,47 +381,56 @@ public class InvocationExprent extends Exprent { return buf; } - private Set getAmbiguousParameters() { - - Set ret = new HashSet(); - - StructClass cstr = DecompilerContext.getStructContext().getClass(classname); - if (cstr != null) { - List lstMethods = new ArrayList(); - for (StructMethod meth : cstr.getMethods()) { - if (name.equals(meth.getName())) { - MethodDescriptor md = MethodDescriptor.parseDescriptor(meth.getDescriptor()); - if (md.params.length == descriptor.params.length) { - boolean equals = true; - 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); + private BitSet getAmbiguousParameters() { + StructClass cl = DecompilerContext.getStructContext().getClass(classname); + if (cl == null) return EMPTY_BIT_SET; + + // check number of matches + List matches = new ArrayList(); + nextMethod: + for (StructMethod mt : cl.getMethods()) { + if (name.equals(mt.getName())) { + MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); + if (md.params.length == descriptor.params.length) { + for (int i = 0; i < md.params.length; i++) { + if (md.params[i].type_family != descriptor.params[i].type_family) { + continue nextMethod; } } + matches.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; - } + } + if (matches.size() == 1) return EMPTY_BIT_SET; + + // 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; } } - return ret; + // 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) { diff --git a/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java b/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java index 60e40c0..fceae35 100644 --- a/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java +++ b/src/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java @@ -35,7 +35,7 @@ import java.util.Map; */ public class StructLocalVariableTableAttribute extends StructGeneralAttribute { - private Map mapVarNames = new HashMap(); + private Map mapVarNames = Collections.emptyMap(); @Override public void initContent(ConstantPool pool) throws IOException { diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 20d4fa8..c1b36de 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -37,4 +37,6 @@ public class SingleClassesTest extends SingleClassesTestBase { @Test public void testInnerClassConstructor() { doTest("pkg/TestInnerClassConstructor"); } @Test public void testInnerClassConstructor11() { doTest("v11/TestInnerClassConstructor"); } @Test public void testTryCatchFinally() { doTest("pkg/TestTryCatchFinally"); } + @Test public void testAmbiguousCall() { doTest("pkg/TestAmbiguousCall"); } + @Test public void testAmbiguousCallWithDebugInfo() { doTest("pkg/TestAmbiguousCallWithDebugInfo"); } } diff --git a/testData/classes/pkg/TestAmbiguousCall.class b/testData/classes/pkg/TestAmbiguousCall.class new file mode 100644 index 0000000000000000000000000000000000000000..ed5ab9a1dc2b083db05d718884f15239807f7d4a GIT binary patch literal 606 zcmah_T}uK{5IuKY-E}iHQ_DUig1}TVp_ecM5d*;rRD#~xwac=$AF}R7f2$XTg6O#) z70qsufrJlp=Wu4`%$fV~`SJ$f1Um}i$V$j55RjFTS0H0U#%7QU61F64GsMme+wjgA zBBjF{2C?PbbB0vcu=$m5Y1|#Cnn{dc)fwug?nr%9Yo==JwVrQ#hQ-@YLq7Hl$8P+o z^*z_H^+uq0`gf*dnp{`SrmOoFx4mVvqQ@s5gVJ|=cgQb{z({^TT+`AF-FN&+OEt}- zz*7PWRv7l@{{GuVxAfWxB$1+{JIxTL8FJ$Xy|$puke(}EYa>4Nut)zFr!NLX3R(+> z1fgBZjB>O*1A8XGuu5+%BqM}qCE=j8KoKwtZGmDE>1AzEYFqnVd`DV=+VLxd+ZiI= zawQ{9$wwsw5-8e_Tk?9+~+>$InO!C??2yv0(geU7M9@{cwj+;W1?fh#6uHn>U?Bi z-N1%G{e?_q{!*aUeR3?I@1`FDfu<*u;B65PgY3v3M$Fh=I`X4qKa=V{P3rkaITmPp zr=LRiC>ZC1cqqdnEylZk6!itPct>ET>z(+YeK+!x&^;)UT*krPmr-z<%QWd%-VXCj zCShOAAxODed76W