Skip to content

Commit

Permalink
fix(gui): highlight word even if cursor at the end of that word (#2083)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jan 18, 2024
1 parent fb703cd commit 4483533
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 55 deletions.
59 changes: 43 additions & 16 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -272,40 +272,68 @@ public String getWordUnderCaret() {
return getWordByPosition(getCaretPosition());
}

@Nullable
public String getWordByPosition(int pos) {
public @Nullable String getWordByPosition(int offset) {
Token token = getWordTokenAtOffset(offset);
if (token != null) {
return token.getLexeme();
}
return null;
}

/**
* Return any word token (not whitespace or special symbol) at offset.
* Select the previous token if the cursor at word end (current token already is whitespace)
*/
public @Nullable Token getWordTokenAtOffset(int offset) {
try {
Token token = modelToToken(pos);
return getWordFromToken(token);
int line = this.getLineOfOffset(offset);
Token lineTokens = this.getTokenListForLine(line);
Token token = null;
Token prevToken = null;
for (Token t = lineTokens; t != null && t.isPaintable(); t = t.getNextToken()) {
if (t.containsPosition(offset)) {
token = t;
break;
}
prevToken = t;
}
if (token == null) {
return null;
}
if (isWordToken(token)) {
return token;
}
if (isWordToken(prevToken)) {
return prevToken;
}
return null;
} catch (Exception e) {
LOG.error("Failed to get word at pos: {}", pos, e);
LOG.error("Failed to get token at pos: {}", offset, e);
return null;
}
}

@Nullable
private static String getWordFromToken(@Nullable Token token) {
public static boolean isWordToken(@Nullable Token token) {
if (token == null) {
return null;
return false;
}
switch (token.getType()) {
case TokenTypes.NULL:
case TokenTypes.WHITESPACE:
case TokenTypes.SEPARATOR:
case TokenTypes.OPERATOR:
return null;
case TokenTypes.FUNCTION:
return false;

case TokenTypes.IDENTIFIER:
if (token.length() == 1) {
char ch = token.charAt(0);
if (ch == ';' || ch == '.') {
return null;
}
return ch != ';' && ch != '.' && ch != ',';
}
return token.getLexeme();
return true;

default:
return token.getLexeme();
return true;
}
}

Expand Down Expand Up @@ -386,8 +414,7 @@ public void centerCurrentLine() {
}

/**
* @param str
* - if null -> reset current highlights
* @param str - if null -> reset current highlights
*/
private void highlightAllMatches(@Nullable String str) {
SearchContext context = new SearchContext(str);
Expand Down
52 changes: 21 additions & 31 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public final class CodeArea extends AbstractCodeArea {
@Override
public void mouseClicked(MouseEvent e) {
if (e.isControlDown() || jumpOnDoubleClick(e)) {
navToDecl(e.getPoint(), codeLinkGenerator);
navToDecl(e.getPoint());
}
}
});
Expand All @@ -82,10 +82,9 @@ private boolean jumpOnDoubleClick(MouseEvent e) {
return e.getClickCount() == 2 && getMainWindow().getSettings().isJumpOnDoubleClick();
}

@SuppressWarnings("deprecation")
private void navToDecl(Point point, CodeLinkGenerator codeLinkGenerator) {
int offs = viewToModel(point);
JNode node = getJNodeAtOffset(codeLinkGenerator.getLinkSourceOffset(offs));
private void navToDecl(Point point) {
int offs = viewToModel2D(point);
JNode node = getJNodeAtOffset(adjustOffsetForWordToken(offs));
if (node != null) {
contentPanel.getTabbedPane().codeJump(node);
}
Expand Down Expand Up @@ -154,17 +153,16 @@ private void addMenuForJsonFile() {
popup.add(new JsonPrettifyAction(this));
}

public int adjustOffsetForToken(@Nullable Token token) {
/**
* Search start of word token at specified offset
*
* @return -1 if no word token found
*/
public int adjustOffsetForWordToken(int offset) {
Token token = getWordTokenAtOffset(offset);
if (token == null) {
return -1;
}
// fast skip
if (token.length() == 1) {
char ch = token.getTextArray()[token.getTextOffset()];
if (ch == '.' || ch == ',' || ch == ';') {
return -1;
}
}
int type = token.getType();
if (node instanceof JClass) {
if (type == TokenTypes.IDENTIFIER || type == TokenTypes.FUNCTION) {
Expand Down Expand Up @@ -208,25 +206,13 @@ private JNode convertJavaNode(JavaNode javaNode) {
@Nullable
public JNode getNodeUnderCaret() {
int caretPos = getCaretPosition();
Token token = modelToToken(caretPos);
if (token == null) {
return null;
}
int start = adjustOffsetForToken(token);
if (start == -1) {
start = caretPos;
}
return getJNodeAtOffset(start);
return getJNodeAtOffset(adjustOffsetForWordToken(caretPos));
}

@Nullable
public JNode getEnclosingNodeUnderCaret() {
int caretPos = getCaretPosition();
Token token = modelToToken(caretPos);
if (token == null) {
return null;
}
int start = adjustOffsetForToken(token);
int start = adjustOffsetForWordToken(caretPos);
if (start == -1) {
start = caretPos;
}
Expand All @@ -236,15 +222,13 @@ public JNode getEnclosingNodeUnderCaret() {
@Nullable
public JNode getNodeUnderMouse() {
Point pos = UiUtils.getMousePosition(this);
int offset = adjustOffsetForToken(viewToToken(pos));
return getJNodeAtOffset(offset);
return getJNodeAtOffset(adjustOffsetForWordToken(viewToModel2D(pos)));
}

@Nullable
public JNode getEnclosingNodeUnderMouse() {
Point pos = UiUtils.getMousePosition(this);
int offset = adjustOffsetForToken(viewToToken(pos));
return getEnclosingJNodeAtOffset(offset);
return getEnclosingJNodeAtOffset(adjustOffsetForWordToken(viewToModel2D(pos)));
}

@Nullable
Expand Down Expand Up @@ -281,6 +265,9 @@ public JavaNode getJavaNodeAtOffset(int offset) {
}

public JavaNode getClosestJavaNode(int offset) {
if (offset == -1) {
return null;
}
try {
return getJadxWrapper().getDecompiler().getClosestJavaNode(getCodeInfo(), offset);
} catch (Exception e) {
Expand All @@ -290,6 +277,9 @@ public JavaNode getClosestJavaNode(int offset) {
}

public JavaNode getEnclosingJavaNode(int offset) {
if (offset == -1) {
return null;
}
try {
return getJadxWrapper().getDecompiler().getEnclosingNode(getCodeInfo(), offset);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
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.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -32,7 +31,7 @@ public JavaNode getNodeAtOffset(int offset) {
if (!codeArea.getCodeInfo().hasMetadata()) {
return null;
}
int sourceOffset = getLinkSourceOffset(offset);
int sourceOffset = codeArea.adjustOffsetForWordToken(offset);
if (sourceOffset == -1) {
return null;
}
Expand All @@ -49,7 +48,7 @@ public LinkGeneratorResult isLinkAtOffset(RSyntaxTextArea textArea, int offset)
if (!codeArea.getCodeInfo().hasMetadata()) {
return null;
}
int sourceOffset = getLinkSourceOffset(offset);
int sourceOffset = codeArea.adjustOffsetForWordToken(offset);
if (sourceOffset == -1) {
return null;
}
Expand All @@ -75,11 +74,6 @@ public int getSourceOffset() {
}
}

public int getLinkSourceOffset(int offset) {
Token token = codeArea.modelToToken(offset);
return codeArea.adjustOffsetForToken(token);
}

@Nullable
private JumpPosition getJumpBySourceOffset(int sourceOffset) {
final JumpPosition defPos = codeArea.getDefPosForNodeAtOffset(sourceOffset);
Expand Down

0 comments on commit 4483533

Please sign in to comment.