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 findRealCaseValuesHashCodes(@NotNull SwitchStatement switchStatement) { - //noinspection SSBasedInspection,ConstantConditions + // noinspection SSBasedInspection return switchStatement.getCaseValues().stream() // We take only buckets that don't contain null value. // null value represents default branch and no temp variable is assigned there. diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java index 030841c848e8..d6267aed28ed 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/StructClass.java @@ -204,16 +204,32 @@ public class StructClass extends StructMember { return majorVersion >= CodeConstants.BYTECODE_JAVA_8; } - public boolean hasSealedClassesSupport() { - return majorVersion >= CodeConstants.BYTECODE_JAVA_17 || (majorVersion >= CodeConstants.BYTECODE_JAVA_15 && isPreviewVersion()); + public boolean isVersion14() { + return majorVersion >= CodeConstants.BYTECODE_JAVA_14; + } + + public boolean isVersion15() { + return majorVersion >= CodeConstants.BYTECODE_JAVA_15; + } + + public boolean isVersion16() { + return majorVersion >= CodeConstants.BYTECODE_JAVA_16; + } + + public boolean isVersion17() { + return majorVersion >= CodeConstants.BYTECODE_JAVA_17; } public boolean isPreviewVersion() { return minorVersion == 0xFFFF; } - public boolean isVersion16() { - return majorVersion >= CodeConstants.BYTECODE_JAVA_16; + public boolean hasSealedClassesSupport() { + return isVersion17() || (isVersion15() && isPreviewVersion()); + } + + public boolean hasPatternsInInstanceofSupport() { + return isVersion16() || (isVersion14() && isPreviewVersion()); } @Override diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index f8a55febe5e2..6958296479d6 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -212,24 +212,13 @@ public class SingleClassesTest { @Test public void testInheritanceChainCycle() { doTest("pkg/TestInheritanceChainCycle"); } @Test public void testDynamicConstantPoolEntry() { doTest("java11/TestDynamicConstantPoolEntry"); } - @Test - public void testInstanceof() { - doTest("patterns/TestInstanceof"); - } - @Test - public void testInvertedInstanceof() { - doTest("patterns/TestInvertedInstanceof"); + @Test public void testInstanceofWithPattern() { + doTest("patterns/TestInstanceofWithPattern"); } - - @Test - public void testInstanceofBinaryExpr() { - doTest("patterns/TestInstanceofBinaryExpr"); - } - - @Test - public void testInstanceofVarNotSupported() { - doTest("patterns/TestInstanceofVarNotSupported"); + @Test public void testInstanceofVarNotSupported() { + // bytecode version of this test data doesn't support patterns in instanceof, so no modifications regarding that are applied + doTest("patterns/TestInstanceofPatternNotSupported"); } @Test(expected = ClassFormatException.class) diff --git a/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceof.class b/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceof.class deleted file mode 100644 index b22c6931cbd2..000000000000 Binary files a/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceof.class and /dev/null differ diff --git a/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofBinaryExpr.class b/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofBinaryExpr.class deleted file mode 100644 index c184c05c48d4..000000000000 Binary files a/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofBinaryExpr.class and /dev/null differ diff --git a/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofVarNotSupported.class b/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofPatternNotSupported.class similarity index 71% rename from plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofVarNotSupported.class rename to plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofPatternNotSupported.class index 3c80580e72d3..6827b695d0ca 100644 Binary files a/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofVarNotSupported.class and b/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofPatternNotSupported.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofWithPattern.class b/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofWithPattern.class new file mode 100644 index 000000000000..85b7c96d933d Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/patterns/TestInstanceofWithPattern.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/patterns/TestInvertedInstanceof.class b/plugins/java-decompiler/engine/testData/classes/patterns/TestInvertedInstanceof.class deleted file mode 100644 index b65859dfecc1..000000000000 Binary files a/plugins/java-decompiler/engine/testData/classes/patterns/TestInvertedInstanceof.class and /dev/null differ diff --git a/plugins/java-decompiler/engine/testData/results/TestInstanceof.dec b/plugins/java-decompiler/engine/testData/results/TestInstanceof.dec deleted file mode 100644 index 4fdd9c096ce7..000000000000 --- a/plugins/java-decompiler/engine/testData/results/TestInstanceof.dec +++ /dev/null @@ -1,31 +0,0 @@ -package patterns; - -public class TestInstanceof { - void typePattern(Object str) { - if (str instanceof String s) {// 6 - System.out.println(s);// 7 - } else { - System.out.println("no");// 9 - } - - }// 11 -} - -class 'patterns/TestInstanceof' { - method 'typePattern (Ljava/lang/Object;)V' { - 3 4 - 6 4 - e 5 - 12 5 - 18 7 - 1b 7 - 1d 7 - 20 10 - } -} - -Lines mapping: -6 <-> 5 -7 <-> 6 -9 <-> 8 -11 <-> 11 diff --git a/plugins/java-decompiler/engine/testData/results/TestInstanceofBinaryExpr.dec b/plugins/java-decompiler/engine/testData/results/TestInstanceofBinaryExpr.dec deleted file mode 100644 index 362f1ff057ec..000000000000 --- a/plugins/java-decompiler/engine/testData/results/TestInstanceofBinaryExpr.dec +++ /dev/null @@ -1,39 +0,0 @@ -package patterns; - -public class TestInstanceofBinaryExpr { - void typePattern(Object str) { - if (str instanceof String s) {// 6 - if (s.length() > 1 || s.startsWith("a")) { - System.out.println(s);// 7 - return;// 11 - } - } - - System.out.println("no");// 9 - } -} - -class 'patterns/TestInstanceofBinaryExpr' { - method 'typePattern (Ljava/lang/Object;)V' { - 3 4 - 6 4 - f 5 - 12 5 - 13 5 - 17 5 - 19 5 - 1c 5 - 1f 6 - 23 6 - 29 11 - 2c 11 - 2e 11 - 31 7 - } -} - -Lines mapping: -6 <-> 5 -7 <-> 7 -9 <-> 12 -11 <-> 8 diff --git a/plugins/java-decompiler/engine/testData/results/TestInstanceofVarNotSupported.dec b/plugins/java-decompiler/engine/testData/results/TestInstanceofPatternNotSupported.dec similarity index 87% rename from plugins/java-decompiler/engine/testData/results/TestInstanceofVarNotSupported.dec rename to plugins/java-decompiler/engine/testData/results/TestInstanceofPatternNotSupported.dec index 6d885e0fcbfd..caed57462964 100644 --- a/plugins/java-decompiler/engine/testData/results/TestInstanceofVarNotSupported.dec +++ b/plugins/java-decompiler/engine/testData/results/TestInstanceofPatternNotSupported.dec @@ -1,6 +1,6 @@ -package patterns; +package decompiler; -public class TestInstanceofVarNotSupported { +public class TestInstanceofPatternNotSupported { void typePattern(Object str) { if (!(str instanceof String)) {// 5 System.out.println("no");// 6 @@ -16,7 +16,7 @@ public class TestInstanceofVarNotSupported { }// 7 15 } -class 'patterns/TestInstanceofVarNotSupported' { +class 'decompiler/TestInstanceofPatternNotSupported' { method 'typePattern (Ljava/lang/Object;)V' { 1 4 4 4 diff --git a/plugins/java-decompiler/engine/testData/results/TestInstanceofWithPattern.dec b/plugins/java-decompiler/engine/testData/results/TestInstanceofWithPattern.dec new file mode 100644 index 000000000000..48e1811b617e --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestInstanceofWithPattern.dec @@ -0,0 +1,235 @@ +package decompiler; + +import java.util.Collection; +import java.util.List; + +public class TestInstanceofWithPattern { + void typePattern1(Object str) { + if (str instanceof String s) {// 9 + System.out.println(s);// 10 + } else { + System.out.println("no");// 12 + } + + }// 14 + + void typePattern2(Object str) { + if (!(str instanceof String s)) {// 17 + System.out.println("no");// 18 + } else { + if (s.length() > 3) {// 22 + System.out.println(s);// 23 + } else if (s.startsWith("a")) {// 24 + System.out.println("" + s);// 25 + } + + } + }// 19 27 + + void typePatternInBinaryExpr(Object str) { + if (str instanceof String s) {// 30 + if (s.length() > 1 || s.startsWith("a")) { + System.out.println(s);// 31 + return;// 35 + } + } + + System.out.println("no");// 33 + } + + String returnInstanceof(Object obj) { + if (obj instanceof String s) {// 38 + if (s.length() > 50) { + return "\"" + s.substring(0, 50) + "...\"";// 39 + } + } + + if (obj instanceof String s) {// 41 + return "\"" + s + "\"";// 42 + } else if (obj instanceof Collection c) {// 44 + return "Collection (size = " + c.size() + ")";// 45 + } else { + return obj.toString();// 47 + } + } + + String complex(Object obj1, Object obj2) { + while(true) { + try { + if (obj1 instanceof String s) {// 53 + while(!s.startsWith("a")) {// 55 + } + + return s;// 56 + } + + if (obj2 instanceof Collection c) {// 59 + return c.toString();// 60 + } + } catch (Exception var7) {// 62 + if (obj2 instanceof String s) {// 63 + while(!s.startsWith("b")) {// 65 + } + + return s + "b";// 66 + } + + if (obj2 instanceof List l) {// 69 + String var10000 = this.getStr();// 70 + return var10000 + l.size(); + } + } + } + } + + String getStr() { + return null;// 77 + } +} + +class 'decompiler/TestInstanceofWithPattern' { + method 'typePattern1 (Ljava/lang/Object;)V' { + 3 7 + 6 7 + e 8 + 12 8 + 18 10 + 1b 10 + 1d 10 + 20 13 + } + + method 'typePattern2 (Ljava/lang/Object;)V' { + 1 16 + 4 16 + 7 17 + a 17 + c 17 + f 26 + 16 19 + 19 19 + 1a 19 + 1d 20 + 21 20 + 28 21 + 2a 21 + 2d 21 + 30 22 + 34 22 + 39 22 + 3c 26 + } + + method 'typePatternInBinaryExpr (Ljava/lang/Object;)V' { + 3 29 + 6 29 + f 30 + 12 30 + 13 30 + 17 30 + 19 30 + 1c 30 + 1f 31 + 23 31 + 29 36 + 2c 36 + 2e 36 + 31 32 + } + + method 'returnInstanceof (Ljava/lang/Object;)Ljava/lang/String;' { + 3 40 + 6 40 + f 41 + 12 41 + 14 41 + 18 42 + 19 42 + 1b 42 + 1e 42 + 23 42 + 27 46 + 2a 46 + 33 47 + 38 47 + 3c 48 + 3f 48 + 48 49 + 4d 49 + 52 49 + 54 51 + 57 51 + } + + method 'complex (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/String;' { + 5 58 + 8 58 + 14 59 + 16 59 + 19 59 + 1e 62 + 24 65 + 27 65 + 31 66 + 34 66 + 38 68 + 3e 69 + 41 69 + 4d 70 + 4f 70 + 52 70 + 57 73 + 5c 73 + 62 76 + 65 76 + 70 77 + 75 78 + 7a 78 + 7f 78 + } + + method 'getStr ()Ljava/lang/String;' { + 0 85 + 1 85 + } +} + +Lines mapping: +9 <-> 8 +10 <-> 9 +12 <-> 11 +14 <-> 14 +17 <-> 17 +18 <-> 18 +19 <-> 27 +22 <-> 20 +23 <-> 21 +24 <-> 22 +25 <-> 23 +27 <-> 27 +30 <-> 30 +31 <-> 32 +33 <-> 37 +35 <-> 33 +38 <-> 41 +39 <-> 43 +41 <-> 47 +42 <-> 48 +44 <-> 49 +45 <-> 50 +47 <-> 52 +53 <-> 59 +55 <-> 60 +56 <-> 63 +59 <-> 66 +60 <-> 67 +62 <-> 69 +63 <-> 70 +65 <-> 71 +66 <-> 74 +69 <-> 77 +70 <-> 78 +77 <-> 86 +Not mapped: +21 +72 diff --git a/plugins/java-decompiler/engine/testData/results/TestInvertedInstanceof.dec b/plugins/java-decompiler/engine/testData/results/TestInvertedInstanceof.dec deleted file mode 100644 index 6118cd59f60d..000000000000 --- a/plugins/java-decompiler/engine/testData/results/TestInvertedInstanceof.dec +++ /dev/null @@ -1,51 +0,0 @@ -package patterns; - -public class TestInvertedInstanceof { - void typePattern(Object str) { - if (!(str instanceof String s)) {// 5 - System.out.println("no");// 6 - } else { - if (s.length() > 3) {// 10 - System.out.println(s);// 11 - } else if (s.startsWith("a")) {// 12 - System.out.println("" + s);// 13 - } - - } - }// 7 15 -} - -class 'patterns/TestInvertedInstanceof' { - method 'typePattern (Ljava/lang/Object;)V' { - 1 4 - 4 4 - 7 5 - a 5 - c 5 - f 14 - 16 7 - 19 7 - 1a 7 - 1d 8 - 21 8 - 28 9 - 2a 9 - 2d 9 - 30 10 - 34 10 - 39 10 - 3c 14 - } -} - -Lines mapping: -5 <-> 5 -6 <-> 6 -7 <-> 15 -10 <-> 8 -11 <-> 9 -12 <-> 10 -13 <-> 11 -15 <-> 15 -Not mapped: -9 diff --git a/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceof.java b/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceof.java deleted file mode 100644 index dde0f9fc33a9..000000000000 --- a/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceof.java +++ /dev/null @@ -1,12 +0,0 @@ -package patterns; - -public class TestInstanceof { - - void typePattern(Object str) { - if (str instanceof String s) { - System.out.println(s); - } else { - System.out.println("no"); - } - } -} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofBinaryExpr.java b/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofBinaryExpr.java deleted file mode 100644 index af674629a6df..000000000000 --- a/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofBinaryExpr.java +++ /dev/null @@ -1,12 +0,0 @@ -package patterns; - -public class TestInstanceofBinaryExpr { - - void typePattern(Object str) { - if (str instanceof String s && (s.length() > 1 || s.startsWith("a"))) { - System.out.println(s); - } else { - System.out.println("no"); - } - } -} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofVarNotSupported.java b/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofPatternNotSupported.java similarity index 88% rename from plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofVarNotSupported.java rename to plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofPatternNotSupported.java index cdca07fa2498..b0c31c9b9d25 100644 --- a/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofVarNotSupported.java +++ b/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofPatternNotSupported.java @@ -1,6 +1,6 @@ package decompiler; -public class TestInstanceofVarNotSupported { +public class TestInstanceofPatternNotSupported { void typePattern(Object str) { if (!(str instanceof String)) { System.out.println("no"); diff --git a/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofWithPattern.java b/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofWithPattern.java new file mode 100644 index 000000000000..f25d7642d99f --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/patterns/TestInstanceofWithPattern.java @@ -0,0 +1,79 @@ +package patterns; + +import java.util.Collection; +import java.util.List; + +public class TestInstanceofWithPattern { + + void typePattern1(Object str) { + if (str instanceof String s) { + System.out.println(s); + } else { + System.out.println("no"); + } + } + + void typePattern2(Object str) { + if (!(str instanceof String)) { + System.out.println("no"); + return; + } + String s = (String) str; + if (s.length() > 3) { + System.out.println(s); + } else if (s.startsWith("a")) { + System.out.println(s + ""); + } + } + + void typePatternInBinaryExpr(Object str) { + if (str instanceof String s && (s.length() > 1 || s.startsWith("a"))) { + System.out.println(s); + } else { + System.out.println("no"); + } + } + + String returnInstanceof(Object obj) { + if (obj instanceof String s && s.length() > 50) { + return '"' + s.substring(0, 50) + "...\""; + } + if (obj instanceof String s) { + return '"' + s + '"'; + } + if (obj instanceof Collection c) { + return "Collection (size = " + c.size() + ")"; + } + return obj.toString(); + } + + String complex(Object obj1, Object obj2) { + while(true) { + try { + if (obj1 instanceof String s) { + while (true) { + if (s.startsWith("a")) { + return s; + } + } + } else if (obj2 instanceof Collection c) { + return c.toString(); + } + } catch (Exception e) { + if (obj2 instanceof String s) { + while (true) { + if (s.startsWith("b")) { + return s + "b"; + } + } + } else if (obj2 instanceof List l) { + return getStr() + l.size(); + } + } + } + } + + String getStr() { + return null; + } +} diff --git a/plugins/java-decompiler/engine/testData/src/patterns/TestInvertedInstanceof.java b/plugins/java-decompiler/engine/testData/src/patterns/TestInvertedInstanceof.java deleted file mode 100644 index 3e295575aee2..000000000000 --- a/plugins/java-decompiler/engine/testData/src/patterns/TestInvertedInstanceof.java +++ /dev/null @@ -1,16 +0,0 @@ -package patterns; - -public class TestInvertedInstanceof { - void typePattern(Object str) { - if (!(str instanceof String)) { - System.out.println("no"); - return; - } - String s = (String) str; - if (s.length() > 3) { - System.out.println(s); - } else if (s.startsWith("a")) { - System.out.println(s + ""); - } - } -}