mirror of
https://github.com/moparisthebest/fernflower
synced 2024-08-13 17:03:46 -04:00
IDEA-127301: handling of static method references
This commit is contained in:
parent
6606a474bf
commit
7f116b6eb5
@ -134,6 +134,16 @@ public class ClassWriter {
|
|||||||
|
|
||||||
DecompilerContext.getLogger().startWriteClass(node.simpleName);
|
DecompilerContext.getLogger().startWriteClass(node.simpleName);
|
||||||
|
|
||||||
|
if(node.lambda_information.is_method_reference) {
|
||||||
|
|
||||||
|
writer.write(ExprProcessor.getCastTypeName(new VarType(node.lambda_information.content_class_name, false)));
|
||||||
|
writer.write("::");
|
||||||
|
writer.write(node.lambda_information.content_method_name);
|
||||||
|
|
||||||
|
writer.flush();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
// lambda method
|
// lambda method
|
||||||
StructMethod mt = cl.getMethod(node.lambda_information.content_method_key);
|
StructMethod mt = cl.getMethod(node.lambda_information.content_method_key);
|
||||||
MethodWrapper meth = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
|
MethodWrapper meth = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
|
||||||
@ -191,6 +201,7 @@ public class ClassWriter {
|
|||||||
writer.write(InterpreterUtil.getIndentString(indent));
|
writer.write(InterpreterUtil.getIndentString(indent));
|
||||||
writer.write("}");
|
writer.write("}");
|
||||||
writer.flush();
|
writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASSNODE, nodeold);
|
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASSNODE, nodeold);
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ import de.fernflower.modules.decompiler.exps.InvocationExprent;
|
|||||||
import de.fernflower.modules.decompiler.vars.VarVersionPaar;
|
import de.fernflower.modules.decompiler.vars.VarVersionPaar;
|
||||||
import de.fernflower.struct.StructClass;
|
import de.fernflower.struct.StructClass;
|
||||||
import de.fernflower.struct.StructContext;
|
import de.fernflower.struct.StructContext;
|
||||||
|
import de.fernflower.struct.StructMethod;
|
||||||
import de.fernflower.struct.attr.StructInnerClassesAttribute;
|
import de.fernflower.struct.attr.StructInnerClassesAttribute;
|
||||||
import de.fernflower.struct.gen.VarType;
|
import de.fernflower.struct.gen.VarType;
|
||||||
import de.fernflower.util.InterpreterUtil;
|
import de.fernflower.util.InterpreterUtil;
|
||||||
@ -378,7 +379,7 @@ public class ClassesProcessor {
|
|||||||
|
|
||||||
public LambdaInformation lambda_information;
|
public LambdaInformation lambda_information;
|
||||||
|
|
||||||
public ClassNode(String content_method_name, String content_method_descriptor, String lambda_class_name, String lambda_method_name,
|
public ClassNode(String content_class_name, String content_method_name, String content_method_descriptor, String lambda_class_name, String lambda_method_name,
|
||||||
String lambda_method_descriptor, StructClass classStruct) { // lambda class constructor
|
String lambda_method_descriptor, StructClass classStruct) { // lambda class constructor
|
||||||
this.type = CLASS_LAMBDA;
|
this.type = CLASS_LAMBDA;
|
||||||
this.classStruct = classStruct; // 'parent' class containing the static function
|
this.classStruct = classStruct; // 'parent' class containing the static function
|
||||||
@ -389,13 +390,22 @@ public class ClassesProcessor {
|
|||||||
lambda_information.method_name = lambda_method_name;
|
lambda_information.method_name = lambda_method_name;
|
||||||
lambda_information.method_descriptor = lambda_method_descriptor;
|
lambda_information.method_descriptor = lambda_method_descriptor;
|
||||||
|
|
||||||
|
lambda_information.content_class_name = content_class_name;
|
||||||
lambda_information.content_method_name = content_method_name;
|
lambda_information.content_method_name = content_method_name;
|
||||||
lambda_information.content_method_descriptor = content_method_descriptor;
|
lambda_information.content_method_descriptor = content_method_descriptor;
|
||||||
lambda_information.content_method_key = InterpreterUtil.makeUniqueKey(lambda_information.content_method_name, lambda_information.content_method_descriptor);
|
lambda_information.content_method_key = InterpreterUtil.makeUniqueKey(lambda_information.content_method_name, lambda_information.content_method_descriptor);
|
||||||
|
|
||||||
anonimousClassType = new VarType(lambda_class_name, true);
|
anonimousClassType = new VarType(lambda_class_name, true);
|
||||||
|
|
||||||
lambda_information.is_content_method_static = ((classStruct.getMethod(content_method_name, content_method_descriptor).getAccessFlags() & CodeConstants.ACC_STATIC) != 0);
|
if(content_class_name != classStruct.qualifiedName) { // method reference. FIXME: class name alone doesn't cover it. Synthetic flag seems to be the only 'reliable' difference.
|
||||||
|
lambda_information.is_method_reference = true;
|
||||||
|
lambda_information.is_content_method_static = true; // FIXME: consider argument flag
|
||||||
|
} else {
|
||||||
|
StructMethod mt = classStruct.getMethod(content_method_name, content_method_descriptor);
|
||||||
|
|
||||||
|
lambda_information.is_method_reference = false;
|
||||||
|
lambda_information.is_content_method_static = ((mt.getAccessFlags() & CodeConstants.ACC_STATIC) != 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassNode(int type, StructClass classStruct) {
|
public ClassNode(int type, StructClass classStruct) {
|
||||||
@ -419,10 +429,13 @@ public class ClassesProcessor {
|
|||||||
public String method_name;
|
public String method_name;
|
||||||
public String method_descriptor;
|
public String method_descriptor;
|
||||||
|
|
||||||
|
public String content_class_name;
|
||||||
public String content_method_name;
|
public String content_method_name;
|
||||||
public String content_method_descriptor;
|
public String content_method_descriptor;
|
||||||
|
|
||||||
public String content_method_key;
|
public String content_method_key;
|
||||||
|
|
||||||
|
public boolean is_method_reference;
|
||||||
public boolean is_content_method_static;
|
public boolean is_content_method_static;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,9 @@ public class LambdaProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StructBootstrapMethodsAttribute bootstrap = (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
|
StructBootstrapMethodsAttribute bootstrap = (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
|
||||||
if(bootstrap != null && bootstrap.getMethodsNumber() > 0) {
|
if(bootstrap == null || bootstrap.getMethodsNumber() == 0) {
|
||||||
|
return false; // no bootstrap constants in pool
|
||||||
|
}
|
||||||
|
|
||||||
Set<Integer> lambda_methods = new HashSet<Integer>();
|
Set<Integer> lambda_methods = new HashSet<Integer>();
|
||||||
|
|
||||||
@ -66,7 +68,7 @@ public class LambdaProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(lambda_methods.isEmpty()) {
|
if(lambda_methods.isEmpty()) {
|
||||||
return false;
|
return false; // no lambda bootstrap constant found
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> mapMethodsLambda = new HashMap<String, String>();
|
Map<String, String> mapMethodsLambda = new HashMap<String, String>();
|
||||||
@ -96,8 +98,8 @@ public class LambdaProcessor {
|
|||||||
|
|
||||||
LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
|
LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
|
||||||
|
|
||||||
ClassNode node_lambda = clprocessor.new ClassNode(content_method_handle.elementname, content_method_handle.descriptor, lambda_class_name,
|
ClassNode node_lambda = clprocessor.new ClassNode(content_method_handle.classname, content_method_handle.elementname, content_method_handle.descriptor,
|
||||||
lambda_method_name, lambda_method_descriptor, cl);
|
lambda_class_name, lambda_method_name, lambda_method_descriptor, cl);
|
||||||
node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
|
node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
|
||||||
node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());
|
node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());
|
||||||
|
|
||||||
@ -110,6 +112,8 @@ public class LambdaProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mt.releaseResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
// build class hierarchy on lambda
|
// build class hierarchy on lambda
|
||||||
@ -127,8 +131,6 @@ public class LambdaProcessor {
|
|||||||
|
|
||||||
// FIXME: mixed hierarchy?
|
// FIXME: mixed hierarchy?
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +112,10 @@ public class NestedClassProcessor {
|
|||||||
|
|
||||||
private void setLambdaVars(ClassNode parent, ClassNode child) {
|
private void setLambdaVars(ClassNode parent, ClassNode child) {
|
||||||
|
|
||||||
|
if(child.lambda_information.is_method_reference) { // method reference, no code and no parameters
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final MethodWrapper meth = parent.wrapper.getMethods().getWithKey(child.lambda_information.content_method_key);
|
final MethodWrapper meth = parent.wrapper.getMethods().getWithKey(child.lambda_information.content_method_key);
|
||||||
final MethodWrapper encmeth = parent.wrapper.getMethods().getWithKey(child.enclosingMethod);
|
final MethodWrapper encmeth = parent.wrapper.getMethods().getWithKey(child.enclosingMethod);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user