fix(gui): show options from all plugins
This commit is contained in:
@@ -119,11 +119,12 @@ public class JadxPluginManager {
|
||||
init(context, resolvedPlugins);
|
||||
}
|
||||
|
||||
private void init(PluginsContext context, List<JadxPlugin> plugins) {
|
||||
public void init(PluginsContext context, List<JadxPlugin> plugins) {
|
||||
for (JadxPlugin plugin : plugins) {
|
||||
try {
|
||||
context.setCurrentPlugin(plugin);
|
||||
plugin.init(context);
|
||||
context.setCurrentPlugin(null);
|
||||
} catch (Exception e) {
|
||||
String pluginId = plugin.getPluginInfo().getPluginId();
|
||||
throw new JadxRuntimeException("Failed to init plugin: " + pluginId, e);
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -19,7 +20,6 @@ import jadx.api.JavaNode;
|
||||
import jadx.api.JavaPackage;
|
||||
import jadx.api.ResourceFile;
|
||||
import jadx.api.impl.InMemoryCodeCache;
|
||||
import jadx.api.impl.plugins.PluginsContext;
|
||||
import jadx.api.metadata.ICodeNodeRef;
|
||||
import jadx.api.usage.impl.EmptyUsageInfoCache;
|
||||
import jadx.api.usage.impl.InMemoryUsageInfoCache;
|
||||
@@ -27,7 +27,6 @@ import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.ProcessState;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import jadx.gui.cache.code.CodeStringCache;
|
||||
import jadx.gui.cache.code.disk.BufferCodeCache;
|
||||
import jadx.gui.cache.code.disk.DiskCodeCache;
|
||||
@@ -227,15 +226,9 @@ public class JadxWrapper {
|
||||
getSettings().sync();
|
||||
}
|
||||
|
||||
public PluginsContext getPluginsContext() {
|
||||
if (decompiler != null) {
|
||||
return decompiler.getPluginsContext();
|
||||
}
|
||||
try (JadxDecompiler tmpDecompiler = new JadxDecompiler()) {
|
||||
// TODO: override input file checks
|
||||
tmpDecompiler.getArgs().setInputFile(FileUtils.createTempFile("tmp.txt").toFile());
|
||||
tmpDecompiler.load();
|
||||
return tmpDecompiler.getPluginsContext();
|
||||
public Optional<JadxDecompiler> getCurrentDecompiler() {
|
||||
synchronized (DECOMPILER_UPDATE_SYNC) {
|
||||
return Optional.ofNullable(decompiler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -62,7 +62,6 @@ import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
|
||||
import jadx.api.args.GeneratedRenamesMappingFileMode;
|
||||
import jadx.api.args.ResourceNameSource;
|
||||
import jadx.api.impl.plugins.PluginsContext;
|
||||
import jadx.api.plugins.JadxPlugin;
|
||||
import jadx.api.plugins.options.JadxPluginOptions;
|
||||
import jadx.api.plugins.options.OptionDescription;
|
||||
@@ -75,6 +74,8 @@ import jadx.gui.utils.LafManager;
|
||||
import jadx.gui.utils.LangLocale;
|
||||
import jadx.gui.utils.NLS;
|
||||
import jadx.gui.utils.UiUtils;
|
||||
import jadx.gui.utils.plugins.CollectPluginOptions;
|
||||
import jadx.gui.utils.plugins.PluginWithOptions;
|
||||
import jadx.gui.utils.ui.DocumentUpdateListener;
|
||||
|
||||
public class JadxSettingsWindow extends JDialog {
|
||||
@@ -612,39 +613,41 @@ public class JadxSettingsWindow extends JDialog {
|
||||
|
||||
private SettingsGroup makePluginOptionsGroup() {
|
||||
SettingsGroup pluginsGroup = new SettingsGroup(NLS.str("preferences.plugins"));
|
||||
PluginsContext pluginsContext = mainWindow.getWrapper().getPluginsContext();
|
||||
for (Map.Entry<JadxPlugin, JadxPluginOptions> entry : pluginsContext.getOptionsMap().entrySet()) {
|
||||
JadxPlugin plugin = entry.getKey();
|
||||
JadxPluginOptions options = entry.getValue();
|
||||
String pluginId = plugin.getPluginInfo().getPluginId();
|
||||
for (OptionDescription opt : options.getOptionsDescriptions()) {
|
||||
String title;
|
||||
if (pluginId.equals("jadx-script")) {
|
||||
title = '[' + opt.name().replace("jadx-script.", "script:") + "] " + opt.description();
|
||||
} else {
|
||||
title = '[' + pluginId + "] " + opt.description();
|
||||
}
|
||||
if (opt.values().isEmpty() || opt.getType() == OptionDescription.OptionType.BOOLEAN) {
|
||||
try {
|
||||
pluginsGroup.addRow(title, getPluginOptionEditor(opt));
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to add editor for plugin option: {}", opt.name(), e);
|
||||
}
|
||||
} else {
|
||||
String curValue = settings.getPluginOptions().get(opt.name());
|
||||
JComboBox<String> combo = new JComboBox<>(opt.values().toArray(new String[0]));
|
||||
combo.setSelectedItem(curValue != null ? curValue : opt.defaultValue());
|
||||
combo.addActionListener(e -> {
|
||||
settings.getPluginOptions().put(opt.name(), ((String) combo.getSelectedItem()));
|
||||
needReload();
|
||||
});
|
||||
pluginsGroup.addRow(title, combo);
|
||||
}
|
||||
}
|
||||
List<PluginWithOptions> list = new CollectPluginOptions(mainWindow.getWrapper()).build();
|
||||
for (PluginWithOptions data : list) {
|
||||
addPluginOptions(pluginsGroup, data.getPlugin(), data.getOptions());
|
||||
}
|
||||
return pluginsGroup;
|
||||
}
|
||||
|
||||
private void addPluginOptions(SettingsGroup pluginsGroup, JadxPlugin plugin, JadxPluginOptions options) {
|
||||
String pluginId = plugin.getPluginInfo().getPluginId();
|
||||
for (OptionDescription opt : options.getOptionsDescriptions()) {
|
||||
String title;
|
||||
if (pluginId.equals("jadx-script")) {
|
||||
title = '[' + opt.name().replace("jadx-script.", "script:") + "] " + opt.description();
|
||||
} else {
|
||||
title = '[' + pluginId + "] " + opt.description();
|
||||
}
|
||||
if (opt.values().isEmpty() || opt.getType() == OptionDescription.OptionType.BOOLEAN) {
|
||||
try {
|
||||
pluginsGroup.addRow(title, getPluginOptionEditor(opt));
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to add editor for plugin option: {}", opt.name(), e);
|
||||
}
|
||||
} else {
|
||||
String curValue = settings.getPluginOptions().get(opt.name());
|
||||
JComboBox<String> combo = new JComboBox<>(opt.values().toArray(new String[0]));
|
||||
combo.setSelectedItem(curValue != null ? curValue : opt.defaultValue());
|
||||
combo.addActionListener(e -> {
|
||||
settings.getPluginOptions().put(opt.name(), ((String) combo.getSelectedItem()));
|
||||
needReload();
|
||||
});
|
||||
pluginsGroup.addRow(title, combo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JComponent getPluginOptionEditor(OptionDescription opt) {
|
||||
String curValue = settings.getPluginOptions().get(opt.name());
|
||||
String value = curValue == null ? opt.defaultValue() : curValue;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package jadx.gui.utils.plugins;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import jadx.api.plugins.JadxPlugin;
|
||||
import jadx.api.plugins.JadxPluginManager;
|
||||
import jadx.api.plugins.options.JadxPluginOptions;
|
||||
import jadx.gui.JadxWrapper;
|
||||
|
||||
/**
|
||||
* Collect options from all plugins.
|
||||
* Init not yet loaded plugins in new temporary context.
|
||||
* Support case if decompiler in wrapper not initialized yet.
|
||||
*/
|
||||
public class CollectPluginOptions {
|
||||
|
||||
private final JadxWrapper wrapper;
|
||||
private final Map<Class<?>, PluginWithOptions> plugins;
|
||||
|
||||
public CollectPluginOptions(JadxWrapper wrapper) {
|
||||
this.wrapper = wrapper;
|
||||
this.plugins = new HashMap<>();
|
||||
}
|
||||
|
||||
public List<PluginWithOptions> build() {
|
||||
wrapper.getCurrentDecompiler().ifPresent(decompiler -> {
|
||||
List<JadxPlugin> loadedPlugins = decompiler.getPluginManager().getResolvedPlugins();
|
||||
addOptions(decompiler, loadedPlugins);
|
||||
});
|
||||
// collect and init not loaded plugins in new context
|
||||
try (JadxDecompiler decompiler = new JadxDecompiler(new JadxArgs())) {
|
||||
JadxPluginManager pluginManager = decompiler.getPluginManager();
|
||||
List<JadxPlugin> missingPlugins = new ArrayList<>();
|
||||
for (JadxPlugin plugin : pluginManager.getAllPlugins()) {
|
||||
if (!plugins.containsKey(plugin.getClass())) {
|
||||
missingPlugins.add(plugin);
|
||||
}
|
||||
}
|
||||
pluginManager.init(decompiler.getPluginsContext(), missingPlugins);
|
||||
addOptions(decompiler, missingPlugins);
|
||||
}
|
||||
return plugins.values().stream()
|
||||
.filter(data -> data != PluginWithOptions.NULL)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void addOptions(JadxDecompiler decompiler, List<JadxPlugin> loadedPlugins) {
|
||||
Map<JadxPlugin, JadxPluginOptions> optionsMap = decompiler.getPluginsContext().getOptionsMap();
|
||||
for (JadxPlugin loadedPlugin : loadedPlugins) {
|
||||
JadxPluginOptions pluginOptions = optionsMap.get(loadedPlugin);
|
||||
PluginWithOptions options;
|
||||
if (pluginOptions != null) {
|
||||
options = new PluginWithOptions(loadedPlugin, pluginOptions);
|
||||
} else {
|
||||
options = PluginWithOptions.NULL;
|
||||
}
|
||||
plugins.put(loadedPlugin.getClass(), options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package jadx.gui.utils.plugins;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import jadx.api.plugins.JadxPlugin;
|
||||
import jadx.api.plugins.options.JadxPluginOptions;
|
||||
|
||||
public class PluginWithOptions implements Comparable<PluginWithOptions> {
|
||||
public static final PluginWithOptions NULL = new PluginWithOptions(null, null);
|
||||
|
||||
private final JadxPlugin plugin;
|
||||
private final JadxPluginOptions options;
|
||||
|
||||
public PluginWithOptions(JadxPlugin plugin, JadxPluginOptions options) {
|
||||
this.plugin = plugin;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public JadxPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public JadxPluginOptions getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull PluginWithOptions other) {
|
||||
return plugin.getClass().getName().compareTo(other.getClass().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PluginWithOptions{plugin=" + plugin + ", options=" + options + '}';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user