From ff5f6fca3c0b2dd47755288153d90140148d451f Mon Sep 17 00:00:00 2001 From: Skylot Date: Sun, 11 Aug 2019 22:03:47 +0300 Subject: [PATCH] fix(gui): fix "Go to declaration" and "Find usage" menu actions --- .../java/jadx/gui/ui/codearea/CodeArea.java | 47 ++++++++++++++-- .../gui/ui/codearea/CodeLinkGenerator.java | 29 +--------- .../jadx/gui/ui/codearea/FindUsageAction.java | 53 ++---------------- .../ui/codearea/GoToDeclarationAction.java | 53 +++--------------- .../jadx/gui/ui/codearea/JNodeMenuAction.java | 55 +++++++++++++++++++ 5 files changed, 113 insertions(+), 124 deletions(-) create mode 100644 jadx-gui/src/main/java/jadx/gui/ui/codearea/JNodeMenuAction.java diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java index 2e883691..7e34d46a 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java @@ -3,6 +3,9 @@ package jadx.gui.ui.codearea; import javax.swing.*; import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; +import org.fife.ui.rsyntaxtextarea.Token; +import org.fife.ui.rsyntaxtextarea.TokenTypes; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,9 +31,8 @@ public final class CodeArea extends AbstractCodeArea { setSyntaxEditingStyle(node.getSyntaxName()); if (node instanceof JClass) { - JClass jClsNode = (JClass) this.node; ((RSyntaxDocument) getDocument()).setSyntaxStyle(new JadxTokenMaker(this)); - addMenuItems(jClsNode); + addMenuItems(); } setHyperlinksEnabled(true); @@ -47,9 +49,9 @@ public final class CodeArea extends AbstractCodeArea { } } - private void addMenuItems(JClass jCls) { - FindUsageAction findUsage = new FindUsageAction(contentPanel, this); - GoToDeclarationAction goToDeclaration = new GoToDeclarationAction(contentPanel, this, jCls); + private void addMenuItems() { + FindUsageAction findUsage = new FindUsageAction(this); + GoToDeclarationAction goToDeclaration = new GoToDeclarationAction(this); JPopupMenu popup = getPopupMenu(); popup.addSeparator(); @@ -59,11 +61,46 @@ public final class CodeArea extends AbstractCodeArea { popup.addPopupMenuListener(goToDeclaration); } + public int adjustOffsetForToken(@Nullable Token token) { + if (token == null) { + return -1; + } + int type = token.getType(); + final int sourceOffset; + if (node instanceof JClass) { + if (type == TokenTypes.IDENTIFIER) { + sourceOffset = token.getOffset(); + } else if (type == TokenTypes.ANNOTATION && token.length() > 1) { + sourceOffset = token.getOffset() + 1; + } else { + return -1; + } + } else { + if (type == TokenTypes.MARKUP_TAG_ATTRIBUTE_VALUE) { + sourceOffset = token.getOffset() + 1; // skip quote at start (") + } else { + return -1; + } + } + // fast skip + if (token.length() == 1) { + char ch = token.getTextArray()[token.getTextOffset()]; + if (ch == '.' || ch == ',' || ch == ';') { + return -1; + } + } + return sourceOffset; + } + /** * Search node by offset in {@code jCls} code and return its definition position * (useful for jumps from usage) */ + @Nullable public JumpPosition getDefPosForNodeAtOffset(int offset) { + if (offset == -1) { + return null; + } JavaNode foundNode = getJavaNodeAtOffset(offset); if (foundNode == null) { return null; diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java index b15fe862..44dcdc2c 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java @@ -9,11 +9,9 @@ import org.fife.ui.rsyntaxtextarea.LinkGenerator; import org.fife.ui.rsyntaxtextarea.LinkGeneratorResult; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.Token; -import org.fife.ui.rsyntaxtextarea.TokenTypes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JNode; import jadx.gui.ui.ContentPanel; import jadx.gui.utils.JumpPosition; @@ -38,33 +36,10 @@ public class CodeLinkGenerator implements LinkGenerator, HyperlinkListener { return null; } Token token = textArea.modelToToken(offset); - if (token == null) { + int sourceOffset = codeArea.adjustOffsetForToken(token); + if (sourceOffset == -1) { return null; } - int type = token.getType(); - final int sourceOffset; - if (jNode instanceof JClass) { - if (type == TokenTypes.IDENTIFIER) { - sourceOffset = token.getOffset(); - } else if (type == TokenTypes.ANNOTATION && token.length() > 1) { - sourceOffset = token.getOffset() + 1; - } else { - return null; - } - } else { - if (type == TokenTypes.MARKUP_TAG_ATTRIBUTE_VALUE) { - sourceOffset = token.getOffset() + 1; // skip quote at start (") - } else { - return null; - } - } - // fast skip - if (token.length() == 1) { - char ch = token.getTextArray()[token.getTextOffset()]; - if (ch == '.' || ch == ',' || ch == ';') { - return null; - } - } final JumpPosition defPos = codeArea.getDefPosForNodeAtOffset(sourceOffset); if (defPos == null) { return null; diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/FindUsageAction.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/FindUsageAction.java index 68276b51..609587b1 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/FindUsageAction.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/FindUsageAction.java @@ -1,66 +1,25 @@ package jadx.gui.ui.codearea; -import java.awt.*; import java.awt.event.ActionEvent; -import javax.swing.*; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; - -import org.fife.ui.rsyntaxtextarea.Token; - -import jadx.api.JavaNode; -import jadx.gui.treemodel.JNode; -import jadx.gui.ui.ContentPanel; import jadx.gui.ui.MainWindow; import jadx.gui.ui.UsageDialog; import jadx.gui.utils.NLS; -public final class FindUsageAction extends AbstractAction implements PopupMenuListener { +public final class FindUsageAction extends JNodeMenuAction { private static final long serialVersionUID = 4692546569977976384L; - private final transient ContentPanel contentPanel; - private final transient CodeArea codeArea; - - private transient JavaNode node; - - public FindUsageAction(ContentPanel contentPanel, CodeArea codeArea) { - super(NLS.str("popup.find_usage")); - this.contentPanel = contentPanel; - this.codeArea = codeArea; + public FindUsageAction(CodeArea codeArea) { + super(NLS.str("popup.find_usage"), codeArea); } @Override public void actionPerformed(ActionEvent e) { - if (node == null) { + if (jumpPos == null) { return; } - MainWindow mainWindow = contentPanel.getTabbedPane().getMainWindow(); - JNode jNode = mainWindow.getCacheObject().getNodeCache().makeFrom(node); - UsageDialog usageDialog = new UsageDialog(mainWindow, jNode); + MainWindow mainWindow = codeArea.getContentPanel().getTabbedPane().getMainWindow(); + UsageDialog usageDialog = new UsageDialog(mainWindow, jumpPos.getNode()); usageDialog.setVisible(true); } - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - node = null; - Point pos = codeArea.getMousePosition(); - if (pos != null) { - Token token = codeArea.viewToToken(pos); - if (token != null) { - node = codeArea.getJavaNodeAtOffset(token.getOffset()); - } - } - setEnabled(node != null); - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - // do nothing - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - // do nothing - } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java index d0585789..d1886356 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/GoToDeclarationAction.java @@ -1,67 +1,30 @@ package jadx.gui.ui.codearea; -import java.awt.Point; import java.awt.event.ActionEvent; -import javax.swing.AbstractAction; +import javax.swing.*; import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import org.fife.ui.rsyntaxtextarea.Token; - -import jadx.api.JavaNode; -import jadx.gui.treemodel.JClass; -import jadx.gui.treemodel.JNode; -import jadx.gui.ui.ContentPanel; -import jadx.gui.ui.MainWindow; -import jadx.gui.utils.JumpPosition; import jadx.gui.utils.NLS; -public final class GoToDeclarationAction extends AbstractAction implements PopupMenuListener { +public final class GoToDeclarationAction extends JNodeMenuAction { private static final long serialVersionUID = -1186470538894941301L; - private final transient ContentPanel contentPanel; - private final transient CodeArea codeArea; - private final transient JClass jCls; - - private transient JavaNode node; - public GoToDeclarationAction(ContentPanel contentPanel, CodeArea codeArea, JClass jCls) { - super(NLS.str("popup.go_to_declaration")); - this.contentPanel = contentPanel; - this.codeArea = codeArea; - this.jCls = jCls; + public GoToDeclarationAction(CodeArea codeArea) { + super(NLS.str("popup.go_to_declaration"), codeArea); } @Override public void actionPerformed(ActionEvent e) { - if (node == null) { - return; + if (jumpPos != null) { + codeArea.getContentPanel().getTabbedPane().codeJump(jumpPos); } - MainWindow mainWindow = contentPanel.getTabbedPane().getMainWindow(); - JNode jNode = mainWindow.getCacheObject().getNodeCache().makeFrom(node); - mainWindow.getTabbedPane().codeJump(new JumpPosition(jNode, jNode.getLine())); } @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - node = null; - Point pos = codeArea.getMousePosition(); - if (pos != null) { - Token token = codeArea.viewToToken(pos); - if (token != null) { - node = codeArea.getJavaNodeAtOffset(token.getOffset()); - } - } - setEnabled(node != null); - } + super.popupMenuWillBecomeVisible(e); - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - // do nothing - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - // do nothing + putValue(Action.SMALL_ICON, jumpPos == null ? null : jumpPos.getNode().getIcon()); } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/JNodeMenuAction.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/JNodeMenuAction.java new file mode 100644 index 00000000..f4e42729 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/JNodeMenuAction.java @@ -0,0 +1,55 @@ +package jadx.gui.ui.codearea; + +import java.awt.*; +import java.awt.event.ActionEvent; + +import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +import org.fife.ui.rsyntaxtextarea.Token; +import org.jetbrains.annotations.Nullable; + +import jadx.gui.utils.JumpPosition; + +public abstract class JNodeMenuAction extends AbstractAction implements PopupMenuListener { + + protected final transient CodeArea codeArea; + @Nullable + protected transient JumpPosition jumpPos; + + public JNodeMenuAction(String name, CodeArea codeArea) { + super(name); + this.codeArea = codeArea; + } + + @Override + public abstract void actionPerformed(ActionEvent e); + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + jumpPos = getJumpPos(); + setEnabled(jumpPos != null); + } + + @Nullable + private JumpPosition getJumpPos() { + Point pos = codeArea.getMousePosition(); + if (pos != null) { + Token token = codeArea.viewToToken(pos); + int offset = codeArea.adjustOffsetForToken(token); + return codeArea.getDefPosForNodeAtOffset(offset); + } + return null; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + // do nothing + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + // do nothing + } +} -- GitLab