From 5099e02c9b130b59fc49acd5de016c3f5789aa20 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 23 May 2022 16:48:17 +0100 Subject: [PATCH] fix(gui): correct merge for plugin options from command line (#1490) --- .../main/java/jadx/cli/JCommanderWrapper.java | 18 ++++++++- .../test/java/jadx/cli/JadxCLIArgsTest.java | 39 +++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java b/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java index 3548cb62a..2929d3284 100644 --- a/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java +++ b/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java @@ -8,6 +8,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; @@ -22,6 +23,7 @@ import jadx.api.plugins.JadxPluginInfo; import jadx.api.plugins.JadxPluginManager; import jadx.api.plugins.options.JadxPluginOptions; import jadx.api.plugins.options.OptionDescription; +import jadx.core.utils.Utils; public class JCommanderWrapper { private final JCommander jc; @@ -50,12 +52,24 @@ public class JCommanderWrapper { if (parameter.isAssigned()) { // copy assigned field value to obj Parameterized parameterized = parameter.getParameterized(); - Object val = parameterized.get(parameter.getObject()); - parameterized.set(obj, val); + Object providedValue = parameterized.get(parameter.getObject()); + Object newValue = mergeValues(parameterized.getType(), providedValue, () -> parameterized.get(obj)); + parameterized.set(obj, newValue); } } } + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static Object mergeValues(Class type, Object value, Supplier prevValueProvider) { + if (type.isAssignableFrom(Map.class)) { + // merge maps instead replacing whole map + Map prevMap = (Map) prevValueProvider.get(); + return Utils.mergeMaps(prevMap, (Map) value); // value map will override keys in prevMap + } + // simple override + return value; + } + public void printUsage() { // print usage in not sorted fields order (by default its sorted by description) PrintStream out = System.out; diff --git a/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java b/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java index dded75155..54edbd5fd 100644 --- a/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java +++ b/jadx-cli/src/test/java/jadx/cli/JadxCLIArgsTest.java @@ -1,9 +1,14 @@ package jadx.cli; +import java.util.Collections; +import java.util.Map; + +import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static jadx.core.utils.Utils.newConstStringMap; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -47,6 +52,40 @@ public class JadxCLIArgsTest { assertThat(override(args, "").isUseImports(), is(false)); } + @Test + public void testPluginOptionsOverride() { + // add key to empty base map + checkPluginOptionsMerge( + Collections.emptyMap(), + "-Poption=otherValue", + newConstStringMap("option", "otherValue")); + + // override one key + checkPluginOptionsMerge( + newConstStringMap("option", "value"), + "-Poption=otherValue", + newConstStringMap("option", "otherValue")); + + // merge different keys + checkPluginOptionsMerge( + Collections.singletonMap("option1", "value1"), + "-Poption2=otherValue2", + newConstStringMap("option1", "value1", "option2", "otherValue2")); + + // merge and override + checkPluginOptionsMerge( + newConstStringMap("option1", "value1", "option2", "value2"), + "-Poption2=otherValue2", + newConstStringMap("option1", "value1", "option2", "otherValue2")); + } + + private void checkPluginOptionsMerge(Map baseMap, String providedArgs, Map expectedMap) { + JadxCLIArgs args = new JadxCLIArgs(); + args.pluginOptions = baseMap; + Map resultMap = override(args, providedArgs).getPluginOptions(); + assertThat(resultMap, Matchers.equalTo(expectedMap)); + } + private JadxCLIArgs parse(String... args) { return parse(new JadxCLIArgs(), args); }