diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PatternHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PatternHelper.java
index a1082739970b..ab97dd180b9b 100644
--- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PatternHelper.java
+++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PatternHelper.java
@@ -1,11 +1,15 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.modules.decompiler;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.stats.*;
import org.jetbrains.java.decompiler.struct.StructClass;
+import org.jetbrains.java.decompiler.struct.gen.VarType;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class PatternHelper {
@@ -17,12 +21,16 @@ public class PatternHelper {
* @param statement root statement to start traversal
* @param structClass owner class of statement
*/
- public static void replaceAssignmentsWithPatternVariables(RootStatement statement, StructClass structClass) {
- if (!structClass.isVersion16()) return;
- replaceAssignmentsWithPatternVariables(statement);
+ public static void replaceAssignmentsWithPatternVariables(@NotNull RootStatement statement, @NotNull StructClass structClass) {
+ if (!structClass.hasPatternsInInstanceofSupport()) return;
+ // todo VarExprent overrides equals, but not hashCode, duplicates are possible
+ Map tempVarAssignments = new HashMap<>();
+ replaceAssignmentsWithPatternVariables(statement, tempVarAssignments);
+ SwitchHelper.removeTempVariableDeclarations(tempVarAssignments);
}
- private static void replaceAssignmentsWithPatternVariables(Statement statement) {
+ private static void replaceAssignmentsWithPatternVariables(@NotNull Statement statement,
+ @NotNull Map tempVarAssignments) {
if (statement instanceof IfStatement) {
IfStatement ifStatement = (IfStatement)statement;
FunctionExprent instanceOfExprent = findInstanceofExprent(ifStatement);
@@ -34,29 +42,34 @@ public class PatternHelper {
ConstExprent checkType = (ConstExprent)operands.get(1);
PatternVariableCandidate patternVarCandidate = findPatternVarCandidate(ifStatement.getIfstat(), operand, checkType);
- if (patternVarCandidate == null) {
+ if (patternVarCandidate == null && ifStatement.getElsestat() != null) {
patternVarCandidate = findPatternVarCandidate(ifStatement.getElsestat(), operand, checkType);
}
if (patternVarCandidate == null) return;
- instanceOfExprent.getLstOperands().remove(1);
- instanceOfExprent.getLstOperands().add(patternVarCandidate.varExprent);
+ operands.remove(1);
+ if (!patternVarCandidate.varExprent.isDefinition()) {
+ patternVarCandidate.varExprent.setDefinition(true);
+ tempVarAssignments.put(patternVarCandidate.varExprent, ifStatement);
+ }
+ operands.add(patternVarCandidate.varExprent);
patternVarCandidate.ifElseStat.getExprents().remove(patternVarCandidate.assignmentExprent);
- return;
}
for (Statement child : statement.getStats()) {
- replaceAssignmentsWithPatternVariables(child);
+ replaceAssignmentsWithPatternVariables(child, tempVarAssignments);
}
}
- private static FunctionExprent findInstanceofExprent(IfStatement ifStat) {
+ private static FunctionExprent findInstanceofExprent(@NotNull IfStatement ifStat) {
return ifStat.getHeadexprent().getAllExprents(true).stream()
.filter(expr -> expr.type == Exprent.EXPRENT_FUNCTION).map(expr -> (FunctionExprent)expr)
.filter(expr -> expr.getFuncType() == FunctionExprent.FUNCTION_INSTANCEOF)
.findFirst().orElse(null);
}
- private static PatternVariableCandidate findPatternVarCandidate(Statement ifElseStat, VarExprent operand, ConstExprent checkType) {
+ private static PatternVariableCandidate findPatternVarCandidate(@NotNull Statement ifElseStat,
+ @NotNull VarExprent operand,
+ @NotNull ConstExprent checkType) {
if (ifElseStat instanceof BasicBlockStatement) {
List ifElseExprents = ifElseStat.getExprents();
if (ifElseExprents.isEmpty() || ifElseExprents.get(0).type != Exprent.EXPRENT_ASSIGNMENT) return null;
@@ -64,11 +77,24 @@ public class PatternHelper {
AssignmentExprent assignmentExprent = (AssignmentExprent)ifElseExprents.get(0);
if (assignmentExprent.getLeft().type != Exprent.EXPRENT_VAR) return null;
VarExprent varExprent = (VarExprent)assignmentExprent.getLeft();
- if (!varExprent.isDefinition()) return null;
if (assignmentExprent.getRight().type != Exprent.EXPRENT_FUNCTION) return null;
FunctionExprent castExprent = (FunctionExprent)assignmentExprent.getRight();
if (castExprent.getFuncType() != FunctionExprent.FUNCTION_CAST) return null;
+ if (!varExprent.isDefinition()) {
+ Exprent leftAssignmentPart = assignmentExprent.getLeft();
+ Exprent rightAssignmentPart = assignmentExprent.getRight();
+ if (leftAssignmentPart.type != Exprent.EXPRENT_VAR || rightAssignmentPart.type != Exprent.EXPRENT_FUNCTION ||
+ ((FunctionExprent)rightAssignmentPart).getFuncType() != FunctionExprent.FUNCTION_CAST) {
+ return null;
+ }
+ varExprent = ((VarExprent)leftAssignmentPart);
+ List castOperands = ((FunctionExprent)rightAssignmentPart).getLstOperands();
+ if (castOperands.size() != 2 || castOperands.get(1).type != Exprent.EXPRENT_CONST) return null;
+ VarType castType = ((ConstExprent)castOperands.get(1)).getConstType();
+ varExprent.setVarType(castType);
+ }
+
List castExprents = castExprent.getAllExprents();
if (castExprents.size() == 2 && operand.equals(castExprents.get(0)) && checkType.equals(castExprents.get(1))) {
return new PatternVariableCandidate(ifElseStat, assignmentExprent, varExprent);
@@ -82,11 +108,13 @@ public class PatternHelper {
}
private static class PatternVariableCandidate {
- private final Statement ifElseStat;
- private final AssignmentExprent assignmentExprent;
- private final VarExprent varExprent;
+ private final @NotNull Statement ifElseStat;
+ private final @NotNull AssignmentExprent assignmentExprent;
+ private final @NotNull VarExprent varExprent;
- private PatternVariableCandidate(Statement ifElseStat, AssignmentExprent assignmentExprent, VarExprent varExprent) {
+ private PatternVariableCandidate(@NotNull Statement ifElseStat,
+ @NotNull AssignmentExprent assignmentExprent,
+ @NotNull VarExprent varExprent) {
this.ifElseStat = ifElseStat;
this.assignmentExprent = assignmentExprent;
this.varExprent = varExprent;
diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchHelper.java
index be0acff93686..d6611733b0e2 100644
--- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchHelper.java
+++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchHelper.java
@@ -138,32 +138,39 @@ public final class SwitchHelper {
(index instanceof InvocationExprent && ((InvocationExprent)index).getName().equals("ordinal")));
}
- private static void removeTempVariableDeclarations(@NotNull Map tempVarAssignments) {
+ static void removeTempVariableDeclarations(@NotNull Map tempVarAssignments) {
if (tempVarAssignments.isEmpty()) return;
for (Statement statement : new HashSet<>(tempVarAssignments.values())) {
Statement parent = statement;
while (parent != null) {
boolean removed = false;
- Statement firstStatement = parent.getFirst();
- if (firstStatement.type == Statement.TYPE_BASIC_BLOCK) {
- for (int i = 0; i < firstStatement.getExprents().size(); i++) {
- Exprent exprent = firstStatement.getExprents().get(i);
- Exprent assignmentExprent = null;
- if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) {
- assignmentExprent = exprent;
- exprent = ((AssignmentExprent)exprent).getLeft();
- }
- if (exprent.type != Exprent.EXPRENT_VAR) continue;
- VarExprent varExprent = (VarExprent)exprent;
- if (varExprent.isDefinition() && tempVarAssignments.keySet().stream()
- .anyMatch(expr -> expr.getIndex() == varExprent.getIndex() && expr.getVersion() == varExprent.getVersion())) {
- firstStatement.getExprents().remove(assignmentExprent == null ? varExprent : assignmentExprent);
- removed = true;
- break;
- }
- }
- if (removed) break;
+ List varExprents;
+ if (parent.getFirst().type == Statement.TYPE_BASIC_BLOCK) {
+ varExprents = parent.getFirst().getExprents();
}
+ else if (parent.type == Statement.TYPE_TRY_CATCH) {
+ varExprents = parent.getVarDefinitions();
+ }
+ else {
+ varExprents = Collections.emptyList();
+ }
+ for (int i = 0; i < varExprents.size(); i++) {
+ Exprent exprent = varExprents.get(i);
+ Exprent assignmentExprent = null;
+ if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) {
+ assignmentExprent = exprent;
+ exprent = ((AssignmentExprent)exprent).getLeft();
+ }
+ if (exprent.type != Exprent.EXPRENT_VAR) continue;
+ VarExprent varExprent = (VarExprent)exprent;
+ if (varExprent.isDefinition() && tempVarAssignments.keySet().stream()
+ .anyMatch(expr -> expr.getIndex() == varExprent.getIndex() && expr.getVersion() == varExprent.getVersion())) {
+ varExprents.remove(assignmentExprent == null ? varExprent : assignmentExprent);
+ removed = true;
+ break;
+ }
+ }
+ if (removed) break;
parent = parent.getParent();
}
}
@@ -176,7 +183,7 @@ public final class SwitchHelper {
@NotNull
Set