summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStiver <stiver.mail@gmail.com>2014-07-23 22:49:29 +0200
committerStiver <stiver.mail@gmail.com>2014-07-23 22:49:29 +0200
commit7f116b6eb506080d552c71445737e444a065e7e1 (patch)
tree2af492b23a0bfb9a82d6ab33635a01d57e108ad1
parent6606a474bf8a634e6ee5a525f338c06a40590712 (diff)
downloadfernflower-7f116b6eb506080d552c71445737e444a065e7e1.tar
fernflower-7f116b6eb506080d552c71445737e444a065e7e1.tar.gz
fernflower-7f116b6eb506080d552c71445737e444a065e7e1.tar.lz
fernflower-7f116b6eb506080d552c71445737e444a065e7e1.tar.xz
fernflower-7f116b6eb506080d552c71445737e444a065e7e1.zip
IDEA-127301: handling of static method references
-rw-r--r--src/de/fernflower/main/ClassWriter.java231
-rw-r--r--src/de/fernflower/main/ClassesProcessor.java17
-rw-r--r--src/de/fernflower/main/rels/LambdaProcessor.java122
-rw-r--r--src/de/fernflower/main/rels/NestedClassProcessor.java30
4 files changed, 215 insertions, 185 deletions
diff --git a/src/de/fernflower/main/ClassWriter.java b/src/de/fernflower/main/ClassWriter.java
index 6a12cc5..8e569d7 100644
--- a/src/de/fernflower/main/ClassWriter.java
+++ b/src/de/fernflower/main/ClassWriter.java
@@ -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(!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(node.lambda_information.is_method_reference) {
- 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(ExprProcessor.getCastTypeName(new VarType(node.lambda_information.content_class_name, false)));
+ writer.write("::");
+ writer.write(node.lambda_information.content_method_name);
+
+ writer.flush();
- 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(", ");
diff --git a/src/de/fernflower/main/ClassesProcessor.java b/src/de/fernflower/main/ClassesProcessor.java
index f2a25c9..7f85696 100644
--- a/src/de/fernflower/main/ClassesProcessor.java
+++ b/src/de/fernflower/main/ClassesProcessor.java
@@ -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;
}
}
diff --git a/src/de/fernflower/main/rels/LambdaProcessor.java b/src/de/fernflower/main/rels/LambdaProcessor.java
index d2fe790..6e404ae 100644
--- a/src/de/fernflower/main/rels/LambdaProcessor.java
+++ b/src/de/fernflower/main/rels/LambdaProcessor.java
@@ -50,85 +50,87 @@ public class LambdaProcessor {
}
StructBootstrapMethodsAttribute bootstrap = (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
- if(bootstrap != null && bootstrap.getMethodsNumber() > 0) {
-
- 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(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
- if(lambda_methods.isEmpty()) {
- return false;
+ 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();
- 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;
- }
+ 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?
-
}
+ // FIXME: mixed hierarchy?
+
return false;
}
diff --git a/src/de/fernflower/main/rels/NestedClassProcessor.java b/src/de/fernflower/main/rels/NestedClassProcessor.java
index 6667f02..32b0161 100644
--- a/src/de/fernflower/main/rels/NestedClassProcessor.java
+++ b/src/de/fernflower/main/rels/NestedClassProcessor.java
@@ -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);