Detect external vararg methods too (if available on the classpath)

master
Dmitry Cherniachenko 8 years ago committed by Egor.Ushakov
parent dfd90978c9
commit 94198aa8a5
  1. 70
      src/org/jetbrains/java/decompiler/modules/decompiler/ClasspathHelper.java
  2. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java
  3. 2
      testData/results/TestClassLambda.dec
  4. 9
      testData/results/TestVarArgCalls.dec

@ -0,0 +1,70 @@
package org.jetbrains.java.decompiler.modules.decompiler;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class ClasspathHelper {
private static final Map<String, Method> METHOD_CACHE = Collections.synchronizedMap(new HashMap<>());
public static Method findMethod(String classname, String methodName, MethodDescriptor descriptor) {
String targetClass = classname.replace('/', '.');
String methodSignature = buildMethodSignature(targetClass + '.' + methodName, descriptor);
Method method;
if (METHOD_CACHE.containsKey(methodSignature)) {
method = METHOD_CACHE.get(methodSignature);
}
else {
method = findMethodOnClasspath(targetClass, methodSignature);
METHOD_CACHE.put(methodSignature, method);
}
return method;
}
private static Method findMethodOnClasspath(String targetClass, String methodSignature) {
try {
Class cls = Class.forName(targetClass);
for (Method mtd : cls.getMethods()) {
// use contains() to ignore access modifiers and thrown exceptions
if (mtd.toString().contains(methodSignature)) {
return mtd;
}
}
}
catch (Exception e) {
// ignore
}
return null;
}
private static String buildMethodSignature(String name, MethodDescriptor md) {
StringBuilder sb = new StringBuilder();
appendType(sb, md.ret);
sb.append(' ').append(name).append('(');
for (VarType param : md.params) {
appendType(sb, param);
sb.append(',');
}
if (sb.charAt(sb.length() - 1) == ',') {
sb.setLength(sb.length() - 1);
}
sb.append(')');
return sb.toString();
}
private static void appendType(StringBuilder sb, VarType type) {
sb.append(type.value.replace('/', '.'));
for (int i = 0; i < type.arrayDim; i++) {
sb.append("[]");
}
}
}

@ -22,6 +22,7 @@ import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ClasspathHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
@ -39,6 +40,7 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import org.jetbrains.java.decompiler.util.TextUtil; import org.jetbrains.java.decompiler.util.TextUtil;
import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -392,7 +394,9 @@ public class InvocationExprent extends Exprent {
} }
} }
else { else {
// TODO: try to check the class on the classpath // try to check the class on the classpath
Method mtd = ClasspathHelper.findMethod(classname, name, descriptor);
return mtd != null && mtd.isVarArgs();
} }
return false; return false;
} }

@ -15,7 +15,7 @@ public class TestClassLambda {
public int field = 0; public int field = 0;
public void testLambda() { public void testLambda() {
List var1 = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7)});// 29 List var1 = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7));// 29
int var2 = (int)Math.random();// 30 int var2 = (int)Math.random();// 30
var1.forEach((var2x) -> {// 32 var1.forEach((var2x) -> {// 32
int var3 = 2 * var2x.intValue();// 33 int var3 = 2 * var2x.intValue();// 33

@ -8,11 +8,11 @@ public class TestVarArgCalls {
this.printComplex("Test");// 9 this.printComplex("Test");// 9
this.printComplex("Test: %[0]s", new String[]{"abc"});// 10 this.printComplex("Test: %[0]s", new String[]{"abc"});// 10
this.printComplex("Test: %[0]s - %[0]s", new String[]{"abc"}, new String[]{"DEF"});// 11 this.printComplex("Test: %[0]s - %[0]s", new String[]{"abc"}, new String[]{"DEF"});// 11
String.format("Test", new Object[0]);// 13 String.format("Test");// 13
String.format("Test: %d", new Object[]{Integer.valueOf(123)});// 14 String.format("Test: %d", Integer.valueOf(123));// 14
String.format("Test: %d - %s", new Object[]{Integer.valueOf(123), "DEF"});// 15 String.format("Test: %d - %s", Integer.valueOf(123), "DEF");// 15
Object[] data = new Object[]{"Hello"};// 17 Object[] data = new Object[]{"Hello"};// 17
String.format("Test: %s", new Object[]{data});// 18 String.format("Test: %s", (Object)data);// 18
String.format("Test: %s", (Object[])data);// 19 String.format("Test: %s", (Object[])data);// 19
}// 20 }// 20
@ -46,7 +46,6 @@ class 'pkg/TestVarArgCalls' {
68 9 68 9
6c 9 6c 9
6f 10 6f 10
71 10
75 10 75 10
79 11 79 11
81 11 81 11

Loading…
Cancel
Save