Detect external vararg methods too (if available on the classpath)
This commit is contained in:
committed by
Egor.Ushakov
parent
dfd90978c9
commit
94198aa8a5
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user