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

This commit is contained in:
Dmitry Cherniachenko
2017-04-18 23:34:08 +02:00
committed by Egor.Ushakov
parent dfd90978c9
commit 94198aa8a5
4 changed files with 80 additions and 7 deletions

View File

@@ -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("[]");
}
}
}

View File

@@ -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.extern.IFernflowerPreferences;
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.vars.CheckTypesResult;
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.TextUtil;
import java.lang.reflect.Method;
import java.util.*;
import java.util.Map.Entry;
@@ -392,7 +394,9 @@ public class InvocationExprent extends Exprent {
}
}
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;
}