feat(gui): report plugin exceptions to plugin github project
This commit is contained in:
@@ -16,7 +16,6 @@ import jadx.gui.logs.LogCollector;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.JadxSettingsData;
|
||||
import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.ui.dialog.ExceptionDialog;
|
||||
import jadx.gui.utils.LafManager;
|
||||
import jadx.gui.utils.NLS;
|
||||
|
||||
@@ -35,7 +34,6 @@ public class JadxGUI {
|
||||
|
||||
LogCollector.register();
|
||||
printSystemInfo();
|
||||
ExceptionDialog.registerUncaughtExceptionHandler();
|
||||
NLS.setLocale(settings.getLangLocale());
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
LafManager.init(settings);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package jadx.gui.report;
|
||||
|
||||
final class ExceptionData {
|
||||
private final Throwable exception;
|
||||
private final String githubProject;
|
||||
|
||||
ExceptionData(Throwable exception, String githubProject) {
|
||||
this.exception = exception;
|
||||
this.githubProject = githubProject;
|
||||
}
|
||||
|
||||
public Throwable getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
public String getGithubProject() {
|
||||
return githubProject;
|
||||
}
|
||||
}
|
||||
+20
-21
@@ -1,4 +1,4 @@
|
||||
package jadx.gui.ui.dialog;
|
||||
package jadx.gui.report;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
@@ -8,7 +8,6 @@ import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
@@ -37,8 +36,10 @@ import jadx.commons.app.JadxSystemInfo;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.JadxSettingsData;
|
||||
import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.utils.LafManager;
|
||||
import jadx.gui.utils.Link;
|
||||
import jadx.gui.utils.TextStandardActions;
|
||||
|
||||
public class ExceptionDialog extends JDialog {
|
||||
|
||||
@@ -46,17 +47,8 @@ public class ExceptionDialog extends JDialog {
|
||||
|
||||
private static final String FMT_DETAIL_LENGTH = "-13";
|
||||
|
||||
public static void registerUncaughtExceptionHandler() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(ExceptionDialog::showExceptionDialog);
|
||||
}
|
||||
|
||||
public static void showExceptionDialog(Thread thread, Throwable ex) {
|
||||
LOG.error("Exception was thrown", ex);
|
||||
new ExceptionDialog(thread, ex);
|
||||
}
|
||||
|
||||
public ExceptionDialog(Thread thread, Throwable ex) {
|
||||
super((Window) null, "Jadx Error");
|
||||
ExceptionDialog(MainWindow mainWindow, ExceptionData data) {
|
||||
super(mainWindow, "Jadx Error");
|
||||
this.getContentPane().setLayout(new BorderLayout());
|
||||
JPanel titlePanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
@@ -84,6 +76,7 @@ public class ExceptionDialog extends JDialog {
|
||||
LOG.error("failed to get program arguments", t);
|
||||
}
|
||||
|
||||
Throwable ex = data.getException();
|
||||
StringWriter stackTraceWriter = new StringWriter(1024);
|
||||
ex.printStackTrace(new PrintWriter(stackTraceWriter));
|
||||
final String stackTrace = stackTraceWriter.toString();
|
||||
@@ -96,13 +89,13 @@ public class ExceptionDialog extends JDialog {
|
||||
issueTitle = ex.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
String message = "Please describe what you did before the error occurred.\n";
|
||||
message += "**IMPORTANT!** If the error occurs with a specific APK file please attach or provide link to apk file!\n";
|
||||
String message = "Please describe what you did before the error occurred.\n\n";
|
||||
message += "**IMPORTANT!** If the error occurs with a specific APK file please attach or provide link to apk file!\n\n";
|
||||
|
||||
StringBuilder detailsIssueBuilder = new StringBuilder();
|
||||
details.forEach((key, value) -> detailsIssueBuilder.append(String.format("* %s: %s\n", key, value)));
|
||||
|
||||
String body = String.format("%s %s\n```\n%s\n```", message, detailsIssueBuilder, stackTrace);
|
||||
String body = String.format("%s%s\n```\n%s\n```", message, detailsIssueBuilder, stackTrace);
|
||||
|
||||
String issueBody;
|
||||
try {
|
||||
@@ -112,13 +105,19 @@ public class ExceptionDialog extends JDialog {
|
||||
issueBody = "Please copy the displayed text in the Jadx error dialog and paste it here";
|
||||
}
|
||||
|
||||
String url = String.format("https://github.com/skylot/jadx/issues/new?labels=bug&title=%s&body=%s", issueTitle, issueBody);
|
||||
Link issueLink = new Link("<html><u><b>Create a new issue at GitHub</b></u></html>", url);
|
||||
c.gridy = 0;
|
||||
titlePanel.add(titleLabel, c);
|
||||
c.gridy = 1;
|
||||
titlePanel.add(issueLink, c);
|
||||
|
||||
String project = data.getGithubProject();
|
||||
if (!project.isEmpty()) {
|
||||
String url = String.format("https://github.com/%s/issues/new?labels=bug&title=%s&body=%s",
|
||||
project, issueTitle, issueBody);
|
||||
Link issueLink = new Link("<html><u><b>Create a new issue at GitHub</b></u></html>", url);
|
||||
c.gridy = 1;
|
||||
titlePanel.add(issueLink, c);
|
||||
}
|
||||
JTextArea messageArea = new JTextArea();
|
||||
TextStandardActions.attach(messageArea);
|
||||
messageArea.setEditable(false);
|
||||
messageArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
|
||||
messageArea.setForeground(Color.BLACK);
|
||||
@@ -173,7 +172,7 @@ public class ExceptionDialog extends JDialog {
|
||||
try {
|
||||
throwTestException();
|
||||
} catch (Exception e) {
|
||||
showExceptionDialog(Thread.currentThread(), e);
|
||||
new ExceptionDialog(null, new ExceptionData(e, JadxExceptionHandler.MAIN_PROJECT_STRING));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package jadx.gui.report;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.gui.ui.MainWindow;
|
||||
import jadx.plugins.tools.JadxPluginsTools;
|
||||
import jadx.plugins.tools.data.JadxPluginMetadata;
|
||||
|
||||
import static jadx.plugins.tools.JadxExternalPluginsLoader.JADX_PLUGIN_CLASSLOADER_PREFIX;
|
||||
|
||||
public class JadxExceptionHandler implements Thread.UncaughtExceptionHandler {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JadxExceptionHandler.class);
|
||||
|
||||
public static final String MAIN_PROJECT_STRING = "skylot/jadx";
|
||||
|
||||
public static void register(MainWindow mainWindow) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new JadxExceptionHandler(mainWindow));
|
||||
}
|
||||
|
||||
private final MainWindow mainWindow;
|
||||
|
||||
private JadxExceptionHandler(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable ex) {
|
||||
LOG.error("Exception was thrown", ex);
|
||||
new ExceptionDialog(mainWindow, buildExceptionData(ex));
|
||||
}
|
||||
|
||||
private ExceptionData buildExceptionData(Throwable ex) {
|
||||
for (StackTraceElement stackTraceElement : ex.getStackTrace()) {
|
||||
String classLoaderName = stackTraceElement.getClassLoaderName();
|
||||
if (classLoaderName != null && classLoaderName.startsWith(JADX_PLUGIN_CLASSLOADER_PREFIX)) {
|
||||
// plugin exception
|
||||
String jarName = classLoaderName.substring(JADX_PLUGIN_CLASSLOADER_PREFIX.length());
|
||||
String pluginProject = resolvePluginByJarName(jarName);
|
||||
LOG.debug("Report exception in plugin: {}", pluginProject);
|
||||
return new ExceptionData(ex, pluginProject);
|
||||
}
|
||||
}
|
||||
return new ExceptionData(ex, MAIN_PROJECT_STRING);
|
||||
}
|
||||
|
||||
private String resolvePluginByJarName(String jarName) {
|
||||
for (JadxPluginMetadata jadxPluginMetadata : JadxPluginsTools.getInstance().getInstalled()) {
|
||||
if (jadxPluginMetadata.getJar().equals(jarName)) {
|
||||
String githubProject = getGithubProject(jadxPluginMetadata.getLocationId());
|
||||
return githubProject != null ? githubProject : "";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static @Nullable String getGithubProject(String locationId) {
|
||||
if (locationId.startsWith("github:")) {
|
||||
return locationId.substring("github:".length()).replace(':', '/');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -118,6 +118,8 @@ import jadx.gui.plugins.context.CommonGuiPluginsContext;
|
||||
import jadx.gui.plugins.context.TreePopupMenuEntry;
|
||||
import jadx.gui.plugins.mappings.RenameMappingsGui;
|
||||
import jadx.gui.plugins.quark.QuarkDialog;
|
||||
import jadx.gui.report.ExceptionDialog;
|
||||
import jadx.gui.report.JadxExceptionHandler;
|
||||
import jadx.gui.settings.JadxProject;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.data.SaveOptionEnum;
|
||||
@@ -138,7 +140,6 @@ import jadx.gui.ui.codearea.theme.EditorThemeManager;
|
||||
import jadx.gui.ui.dialog.ADBDialog;
|
||||
import jadx.gui.ui.dialog.AboutDialog;
|
||||
import jadx.gui.ui.dialog.CharsetDialog;
|
||||
import jadx.gui.ui.dialog.ExceptionDialog;
|
||||
import jadx.gui.ui.dialog.GotoAddressDialog;
|
||||
import jadx.gui.ui.dialog.LogViewerDialog;
|
||||
import jadx.gui.ui.dialog.SearchDialog;
|
||||
@@ -266,6 +267,7 @@ public class MainWindow extends JFrame {
|
||||
this.editorThemeManager = new EditorThemeManager(settings);
|
||||
|
||||
JadxEventQueue.register();
|
||||
JadxExceptionHandler.register(this);
|
||||
resetCache();
|
||||
initUI();
|
||||
this.editorSyncManager = new EditorSyncManager(this, tabbedPane);
|
||||
|
||||
Reference in New Issue
Block a user