From 78eed8629cbe63702061c1292b01f975294f7b5d Mon Sep 17 00:00:00 2001 From: Soul Trace Date: Tue, 10 Dec 2019 21:41:57 +0300 Subject: [PATCH] feat(gui): reopened tabs on file reload (PR #793 #792) * Add getRealFullName() to ClassNode and JavaClass and searchJavaClassByRealName() to JadxWrapper Those methods is like getFullName() and searchJavaClassByClassName(), but for class names without aliases. It is necessary for renaming classes/methods/fields. * MainWindow: Try to restore open tabs on deobfuscation toggle Restore open tabs if possible when user toggles deobfuscation mode. Try to scroll to the position before toggling deobfuscation mode (may be not exact cause of the comments). --- .../src/main/java/jadx/api/JavaClass.java | 4 ++ .../java/jadx/core/dex/nodes/ClassNode.java | 4 ++ .../src/main/java/jadx/gui/JadxWrapper.java | 9 ++++ .../src/main/java/jadx/gui/ui/MainWindow.java | 41 +++++++++++++++++++ .../src/main/java/jadx/gui/ui/TabbedPane.java | 2 +- 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/jadx-core/src/main/java/jadx/api/JavaClass.java b/jadx-core/src/main/java/jadx/api/JavaClass.java index b0022b53d..609463b9f 100644 --- a/jadx-core/src/main/java/jadx/api/JavaClass.java +++ b/jadx-core/src/main/java/jadx/api/JavaClass.java @@ -174,6 +174,10 @@ public final class JavaClass implements JavaNode { return cls.getFullName(); } + public String getRealFullName() { + return cls.getRealFullName(); + } + public String getPackage() { return cls.getPackage(); } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java index 7064be9d9..03a6ea94a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java @@ -517,6 +517,10 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { return clsInfo.getAliasFullName(); } + public String getRealFullName() { + return clsInfo.getType().getObject(); + } + public String getPackage() { return clsInfo.getAliasPkg(); } diff --git a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java index 7b3f5667b..4070bf889 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java @@ -147,4 +147,13 @@ public class JadxWrapper { return decompiler.getClasses().stream().filter(cls -> cls.getFullName().equals(fullName)) .findFirst().orElse(null); } + + /** + * @param realName Real name of an outer class. Inner classes are not supported. + * @return + */ + public @Nullable JavaClass searchJavaClassByRealName(String realName) { + return decompiler.getClasses().stream().filter(cls -> cls.getRealFullName().equals(realName)) + .findFirst().orElse(null); + } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index 6b15a4ec7..86de10d32 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -19,8 +19,10 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Timer; import java.util.TimerTask; @@ -38,11 +40,13 @@ import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.fife.ui.rsyntaxtextarea.Theme; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jadx.api.JadxArgs; +import jadx.api.JavaClass; import jadx.api.JavaNode; import jadx.api.ResourceFile; import jadx.gui.JadxWrapper; @@ -373,9 +377,46 @@ public class MainWindow extends JFrame { public void reOpenFile() { File openedFile = wrapper.getOpenFile(); + Map openTabs = storeOpenTabs(); if (openedFile != null) { open(openedFile.toPath()); } + restoreOpenTabs(openTabs); + } + + @NotNull + private Map storeOpenTabs() { + Map openTabs = new LinkedHashMap<>(); + for (Map.Entry entry : tabbedPane.getOpenTabs().entrySet()) { + JavaNode javaNode = entry.getKey().getJavaNode(); + String classRealName = ""; + if (javaNode instanceof JavaClass) { + JavaClass javaClass = (JavaClass) javaNode; + classRealName = javaClass.getRealFullName(); + } + @Nullable + JumpPosition position = entry.getValue().getTabbedPane().getCurrentPosition(); + int line = 0; + if (position != null) { + line = position.getLine(); + } + openTabs.put(classRealName, line); + } + return openTabs; + } + + private void restoreOpenTabs(Map openTabs) { + for (Map.Entry entry : openTabs.entrySet()) { + String classRealName = entry.getKey(); + int position = entry.getValue(); + @Nullable + JavaClass newClass = wrapper.searchJavaClassByRealName(classRealName); + if (newClass == null) { + continue; + } + JNode newNode = cacheObject.getNodeCache().makeFrom(newClass); + tabbedPane.codeJump(new JumpPosition(newNode, position)); + } } private void saveAll(boolean export) { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java b/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java index 146fe896b..c3fbac9e8 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java @@ -105,7 +105,7 @@ public class TabbedPane extends JTabbedPane { } @Nullable - private JumpPosition getCurrentPosition() { + JumpPosition getCurrentPosition() { ContentPanel selectedCodePanel = getSelectedCodePanel(); if (selectedCodePanel instanceof AbstractCodeContentPanel) { return ((AbstractCodeContentPanel) selectedCodePanel).getCodeArea().getCurrentPosition();