diff options
Diffstat (limited to 'src/org/jetbrains/java')
14 files changed, 252 insertions, 34 deletions
diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 2b61dc2..7d3e66d 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -188,6 +188,7 @@ public class ClassWriter { // fields boolean enumFields = false; + boolean endEnumWritten = false; // Spigot for (StructField fd : cl.getFields()) { boolean hide = fd.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || @@ -202,19 +203,24 @@ public class ClassWriter { } enumFields = true; } - else if (enumFields) { + else if (enumFields && !endEnumWritten) { // Spigot buffer.append(';'); buffer.append(lineSeparator); buffer.append(lineSeparator); - enumFields = false; + endEnumWritten = true; // Spigot } fieldToJava(wrapper, cl, fd, buffer, indent + 1, dummy_tracer); // FIXME: insert real tracer hasContent = true; } - - if (enumFields) { + // Spigot Start + int flags = node.type == ClassNode.CLASS_ROOT ? cl.getAccessFlags() : node.access; + boolean isEnum = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM) && (flags & CodeConstants.ACC_ENUM) != 0; + if (isEnum && !endEnumWritten) { + buffer.append(lineSeparator); + buffer.append(lineSeparator); + // Spigot End buffer.append(';'); buffer.append(lineSeparator); } @@ -385,6 +391,7 @@ public class ClassWriter { buffer.append('{'); buffer.append(lineSeparator); + buffer.append(lineSeparator); // Spigot } private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { @@ -514,7 +521,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 +708,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 +726,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 +746,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 +765,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; @@ -918,7 +929,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/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/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/modules/decompiler/ExprProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java index e283fdf..7b2f3a2 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -41,6 +41,7 @@ import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.InterpreterUtil; import java.util.*; +import org.jetbrains.java.decompiler.util.SortUtil; public class ExprProcessor implements CodeConstants { @@ -814,8 +815,10 @@ public class ExprProcessor implements CodeConstants { String new_line_separator = DecompilerContext.getNewLineSeparator(); StringBuilder buf = new StringBuilder(); - - for (Exprent expr : lst) { + // Spigot Start + for (Iterator<Exprent> iter = SortUtil.sortIndexed(lst.iterator()); iter.hasNext();) { + Exprent expr = iter.next(); + // Spigot End String content = expr.toJava(indent, tracer); if (content.length() > 0) { if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassdef()) { @@ -877,7 +880,7 @@ public class ExprProcessor implements CodeConstants { boolean cast = !leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT); - cast |= castAlways; + cast |= castAlways && !leftType.equals(rightType); // Spigot if (!cast && castNull && rightType.type == CodeConstants.TYPE_NULL) { // check for a nameless anonymous class diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java index 6198da1..6f83baf 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java @@ -529,7 +529,7 @@ public class FinallyProcessor { } while (index < lst.size()); - HashSet<BasicBlock> res = new HashSet<BasicBlock>(); + HashSet<BasicBlock> res = new LinkedHashSet<BasicBlock>(); // Spigot: Fix determinism for (Statement st : lst) { res.add(((BasicBlockStatement)st).getBlock()); @@ -571,7 +571,7 @@ public class FinallyProcessor { } // identify start blocks - HashSet<BasicBlock> startBlocks = new HashSet<BasicBlock>(); + HashSet<BasicBlock> startBlocks = new LinkedHashSet<BasicBlock>(); // Spigot: Fix determinism for (BasicBlock block : tryBlocks) { startBlocks.addAll(block.getSuccs()); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java index e51615d..5363477 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java @@ -102,7 +102,7 @@ public class FieldExprent extends Exprent { if (isStatic) { ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); - if (node == null || !classname.equals(node.classStruct.qualifiedName)) { + if (true || node == null || !classname.equals(node.classStruct.qualifiedName)) { // Spigot buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(classname))); buf.append("."); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java index 92d549e..e9d9064 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -373,13 +373,26 @@ public class InvocationExprent extends Exprent { return buf.toString(); } + private Set<StructClass> addAllSuper(Set<StructClass> set, String clazz) { + StructClass cstr = DecompilerContext.getStructContext().getClass(clazz); + if (cstr == null) { + return set; + } + set.add(cstr); + for (String inter : cstr.getInterfaceNames()) { + addAllSuper(set, inter); + } + addAllSuper(set, cstr.superClass.getString()); + + return set; + } + private Set<Integer> getAmbiguousParameters() { Set<Integer> ret = new HashSet<Integer>(); - StructClass cstr = DecompilerContext.getStructContext().getClass(classname); - if (cstr != null) { - List<MethodDescriptor> lstMethods = new ArrayList<MethodDescriptor>(); + List<MethodDescriptor> lstMethods = new ArrayList<MethodDescriptor>(); + for (StructClass cstr : addAllSuper(new HashSet<StructClass>(), classname)) { for (StructMethod meth : cstr.getMethods()) { if (name.equals(meth.getName())) { MethodDescriptor md = MethodDescriptor.parseDescriptor(meth.getDescriptor()); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java index 16e6c64..b8e60e7 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java @@ -27,11 +27,12 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.InterpreterUtil; +import org.jetbrains.java.decompiler.util.SortUtil; import java.util.ArrayList; import java.util.List; -public class VarExprent extends Exprent { +public class VarExprent extends Exprent implements SortUtil.Indexed { // Spigot public static final int STACK_BASE = 10000; @@ -94,15 +95,16 @@ public class VarExprent extends Exprent { } else { String name = null; + String typeName = ExprProcessor.getCastTypeName(getVartype()); // Spigot if (processor != null) { - name = processor.getVarName(new VarVersionPaar(index, version)); + name = processor.getVarName(new VarVersionPaar(index, version, typeName, false)); // Spigot } if (definition) { if (processor != null && processor.getVarFinal(new VarVersionPaar(index, version)) == VarTypeProcessor.VAR_FINALEXPLICIT) { buffer.append("final "); } - buffer.append(ExprProcessor.getCastTypeName(getVartype())).append(" "); + buffer.append(typeName).append(" "); // Spigot } buffer.append(name == null ? ("var" + index + (version == 0 ? "" : "_" + version)) : name); } @@ -128,6 +130,13 @@ public class VarExprent extends Exprent { this.index = index; } + // Spigot Start + @Override + public int getSortIndex() { + return (definition) ? index : -1; + } + // Spigot End + public VarType getVartype() { VarType vt = null; if (processor != null) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java index 266ba94..4d4dabb 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java @@ -21,6 +21,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement; import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement; import org.jetbrains.java.decompiler.struct.StructMethod; import org.jetbrains.java.decompiler.struct.gen.VarType; +import org.jetbrains.java.decompiler.util.VarHelper; // Spigot import java.util.*; import java.util.Map.Entry; @@ -36,6 +37,8 @@ public class VarProcessor { private HashSet<VarVersionPaar> externvars = new HashSet<VarVersionPaar>(); + private VarHelper helper = new VarHelper(); // Spigot + public void setVarVersions(RootStatement root) { varvers = new VarVersionsProcessor(); @@ -104,7 +107,13 @@ public class VarProcessor { } public String getVarName(VarVersionPaar varpaar) { - return mapVarNames == null ? null : mapVarNames.get(varpaar); + // Spigot Start + String name = mapVarNames.get(varpaar); + if (name != null) { + mapVarNames.put(varpaar, name = helper.help(name, varpaar.type, varpaar.varargs)); + } + return name; + // Spigot End } public void setVarName(VarVersionPaar varpaar, String name) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionPaar.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionPaar.java index 5f3e520..3bf29fe 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionPaar.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionPaar.java @@ -17,10 +17,12 @@ package org.jetbrains.java.decompiler.modules.decompiler.vars; import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent; -public class VarVersionPaar { +public class VarVersionPaar implements Comparable<VarVersionPaar> { // Spigot public int var; public int version; + public String type; + public boolean varargs; private int hashCode = -1; @@ -29,9 +31,11 @@ public class VarVersionPaar { this.version = version; } - public VarVersionPaar(Integer var, Integer version) { - this.var = var.intValue(); - this.version = version.intValue(); + public VarVersionPaar(int var, int version, String type, boolean varargs) { + this.var = var; + this.version = version; + this.type = type; + this.varargs = varargs; } public VarVersionPaar(VarExprent var) { @@ -60,4 +64,14 @@ public class VarVersionPaar { public String toString() { return "(" + var + "," + version + ")"; } + + // Spigot Start + @Override + public int compareTo(VarVersionPaar o) { + if (this.var != o.var) { + return this.var - o.var; + } + return this.version - o.version; + } + // Spigot End } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsProcessor.java index 06b7216..6a30f1b 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsProcessor.java @@ -31,6 +31,7 @@ import org.jetbrains.java.decompiler.util.FastSparseSetFactory.FastSparseSet; import java.util.*; import java.util.Map.Entry; +import org.jetbrains.java.decompiler.util.SortUtil; public class VarVersionsProcessor { @@ -254,9 +255,10 @@ public class VarVersionsProcessor { HashMap<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>(); // map var-version paars on new var indexes - HashSet<VarVersionPaar> set = new HashSet<VarVersionPaar>(mapExprentMinTypes.keySet()); - for (VarVersionPaar vpaar : set) { - + // Spigot Start + for (Iterator<VarVersionPaar> iter = SortUtil.sortComparable(mapExprentMinTypes.keySet().iterator()); iter.hasNext();) { + VarVersionPaar vpaar = iter.next(); + // Spigot End if (vpaar.version >= 0) { int newindex = vpaar.version == 1 ? vpaar.var : ccon.getCounterAndIncrement(CounterContainer.VAR_COUNTER); diff --git a/src/org/jetbrains/java/decompiler/util/SortUtil.java b/src/org/jetbrains/java/decompiler/util/SortUtil.java new file mode 100644 index 0000000..e227e02 --- /dev/null +++ b/src/org/jetbrains/java/decompiler/util/SortUtil.java @@ -0,0 +1,65 @@ +package org.jetbrains.java.decompiler.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +public class SortUtil +{ + public static interface Indexed + { + public int getSortIndex(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static Iterator sortIndexed(Iterator itr) + { + List list = new ArrayList(); + List<Indexed> def_dec = new ArrayList<Indexed>(); + int first = -1; + + while(itr.hasNext()) + { + Object i = itr.next(); + //Split off any default variable declarations and sort them. + if (i instanceof Indexed && ((Indexed)i).getSortIndex() >= 0) + { + if (first == -1) first = list.size(); + def_dec.add((Indexed)i); + } + else + { + list.add(i); + } + } + + if (def_dec.size() > 0) + { + Collections.sort(def_dec, new Comparator<Indexed>() + { + @Override + public int compare(Indexed o1, Indexed o2) + { + return o1.getSortIndex() - o2.getSortIndex(); + } + }); + list.addAll(first, def_dec); + } + + return list.iterator(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static <T extends Comparable> Iterator<T> sortComparable(Iterator<T> itr) + { + List<T> list = new ArrayList<T>(); + + while (itr.hasNext()) + list.add(itr.next()); + + Collections.sort(list); + return list.iterator(); + } +} diff --git a/src/org/jetbrains/java/decompiler/util/VarHelper.java b/src/org/jetbrains/java/decompiler/util/VarHelper.java new file mode 100644 index 0000000..5001cb0 --- /dev/null +++ b/src/org/jetbrains/java/decompiler/util/VarHelper.java @@ -0,0 +1,92 @@ +package org.jetbrains.java.decompiler.util; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class VarHelper { + + private static final Map<String, String[]> switches = new HashMap<String, String[]>(); + + static { + switches.put("byte", new String[]{ + "b" + }); + switches.put("char", new String[]{ + "c" + }); + switches.put("short", new String[]{ + "short" + }); + switches.put("int", new String[]{ + "i", "j", "k", "l" + }); + switches.put("long", new String[]{ + "i", "j", "k", "l" + }); + switches.put("boolean", new String[]{ + "flag" + }); + switches.put("double", new String[]{ + "d" + }); + switches.put("float", new String[]{ + "f", "f" // Add twice because the original script is inconsistent + }); + switches.put("String", new String[]{ + "s", "s" // Add twice because the original script is inconsistent + }); + switches.put("Class", new String[]{ + "oclass" + }); + switches.put("Long", new String[]{ + "olong" + }); + switches.put("Byte", new String[]{ + "obyte" + }); + switches.put("Short", new String[]{ + "oshort" + }); + switches.put("Boolean", new String[]{ + "obool" + }); + switches.put("Long", new String[]{ + "olong" + }); + switches.put("Enum", new String[]{ + "oenum" + }); + } + private final Set<String> used = new HashSet<String>(); + + public String help(String name, String type, boolean varArgs) { + if (type == null || !name.startsWith("var")) { + return name; + } + + if (type.endsWith("]")) { + type = "a" + type.substring(0, type.indexOf('[')); + } else if (varArgs) { + type = "a" + type; + } + + String[] remap = switches.get(type); + if (remap == null) { + remap = new String[]{ + type.toLowerCase() + }; + } + + for (int counter = 0;; counter++) { + for (String subMap : remap) { + String attempt = subMap + ((counter == 0 && !subMap.equals("short") && (remap.length > 1 || subMap.length() > 1)) ? "" : counter); + if (!used.contains(attempt)) { + used.add(attempt); + return attempt; + } + } + } + } +} |