Skip to content

Commit

Permalink
feat(gui): on mouse hover highlight identifiers with enabled actions …
Browse files Browse the repository at this point in the history
…(like 'find usage' or 'rename')
  • Loading branch information
skylot committed Aug 17, 2020
1 parent a485942 commit 94a06d9
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public AbstractCodeArea(ContentPanel contentPanel) {
this.contentPanel = contentPanel;
this.node = contentPanel.getNode();

setMarkOccurrences(true);
setMarkOccurrences(false);
setEditable(false);
setCodeFoldingEnabled(false);
loadSettings();
Expand Down
7 changes: 6 additions & 1 deletion jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public final class CodeArea extends AbstractCodeArea {
super(contentPanel);
setSyntaxEditingStyle(node.getSyntaxName());

if (node instanceof JClass) {
boolean isJavaCode = node instanceof JClass;
if (isJavaCode) {
((RSyntaxDocument) getDocument()).setSyntaxStyle(new JadxTokenMaker(this));
addMenuItems();
}
Expand All @@ -46,6 +47,7 @@ public final class CodeArea extends AbstractCodeArea {
CodeLinkGenerator codeLinkGenerator = new CodeLinkGenerator(this);
setLinkGenerator(codeLinkGenerator);
addMouseListener(new MouseAdapter() {
@SuppressWarnings("deprecation")
@Override
public void mouseClicked(MouseEvent e) {
if (e.isControlDown()) {
Expand All @@ -57,6 +59,9 @@ public void mouseClicked(MouseEvent e) {
}
}
});
if (isJavaCode) {
addMouseMotionListener(new MouseHoverHighlighter(this, codeLinkGenerator));
}
}

@Override
Expand Down
31 changes: 23 additions & 8 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/JadxTokenMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public JadxTokenMaker(CodeArea codeArea) {
@Override
public Token getTokenList(Segment text, int initialTokenType, int startOffset) {
Token tokens = super.getTokenList(text, initialTokenType, startOffset);
if (startOffset > 0 && tokens.getType() != TokenTypes.NULL) {
if (tokens.getType() != TokenTypes.NULL) {
try {
processTokens(tokens);
} catch (Exception e) {
Expand All @@ -41,11 +41,14 @@ private void processTokens(Token tokens) {
Token current = tokens;
while (current != null) {
if (prev != null) {
int tokenType = current.getType();
if (tokenType == TokenTypes.IDENTIFIER) {
current = mergeLongClassNames(prev, current, false);
} else if (tokenType == TokenTypes.ANNOTATION) {
current = mergeLongClassNames(prev, current, true);
switch (current.getType()) {
case TokenTypes.IDENTIFIER:
current = mergeLongClassNames(prev, current, false);
break;

case TokenTypes.ANNOTATION:
current = mergeLongClassNames(prev, current, true);
break;
}
}
prev = current;
Expand All @@ -55,7 +58,7 @@ private void processTokens(Token tokens) {

@NotNull
private Token mergeLongClassNames(Token prev, Token current, boolean annotation) {
int offset = current.getOffset();
int offset = current.getTextOffset();
if (annotation) {
offset++;
}
Expand All @@ -66,7 +69,7 @@ private Token mergeLongClassNames(Token prev, Token current, boolean annotation)
if (annotation && lexeme.length() > 1) {
lexeme = lexeme.substring(1);
}
if (!lexeme.equals(name) && javaNode.getFullName().startsWith(lexeme)) {
if (!lexeme.equals(name) && isClassNameStart(javaNode, lexeme)) {
// try to replace long class name with one token
Token replace = concatTokensUntil(current, name);
if (replace != null && prev instanceof TokenImpl) {
Expand All @@ -79,6 +82,18 @@ private Token mergeLongClassNames(Token prev, Token current, boolean annotation)
return current;
}

private boolean isClassNameStart(JavaNode javaNode, String lexeme) {
if (javaNode.getFullName().startsWith(lexeme)) {
// full class name
return true;
}
if (javaNode.getTopParentClass().getName().startsWith(lexeme)) {
// inner class references from parent class
return true;
}
return false;
}

@Nullable
private Token concatTokensUntil(Token start, String endText) {
StringBuilder sb = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package jadx.gui.ui.codearea;

import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.text.Highlighter;

import org.fife.ui.rsyntaxtextarea.Token;
import org.fife.ui.rsyntaxtextarea.TokenTypes;
import org.fife.ui.rtextarea.SmartHighlightPainter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.gui.utils.JumpPosition;

class MouseHoverHighlighter extends MouseMotionAdapter {
private static final Logger LOG = LoggerFactory.getLogger(MouseHoverHighlighter.class);

private final CodeArea codeArea;
private final CodeLinkGenerator codeLinkGenerator;
private final Highlighter.HighlightPainter highlighter;

private boolean added;

public MouseHoverHighlighter(CodeArea codeArea, CodeLinkGenerator codeLinkGenerator) {
this.codeArea = codeArea;
this.codeLinkGenerator = codeLinkGenerator;
this.highlighter = new SmartHighlightPainter(codeArea.getMarkOccurrencesColor());
}

@Override
public void mouseMoved(MouseEvent e) {
Highlighter highlighter = codeArea.getHighlighter();
if (added) {
highlighter.removeAllHighlights();
added = false;
}
if (e.getModifiersEx() != 0) {
return;
}
try {
Token token = codeArea.viewToToken(e.getPoint());
if (token == null || token.getType() != TokenTypes.IDENTIFIER) {
return;
}
JumpPosition jump = codeLinkGenerator.getJumpLinkAtOffset(codeArea, token.getOffset());
if (jump == null) {
return;
}
highlighter.removeAllHighlights();
highlighter.addHighlight(token.getOffset(), token.getEndOffset(), this.highlighter);
added = true;
} catch (Exception exc) {
LOG.error("Mouse hover highlight error", exc);
}
}
}

0 comments on commit 94a06d9

Please sign in to comment.