diff --git a/FernFlower-Patches/0013-Fix-primitive-unboxing-causing-invocations-of-wrong-.patch b/FernFlower-Patches/0013-Fix-primitive-un-boxing-issues.patch similarity index 76% rename from FernFlower-Patches/0013-Fix-primitive-unboxing-causing-invocations-of-wrong-.patch rename to FernFlower-Patches/0013-Fix-primitive-un-boxing-issues.patch index be5b43a..e3b9872 100644 --- a/FernFlower-Patches/0013-Fix-primitive-unboxing-causing-invocations-of-wrong-.patch +++ b/FernFlower-Patches/0013-Fix-primitive-un-boxing-issues.patch @@ -1,8 +1,7 @@ -From f2e544c628b6e1558e4c59c4382ed5aade934228 Mon Sep 17 00:00:00 2001 +From d2f6207885de9b82c2d37d87a7ee26328efb6aa1 Mon Sep 17 00:00:00 2001 From: LexManos Date: Thu, 11 May 2017 03:24:33 -0700 -Subject: [PATCH] Fix primitive unboxing causing invocations of wrong - overloaded functions. +Subject: [PATCH] Fix primitive un/boxing issues. diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -30,19 +29,44 @@ index 03a59cb..474ffda 100644 } } } +diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java +index 161f55c..068e44b 100644 +--- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java ++++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java +@@ -566,6 +566,19 @@ public class FunctionExprent extends Exprent { + } + + if (funcType <= FUNCTION_I2S) { ++ // We can't directly cast some object types, so we need to make sure the unboxing happens. ++ // The types seem to be inconsistant but there is no harm in forcing the unboxing when not strictly needed. ++ // Type | Works | Doesn't ++ // Integer| LFD | BCS ++ // Long | FD | I ++ // Float | D | IL ++ // Double | | ILF ++ if (lstOperands.get(0).type == Exprent.EXPRENT_INVOCATION) { ++ InvocationExprent inv = (InvocationExprent)lstOperands.get(0); ++ if (inv.isUnboxingCall()) { ++ inv.forceUnboxing(true); ++ } ++ } + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("(" + ExprProcessor.getTypeName( + TYPES[funcType - FUNCTION_I2L]) + ")"); + } 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 d72870e..3c13e14 100644 +index d72870e..1c822f3 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java -@@ -59,6 +59,7 @@ public class InvocationExprent extends Exprent { +@@ -59,6 +59,8 @@ public class InvocationExprent extends Exprent { private List lstParameters = new ArrayList<>(); private List bootstrapArguments; private List genericArgs = new ArrayList<>(); + private boolean forceBoxing = false; ++ private boolean forceUnboxing = false; public InvocationExprent() { super(EXPRENT_INVOCATION); -@@ -261,7 +262,7 @@ public class InvocationExprent extends Exprent { +@@ -261,10 +263,10 @@ public class InvocationExprent extends Exprent { } if (isStatic) { @@ -50,23 +74,39 @@ index d72870e..3c13e14 100644 + if (isBoxingCall() && canIgnoreBoxing && !forceBoxing) { // process general "boxing" calls, e.g. 'Object[] data = { true }' or 'Byte b = 123' // here 'byte' and 'short' values do not need an explicit narrowing type cast - ExprProcessor.getCastedExprent(lstParameters.get(0), descriptor.params[0], buf, indent, false, false, false, false, tracer); -@@ -310,14 +311,24 @@ public class InvocationExprent extends Exprent { +- ExprProcessor.getCastedExprent(lstParameters.get(0), descriptor.params[0], buf, indent, false, false, false, false, tracer); ++ ExprProcessor.getCastedExprent(lstParameters.get(0), descriptor.params[0], buf, indent, false, false, true, false, tracer); + return buf; + } + +@@ -310,16 +312,36 @@ public class InvocationExprent extends Exprent { TextUtil.writeQualifiedSuper(buf, super_qualifier); } else if (instance != null) { - TextBuffer res = instance.toJava(indent, tracer); - - if (isUnboxingCall()) { +- if (isUnboxingCall()) { ++ VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); ++ if (isUnboxingCall() && !forceUnboxing) { // we don't print the unboxing call - no need to bother with the instance wrapping / casting - buf.append(res); + if (instance.type == Exprent.EXPRENT_FUNCTION) { + FunctionExprent func = (FunctionExprent)instance; + if (func.getFuncType() == FunctionExprent.FUNCTION_CAST && func.getLstOperands().get(1).type == Exprent.EXPRENT_CONST) { + ConstExprent _const = (ConstExprent)func.getLstOperands().get(1); -+ if (this.classname.equals(_const.getConstType().value)) { -+ buf.append(func.getLstOperands().get(0).toJava(indent, tracer)); -+ return buf; ++ boolean skipCast = false; ++ ++ if (func.getLstOperands().get(0).type == Exprent.EXPRENT_VAR) { ++ VarType inferred = func.getLstOperands().get(0).getInferredExprType(leftType); ++ skipCast = inferred.type != CodeConstants.TYPE_OBJECT || ++ DecompilerContext.getStructContext().instanceOf(inferred.value, this.classname); ++ } else if (this.classname.equals(_const.getConstType().value)) { ++ skipCast = true; ++ } ++ ++ if (skipCast) { ++ buf.append(func.getLstOperands().get(0).toJava(indent, tracer)); ++ return buf; + } + } + } @@ -77,9 +117,11 @@ index d72870e..3c13e14 100644 + TextBuffer res = instance.toJava(indent, tracer); + VarType rightType = instance.getExprType(); - VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); +- VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); -@@ -417,8 +428,62 @@ public class InvocationExprent extends Exprent { + if (rightType.equals(VarType.VARTYPE_OBJECT) && !leftType.equals(rightType)) { + buf.append("((").append(ExprProcessor.getCastTypeName(leftType)).append(")"); +@@ -417,8 +439,85 @@ public class InvocationExprent extends Exprent { } } @@ -89,53 +131,76 @@ index d72870e..3c13e14 100644 + VarType[] types = Arrays.copyOf(descriptor.params, descriptor.params.length); + for (int i = start; i < parameters.size(); i++) { + Exprent par = parameters.get(i); -+ -+ // "unbox" invocation parameters, e.g. 'byteSet.add((byte)123)' or 'new ShortContainer((short)813)' -+ //However, we must make sure we don't accidentally make the call ambiguous. -+ //An example being List, remove(Integer.valueOf(1)) and remove(1) are different functions -+ if (par.type == Exprent.EXPRENT_INVOCATION && ((InvocationExprent)par).isBoxingCall()) { -+ InvocationExprent inv = (InvocationExprent)par; -+ Exprent value = inv.lstParameters.get(0); -+ types[i] = value.getExprType(); //Infer? -+ //Unboxing in this case is lossy, so we need to explicitly set the type -+ if (types[i] .typeFamily == CodeConstants.TYPE_FAMILY_INTEGER) { -+ types[i] = ++ if (par.type == Exprent.EXPRENT_INVOCATION) { ++ InvocationExprent inv = (InvocationExprent)par; ++ // "unbox" invocation parameters, e.g. 'byteSet.add((byte)123)' or 'new ShortContainer((short)813)' ++ //However, we must make sure we don't accidentally make the call ambiguous. ++ //An example being List, remove(Integer.valueOf(1)) and remove(1) are different functions ++ if (inv.isBoxingCall()) { ++ Exprent value = inv.lstParameters.get(0); ++ types[i] = value.getExprType(); //Infer? ++ //Unboxing in this case is lossy, so we need to explicitly set the type ++ if (types[i].typeFamily == CodeConstants.TYPE_FAMILY_INTEGER) { ++ types[i] = + "java/lang/Short".equals(inv.classname) ? VarType.VARTYPE_SHORT : + "java/lang/Byte".equals(inv.classname) ? VarType.VARTYPE_BYTE : + "java/lang/Integer".equals(inv.classname) ? VarType.VARTYPE_INT : + VarType.VARTYPE_CHAR; -+ } ++ } ++ ++ int count = 0; ++ StructClass stClass = DecompilerContext.getStructContext().getClass(classname); ++ if (stClass != null) { ++ nextMethod: ++ for (StructMethod mt : stClass.getMethods()) { ++ if (name.equals(mt.getName())) { ++ MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); ++ if (md.params.length == descriptor.params.length) { ++ for (int x = 0; x < md.params.length; x++) { ++ if (md.params[x].typeFamily != descriptor.params[x].typeFamily && ++ md.params[x].typeFamily != types[x].typeFamily) { ++ continue nextMethod; ++ } ++ } ++ count++; ++ } ++ } ++ } ++ } + -+ int count = 0; -+ StructClass stClass = DecompilerContext.getStructContext().getClass(classname); -+ if (stClass != null) { -+ nextMethod: ++ if (count != matches.size()) { //We become more ambiguous? Lets keep the explicit boxing ++ types[i] = descriptor.params[i]; ++ inv.forceBoxing = true; ++ } else { ++ value.addBytecodeOffsets(inv.bytecode); //Keep the bytecode for matching/debug ++ parameters.set(i, value); ++ } ++ } ++ // We also need to care about when things are intentionally unboxed to call a different overloaded method, ++ //and skipping unboxing causes us to call ourselves. ++ // EXA: ++ // int compare(Integer a, Integer b) { return this.compare(a.intValue(), b.intValue()); } ++ // int compare(int a, int b) { return a - b; } ++ // Allowing the first function to unbox would cause infinite recursion ++ // Right now it just do a quick check, but a proper check would be to do compiler like inference of argument ++ // types, and check unboxing as needed. Currently it causes some false forces ++ else if (inv.isUnboxingCall() && !inv.shouldForceUnboxing()) { ++ StructClass stClass = DecompilerContext.getStructContext().getClass(classname); + for (StructMethod mt : stClass.getMethods()) { -+ if (name.equals(mt.getName())) { ++ if (name.equals(mt.getName()) && !stringDescriptor.equals(mt.getDescriptor())) { + MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); + if (md.params.length == descriptor.params.length) { -+ for (int x = 0; x < md.params.length; x++) { -+ if (md.params[x].typeFamily != descriptor.params[x].typeFamily && -+ md.params[x].typeFamily != types[x].typeFamily) { -+ continue nextMethod; ++ if (md.params[i].type == CodeConstants.TYPE_OBJECT) { ++ if (DecompilerContext.getStructContext().instanceOf(inv.getInstance().getExprType().value, md.params[i].value)) { ++ inv.forceUnboxing(true); ++ break; + } + } -+ count++; + } + } + } + } -+ -+ if (count != matches.size()) { //We become more ambiguous? Lets keep the explicit boxing -+ types[i] = descriptor.params[i]; -+ inv.forceBoxing = true; -+ } -+ else { -+ value.addBytecodeOffsets(inv.bytecode); //Keep the bytecode for matching/debug -+ parameters.set(i, value); -+ } + } -+ + } + + @@ -143,7 +208,7 @@ index d72870e..3c13e14 100644 for (int i = start; i < lstParameters.size(); i++) { if (mask == null || mask.get(i) == null) { TextBuffer buff = new TextBuffer(); -@@ -453,7 +518,7 @@ public class InvocationExprent extends Exprent { +@@ -453,7 +552,7 @@ public class InvocationExprent extends Exprent { */ // 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter @@ -152,7 +217,7 @@ index d72870e..3c13e14 100644 // the last "new Object[0]" in the vararg call is not printed if (buff.length() > 0) { -@@ -506,7 +571,7 @@ public class InvocationExprent extends Exprent { +@@ -506,7 +605,7 @@ public class InvocationExprent extends Exprent { } if (paramType == CodeConstants.TYPE_BYTECHAR || paramType == CodeConstants.TYPE_SHORTCHAR) { @@ -161,18 +226,26 @@ index d72870e..3c13e14 100644 return true; } } -@@ -565,6 +630,10 @@ public class InvocationExprent extends Exprent { +@@ -565,6 +664,18 @@ public class InvocationExprent extends Exprent { return !isStatic && lstParameters.size() == 0 && classname.equals(UNBOXING_METHODS.get(name)); } + public boolean shouldForceBoxing() { + return forceBoxing; + } ++ ++ public void forceUnboxing(boolean value) { ++ this.forceUnboxing = value; ++ } ++ ++ public boolean shouldForceUnboxing() { ++ return this.forceUnboxing; ++ } + private List getMatchedDescriptors() { List matches = new ArrayList<>(); StructClass cl = DecompilerContext.getStructContext().getClass(classname); -@@ -594,6 +663,8 @@ public class InvocationExprent extends Exprent { +@@ -594,6 +705,8 @@ public class InvocationExprent extends Exprent { return EMPTY_BIT_SET; } @@ -181,7 +254,7 @@ index d72870e..3c13e14 100644 // check if a call is unambiguous StructMethod mt = cl.getMethod(InterpreterUtil.makeUniqueKey(name, stringDescriptor)); if (mt != null) { -@@ -603,18 +674,50 @@ public class InvocationExprent extends Exprent { +@@ -603,18 +716,50 @@ public class InvocationExprent extends Exprent { for (int i = 0; i < md.params.length; i++) { if (!md.params[i].equals(lstParameters.get(i).getExprType())) { exact = false; diff --git a/FernFlower-Patches/0018-Enhance-Generic-Invocations-Temporarily.patch b/FernFlower-Patches/0018-Enhance-Generic-Invocations-Temporarily.patch index 219ed0d..60d76f4 100644 --- a/FernFlower-Patches/0018-Enhance-Generic-Invocations-Temporarily.patch +++ b/FernFlower-Patches/0018-Enhance-Generic-Invocations-Temporarily.patch @@ -1,4 +1,4 @@ -From 893e1e6fb3798cffacf847abec2b1617897698fa Mon Sep 17 00:00:00 2001 +From a05f3907b40a0e9deb19f31882a0b5e944e30b8d Mon Sep 17 00:00:00 2001 From: LexManos Date: Fri, 16 Feb 2018 22:04:00 -0800 Subject: [PATCH] Enhance Generic Invocations Temporarily. @@ -24,7 +24,7 @@ index 4aeda0e..58c3471 100644 left = left.resizeArrayDim(0); right = right.resizeArrayDim(0); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java -index 161f55c..d15b858 100644 +index 068e44b..8f69e43 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java @@ -7,6 +7,8 @@ import org.jetbrains.java.decompiler.code.CodeConstants; @@ -66,7 +66,7 @@ index 161f55c..d15b858 100644 } else { //TODO: Capture generics to make cast better? this.needsCast = right.type == CodeConstants.TYPE_NULL || !DecompilerContext.getStructContext().instanceOf(right.value, cast.value); -@@ -570,7 +581,7 @@ public class FunctionExprent extends Exprent { +@@ -583,7 +594,7 @@ public class FunctionExprent extends Exprent { TYPES[funcType - FUNCTION_I2L]) + ")"); } @@ -75,7 +75,7 @@ index 161f55c..d15b858 100644 throw new RuntimeException("invalid function"); } -@@ -651,7 +662,7 @@ public class FunctionExprent extends Exprent { +@@ -664,7 +675,7 @@ public class FunctionExprent extends Exprent { measureBytecode(values, lstOperands); measureBytecode(values); } @@ -84,7 +84,7 @@ index 161f55c..d15b858 100644 // ***************************************************************************** // IMatchable implementation // ***************************************************************************** -@@ -665,4 +676,4 @@ public class FunctionExprent extends Exprent { +@@ -678,4 +689,4 @@ public class FunctionExprent extends Exprent { Integer type = (Integer)matchNode.getRuleValue(MatchProperties.EXPRENT_FUNCTYPE); return type == null || this.funcType == type; } @@ -92,10 +92,10 @@ index 161f55c..d15b858 100644 \ No newline at end of file +} 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 3c13e14..50d8799 100644 +index 1c822f3..a16aa29 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java -@@ -395,6 +395,7 @@ public class InvocationExprent extends Exprent { +@@ -406,6 +406,7 @@ public class InvocationExprent extends Exprent { isEnum = newNode.classStruct.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); } } @@ -103,17 +103,26 @@ index 3c13e14..50d8799 100644 List matches = getMatchedDescriptors(); BitSet setAmbiguousParameters = getAmbiguousParameters(matches); StructMethod desc = null; -@@ -455,7 +456,7 @@ public class InvocationExprent extends Exprent { - if (stClass != null) { - nextMethod: +@@ -466,7 +467,7 @@ public class InvocationExprent extends Exprent { + if (stClass != null) { + nextMethod: + for (StructMethod mt : stClass.getMethods()) { +- if (name.equals(mt.getName())) { ++ if (name.equals(mt.getName()) && (currCls == null || canAccess(currCls.classStruct, mt))) { + MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); + if (md.params.length == descriptor.params.length) { + for (int x = 0; x < md.params.length; x++) { +@@ -500,7 +501,7 @@ public class InvocationExprent extends Exprent { + else if (inv.isUnboxingCall() && !inv.shouldForceUnboxing()) { + StructClass stClass = DecompilerContext.getStructContext().getClass(classname); for (StructMethod mt : stClass.getMethods()) { -- if (name.equals(mt.getName())) { -+ if (name.equals(mt.getName()) && (currCls == null || canAccess(currCls.classStruct, mt))) { +- if (name.equals(mt.getName()) && !stringDescriptor.equals(mt.getDescriptor())) { ++ if (name.equals(mt.getName()) && (currCls == null || canAccess(currCls.classStruct, mt)) && !stringDescriptor.equals(mt.getDescriptor())) { MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); if (md.params.length == descriptor.params.length) { - for (int x = 0; x < md.params.length; x++) { -@@ -482,6 +483,22 @@ public class InvocationExprent extends Exprent { - + if (md.params[i].type == CodeConstants.TYPE_OBJECT) { +@@ -516,6 +517,22 @@ public class InvocationExprent extends Exprent { + } } + if (instance != null && !genArgs.isEmpty()) { @@ -135,7 +144,7 @@ index 3c13e14..50d8799 100644 boolean firstParameter = true; for (int i = start; i < lstParameters.size(); i++) { -@@ -636,27 +653,98 @@ public class InvocationExprent extends Exprent { +@@ -678,27 +695,98 @@ public class InvocationExprent extends Exprent { private List getMatchedDescriptors() { List matches = new ArrayList<>(); diff --git a/FernFlower-Patches/0022-Synthetic-getClass-cleanup.patch b/FernFlower-Patches/0022-Synthetic-getClass-cleanup.patch index 7783ff5..742acf1 100644 --- a/FernFlower-Patches/0022-Synthetic-getClass-cleanup.patch +++ b/FernFlower-Patches/0022-Synthetic-getClass-cleanup.patch @@ -1,4 +1,4 @@ -From f9d03a80c989001aa805f65153603bb5fb9fe907 Mon Sep 17 00:00:00 2001 +From 348a11626d2ef165fe51a9ceed8bc4ecaded8b29 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 26 Jul 2018 13:28:40 -0700 Subject: [PATCH] Synthetic getClass cleanup @@ -94,18 +94,18 @@ index 986a8a7..767f6bd 100644 String classname = newExpr.getNewType().value; ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname); 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 50d8799..b38b834 100644 +index a16aa29..593a5be 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java -@@ -60,6 +60,7 @@ public class InvocationExprent extends Exprent { - private List bootstrapArguments; +@@ -61,6 +61,7 @@ public class InvocationExprent extends Exprent { private List genericArgs = new ArrayList<>(); private boolean forceBoxing = false; + private boolean forceUnboxing = false; + private boolean isSyntheticGetClass = false; public InvocationExprent() { super(EXPRENT_INVOCATION); -@@ -160,6 +161,7 @@ public class InvocationExprent extends Exprent { +@@ -161,6 +162,7 @@ public class InvocationExprent extends Exprent { addBytecodeOffsets(expr.bytecode); bootstrapArguments = expr.getBootstrapArguments(); @@ -113,7 +113,7 @@ index 50d8799..b38b834 100644 } @Override -@@ -926,6 +928,14 @@ public class InvocationExprent extends Exprent { +@@ -968,6 +970,14 @@ public class InvocationExprent extends Exprent { return bootstrapArguments; } diff --git a/FernFlower-Patches/0028-Fix-ambiguous-lambdas.patch b/FernFlower-Patches/0028-Fix-ambiguous-lambdas.patch index 5ee6a15..22f4cc9 100644 --- a/FernFlower-Patches/0028-Fix-ambiguous-lambdas.patch +++ b/FernFlower-Patches/0028-Fix-ambiguous-lambdas.patch @@ -1,4 +1,4 @@ -From 29e27a2882f72501daf6e68019c24f78c7576ead Mon Sep 17 00:00:00 2001 +From 4d39e77afc4bfba7fd4df4370b7f5c8b1ccfc28e Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 19 Sep 2018 22:51:00 -0700 Subject: [PATCH] Fix ambiguous lambdas @@ -41,10 +41,10 @@ index 4933b5c..cc67f34 100644 + } } 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 b38b834..fded2f8 100644 +index 593a5be..43db4dc 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java -@@ -762,7 +762,8 @@ public class InvocationExprent extends Exprent { +@@ -804,7 +804,8 @@ public class InvocationExprent extends Exprent { if (md.params.length == lstParameters.size()) { boolean exact = true; for (int i = 0; i < md.params.length; i++) { @@ -54,7 +54,7 @@ index b38b834..fded2f8 100644 exact = false; missed.set(i); } -@@ -776,7 +777,8 @@ public class InvocationExprent extends Exprent { +@@ -818,7 +819,8 @@ public class InvocationExprent extends Exprent { boolean failed = false; MethodDescriptor md = MethodDescriptor.parseDescriptor(mtt.getDescriptor()); for (int i = 0; i < lstParameters.size(); i++) { @@ -64,7 +64,7 @@ index b38b834..fded2f8 100644 if (!missed.get(i)) { if (!md.params[i].equals(ptype)) { failed = true; -@@ -784,6 +786,17 @@ public class InvocationExprent extends Exprent { +@@ -826,6 +828,17 @@ public class InvocationExprent extends Exprent { } } else { @@ -82,7 +82,7 @@ index b38b834..fded2f8 100644 if (md.params[i].type == CodeConstants.TYPE_OBJECT) { if (ptype.type != CodeConstants.TYPE_NULL) { if (!DecompilerContext.getStructContext().instanceOf(ptype.value, md.params[i].value)) { -@@ -811,7 +824,10 @@ public class InvocationExprent extends Exprent { +@@ -853,7 +866,10 @@ public class InvocationExprent extends Exprent { GenericMethodDescriptor gen = mtt.getSignature(); //TODO: Find synthetic flags for params, as Enum generic signatures do no contain the String,int params if (gen != null && gen.parameterTypes.size() > i && gen.parameterTypes.get(i).isGeneric()) { diff --git a/FernFlower-Patches/0029-Improve-inferred-generic-types.patch b/FernFlower-Patches/0029-Improve-inferred-generic-types.patch index 45f3d65..edbf3d5 100644 --- a/FernFlower-Patches/0029-Improve-inferred-generic-types.patch +++ b/FernFlower-Patches/0029-Improve-inferred-generic-types.patch @@ -1,4 +1,4 @@ -From 1be9c093784ec082fd073bd5f61148340d68cb31 Mon Sep 17 00:00:00 2001 +From 8001cd51a44dd519547d593e1e2e79b5d1dcf7ab Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 30 Apr 2019 10:34:56 -0700 Subject: [PATCH] Improve inferred generic types @@ -231,7 +231,7 @@ index 880a5d2..5143f83 100644 return getExprType(); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java -index d15b858..f30fdf0 100644 +index 8f69e43..1f27ed6 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java @@ -342,6 +342,11 @@ public class FunctionExprent extends Exprent { @@ -246,7 +246,7 @@ index d15b858..f30fdf0 100644 return getExprType(); } -@@ -657,6 +662,16 @@ public class FunctionExprent extends Exprent { +@@ -670,6 +675,16 @@ public class FunctionExprent extends Exprent { this.implicitType = implicitType; } @@ -264,7 +264,7 @@ index d15b858..f30fdf0 100644 public void getBytecodeRange(BitSet values) { measureBytecode(values, lstOperands); 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 fded2f8..e855a1a 100644 +index 43db4dc..25b88c3 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -52,6 +52,7 @@ public class InvocationExprent extends Exprent { @@ -282,9 +282,9 @@ index fded2f8..e855a1a 100644 + private Map genericsMap = new HashMap<>(); + private boolean isInvocationInstance = false; private boolean forceBoxing = false; + private boolean forceUnboxing = false; private boolean isSyntheticGetClass = false; - -@@ -172,45 +175,272 @@ public class InvocationExprent extends Exprent { +@@ -173,45 +176,272 @@ public class InvocationExprent extends Exprent { @Override public VarType getInferredExprType(VarType upperBound) { @@ -415,7 +415,7 @@ index fded2f8..e855a1a 100644 + tempMap.forEach((from, to) -> { + if (!fparams.contains(from.value)) { + processGenericMapping(from, to, named, bounds); - } ++ } + }); + tempMap.clear(); + } @@ -434,8 +434,8 @@ index fded2f8..e855a1a 100644 + Map> hierarchy = currentCls.classStruct.getAllGenerics(); + if (hierarchy.containsKey(mthCls.qualifiedName)) { + hierarchy.get(mthCls.qualifiedName).forEach(genericsMap::put); - } - } ++ } ++ } + } + } + @@ -446,9 +446,7 @@ index fded2f8..e855a1a 100644 + } + }); + } - -- if (!map.isEmpty()) { -- ret = ret.remap(map); ++ + Set paramGenerics = new HashSet<>(); + if (!lstParameters.isEmpty() && desc.getSignature() != null) { + List mask = null; @@ -511,16 +509,12 @@ index fded2f8..e855a1a 100644 + } + paramGenerics.add(paramType); + processGenericMapping(paramType, argtype, named, bounds); -+ } -+ } + } + } } - } - } -- } - -- VarType _new = this.gatherGenerics(upperBound, ret, desc.getSignature().typeParameters, genericArgs); -- if (desc.getSignature().returnType != _new) { -- return _new; ++ } ++ } ++ + upperBoundsMap.forEach((k, v) -> { + if (fparams.contains(k.value) && !GenericType.DUMMY_VAR.equals(v)) { + processGenericMapping(k, v ,named, bounds); @@ -529,7 +523,9 @@ index fded2f8..e855a1a 100644 + + if (!genericsMap.isEmpty()) { + VarType newRet = ret.remap(hierarchyMap); -+ + +- if (!map.isEmpty()) { +- ret = ret.remap(map); + boolean skipArgs = true; + if (!fparams.isEmpty() && newRet.isGeneric()) { + for (VarType genVar : ((GenericType)newRet).getAllGenericVars()) { @@ -537,8 +533,8 @@ index fded2f8..e855a1a 100644 + skipArgs = false; + break; + } -+ } -+ } + } + } + + newRet = newRet.remap(genericsMap); + if (newRet == null) { @@ -571,21 +567,25 @@ index fded2f8..e855a1a 100644 + if (newRet != ret && !(newRet.isGeneric() && ((GenericType)newRet).hasUnknownGenericType(named.keySet()))) { + return newRet; + } -+ } -+ + } +- } + +- VarType _new = this.gatherGenerics(upperBound, ret, desc.getSignature().typeParameters, genericArgs); +- if (desc.getSignature().returnType != _new) { +- return _new; + if (ret.isGeneric() && ((GenericType)ret).getAllGenericVars().isEmpty()) { + return ret; + } } } -@@ -313,6 +543,19 @@ public class InvocationExprent extends Exprent { +@@ -314,7 +544,19 @@ public class InvocationExprent extends Exprent { TextUtil.writeQualifiedSuper(buf, super_qualifier); } else if (instance != null) { + StructClass cl = DecompilerContext.getStructContext().getClass(classname); + -+ VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); + VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); + if (!genericsMap.isEmpty() && cl != null && cl.getSignature() != null) { + VarType _new = cl.getSignature().genericType.remap(genericsMap); + if (_new != cl.getSignature().genericType) { @@ -596,21 +596,20 @@ index fded2f8..e855a1a 100644 + instance.setInvocationInstance(); + VarType rightType = instance.getInferredExprType(leftType); + - if (isUnboxingCall()) { + if (isUnboxingCall() && !forceUnboxing) { // we don't print the unboxing call - no need to bother with the instance wrapping / casting if (instance.type == Exprent.EXPRENT_FUNCTION) { -@@ -331,8 +574,8 @@ public class InvocationExprent extends Exprent { +@@ -343,7 +585,8 @@ public class InvocationExprent extends Exprent { TextBuffer res = instance.toJava(indent, tracer); - VarType rightType = instance.getExprType(); -- VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); + boolean skippedCast = instance.type == EXPRENT_FUNCTION && + ((FunctionExprent)instance).getFuncType() == FunctionExprent.FUNCTION_CAST && !((FunctionExprent)instance).doesCast(); if (rightType.equals(VarType.VARTYPE_OBJECT) && !leftType.equals(rightType)) { buf.append("((").append(ExprProcessor.getCastTypeName(leftType)).append(")"); -@@ -342,7 +585,7 @@ public class InvocationExprent extends Exprent { +@@ -353,7 +596,7 @@ public class InvocationExprent extends Exprent { } buf.append(res).append(")"); } @@ -619,7 +618,7 @@ index fded2f8..e855a1a 100644 buf.append("(").append(res).append(")"); } else { -@@ -388,6 +631,12 @@ public class InvocationExprent extends Exprent { +@@ -399,6 +642,12 @@ public class InvocationExprent extends Exprent { } } @@ -632,7 +631,7 @@ index fded2f8..e855a1a 100644 List mask = null; boolean isEnum = false; if (functype == TYP_INIT) { -@@ -400,28 +649,6 @@ public class InvocationExprent extends Exprent { +@@ -411,28 +660,6 @@ public class InvocationExprent extends Exprent { ClassNode currCls = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)); List matches = getMatchedDescriptors(); BitSet setAmbiguousParameters = getAmbiguousParameters(matches); @@ -661,8 +660,8 @@ index fded2f8..e855a1a 100644 // omit 'new Type[] {}' for the last parameter of a vararg method call if (lstParameters.size() == descriptor.params.length && isVarArgCall()) { -@@ -485,20 +712,32 @@ public class InvocationExprent extends Exprent { - +@@ -519,20 +746,32 @@ public class InvocationExprent extends Exprent { + } } - if (instance != null && !genArgs.isEmpty()) { @@ -707,7 +706,7 @@ index fded2f8..e855a1a 100644 } -@@ -536,6 +775,10 @@ public class InvocationExprent extends Exprent { +@@ -570,6 +809,10 @@ public class InvocationExprent extends Exprent { } */ @@ -718,7 +717,7 @@ index fded2f8..e855a1a 100644 // 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter ExprProcessor.getCastedExprent(lstParameters.get(i), types[i], buff, indent, true, ambiguous, true, true, tracer); -@@ -551,8 +794,6 @@ public class InvocationExprent extends Exprent { +@@ -585,8 +828,6 @@ public class InvocationExprent extends Exprent { } } @@ -727,7 +726,7 @@ index fded2f8..e855a1a 100644 return buf; } -@@ -840,6 +1081,162 @@ public class InvocationExprent extends Exprent { +@@ -882,6 +1123,162 @@ public class InvocationExprent extends Exprent { return ambiguous; } @@ -890,7 +889,7 @@ index fded2f8..e855a1a 100644 @Override public void replaceExprent(Exprent oldExpr, Exprent newExpr) { if (oldExpr == instance) { -@@ -952,6 +1349,18 @@ public class InvocationExprent extends Exprent { +@@ -994,6 +1391,18 @@ public class InvocationExprent extends Exprent { return isSyntheticGetClass; } diff --git a/FernFlower-Patches/0030-Improve-stack-var-processor-output.patch b/FernFlower-Patches/0030-Improve-stack-var-processor-output.patch index 0c10690..82de6d1 100644 --- a/FernFlower-Patches/0030-Improve-stack-var-processor-output.patch +++ b/FernFlower-Patches/0030-Improve-stack-var-processor-output.patch @@ -1,4 +1,4 @@ -From 63f17f4720350338c77aa4edb247e0dc23e45737 Mon Sep 17 00:00:00 2001 +From c41a9200ee52345805a1a51997d0a663966530f6 Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 25 Aug 2019 18:02:16 -0700 Subject: [PATCH] Improve stack var processor output @@ -319,10 +319,10 @@ index 1232e64..500c5eb 100644 } \ No newline at end of file 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 e855a1a..20cc109 100644 +index 25b88c3..9bbdb53 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java -@@ -165,6 +165,11 @@ public class InvocationExprent extends Exprent { +@@ -166,6 +166,11 @@ public class InvocationExprent extends Exprent { addBytecodeOffsets(expr.bytecode); bootstrapArguments = expr.getBootstrapArguments(); isSyntheticGetClass = expr.isSyntheticGetClass(); diff --git a/FernFlower-Patches/0033-Add-explicit-cast-to-invocations-of-java-nio-Buffer-.patch b/FernFlower-Patches/0033-Add-explicit-cast-to-invocations-of-java-nio-Buffer-.patch index eac4037..66c6d9c 100644 --- a/FernFlower-Patches/0033-Add-explicit-cast-to-invocations-of-java-nio-Buffer-.patch +++ b/FernFlower-Patches/0033-Add-explicit-cast-to-invocations-of-java-nio-Buffer-.patch @@ -1,4 +1,4 @@ -From 9315c08a77b492832a7ecea50becc72cd44f1267 Mon Sep 17 00:00:00 2001 +From 9c65faa246edeb70c783f560388f0d0f3d92e587 Mon Sep 17 00:00:00 2001 From: LexManos Date: Tue, 14 Apr 2020 19:25:41 -0700 Subject: [PATCH] Add explicit cast to invocations of java/nio/Buffer @@ -9,7 +9,7 @@ Subject: [PATCH] Add explicit cast to invocations of java/nio/Buffer 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 20cc109..dd99bd0 100644 +index 9bbdb53..7a3790f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -46,6 +46,8 @@ public class InvocationExprent extends Exprent { @@ -21,7 +21,7 @@ index 20cc109..dd99bd0 100644 private String name; private String classname; private boolean isStatic; -@@ -593,6 +595,12 @@ public class InvocationExprent extends Exprent { +@@ -604,6 +606,12 @@ public class InvocationExprent extends Exprent { else if (instance.getPrecedence() > getPrecedence() && !skippedCast) { buf.append("(").append(res).append(")"); }