diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/LimitContainer.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/LimitContainer.java index 640a9da36627..d47eea2180fd 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/LimitContainer.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/LimitContainer.java @@ -8,45 +8,41 @@ import org.jetbrains.java.decompiler.util.SFormsFastMapDirect; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; -import static org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences.*; +import static org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences.MAX_DIRECT_NODES_COUNT; +import static org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences.MAX_DIRECT_VARIABLE_NODE_COUNT; public class LimitContainer { private final int maxDirectNodeCount;//-1 - don't check @NotNull private final AtomicLong directNodeCount = new AtomicLong(); - @NotNull - private final String maxDirectNodeCountMessage; private final int ssaConstructorSparseExRecordCount;//-1 - don't check - @NotNull - private final String ssaConstructorSparseExRecordCountMessage; public LimitContainer(@NotNull Map properties) { maxDirectNodeCount = (int)properties.getOrDefault(MAX_DIRECT_NODES_COUNT, -1); - maxDirectNodeCountMessage = (String)properties.getOrDefault(MAX_DIRECT_NODES_COUNT_MESSAGE, "Limits are exceeded"); ssaConstructorSparseExRecordCount = (int)properties.getOrDefault(MAX_DIRECT_VARIABLE_NODE_COUNT, -1); - ssaConstructorSparseExRecordCountMessage = (String)properties.getOrDefault(MAX_DIRECT_VARIABLE_NODES_COUNT_MESSAGE, "Limits are exceeded"); } public void incrementAndCheckDirectNodeCount(@NotNull ControlFlowGraph graph) { long newValue = directNodeCount.addAndGet(graph.getBlocks().size()); if (maxDirectNodeCount != -1 && newValue >= maxDirectNodeCount) { - throw new LimitExceededDecompilerException(maxDirectNodeCountMessage); + throw new LimitExceededDecompilerException(maxDirectNodeCount, newValue, "direct nodes"); } } public void checkSFormsFastMapDirect(@NotNull Map inVarVersions, @NotNull Map outVarVersions) { + int newValue = inVarVersions.size() + outVarVersions.size(); if (ssaConstructorSparseExRecordCount != -1 && - inVarVersions.size() + outVarVersions.size() > ssaConstructorSparseExRecordCount) { - throw new LimitExceededDecompilerException(ssaConstructorSparseExRecordCountMessage); + newValue > ssaConstructorSparseExRecordCount) { + throw new LimitExceededDecompilerException(ssaConstructorSparseExRecordCount, newValue, "variable nodes"); } } public static class LimitExceededDecompilerException extends RuntimeException { - public LimitExceededDecompilerException(String message) { - super(message); + public LimitExceededDecompilerException(long limit, long actualValue, String type) { + super("Limits for %s are exceeded. Current value: %s, limit: %s".formatted(type, actualValue, limit)); } } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java index cdbe4cf6d01f..45bcb0d035e2 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java @@ -64,9 +64,7 @@ public interface IFernflowerPreferences { String SKIP_EXTRA_FILES = "sef"; String MAX_DIRECT_NODES_COUNT = "mdnc"; - String MAX_DIRECT_NODES_COUNT_MESSAGE = "mdncm"; String MAX_DIRECT_VARIABLE_NODE_COUNT = "mdvnc"; - String MAX_DIRECT_VARIABLE_NODES_COUNT_MESSAGE = "mdvncm"; Map DEFAULTS = getDefaults(); diff --git a/plugins/java-decompiler/plugin/resources/messages/IdeaDecompilerBundle.properties b/plugins/java-decompiler/plugin/resources/messages/IdeaDecompilerBundle.properties index 39cbca8e098a..0e89e50b9cf4 100644 --- a/plugins/java-decompiler/plugin/resources/messages/IdeaDecompilerBundle.properties +++ b/plugins/java-decompiler/plugin/resources/messages/IdeaDecompilerBundle.properties @@ -27,8 +27,6 @@ action.show.decompiled.name=Show Decompiled Class decompiling.progress=Decompiling {0} -max.direct.nodes.count.message=Limits for direct nodes are exceeded, limits can be increased in Settings->Advanced settings->Java Bytecode Decompiler -max.variable.nodes.count.message=Limits for variable nodes are exceeded, limits can be increased in Settings->Advanced settings->Java Bytecode Decompiler advanced.setting.decompiler.max.direct.nodes.count=Max count of direct nodes advanced.setting.decompiler.max.variable.nodes.count=Max count of variable nodes advanced.setting.group.decompiler=Java Bytecode Decompiler diff --git a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.kt b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.kt index c61ee2f39810..6425ace882c8 100644 --- a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.kt +++ b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.kt @@ -131,10 +131,7 @@ class IdeaDecompiler : ClassFileDecompilers.Light() { if (Registry.`is`("decompiler.dump.original.lines")) { options[IFernflowerPreferences.DUMP_ORIGINAL_LINES] = "1" } - options[IFernflowerPreferences.MAX_DIRECT_NODES_COUNT_MESSAGE] = IdeaDecompilerBundle.message("max.direct.nodes.count.message") options[IFernflowerPreferences.MAX_DIRECT_NODES_COUNT] = AdvancedSettings.getInt("decompiler.max.direct.nodes.count") - - options[IFernflowerPreferences.MAX_DIRECT_VARIABLE_NODES_COUNT_MESSAGE] = IdeaDecompilerBundle.message("max.variable.nodes.count.message") options[IFernflowerPreferences.MAX_DIRECT_VARIABLE_NODE_COUNT] = AdvancedSettings.getInt("decompiler.max.variable.nodes.count") val provider = MyBytecodeProvider(files) diff --git a/plugins/java-decompiler/plugin/test/com/intellij/java/decompiler/IdeaDecompilerTest.kt b/plugins/java-decompiler/plugin/test/com/intellij/java/decompiler/IdeaDecompilerTest.kt index 64d779cbaf00..807d54c3527b 100644 --- a/plugins/java-decompiler/plugin/test/com/intellij/java/decompiler/IdeaDecompilerTest.kt +++ b/plugins/java-decompiler/plugin/test/com/intellij/java/decompiler/IdeaDecompilerTest.kt @@ -80,6 +80,11 @@ class IdeaDecompilerTest : LightJavaCodeInsightFixtureTestCase() { val file = getTestFile("${IdeaTestUtil.getMockJdk18Path().path}/jre/lib/rt.jar!/java/lang/String.class") val decompiled = IdeaDecompiler().getText(file).toString() assertTrue(decompiled, decompiled.contains("Limits for direct nodes are exceeded")) + //small methods are decompiled normally + assertTrue(decompiled, decompiled.contains(""" + public String(char[] var1) { + this.value = Arrays.copyOf(var1, var1.length); + }""".trimIndent())) } finally { AdvancedSettings.setInt(advancedSetting, previousCount) @@ -94,6 +99,14 @@ class IdeaDecompilerTest : LightJavaCodeInsightFixtureTestCase() { val file = getTestFile("${IdeaTestUtil.getMockJdk18Path().path}/jre/lib/rt.jar!/java/lang/String.class") val decompiled = IdeaDecompiler().getText(file).toString() assertTrue(decompiled, decompiled.contains("Limits for variable nodes are exceeded")) + //small methods are decompiled normally + assertTrue(decompiled, decompiled.contains( + """ + public char[] toCharArray() { + char[] var1 = new char[this.value.length]; + System.arraycopy(this.value, 0, var1, 0, this.value.length); + return var1; + }""".trimIndent())) } finally { AdvancedSettings.setInt(advancedSetting, previousCount)