From 2bdde6a528ccb5dcc50e81dc6ac3342f96055eaa Mon Sep 17 00:00:00 2001 From: LBJ-the-GOAT <66319139+LBJ-the-GOAT@users.noreply.github.com> Date: Thu, 28 Jan 2021 00:23:07 +0800 Subject: [PATCH] fix(gui): fix variable usage & caret position after rename (#1099) (PR #1103) Co-authored-by: tobias --- .../main/java/jadx/api/JadxDecompiler.java | 2 +- .../src/main/java/jadx/api/JavaVariable.java | 5 +- .../main/java/jadx/core/codegen/InsnGen.java | 2 - .../java/jadx/core/dex/nodes/MethodNode.java | 18 +----- .../jadx/core/dex/nodes/VariableNode.java | 13 ---- .../java/jadx/gui/ui/codearea/CodePanel.java | 64 ++++++++++++++++++- 6 files changed, 69 insertions(+), 35 deletions(-) diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java index a56479ca4..0bc32ed4e 100644 --- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java +++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java @@ -448,7 +448,7 @@ public final class JadxDecompiler implements Closeable { } if (obj instanceof VariableNode) { VariableNode varNode = (VariableNode) obj; - return new JavaVariable(getJavaClassByNode(varNode.getClassNode()), varNode); + return new JavaVariable(getJavaClassByNode(varNode.getClassNode().getTopParentClass()), varNode); } throw new JadxRuntimeException("Unexpected node type: " + obj); } diff --git a/jadx-core/src/main/java/jadx/api/JavaVariable.java b/jadx-core/src/main/java/jadx/api/JavaVariable.java index 476a8609f..8ae723e1b 100644 --- a/jadx-core/src/main/java/jadx/api/JavaVariable.java +++ b/jadx-core/src/main/java/jadx/api/JavaVariable.java @@ -55,6 +55,9 @@ public class JavaVariable implements JavaNode { @Override public boolean equals(Object obj) { - return node.equals(obj); + if (obj instanceof JavaVariable) { + return node.equals(((JavaVariable) obj).getVariableNode()); + } + return false; } } diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 71bd15a73..eff0acd2d 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -92,7 +92,6 @@ public class InsnGen { if (codeVar != null) { VariableNode node = mth.getVariable(codeVar.getIndex()); if (node != null) { - node.useVar(code, codeVar); code.attachAnnotation(node); } } @@ -653,7 +652,6 @@ public class InsnGen { if (insn.isSuper()) { code.add("super"); } else if (insn.isThis()) { - code.attachAnnotation(mth.getParentClass()); code.add("this"); } else { code.add("new "); diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index 979ae1edf..01a20a514 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -110,15 +110,6 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails, return null; } - public VariableNode getVariable(int index, VarKind varType) { - for (VariableNode variable : variables) { - if (variable.getVarKind() == varType && variable.getIndex() == index) { - return variable; - } - } - return null; - } - public VariableNode declareVar(VisibleVar var, NameGen nameGen, VarKind varKind) { if (var instanceof CodeVar) { if (((CodeVar) var).isThis()) { @@ -127,14 +118,11 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails, } VariableNode varNode; int index = var.getIndex(); - if (index == -1) { + if (index > -1) { + varNode = getVariable(var.getIndex()); + } else { index = variables.size(); var.setIndex(index); - varNode = null; - } else { - varNode = getVariable(var.getIndex()); - } - if (varNode == null) { String name = mthInfo.getVariableName(VariableNode.makeVarIndex(index, varKind)); if (name != null) { var.setName(name); // set name with user renamed previously. diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/VariableNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/VariableNode.java index 5fcc82198..89d91c038 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/VariableNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/VariableNode.java @@ -1,9 +1,7 @@ package jadx.core.dex.nodes; -import jadx.core.codegen.CodeWriter; import jadx.core.dex.attributes.nodes.LineAttrNode; import jadx.core.dex.instructions.args.ArgType; -import jadx.core.dex.instructions.args.CodeVar; import jadx.core.utils.exceptions.JadxRuntimeException; public class VariableNode extends LineAttrNode { @@ -56,17 +54,6 @@ public class VariableNode extends LineAttrNode { return index; } - public void addUsage(int line, int offset, int codeOffset) { - } - - public void useVar(CodeWriter code, CodeVar codeVar) { - if (!codeVar.isThis()) { // TODO: add usage - // IdentifierVisitor.VariableNode node = codeVar.getVariableNode(); - // node.addUsage(code.getLine(), code.getOffset(), code.bufLength()); - // code.attachAnnotation(node); - } - } - public String getRenameKey() { return mth.getMethodInfo().getRawFullId() + VAR_SEPARATOR + makeVarIndex(index, varKind); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java index 5eefeeb10..bd16b1c3f 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java @@ -12,6 +12,9 @@ import javax.swing.JPopupMenu.Separator; import javax.swing.border.EmptyBorder; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; +import javax.swing.text.BadLocationException; + +import org.fife.ui.rsyntaxtextarea.Token; import jadx.api.ICodeInfo; import jadx.core.utils.StringUtils; @@ -146,12 +149,67 @@ public class CodePanel extends JPanel { } public void refresh() { - JViewport viewport = getCodeScrollPane().getViewport(); - Point viewPosition = viewport.getViewPosition(); + int line; + int lineCount; + int tokenIndex; + int pos = codeArea.getCaretPosition(); + try { + // after rename the change of document is undetectable, so + // use Token offset to calculate the new caret position. + line = codeArea.getLineOfOffset(pos); + Token token = codeArea.getTokenListForLine(line); + tokenIndex = getTokenIndexByOffset(token, pos); + } catch (BadLocationException e) { + e.printStackTrace(); + tokenIndex = 0; + line = codeArea.getLineCount() - 1; + } + lineCount = codeArea.getLineCount(); codeArea.refresh(); initLineNumbers(); + int lineDiff = codeArea.getLineCount() - lineCount; + if (lineDiff > 0) { + lineDiff--; + } else if (lineDiff < 0) { + lineDiff++; + } + Token token = codeArea.getTokenListForLine(line + lineDiff); + int newPos = getOffsetOfTokenByIndex(tokenIndex, token); SwingUtilities.invokeLater(() -> { - viewport.setViewPosition(viewPosition); + if (newPos != -1) { + codeArea.scrollToPos(newPos); + } else { + codeArea.scrollToLine(codeArea.getLineCount() - 1); + } }); } + + private int getTokenIndexByOffset(Token token, int offset) { + if (token != null) { + int index = 1; + while (token.getEndOffset() < offset) { + token = token.getNextToken(); + if (token == null) { + index = 0; + break; + } + index++; + } + return index; + } + return -1; + } + + private int getOffsetOfTokenByIndex(int index, Token token) { + if (token != null) { + for (int i = 0; i < index; i++) { + token = token.getNextToken(); + if (token == null) { + return -1; + } + } + return token.getOffset(); + } + return -1; + } }