summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jetbrains/java/decompiler/main')
-rw-r--r--src/org/jetbrains/java/decompiler/main/ClassWriter.java65
-rw-r--r--src/org/jetbrains/java/decompiler/main/Fernflower.java2
-rw-r--r--src/org/jetbrains/java/decompiler/main/InitializerProcessor.java2
-rw-r--r--src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java2
-rw-r--r--src/org/jetbrains/java/decompiler/main/collectors/VarNamesCollector.java3
-rw-r--r--src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java2
-rw-r--r--src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java2
-rw-r--r--src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java26
-rw-r--r--src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java156
9 files changed, 213 insertions, 47 deletions
diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java
index 2b61dc2..3aa552f 100644
--- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java
+++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java
@@ -42,6 +42,7 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.struct.gen.generics.*;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import org.jetbrains.java.decompiler.util.Util;
import java.util.LinkedHashMap;
import java.util.List;
@@ -110,7 +111,7 @@ public class ClassWriter {
}
buffer.append("::");
- buffer.append(node.lambda_information.content_method_name);
+ buffer.append("<init>".equals(node.lambda_information.content_method_name) ? "new" : node.lambda_information.content_method_name);
}
else {
// lambda method
@@ -132,7 +133,13 @@ public class ClassWriter {
buffer.append(", ");
}
- String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0));
+ String typeName = ExprProcessor.getCastTypeName(md_content.params[i].copy());
+ if (ExprProcessor.UNDEFINED_TYPE_STRING.equals(typeName)
+ && DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
+ typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT);
+ }
+
+ String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0, typeName, false));
buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors
firstParameter = false;
@@ -179,7 +186,17 @@ public class ClassWriter {
// write class definition
int start_class_def = buffer.length();
- writeClassDefinition(node, buffer, indent);
+ boolean empty = cl.getFields().isEmpty() && cl.getMethods().isEmpty();
+ if (cl.hasModifier(CodeConstants.ACC_ENUM)) {
+ empty = true;
+ for (StructField fd : cl.getFields()) {
+ if (fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM)) {
+ empty = false;
+ break;
+ }
+ }
+ }
+ writeClassDefinition(node, buffer, indent, empty);
// // count lines in class definition the easiest way
// total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1;
@@ -277,12 +294,12 @@ public class ClassWriter {
DecompilerContext.getLogger().endWriteClass();
}
- private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) {
+ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent, boolean empty) {
String lineSeparator = DecompilerContext.getNewLineSeparator();
if (node.type == ClassNode.CLASS_ANONYMOUS) {
buffer.append(" {");
- buffer.append(lineSeparator);
+ if (!empty) buffer.append(lineSeparator);
return;
}
@@ -384,7 +401,10 @@ public class ClassWriter {
}
buffer.append('{');
- buffer.append(lineSeparator);
+ if (!empty) {
+ buffer.append(lineSeparator);
+ buffer.append(lineSeparator); // Spigot
+ }
}
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
@@ -514,7 +534,7 @@ public class ClassWriter {
buffer.append(typeName);
buffer.append(" ");
- String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0));
+ String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0, typeName, false)); // Spigot
buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors
firstParameter = false;
@@ -701,6 +721,10 @@ public class ClassWriter {
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++) {
+ // Spigot Start
+ String typeName;
+ boolean isVarArg;
+ // Spigot end
if (signFields == null || signFields.get(i) == null) {
if (!firstParameter) {
buffer.append(", ");
@@ -715,12 +739,12 @@ public class ClassWriter {
if (descriptor != null) {
GenericType parameterType = descriptor.params.get(i);
- boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0);
+ isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0); // Spigot
if (isVarArg) {
parameterType.arraydim--;
}
- String typeName = GenericMain.getGenericCastTypeName(parameterType);
+ typeName = GenericMain.getGenericCastTypeName(parameterType); // Spigot
if (ExprProcessor.UNDEFINED_TYPE_STRING.equals(typeName) &&
DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT);
@@ -735,12 +759,12 @@ public class ClassWriter {
else {
VarType parameterType = md.params[i].copy();
- boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0);
+ isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0); // Spigot
if (isVarArg) {
parameterType.decArrayDim();
}
- String typeName = ExprProcessor.getCastTypeName(parameterType);
+ typeName = ExprProcessor.getCastTypeName(parameterType); // Spigot
if (ExprProcessor.UNDEFINED_TYPE_STRING.equals(typeName) &&
DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT);
@@ -754,7 +778,7 @@ public class ClassWriter {
}
buffer.append(' ');
- String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0));
+ String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0, typeName, isVarArg)); // Spigot
buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors
firstParameter = false;
@@ -806,9 +830,10 @@ public class ClassWriter {
//TODO: for now only start line set
buffer.setCurrentLine(startLine);
- buffer.append('{').appendLineSeparator();
+ buffer.append('{');
RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
+ boolean empty = false;
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
try {
@@ -816,8 +841,15 @@ public class ClassWriter {
String code = root.toJava(indent + 1, tracer);
+ if (Util.rtrim(code).isEmpty()) code = "";
+
hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
+ if (!code.isEmpty()) {
+ buffer.appendLineSeparator();
+ } else {
+ empty = true;
+ }
buffer.append(code);
}
catch (Throwable ex) {
@@ -832,7 +864,10 @@ public class ClassWriter {
buffer.append(lineSeparator);
}
- buffer.appendIndent(indent).append('}').appendLineSeparator();
+ if (!empty) {
+ buffer.appendIndent(indent);
+ }
+ buffer.append('}').appendLineSeparator();
}
}
finally {
@@ -918,7 +953,7 @@ public class ClassWriter {
}
private static void appendComment(TextBuffer buffer, String comment, int indent, String lineSeparator) {
- buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator);
+ // buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator); // Spigot: Squash comments
}
private static final String[] ANNOTATION_ATTRIBUTES = {
diff --git a/src/org/jetbrains/java/decompiler/main/Fernflower.java b/src/org/jetbrains/java/decompiler/main/Fernflower.java
index 15baac5..85d9b00 100644
--- a/src/org/jetbrains/java/decompiler/main/Fernflower.java
+++ b/src/org/jetbrains/java/decompiler/main/Fernflower.java
@@ -85,7 +85,7 @@ public class Fernflower implements IDecompiledData {
TextBuffer buffer = new TextBuffer(ClassesProcessor.AVERAGE_CLASS_SIZE);
buffer.append(DecompilerContext.getProperty(IFernflowerPreferences.BANNER).toString());
classesProcessor.writeClass(cl, buffer);
- return buffer.toString();
+ return org.spigotmc.fernflower.EclipseFormatter.format(buffer.toString()); // Spigot
}
catch (Throwable ex) {
DecompilerContext.getLogger().writeMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled.", ex);
diff --git a/src/org/jetbrains/java/decompiler/main/InitializerProcessor.java b/src/org/jetbrains/java/decompiler/main/InitializerProcessor.java
index aabea15..4c3f625 100644
--- a/src/org/jetbrains/java/decompiler/main/InitializerProcessor.java
+++ b/src/org/jetbrains/java/decompiler/main/InitializerProcessor.java
@@ -139,7 +139,7 @@ public class InitializerProcessor {
if (fexpr.isStatic() && fexpr.getClassname().equals(cl.qualifiedName) &&
cl.hasField(fexpr.getName(), fexpr.getDescriptor().descriptorString)) {
- if (isExprentIndependent(asexpr.getRight(), meth)) {
+ if (true || isExprentIndependent(asexpr.getRight(), meth)) { // Spigot
String keyField = InterpreterUtil.makeUniqueKey(fexpr.getName(), fexpr.getDescriptor().descriptorString);
if (!wrapper.getStaticFieldInitializers().containsKey(keyField)) {
diff --git a/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java b/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java
index c66a3e0..fae600a 100644
--- a/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java
+++ b/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java
@@ -145,7 +145,7 @@ public class ImportCollector {
// exclude a current class or one of the nested ones, java.lang and empty packages
if (!setNotImportedNames.contains(ent.getKey()) &&
!JAVA_LANG_PACKAGE.equals(ent.getValue()) &&
- !ent.getValue().isEmpty()) {
+ !ent.getValue().isEmpty() && !ent.getValue().equals(this.currentPackagePoint)) { // Spigot: Remove same package imports
res.add(ent.getValue() + "." + ent.getKey());
}
}
diff --git a/src/org/jetbrains/java/decompiler/main/collectors/VarNamesCollector.java b/src/org/jetbrains/java/decompiler/main/collectors/VarNamesCollector.java
index dfde971..8d9d5c0 100644
--- a/src/org/jetbrains/java/decompiler/main/collectors/VarNamesCollector.java
+++ b/src/org/jetbrains/java/decompiler/main/collectors/VarNamesCollector.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.java.decompiler.main.collectors;
+import java.util.Collection;
import java.util.HashSet;
public class VarNamesCollector {
@@ -24,7 +25,7 @@ public class VarNamesCollector {
public VarNamesCollector() {
}
- public VarNamesCollector(HashSet<String> setNames) {
+ public VarNamesCollector(Collection<String> setNames) {
usedNames.addAll(setNames);
}
diff --git a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
index 677d05d..7d96e62 100644
--- a/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
+++ b/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
@@ -91,6 +91,6 @@ public interface IFernflowerPreferences {
put(MAX_PROCESSING_METHOD, "0");
put(RENAME_ENTITIES, "0");
put(NEW_LINE_SEPARATOR, (InterpreterUtil.IS_WINDOWS ? "0" : "1"));
- put(INDENT_STRING, " ");
+ put(INDENT_STRING, " ");
}});
}
diff --git a/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java b/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
index 4a32179..b89bcd2 100644
--- a/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
+++ b/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
@@ -131,7 +131,7 @@ public class ClassWrapper {
int varindex = 0;
for (int i = 0; i < paramcount; i++) {
- varproc.setVarName(new VarVersionPaar(varindex, 0), vc.getFreeName(varindex));
+ varproc.setVarName(new VarVersionPaar(varindex, 0, classStruct.qualifiedName, false), vc.getFreeName(varindex));
if (thisvar) {
if (i == 0) {
diff --git a/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java b/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
index 743ce12..437568b 100644
--- a/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
+++ b/src/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java
@@ -36,10 +36,9 @@ import java.util.*;
public class LambdaProcessor {
- private static final String JAVAC_LAMBDA_CLASS = "java/lang/invoke/LambdaMetafactory";
- private static final String JAVAC_LAMBDA_METHOD = "metafactory";
- private static final String JAVAC_LAMBDA_METHOD_DESCRIPTOR =
- "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;";
+ @SuppressWarnings("SpellCheckingInspection") private static final String JAVAC_LAMBDA_CLASS = "java/lang/invoke/LambdaMetafactory";
+ @SuppressWarnings("SpellCheckingInspection") private static final String JAVAC_LAMBDA_METHOD = "metafactory";
+ @SuppressWarnings("SpellCheckingInspection") private static final String JAVAC_LAMBDA_ALT_METHOD = "altMetafactory";
public void processClass(ClassNode node) throws IOException {
@@ -47,9 +46,7 @@ public class LambdaProcessor {
processClass(child);
}
- if (node.nested.isEmpty()) {
- hasLambda(node);
- }
+ hasLambda(node);
}
public boolean hasLambda(ClassNode node) throws IOException {
@@ -67,17 +64,16 @@ public class LambdaProcessor {
return false; // no bootstrap constants in pool
}
- Set<Integer> lambda_methods = new HashSet<Integer>();
+ BitSet lambda_methods = new BitSet();
// find lambda bootstrap constants
for (int i = 0; i < bootstrap.getMethodsNumber(); ++i) {
LinkConstant method_ref = bootstrap.getMethodReference(i); // method handle
+ // FIXME: extend for Eclipse etc. at some point
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);
+ (JAVAC_LAMBDA_METHOD.equals(method_ref.elementname) || JAVAC_LAMBDA_ALT_METHOD.equals(method_ref.elementname))) {
+ lambda_methods.set(i);
}
}
@@ -101,7 +97,7 @@ public class LambdaProcessor {
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.get(invoke_dynamic.index1)) { // lambda invocation found
List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_dynamic.index1);
MethodDescriptor md = MethodDescriptor.parseDescriptor(invoke_dynamic.descriptor);
@@ -122,7 +118,9 @@ public class LambdaProcessor {
node_lambda.parent = node;
clprocessor.getMapRootClasses().put(node_lambda.simpleName, node_lambda);
- mapMethodsLambda.put(node_lambda.lambda_information.content_method_key, node_lambda.simpleName);
+ if (!node_lambda.lambda_information.is_method_reference) {
+ mapMethodsLambda.put(node_lambda.lambda_information.content_method_key, node_lambda.simpleName);
+ }
}
}
}
diff --git a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
index 25ff812..23ad443 100644
--- a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
+++ b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
@@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.main.rels;
import org.jetbrains.java.decompiler.code.CodeConstants;
+import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
@@ -25,8 +26,11 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode;
+import org.jetbrains.java.decompiler.modules.decompiler.stats.BasicBlockStatement;
+import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.DoStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
+import org.jetbrains.java.decompiler.modules.decompiler.stats.SequenceStatement;
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
@@ -40,6 +44,7 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.*;
import java.util.Map.Entry;
+import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
public class NestedClassProcessor {
@@ -58,6 +63,10 @@ public class NestedClassProcessor {
return;
}
+ if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM)) {
+ gatherEnumSwitchMaps(node);
+ }
+
if (node.type != ClassNode.CLASS_LAMBDA) {
computeLocalVarsAndDefinitions(node);
@@ -102,9 +111,131 @@ public class NestedClassProcessor {
}
}
+ /**
+ * When Java introduced Enums they aded the ability to use them in Switch statements.
+ * This was done in a purely syntax sugar way using the old switch on int methods.
+ * The compiler creates a synthetic class with a static int array field.
+ * To support enums changing post compile, It initializes this field with a length of the current enum length.
+ * And then for every referenced enum value it adds a mapping in the form of:
+ * try {
+ * field[Enum.VALUE.ordinal()] = 1;
+ * } catch (FieldNotFoundException e) {}
+ *
+ * If a class has multiple switches on multiple enums, the compiler adds the init and try list to the BEGINNING of the static initalizer.
+ * But they add the field to the END of the fields list.
+ */
+ private void gatherEnumSwitchMaps(ClassNode node) {
+ if (node.wrapper == null) {
+ return;
+ }
+ for (ClassNode child : node.nested) {
+ gatherEnumSwitchMaps(child);
+ }
+
+ MethodWrapper clinit = node.wrapper.getMethodWrapper("<clinit>", "()V");
+ if (clinit == null || clinit.root == null || clinit.root.getFirst().type != Statement.TYPE_SEQUENCE) {
+ return;
+ }
+
+ final int STATIC_FINAL_SYNTHETIC = CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL | CodeConstants.ACC_SYNTHETIC;
+ Set<String> potentialFields = new HashSet<String>();
+ for (StructField fd : node.classStruct.getFields()) {
+ if ((fd.getAccessFlags() & STATIC_FINAL_SYNTHETIC) == STATIC_FINAL_SYNTHETIC && "[I".equals(fd.getDescriptor())) {
+ potentialFields.add(fd.getName());
+ }
+ }
+
+ if (potentialFields.size() == 0) {
+ return;
+ }
+
+ SequenceStatement seq = (SequenceStatement)clinit.root.getFirst();
+ for (int x = 0; x < seq.getStats().size();) {
+ Statement stat = seq.getStats().get(x);
+ if (stat.type != Statement.TYPE_BASICBLOCK || stat.getExprents() == null || stat.getExprents().size() != 1 || stat.getExprents().get(0).type != Exprent.EXPRENT_ASSIGNMENT) {
+ break;
+ }
+ AssignmentExprent ass = (AssignmentExprent)stat.getExprents().get(0);
+ if (ass.getLeft().type != Exprent.EXPRENT_FIELD || ass.getRight().type != Exprent.EXPRENT_NEW) {
+ break;
+ }
+ FieldExprent mapField = (FieldExprent)ass.getLeft();
+ NewExprent _new = ((NewExprent)ass.getRight());
+ if (!mapField.getClassname().equals(node.classStruct.qualifiedName) || !potentialFields.contains(mapField.getName()) ||
+ _new.getNewtype().type != CodeConstants.TYPE_INT || _new.getNewtype().arraydim != 1 ||
+ _new.getLstDims().size() != 1 || _new.getLstDims().get(0).type != Exprent.EXPRENT_FUNCTION) {
+ break;
+ }
+ FunctionExprent func = (FunctionExprent)_new.getLstDims().get(0);
+ if (func.getFunctype() != FunctionExprent.FUNCTION_ARRAYLENGTH || func.getLstOperands().size() != 1 || func.getLstOperands().get(0).type != Exprent.EXPRENT_INVOCATION) {
+ break;
+ }
+ InvocationExprent invoc = (InvocationExprent)func.getLstOperands().get(0);
+ if (!"values".equals(invoc.getName()) || !("()[L" + invoc.getClassname() + ";").equals(invoc.getStringDescriptor())) {
+ break;
+ }
+
+ String fieldName = mapField.getName();
+ String enumName = invoc.getClassname();
+ Map<Integer, String> idToName = new HashMap<Integer, String>();
+
+ boolean replace = false;
+ int y = x;
+ while (++y < seq.getStats().size()) {
+ if (seq.getStats().get(y).type != Statement.TYPE_TRYCATCH) {
+ break;
+ }
+ CatchStatement _try = (CatchStatement)seq.getStats().get(y);
+ Statement first = _try.getFirst();
+ List<Exprent> exprents = first.getExprents();
+ if (_try.getVars().size() != 1 || !"java/lang/NoSuchFieldError".equals(_try.getVars().get(0).getVartype().value) ||
+ first.type != Statement.TYPE_BASICBLOCK || exprents == null || exprents.size() != 1 || exprents.get(0).type != Exprent.EXPRENT_ASSIGNMENT) {
+ break;
+ }
+ ass = (AssignmentExprent)exprents.get(0);
+ if (ass.getRight().type != Exprent.EXPRENT_CONST || (!(((ConstExprent)ass.getRight()).getValue() instanceof Integer)) ||
+ ass.getLeft().type != Exprent.EXPRENT_ARRAY){
+ break;
+ }
+ ArrayExprent array = (ArrayExprent)ass.getLeft();
+ if (array.getArray().type != Exprent.EXPRENT_FIELD || !array.getArray().equals(mapField) || array.getIndex().type != Exprent.EXPRENT_INVOCATION) {
+ break;
+ }
+ invoc = (InvocationExprent)array.getIndex();
+ if (!enumName.equals(invoc.getClassname()) || !"ordinal".equals(invoc.getName()) || !"()I".equals(invoc.getStringDescriptor()) ||
+ invoc.getInstance().type != Exprent.EXPRENT_FIELD) {
+ break;
+ }
+
+ FieldExprent enumField = (FieldExprent)invoc.getInstance();
+ if (!enumName.equals(enumField.getClassname()) || !enumField.isStatic()) {
+ break;
+ }
+
+ idToName.put((Integer)((ConstExprent)ass.getRight()).getValue(), enumField.getName());
+ seq.replaceStatement(_try, getNewEmptyStatement());
+ replace = true;
+ }
+
+ if (replace) {
+ seq.replaceStatement(seq.getStats().get(x), getNewEmptyStatement());
+ node.classStruct.enumSwitchMap.put(fieldName, idToName);
+ node.wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fieldName, "[I"));
+ }
+ x = y;
+ }
+ }
+
+ private Statement getNewEmptyStatement() {
+ BasicBlockStatement bstat = new BasicBlockStatement(new BasicBlock(
+ DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER)));
+ bstat.setExprents(new ArrayList<Exprent>());
+ return bstat;
+ }
+
private static void setLambdaVars(ClassNode parent, ClassNode child) {
- if (child.lambda_information.is_method_reference) { // method reference, no code and no parameters
+ if (parent.wrapper == null || child.lambda_information.is_method_reference) { // method reference, no code and no parameters
return;
}
@@ -147,6 +278,7 @@ public class NestedClassProcessor {
if (expr.type == Exprent.EXPRENT_NEW) {
NewExprent new_expr = (NewExprent)expr;
+ VarNamesCollector enclosingCollector = new VarNamesCollector(encmeth.varproc.getVarNames());
if (new_expr.isLambda() && lambda_class_type.equals(new_expr.getNewtype())) {
InvocationExprent inv_dynamic = new_expr.getConstructor();
@@ -154,16 +286,16 @@ public class NestedClassProcessor {
int param_index = is_static_lambda_content ? 0 : 1;
int varindex = is_static_lambda_content ? 0 : 1;
- for (int i = 0; i < vars_count; ++i) {
-
- Exprent param = inv_dynamic.getLstParameters().get(param_index + i);
-
- if (param.type == Exprent.EXPRENT_VAR) {
- VarVersionPaar enc_varpaar = new VarVersionPaar((VarExprent)param);
- String enc_varname = encmeth.varproc.getVarName(enc_varpaar);
+ for (int i = 0; i < md_content.params.length; ++i) {
+ VarVersionPaar varVersion = new VarVersionPaar(varindex, 0, ExprProcessor.getCastTypeName(md_content.params[i].copy()), false);
+ if (i < vars_count) {
+ Exprent param = inv_dynamic.getLstParameters().get(param_index + i);
- //meth.varproc.setVarName(new VarVersionPaar(varindex, 0), enc_varname);
- mapNewNames.put(new VarVersionPaar(varindex, 0), enc_varname);
+ if (param.type == Exprent.EXPRENT_VAR) {
+ mapNewNames.put(varVersion, encmeth.varproc.getVarName(new VarVersionPaar((VarExprent) param)));
+ }
+ } else {
+ mapNewNames.put(varVersion, enclosingCollector.getFreeName(meth.varproc.getVarName(varVersion)));
}
varindex += md_content.params[i].stack_size;
@@ -222,7 +354,7 @@ public class NestedClassProcessor {
if (!hasEnclosing) {
if (child.type == ClassNode.CLASS_ANONYMOUS) {
String message = "Unreferenced anonymous class " + child.classStruct.qualifiedName + "!";
- DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.TRACE);
}
else if (child.type == ClassNode.CLASS_LOCAL) {
String message = "Unreferenced local class " + child.classStruct.qualifiedName + "!";
@@ -276,7 +408,7 @@ public class NestedClassProcessor {
HashMap<String, List<VarFieldPair>> mask = getMaskLocalVars(nd.wrapper);
if (mask.isEmpty()) {
String message = "Nested class " + nd.classStruct.qualifiedName + " has no constructor!";
- DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.TRACE);
}
else {
mapVarMasks.put(nd.classStruct.qualifiedName, mask);