fix(gui): highlight word even if cursor at the end of that word (#2083)
This commit is contained in:
@@ -272,40 +272,68 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,8 +414,7 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -82,10 +82,9 @@ public final class CodeArea extends AbstractCodeArea {
|
||||
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);
|
||||
}
|
||||
@@ -154,17 +153,16 @@ public final class CodeArea extends AbstractCodeArea {
|
||||
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) {
|
||||
@@ -208,25 +206,13 @@ public final class CodeArea extends AbstractCodeArea {
|
||||
@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;
|
||||
}
|
||||
@@ -236,15 +222,13 @@ public final class CodeArea extends AbstractCodeArea {
|
||||
@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
|
||||
@@ -281,6 +265,9 @@ public final class CodeArea extends AbstractCodeArea {
|
||||
}
|
||||
|
||||
public JavaNode getClosestJavaNode(int offset) {
|
||||
if (offset == -1) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return getJadxWrapper().getDecompiler().getClosestJavaNode(getCodeInfo(), offset);
|
||||
} catch (Exception e) {
|
||||
@@ -290,6 +277,9 @@ public final class CodeArea extends AbstractCodeArea {
|
||||
}
|
||||
|
||||
public JavaNode getEnclosingJavaNode(int offset) {
|
||||
if (offset == -1) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return getJadxWrapper().getDecompiler().getEnclosingNode(getCodeInfo(), offset);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import javax.swing.event.HyperlinkEvent;
|
||||
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;
|
||||
@@ -32,7 +31,7 @@ public class CodeLinkGenerator implements LinkGenerator {
|
||||
if (!codeArea.getCodeInfo().hasMetadata()) {
|
||||
return null;
|
||||
}
|
||||
int sourceOffset = getLinkSourceOffset(offset);
|
||||
int sourceOffset = codeArea.adjustOffsetForWordToken(offset);
|
||||
if (sourceOffset == -1) {
|
||||
return null;
|
||||
}
|
||||
@@ -49,7 +48,7 @@ public class CodeLinkGenerator implements LinkGenerator {
|
||||
if (!codeArea.getCodeInfo().hasMetadata()) {
|
||||
return null;
|
||||
}
|
||||
int sourceOffset = getLinkSourceOffset(offset);
|
||||
int sourceOffset = codeArea.adjustOffsetForWordToken(offset);
|
||||
if (sourceOffset == -1) {
|
||||
return null;
|
||||
}
|
||||
@@ -75,11 +74,6 @@ public class CodeLinkGenerator implements LinkGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user