feat(gui): select a class to open via command-line (PR #658)
This commit is contained in:
@@ -130,7 +130,7 @@ public class JadxCLIArgs {
|
||||
* Used to merge saved options and options passed in command line.
|
||||
*/
|
||||
public boolean overrideProvided(String[] args) {
|
||||
JCommanderWrapper<JadxCLIArgs> jcw = new JCommanderWrapper<>(new JadxCLIArgs());
|
||||
JCommanderWrapper<JadxCLIArgs> jcw = new JCommanderWrapper<>(newInstance());
|
||||
if (!jcw.parse(args)) {
|
||||
return false;
|
||||
}
|
||||
@@ -138,6 +138,10 @@ public class JadxCLIArgs {
|
||||
return process(jcw);
|
||||
}
|
||||
|
||||
protected JadxCLIArgs newInstance() {
|
||||
return new JadxCLIArgs();
|
||||
}
|
||||
|
||||
private boolean process(JCommanderWrapper<JadxCLIArgs> jcw) {
|
||||
if (printHelp) {
|
||||
jcw.printUsage();
|
||||
|
||||
@@ -8,8 +8,9 @@ import java.util.List;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.ProgressMonitor;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -133,4 +134,13 @@ public class JadxWrapper {
|
||||
public JadxArgs getArgs() {
|
||||
return decompiler.getArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fullName Full name of an outer class. Inner classes are not supported.
|
||||
* @return
|
||||
*/
|
||||
public @Nullable JavaClass searchJavaClassByClassName(String fullName) {
|
||||
return decompiler.getClasses().stream().filter(cls -> cls.getFullName().equals(fullName))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.cli.JadxCLIArgs;
|
||||
import jadx.gui.ui.MainWindow;
|
||||
@@ -65,6 +67,10 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
|
||||
private int settingsVersion = 0;
|
||||
|
||||
@JadxSettingsAdapter.GsonExclude
|
||||
@Parameter(names = { "-sc", "--select-class" }, description = "GUI: Open the selected class and show the decompiled code")
|
||||
private String cmdSelectClass = null;
|
||||
|
||||
public static JadxSettings makeDefault() {
|
||||
JadxSettings jadxSettings = new JadxSettings();
|
||||
jadxSettings.fixOnLoad();
|
||||
@@ -96,6 +102,10 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
}
|
||||
}
|
||||
|
||||
public String getCmdSelectClass() {
|
||||
return cmdSelectClass;
|
||||
}
|
||||
|
||||
public Path getLastOpenFilePath() {
|
||||
return lastOpenFilePath;
|
||||
}
|
||||
@@ -412,4 +422,8 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
sync();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JadxCLIArgs newInstance() {
|
||||
return new JadxSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package jadx.gui.settings;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.file.Path;
|
||||
import java.util.prefs.Preferences;
|
||||
@@ -31,7 +35,8 @@ public class JadxSettingsAdapter {
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
return JadxSettings.SKIP_FIELDS.contains(f.getName())
|
||||
|| f.hasModifier(Modifier.PUBLIC)
|
||||
|| f.hasModifier(Modifier.TRANSIENT);
|
||||
|| f.hasModifier(Modifier.TRANSIENT)
|
||||
|| (f.getAnnotation(GsonExclude.class) != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,4 +101,12 @@ public class JadxSettingsAdapter {
|
||||
.create()
|
||||
.fromJson(json, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotation for specifying fields that should not be be saved/loaded
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface GsonExclude {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JavaNode;
|
||||
import jadx.api.ResourceFile;
|
||||
import jadx.gui.JadxWrapper;
|
||||
import jadx.gui.jobs.BackgroundWorker;
|
||||
@@ -178,10 +179,25 @@ public class MainWindow extends JFrame {
|
||||
}
|
||||
});
|
||||
|
||||
processCommandLineArgs();
|
||||
}
|
||||
|
||||
private void processCommandLineArgs() {
|
||||
if (settings.getFiles().isEmpty()) {
|
||||
openFileOrProject();
|
||||
} else {
|
||||
open(Paths.get(settings.getFiles().get(0)));
|
||||
if (settings.getCmdSelectClass() != null) {
|
||||
JavaNode javaNode = wrapper.searchJavaClassByClassName(settings.getCmdSelectClass());
|
||||
if (javaNode == null) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
NLS.str("msg.cmd_select_class_error", settings.getCmdSelectClass()),
|
||||
NLS.str("error_dialog.title"), JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
JNode node = cacheObject.getNodeCache().makeFrom(javaNode);
|
||||
tabbedPane.codeJump(new JumpPosition(node.getRootClass(), node.getLine()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ tree.sources_title=Source code
|
||||
tree.resources_title=Resources
|
||||
tree.loading=Loading...
|
||||
|
||||
error_dialog.title=Error
|
||||
|
||||
search.previous=Previous
|
||||
search.next=Next
|
||||
search.mark_all=Mark All
|
||||
@@ -131,6 +133,7 @@ msg.project_error_title=Error
|
||||
msg.project_error=Project could not be loaded
|
||||
msg.rename_disabled_title=Rename disabled
|
||||
msg.rename_disabled=Some of rename settings are disabled, please take this into consideration
|
||||
msg.cmd_select_class_error=Failed to select the class\n%s\nThe class does not exist.
|
||||
|
||||
popup.undo=Undo
|
||||
popup.redo=Redo
|
||||
|
||||
@@ -32,6 +32,8 @@ tree.sources_title=Código fuente
|
||||
tree.resources_title=Recursos
|
||||
tree.loading=Cargando...
|
||||
|
||||
#error_dialog.title=
|
||||
|
||||
search.previous=Anterior
|
||||
search.next=Siguiente
|
||||
search.mark_all=Marcar todo
|
||||
@@ -131,6 +133,7 @@ msg.index_not_initialized=Índice no inicializado, ¡la bósqueda se desactivar
|
||||
#msg.project_error=
|
||||
#msg.rename_disabled_title=
|
||||
#msg.rename_disabled=
|
||||
#msg.cmd_select_class_error=
|
||||
|
||||
popup.undo=Deshacer
|
||||
popup.redo=Rehacer
|
||||
|
||||
@@ -32,6 +32,8 @@ tree.sources_title=源代码
|
||||
tree.resources_title=资源文件
|
||||
tree.loading=稍等...
|
||||
|
||||
#error_dialog.title=
|
||||
|
||||
search.previous=上一个
|
||||
search.next=下一个
|
||||
search.mark_all=标记全部
|
||||
@@ -131,6 +133,7 @@ msg.index_not_initialized=索引尚未初始化,无法进行搜索!
|
||||
#msg.project_error=
|
||||
#msg.rename_disabled_title=
|
||||
#msg.rename_disabled=
|
||||
#msg.cmd_select_class_error=
|
||||
|
||||
popup.undo=撤销
|
||||
popup.redo=重做
|
||||
|
||||
Reference in New Issue
Block a user