Skip to content

Commit

Permalink
fix(gui): fix "Go to declaration" and "Find usage" menu actions
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Aug 11, 2019
1 parent 3578f7d commit ff5f6fc
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 124 deletions.
47 changes: 42 additions & 5 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
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;

Expand All @@ -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);
Expand All @@ -47,9 +49,9 @@ public void load() {
}
}

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();
Expand All @@ -59,11 +61,46 @@ private void addMenuItems(JClass jCls) {
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;
Expand Down
29 changes: 2 additions & 27 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@
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;
Expand All @@ -38,33 +36,10 @@ public LinkGeneratorResult isLinkAtOffset(RSyntaxTextArea textArea, int offset)
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;
Expand Down
53 changes: 6 additions & 47 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/FindUsageAction.java
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
55 changes: 55 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/JNodeMenuAction.java
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit ff5f6fc

Please sign in to comment.