Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit d4d7628

Browse files
authored
Merge pull request #31 from BaseMC/develop
Stability update
2 parents f3ad2e6 + ca93d12 commit d4d7628

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+755
-51
lines changed

.github/workflows/upstream_update.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Pull detached upstream automatically
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
# Run twice per week
7+
- cron: '22 2 * * 2,6'
8+
9+
jobs:
10+
check_upstream:
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 3
13+
steps:
14+
# Checkout this repo
15+
- uses: actions/checkout@v2
16+
# Fetch the history and unshallow the checked out repo so that it can be used
17+
- name: Fetch all history for all tags and branches
18+
run: git fetch --prune --unshallow
19+
# Pull the detached remote and do the magic
20+
- name: Pull Detached Remote
21+
uses: litetex/pull-detached-remote@v0.2.0
22+
with:
23+
upstreamrepo: https://github.com/fesh0r/fernflower
24+
upstreambranch: master
25+
prassignees: litetex
26+
prlabels: upstream
27+
env:
28+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
GITHUB_PAT: ${{ secrets.GH_PAT }}

src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
1+
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.code.cfg;
33

44
import org.jetbrains.java.decompiler.code.*;
@@ -432,7 +432,7 @@ private void processJsr() {
432432
}
433433
}
434434

435-
private static class JsrRecord {
435+
private static final class JsrRecord {
436436
private final BasicBlock jsr;
437437
private final Set<BasicBlock> range;
438438
private final BasicBlock ret;

src/org/jetbrains/java/decompiler/main/ClassWriter.java

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor;
1515
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
1616
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
17-
import org.jetbrains.java.decompiler.struct.StructClass;
18-
import org.jetbrains.java.decompiler.struct.StructField;
19-
import org.jetbrains.java.decompiler.struct.StructMember;
20-
import org.jetbrains.java.decompiler.struct.StructMethod;
17+
import org.jetbrains.java.decompiler.struct.*;
2118
import org.jetbrains.java.decompiler.struct.attr.*;
2219
import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
2320
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
@@ -28,6 +25,7 @@
2825
import org.jetbrains.java.decompiler.util.TextBuffer;
2926

3027
import java.util.*;
28+
import java.util.stream.Collectors;
3129

3230
public class ClassWriter {
3331
private final PoolInterceptor interceptor;
@@ -162,11 +160,19 @@ public void classToJava(ClassNode node, TextBuffer buffer, int indent, BytecodeM
162160

163161
dummy_tracer.incrementCurrentSourceLine(buffer.countLines(start_class_def));
164162

163+
List<StructRecordComponent> components = cl.getRecordComponents();
164+
165165
for (StructField fd : cl.getFields()) {
166166
boolean hide = fd.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) ||
167167
wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()));
168168
if (hide) continue;
169169

170+
if (components != null && fd.getAccessFlags() == (CodeConstants.ACC_FINAL | CodeConstants.ACC_PRIVATE) &&
171+
components.stream().anyMatch(c -> c.getName().equals(fd.getName()) && c.getDescriptor().equals(fd.getDescriptor()))) {
172+
// Record component field: skip it
173+
continue;
174+
}
175+
170176
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
171177
if (isEnum) {
172178
if (enumFields) {
@@ -256,6 +262,21 @@ else if (enumFields) {
256262
DecompilerContext.getLogger().endWriteClass();
257263
}
258264

265+
private static boolean isSyntheticRecordMethod(StructMethod mt, TextBuffer code) {
266+
if (mt.getClassStruct().getRecordComponents() == null) return false;
267+
String name = mt.getName();
268+
String descriptor = mt.getDescriptor();
269+
if (name.equals("equals") && descriptor.equals("(Ljava/lang/Object;)Z") ||
270+
name.equals("hashCode") && descriptor.equals("()I") ||
271+
name.equals("toString") && descriptor.equals("()Ljava/lang/String;")) {
272+
if (code.countLines() == 1) {
273+
String str = code.toString().trim();
274+
return str.startsWith("return this." + name + "<invokedynamic>(this");
275+
}
276+
}
277+
return false;
278+
}
279+
259280
private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
260281
StructLineNumberTableAttribute table = method.getAttribute(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
261282
tracer.setLineNumberTable(table);
@@ -302,6 +323,13 @@ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent)
302323
flags &= ~CodeConstants.ACC_FINAL;
303324
}
304325

326+
List<StructRecordComponent> components = cl.getRecordComponents();
327+
328+
if (components != null) {
329+
// records are implicitly final
330+
flags &= ~CodeConstants.ACC_FINAL;
331+
}
332+
305333
appendModifiers(buffer, flags, CLASS_ALLOWED, isInterface, CLASS_EXCLUDED);
306334

307335
if (isEnum) {
@@ -313,6 +341,9 @@ else if (isInterface) {
313341
}
314342
buffer.append("interface ");
315343
}
344+
else if (components != null) {
345+
buffer.append("record ");
346+
}
316347
else {
317348
buffer.append("class ");
318349
}
@@ -324,9 +355,22 @@ else if (isInterface) {
324355
appendTypeParameters(buffer, descriptor.fparameters, descriptor.fbounds);
325356
}
326357

358+
if (components != null) {
359+
buffer.append('(');
360+
for (int i = 0; i < components.size(); i++) {
361+
StructRecordComponent cd = components.get(i);
362+
if (i > 0) {
363+
buffer.append(", ");
364+
}
365+
boolean varArgComponent = i == components.size() - 1 && isVarArgRecord(cl);
366+
recordComponentToJava(cd, buffer, varArgComponent);
367+
}
368+
buffer.append(')');
369+
}
370+
327371
buffer.append(' ');
328372

329-
if (!isEnum && !isInterface && cl.superClass != null) {
373+
if (!isEnum && !isInterface && components == null && cl.superClass != null) {
330374
VarType supertype = new VarType(cl.superClass.getString(), true);
331375
if (!VarType.VARTYPE_OBJECT.equals(supertype)) {
332376
buffer.append("extends ");
@@ -362,6 +406,13 @@ else if (isInterface) {
362406
buffer.append('{').appendLineSeparator();
363407
}
364408

409+
private boolean isVarArgRecord(StructClass cl) {
410+
String canonicalConstructorDescriptor =
411+
cl.getRecordComponents().stream().map(c -> c.getDescriptor()).collect(Collectors.joining("", "(", ")V"));
412+
StructMethod ctor = cl.getMethod(CodeConstants.INIT_NAME, canonicalConstructorDescriptor);
413+
return ctor != null && ctor.hasModifier(CodeConstants.ACC_VARARGS);
414+
}
415+
365416
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
366417
int start = buffer.length();
367418
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
@@ -452,6 +503,33 @@ else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants
452503
}
453504
}
454505

506+
private static void recordComponentToJava(StructRecordComponent cd, TextBuffer buffer, boolean varArgComponent) {
507+
appendAnnotations(buffer, -1, cd, TypeAnnotation.FIELD);
508+
509+
VarType fieldType = new VarType(cd.getDescriptor(), false);
510+
511+
GenericFieldDescriptor descriptor = null;
512+
if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
513+
StructGenericSignatureAttribute attr = cd.getAttribute(StructGeneralAttribute.ATTRIBUTE_SIGNATURE);
514+
if (attr != null) {
515+
descriptor = GenericMain.parseFieldSignature(attr.getSignature());
516+
}
517+
}
518+
519+
if (descriptor != null) {
520+
buffer.append(GenericMain.getGenericCastTypeName(varArgComponent ? descriptor.type.decreaseArrayDim() : descriptor.type));
521+
}
522+
else {
523+
buffer.append(ExprProcessor.getCastTypeName(varArgComponent ? fieldType.decreaseArrayDim() : fieldType));
524+
}
525+
if (varArgComponent) {
526+
buffer.append("...");
527+
}
528+
buffer.append(' ');
529+
530+
buffer.append(cd.getName());
531+
}
532+
455533
private static void methodLambdaToJava(ClassNode lambdaNode,
456534
ClassWrapper classWrapper,
457535
StructMethod mt,
@@ -817,7 +895,8 @@ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarT
817895
BytecodeMappingTracer codeTracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine());
818896
TextBuffer code = root.toJava(indent + 1, codeTracer);
819897

820-
hideMethod = (code.length() == 0) && (clinit || dinit || hideConstructor(node, init, throwsExceptions, paramCount, flags));
898+
hideMethod = (code.length() == 0) && (clinit || dinit || hideConstructor(node, init, throwsExceptions, paramCount, flags))
899+
|| isSyntheticRecordMethod(mt, code);
821900

822901
buffer.append(code);
823902

@@ -959,7 +1038,13 @@ private static void appendAnnotations(TextBuffer buffer, int indent, StructMembe
9591038
for (AnnotationExprent annotation : attribute.getAnnotations()) {
9601039
String text = annotation.toJava(indent, BytecodeMappingTracer.DUMMY).toString();
9611040
filter.add(text);
962-
buffer.append(text).appendLineSeparator();
1041+
buffer.append(text);
1042+
if (indent < 0) {
1043+
buffer.append(' ');
1044+
}
1045+
else {
1046+
buffer.appendLineSeparator();
1047+
}
9631048
}
9641049
}
9651050
}

src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
1+
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler;
33

44
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -110,7 +110,7 @@ else if (finallyBlockIDs.containsKey(handler.id)) {
110110
return false;
111111
}
112112

113-
private static class Record {
113+
private static final class Record {
114114
private final int firstCode;
115115
private final Map<BasicBlock, Boolean> mapLast;
116116

@@ -527,7 +527,7 @@ private boolean verifyFinallyEx(ControlFlowGraph graph, CatchAllStatement fstat,
527527
return true;
528528
}
529529

530-
private static class Area {
530+
private static final class Area {
531531
private final BasicBlock start;
532532
private final Set<BasicBlock> sample;
533533
private final BasicBlock next;

src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
1+
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler;
33

44
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -170,6 +170,17 @@ private static Exprent identifySecondaryFunctions(Exprent exprent, boolean state
170170
}
171171

172172
if (desttype >= 0) {
173+
if (functype != FunctionExprent.FUNCTION_LCMP) {
174+
boolean oneForNan = functype == FunctionExprent.FUNCTION_DCMPL || functype == FunctionExprent.FUNCTION_FCMPL;
175+
boolean trueForOne = desttype == FunctionExprent.FUNCTION_LT || desttype == FunctionExprent.FUNCTION_LE;
176+
boolean trueForNan = oneForNan == trueForOne;
177+
if (trueForNan) {
178+
List<Exprent> operands = new ArrayList<>();
179+
operands.add(new FunctionExprent(funcsnot[desttype - FunctionExprent.FUNCTION_EQ],
180+
funcexpr.getLstOperands(), funcexpr.bytecode));
181+
return new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, operands, funcexpr.bytecode);
182+
}
183+
}
173184
return new FunctionExprent(desttype, funcexpr.getLstOperands(), funcexpr.bytecode);
174185
}
175186
}
@@ -378,6 +389,7 @@ public static Exprent propagateBoolNot(Exprent exprent) {
378389
FunctionExprent fparam = (FunctionExprent)param;
379390

380391
int ftype = fparam.getFuncType();
392+
boolean canSimplify = false;
381393
switch (ftype) {
382394
case FunctionExprent.FUNCTION_BOOL_NOT:
383395
Exprent newexpr = fparam.getLstOperands().get(0);
@@ -394,12 +406,24 @@ public static Exprent propagateBoolNot(Exprent exprent) {
394406
}
395407
case FunctionExprent.FUNCTION_EQ:
396408
case FunctionExprent.FUNCTION_NE:
409+
canSimplify = true;
397410
case FunctionExprent.FUNCTION_LT:
398411
case FunctionExprent.FUNCTION_GE:
399412
case FunctionExprent.FUNCTION_GT:
400413
case FunctionExprent.FUNCTION_LE:
401-
fparam.setFuncType(funcsnot[ftype - FunctionExprent.FUNCTION_EQ]);
402-
return fparam;
414+
if (!canSimplify) {
415+
operands = fparam.getLstOperands();
416+
VarType left = operands.get(0).getExprType();
417+
VarType right = operands.get(1).getExprType();
418+
VarType commonSupertype = VarType.getCommonSupertype(left, right);
419+
if (commonSupertype != null) {
420+
canSimplify = commonSupertype.type != CodeConstants.TYPE_FLOAT && commonSupertype.type != CodeConstants.TYPE_DOUBLE;
421+
}
422+
}
423+
if (canSimplify) {
424+
fparam.setFuncType(funcsnot[ftype - FunctionExprent.FUNCTION_EQ]);
425+
return fparam;
426+
}
403427
}
404428
}
405429
}

src/org/jetbrains/java/decompiler/modules/decompiler/deobfuscator/ExceptionDeobfuscator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
1+
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler.deobfuscator;
33

44
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -20,7 +20,7 @@
2020

2121
public class ExceptionDeobfuscator {
2222

23-
private static class Range {
23+
private static final class Range {
2424
private final BasicBlock handler;
2525
private final String uniqueStr;
2626
private final Set<BasicBlock> protectedRange;
@@ -407,7 +407,7 @@ public static void insertDummyExceptionHandlerBlocks(ControlFlowGraph graph, int
407407

408408
for (ExceptionRangeCFG range : ranges) {
409409

410-
// add some dummy instructions to prevent optimizing away the empty block
410+
// add some dummy instructions to prevent optimizing away the empty block
411411
SimpleInstructionSequence seq = new SimpleInstructionSequence();
412412
seq.addInstruction(Instruction.create(CodeConstants.opc_bipush, false, CodeConstants.GROUP_GENERAL, bytecode_version, new int[]{0}), -1);
413413
seq.addInstruction(Instruction.create(CodeConstants.opc_pop, false, CodeConstants.GROUP_GENERAL, bytecode_version, null), -1);

src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class ConstExprent extends Exprent {
2828
CHAR_ESCAPES.put(0xC, "\\f"); /* \u000c: form feed FF */
2929
CHAR_ESCAPES.put(0xD, "\\r"); /* \u000d: carriage return CR */
3030
//CHAR_ESCAPES.put(0x22, "\\\""); /* \u0022: double quote " */
31-
CHAR_ESCAPES.put(0x27, "\\\'"); /* \u0027: single quote ' */
31+
CHAR_ESCAPES.put(0x27, "\\'"); /* \u0027: single quote ' */
3232
CHAR_ESCAPES.put(0x5C, "\\\\"); /* \u005c: backslash \ */
3333
}
3434

src/org/jetbrains/java/decompiler/modules/decompiler/sforms/FlattenStatementsHelper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
1+
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler.sforms;
33

44
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
@@ -472,7 +472,7 @@ public Map<Integer, String[]> getMapDestinationNodes() {
472472
return mapDestinationNodes;
473473
}
474474

475-
public static class FinallyPathWrapper {
475+
public static final class FinallyPathWrapper {
476476
public final String source;
477477
public final String destination;
478478
public final String entry;

src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
1+
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler.stats;
33

44
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -17,7 +17,7 @@
1717
import java.util.List;
1818
import java.util.Set;
1919

20-
public class CatchAllStatement extends Statement {
20+
public final class CatchAllStatement extends Statement {
2121

2222
private Statement handler;
2323

src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
1+
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
22
package org.jetbrains.java.decompiler.modules.decompiler.stats;
33

44
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -17,7 +17,7 @@
1717
import java.util.List;
1818
import java.util.Set;
1919

20-
public class CatchStatement extends Statement {
20+
public final class CatchStatement extends Statement {
2121
private final List<List<String>> exctstrings = new ArrayList<>();
2222
private final List<VarExprent> vars = new ArrayList<>();
2323

0 commit comments

Comments
 (0)