mirror of
https://github.com/moparisthebest/fernflower
synced 2024-12-23 08:08:49 -05:00
IDEA-127301: handling of static method references
This commit is contained in:
parent
6606a474bf
commit
7f116b6eb5
@ -134,63 +134,74 @@ public class ClassWriter {
|
||||
|
||||
DecompilerContext.getLogger().startWriteClass(node.simpleName);
|
||||
|
||||
// lambda method
|
||||
StructMethod mt = cl.getMethod(node.lambda_information.content_method_key);
|
||||
MethodWrapper meth = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
|
||||
|
||||
MethodDescriptor md_content = MethodDescriptor.parseDescriptor(node.lambda_information.content_method_descriptor);
|
||||
MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(node.lambda_information.method_descriptor);
|
||||
if(node.lambda_information.is_method_reference) {
|
||||
|
||||
if(!lambda_to_anonymous) { // lambda parameters '() ->'
|
||||
|
||||
StringBuilder buff = new StringBuilder("(");
|
||||
|
||||
boolean firstpar = true;
|
||||
int index = 1;
|
||||
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();
|
||||
|
||||
int start_index = md_content.params.length - md_lambda.params.length;
|
||||
|
||||
for(int i=0;i<md_content.params.length;i++) {
|
||||
|
||||
if(i >= start_index) {
|
||||
|
||||
if(!firstpar) {
|
||||
buff.append(", ");
|
||||
}
|
||||
|
||||
String parname = meth.varproc.getVarName(new VarVersionPaar(index, 0));
|
||||
buff.append(parname==null ? "param"+index : parname); // null iff decompiled with errors
|
||||
|
||||
firstpar = false;
|
||||
}
|
||||
|
||||
index+=md_content.params[i].stack_size;
|
||||
}
|
||||
buff.append(") ->");
|
||||
|
||||
writer.write(buff.toString());
|
||||
}
|
||||
|
||||
StringWriter strwriter = new StringWriter();
|
||||
BufferedWriter bufstrwriter = new BufferedWriter(strwriter);
|
||||
|
||||
if(lambda_to_anonymous) {
|
||||
methodLambdaToJava(node, node_content, mt, bufstrwriter, indent+1, false);
|
||||
} else {
|
||||
methodLambdaToJava(node, node_content, mt, bufstrwriter, indent, true);
|
||||
}
|
||||
|
||||
bufstrwriter.flush();
|
||||
|
||||
// closing up class definition
|
||||
writer.write(" {");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
|
||||
writer.write(strwriter.toString());
|
||||
|
||||
writer.write(InterpreterUtil.getIndentString(indent));
|
||||
writer.write("}");
|
||||
writer.flush();
|
||||
// lambda method
|
||||
StructMethod mt = cl.getMethod(node.lambda_information.content_method_key);
|
||||
MethodWrapper meth = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
|
||||
|
||||
MethodDescriptor md_content = MethodDescriptor.parseDescriptor(node.lambda_information.content_method_descriptor);
|
||||
MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(node.lambda_information.method_descriptor);
|
||||
|
||||
if(!lambda_to_anonymous) { // lambda parameters '() ->'
|
||||
|
||||
StringBuilder buff = new StringBuilder("(");
|
||||
|
||||
boolean firstpar = true;
|
||||
int index = 1;
|
||||
|
||||
int start_index = md_content.params.length - md_lambda.params.length;
|
||||
|
||||
for(int i=0;i<md_content.params.length;i++) {
|
||||
|
||||
if(i >= start_index) {
|
||||
|
||||
if(!firstpar) {
|
||||
buff.append(", ");
|
||||
}
|
||||
|
||||
String parname = meth.varproc.getVarName(new VarVersionPaar(index, 0));
|
||||
buff.append(parname==null ? "param"+index : parname); // null iff decompiled with errors
|
||||
|
||||
firstpar = false;
|
||||
}
|
||||
|
||||
index+=md_content.params[i].stack_size;
|
||||
}
|
||||
buff.append(") ->");
|
||||
|
||||
writer.write(buff.toString());
|
||||
}
|
||||
|
||||
StringWriter strwriter = new StringWriter();
|
||||
BufferedWriter bufstrwriter = new BufferedWriter(strwriter);
|
||||
|
||||
if(lambda_to_anonymous) {
|
||||
methodLambdaToJava(node, node_content, mt, bufstrwriter, indent+1, false);
|
||||
} else {
|
||||
methodLambdaToJava(node, node_content, mt, bufstrwriter, indent, true);
|
||||
}
|
||||
|
||||
bufstrwriter.flush();
|
||||
|
||||
// closing up class definition
|
||||
writer.write(" {");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
|
||||
writer.write(strwriter.toString());
|
||||
|
||||
writer.write(InterpreterUtil.getIndentString(indent));
|
||||
writer.write("}");
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASSNODE, nodeold);
|
||||
|
||||
@ -345,18 +356,18 @@ public class ClassWriter {
|
||||
}
|
||||
}
|
||||
|
||||
if(isDeprecated) {
|
||||
writer.write(indstr);
|
||||
writer.write("/** @deprecated */");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
if (isDeprecated) {
|
||||
writer.write(indstr);
|
||||
writer.write("/** @deprecated */");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
|
||||
// class annotations
|
||||
List<AnnotationExprent> lstAnn = getAllAnnotations(cl.getAttributes());
|
||||
for(AnnotationExprent annexpr : lstAnn) {
|
||||
writer.write(annexpr.toJava(indent));
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
List<AnnotationExprent> lstAnn = getAllAnnotations(cl.getAttributes());
|
||||
for(AnnotationExprent annexpr : lstAnn) {
|
||||
writer.write(annexpr.toJava(indent));
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
|
||||
boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || cl.getAttributes().containsKey("Synthetic");
|
||||
|
||||
@ -481,18 +492,18 @@ public class ClassWriter {
|
||||
|
||||
boolean isDeprecated = fd.getAttributes().containsKey("Deprecated");
|
||||
|
||||
if(isDeprecated) {
|
||||
writer.write(indstr);
|
||||
writer.write("/** @deprecated */");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
if (isDeprecated) {
|
||||
writer.write(indstr);
|
||||
writer.write("/** @deprecated */");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
|
||||
// field annotations
|
||||
List<AnnotationExprent> lstAnn = getAllAnnotations(fd.getAttributes());
|
||||
for(AnnotationExprent annexpr : lstAnn) {
|
||||
writer.write(annexpr.toJava(indent));
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
List<AnnotationExprent> lstAnn = getAllAnnotations(fd.getAttributes());
|
||||
for(AnnotationExprent annexpr : lstAnn) {
|
||||
writer.write(annexpr.toJava(indent));
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
|
||||
boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || fd.getAttributes().containsKey("Synthetic");
|
||||
boolean isEnum = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM) && (flags & CodeConstants.ACC_ENUM) != 0;
|
||||
@ -674,7 +685,7 @@ public class ClassWriter {
|
||||
|
||||
boolean isInterface = (cl.access_flags & CodeConstants.ACC_INTERFACE) != 0;
|
||||
boolean isAnnotation = (cl.access_flags & CodeConstants.ACC_ANNOTATION) != 0;
|
||||
boolean isEnum = (cl.access_flags & CodeConstants.ACC_ENUM) != 0 && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
|
||||
boolean isEnum = (cl.access_flags & CodeConstants.ACC_ENUM) != 0 && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
|
||||
boolean isDeprecated = mt.getAttributes().containsKey("Deprecated");
|
||||
|
||||
String indstr = InterpreterUtil.getIndentString(indent);
|
||||
@ -705,18 +716,18 @@ public class ClassWriter {
|
||||
}
|
||||
}
|
||||
|
||||
if(isDeprecated) {
|
||||
writer.write(indstr);
|
||||
writer.write("/** @deprecated */");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
if (isDeprecated) {
|
||||
writer.write(indstr);
|
||||
writer.write("/** @deprecated */");
|
||||
writer.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
|
||||
// method annotations
|
||||
List<AnnotationExprent> lstAnn = getAllAnnotations(mt.getAttributes());
|
||||
for(AnnotationExprent annexpr : lstAnn) {
|
||||
bufstrwriter.write(annexpr.toJava(indent));
|
||||
bufstrwriter.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
// method annotations
|
||||
List<AnnotationExprent> lstAnn = getAllAnnotations(mt.getAttributes());
|
||||
for(AnnotationExprent annexpr : lstAnn) {
|
||||
bufstrwriter.write(annexpr.toJava(indent));
|
||||
bufstrwriter.write(DecompilerContext.getNewLineSeparator());
|
||||
}
|
||||
|
||||
boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic");
|
||||
boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0;
|
||||
@ -747,19 +758,19 @@ public class ClassWriter {
|
||||
bufstrwriter.write("default ");
|
||||
}
|
||||
|
||||
String name = mt.getName();
|
||||
if("<init>".equals(name)) {
|
||||
if(node.type == ClassNode.CLASS_ANONYMOUS) {
|
||||
name = "";
|
||||
dinit = true;
|
||||
} else {
|
||||
name = node.simpleName;
|
||||
init = true;
|
||||
}
|
||||
} else if("<clinit>".equals(name)) {
|
||||
name = "";
|
||||
clinit = true;
|
||||
}
|
||||
String name = mt.getName();
|
||||
if ("<init>".equals(name)) {
|
||||
if (node.type == ClassNode.CLASS_ANONYMOUS) {
|
||||
name = "";
|
||||
dinit = true;
|
||||
} else {
|
||||
name = node.simpleName;
|
||||
init = true;
|
||||
}
|
||||
} else if ("<clinit>".equals(name)) {
|
||||
name = "";
|
||||
clinit = true;
|
||||
}
|
||||
|
||||
GenericMethodDescriptor descriptor = null;
|
||||
if(DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
|
||||
@ -793,14 +804,14 @@ public class ClassWriter {
|
||||
bufstrwriter.write(descriptor.fparameters.get(i));
|
||||
|
||||
List<GenericType> lstBounds = descriptor.fbounds.get(i);
|
||||
if (lstBounds.size() > 1 || !"java/lang/Object".equals(lstBounds.get(0).value)) {
|
||||
bufstrwriter.write(" extends ");
|
||||
bufstrwriter.write(GenericMain.getGenericCastTypeName(lstBounds.get(0)));
|
||||
if (lstBounds.size() > 1 || !"java/lang/Object".equals(lstBounds.get(0).value)) {
|
||||
bufstrwriter.write(" extends ");
|
||||
bufstrwriter.write(GenericMain.getGenericCastTypeName(lstBounds.get(0)));
|
||||
|
||||
for(int j=1;j<lstBounds.size();j++) {
|
||||
bufstrwriter.write(" & " + GenericMain.getGenericCastTypeName(lstBounds.get(j)));
|
||||
}
|
||||
}
|
||||
for(int j = 1; j < lstBounds.size(); j++) {
|
||||
bufstrwriter.write(" & " + GenericMain.getGenericCastTypeName(lstBounds.get(j)));
|
||||
}
|
||||
}
|
||||
}
|
||||
bufstrwriter.write("> ");
|
||||
}
|
||||
@ -831,11 +842,11 @@ public class ClassWriter {
|
||||
}
|
||||
|
||||
boolean firstpar = true;
|
||||
int index = isEnum && init ? 3 : thisvar ? 1 : 0;
|
||||
int start = isEnum && init && descriptor == null ? 2 : 0;
|
||||
int params = descriptor == null ? md.params.length : descriptor.params.size();
|
||||
for(int i=start;i<params;i++) {
|
||||
if(signFields == null || signFields.get(i) == null) {
|
||||
int index = isEnum && init ? 3 : thisvar ? 1 : 0;
|
||||
int start = isEnum && init && descriptor == null ? 2 : 0;
|
||||
int params = descriptor == null ? md.params.length : descriptor.params.size();
|
||||
for(int i = start; i < params; i++) {
|
||||
if (signFields == null || signFields.get(i) == null) {
|
||||
|
||||
if(!firstpar) {
|
||||
bufstrwriter.write(", ");
|
||||
|
@ -41,6 +41,7 @@ import de.fernflower.modules.decompiler.exps.InvocationExprent;
|
||||
import de.fernflower.modules.decompiler.vars.VarVersionPaar;
|
||||
import de.fernflower.struct.StructClass;
|
||||
import de.fernflower.struct.StructContext;
|
||||
import de.fernflower.struct.StructMethod;
|
||||
import de.fernflower.struct.attr.StructInnerClassesAttribute;
|
||||
import de.fernflower.struct.gen.VarType;
|
||||
import de.fernflower.util.InterpreterUtil;
|
||||
@ -378,7 +379,7 @@ public class ClassesProcessor {
|
||||
|
||||
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
|
||||
this.type = CLASS_LAMBDA;
|
||||
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_descriptor = lambda_method_descriptor;
|
||||
|
||||
lambda_information.content_class_name = content_class_name;
|
||||
lambda_information.content_method_name = content_method_name;
|
||||
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);
|
||||
|
||||
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) {
|
||||
@ -419,10 +429,13 @@ public class ClassesProcessor {
|
||||
public String method_name;
|
||||
public String method_descriptor;
|
||||
|
||||
public String content_class_name;
|
||||
public String content_method_name;
|
||||
public String content_method_descriptor;
|
||||
|
||||
public String content_method_key;
|
||||
|
||||
public boolean is_method_reference;
|
||||
public boolean is_content_method_static;
|
||||
}
|
||||
}
|
||||
|
@ -50,85 +50,87 @@ public class LambdaProcessor {
|
||||
}
|
||||
|
||||
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>();
|
||||
|
||||
// find lambda bootstrap constants
|
||||
for(int i = 0; i < bootstrap.getMethodsNumber(); ++i) {
|
||||
LinkConstant method_ref = bootstrap.getMethodReference(i); // method handle
|
||||
|
||||
Set<Integer> lambda_methods = new HashSet<Integer>();
|
||||
|
||||
// find lambda bootstrap constants
|
||||
for(int i = 0; i < bootstrap.getMethodsNumber(); ++i) {
|
||||
LinkConstant method_ref = bootstrap.getMethodReference(i); // method handle
|
||||
|
||||
if(JAVAC_LAMBDA_CLASS.equals(method_ref.classname) &&
|
||||
JAVAC_LAMBDA_METHOD.equals(method_ref.elementname) &&
|
||||
JAVAC_LAMBDA_METHOD_DESCRIPTOR.equals(method_ref.descriptor)) { // check for javac lambda structure. FIXME: extend for Eclipse etc. at some point
|
||||
lambda_methods.add(i);
|
||||
}
|
||||
if(JAVAC_LAMBDA_CLASS.equals(method_ref.classname) &&
|
||||
JAVAC_LAMBDA_METHOD.equals(method_ref.elementname) &&
|
||||
JAVAC_LAMBDA_METHOD_DESCRIPTOR.equals(method_ref.descriptor)) { // check for javac lambda structure. FIXME: extend for Eclipse etc. at some point
|
||||
lambda_methods.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
if(lambda_methods.isEmpty()) {
|
||||
return false; // no lambda bootstrap constant found
|
||||
}
|
||||
|
||||
Map<String, String> mapMethodsLambda = new HashMap<String, String>();
|
||||
|
||||
// iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
|
||||
for(StructMethod mt: cl.getMethods()) {
|
||||
mt.expandData();
|
||||
|
||||
if(lambda_methods.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, String> mapMethodsLambda = new HashMap<String, String>();
|
||||
|
||||
// iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
|
||||
for(StructMethod mt: cl.getMethods()) {
|
||||
mt.expandData();
|
||||
InstructionSequence seq = mt.getInstructionSequence();
|
||||
if(seq != null && seq.length() > 0) {
|
||||
int len = seq.length();
|
||||
|
||||
InstructionSequence seq = mt.getInstructionSequence();
|
||||
if(seq != null && seq.length() > 0) {
|
||||
int len = seq.length();
|
||||
for(int i = 0; i < len; ++i) {
|
||||
Instruction instr = seq.getInstr(i);
|
||||
|
||||
for(int i = 0; i < len; ++i) {
|
||||
Instruction instr = seq.getInstr(i);
|
||||
if(instr.opcode == CodeConstants.opc_invokedynamic) {
|
||||
LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.getOperand(0));
|
||||
|
||||
if(instr.opcode == CodeConstants.opc_invokedynamic) {
|
||||
LinkConstant invoke_dynamic = cl.getPool().getLinkConstant(instr.getOperand(0));
|
||||
if(lambda_methods.contains(invoke_dynamic.index1)) { // lambda invocation found
|
||||
|
||||
if(lambda_methods.contains(invoke_dynamic.index1)) { // lambda invocation found
|
||||
|
||||
List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_dynamic.index1);
|
||||
MethodDescriptor md = MethodDescriptor.parseDescriptor(invoke_dynamic.descriptor);
|
||||
List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_dynamic.index1);
|
||||
MethodDescriptor md = MethodDescriptor.parseDescriptor(invoke_dynamic.descriptor);
|
||||
|
||||
String lambda_class_name = md.ret.value;
|
||||
String lambda_method_name = invoke_dynamic.elementname;
|
||||
String lambda_method_descriptor = ((PrimitiveConstant)bootstrap_arguments.get(2)).getString(); // method type
|
||||
|
||||
LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
|
||||
String lambda_class_name = md.ret.value;
|
||||
String lambda_method_name = invoke_dynamic.elementname;
|
||||
String lambda_method_descriptor = ((PrimitiveConstant)bootstrap_arguments.get(2)).getString(); // method type
|
||||
|
||||
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,
|
||||
lambda_method_name, lambda_method_descriptor, cl);
|
||||
node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
|
||||
node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());
|
||||
ClassNode node_lambda = clprocessor.new ClassNode(content_method_handle.classname, content_method_handle.elementname, content_method_handle.descriptor,
|
||||
lambda_class_name, lambda_method_name, lambda_method_descriptor, cl);
|
||||
node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
|
||||
node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());
|
||||
|
||||
node.nested.add(node_lambda);
|
||||
node_lambda.parent = node;
|
||||
|
||||
clprocessor.getMapRootClasses().put(node_lambda.simpleName, node_lambda);
|
||||
mapMethodsLambda.put(node_lambda.lambda_information.content_method_key, node_lambda.simpleName);
|
||||
}
|
||||
node.nested.add(node_lambda);
|
||||
node_lambda.parent = node;
|
||||
|
||||
clprocessor.getMapRootClasses().put(node_lambda.simpleName, node_lambda);
|
||||
mapMethodsLambda.put(node_lambda.lambda_information.content_method_key, node_lambda.simpleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build class hierarchy on lambda
|
||||
for(ClassNode nd : node.nested) {
|
||||
if(nd.type == ClassNode.CLASS_LAMBDA) {
|
||||
String parent_class_name = mapMethodsLambda.get(nd.enclosingMethod);
|
||||
if(parent_class_name != null) {
|
||||
ClassNode parent_class = clprocessor.getMapRootClasses().get(parent_class_name);
|
||||
|
||||
parent_class.nested.add(nd);
|
||||
nd.parent = parent_class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: mixed hierarchy?
|
||||
|
||||
mt.releaseResources();
|
||||
}
|
||||
|
||||
// build class hierarchy on lambda
|
||||
for(ClassNode nd : node.nested) {
|
||||
if(nd.type == ClassNode.CLASS_LAMBDA) {
|
||||
String parent_class_name = mapMethodsLambda.get(nd.enclosingMethod);
|
||||
if(parent_class_name != null) {
|
||||
ClassNode parent_class = clprocessor.getMapRootClasses().get(parent_class_name);
|
||||
|
||||
parent_class.nested.add(nd);
|
||||
nd.parent = parent_class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: mixed hierarchy?
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -76,19 +76,19 @@ public class NestedClassProcessor {
|
||||
checkNotFoundClasses(root, node);
|
||||
}
|
||||
|
||||
int nameless = 0, synthetics = 0;
|
||||
for(ClassNode child : node.nested) {
|
||||
// ensure not-empty class name
|
||||
if((child.type == ClassNode.CLASS_LOCAL || child.type == ClassNode.CLASS_MEMBER) && child.simpleName == null) {
|
||||
StructClass cl = child.classStruct;
|
||||
if(((child.access | cl.access_flags) & CodeConstants.ACC_SYNTHETIC) != 0 || cl.getAttributes().containsKey("Synthetic")) {
|
||||
child.simpleName = "SyntheticClass_" + (++synthetics);
|
||||
} else {
|
||||
DecompilerContext.getLogger().writeMessage("Nameless local or member class " + cl.qualifiedName + "!", IFernflowerLogger.WARNING);
|
||||
child.simpleName = "NamelessClass_" + (++nameless);
|
||||
}
|
||||
}
|
||||
}
|
||||
int nameless = 0, synthetics = 0;
|
||||
for(ClassNode child : node.nested) {
|
||||
// ensure not-empty class name
|
||||
if ((child.type == ClassNode.CLASS_LOCAL || child.type == ClassNode.CLASS_MEMBER) && child.simpleName == null) {
|
||||
StructClass cl = child.classStruct;
|
||||
if (((child.access | cl.access_flags) & CodeConstants.ACC_SYNTHETIC) != 0 || cl.getAttributes().containsKey("Synthetic")) {
|
||||
child.simpleName = "SyntheticClass_" + (++synthetics);
|
||||
} else {
|
||||
DecompilerContext.getLogger().writeMessage("Nameless local or member class " + cl.qualifiedName + "!", IFernflowerLogger.WARNING);
|
||||
child.simpleName = "NamelessClass_" + (++nameless);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(ClassNode child : node.nested) {
|
||||
if(child.type == ClassNode.CLASS_LAMBDA) {
|
||||
@ -112,6 +112,10 @@ public class NestedClassProcessor {
|
||||
|
||||
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 encmeth = parent.wrapper.getMethods().getWithKey(child.enclosingMethod);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user