fix: don't apply node positions and prevent eager loading for custom decompile modes (#2116)
This commit is contained in:
@@ -154,7 +154,6 @@ public class AnnotatedCodeWriter extends SimpleCodeWriter implements ICodeWriter
|
||||
|
||||
@Override
|
||||
public ICodeInfo finish() {
|
||||
processDefinitionAnnotations();
|
||||
validateAnnotations();
|
||||
String code = buf.toString();
|
||||
buf = null;
|
||||
@@ -166,18 +165,6 @@ public class AnnotatedCodeWriter extends SimpleCodeWriter implements ICodeWriter
|
||||
return annotations;
|
||||
}
|
||||
|
||||
private void processDefinitionAnnotations() {
|
||||
if (!annotations.isEmpty()) {
|
||||
annotations.forEach((k, v) -> {
|
||||
if (v instanceof NodeDeclareRef) {
|
||||
NodeDeclareRef declareRef = (NodeDeclareRef) v;
|
||||
declareRef.setDefPos(k);
|
||||
declareRef.getNode().setDefPosition(k);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void validateAnnotations() {
|
||||
if (annotations.isEmpty()) {
|
||||
return;
|
||||
|
||||
@@ -23,6 +23,8 @@ import jadx.api.ICodeWriter;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JavaClass;
|
||||
import jadx.api.impl.SimpleCodeInfo;
|
||||
import jadx.api.metadata.ICodeAnnotation;
|
||||
import jadx.api.metadata.annotations.NodeDeclareRef;
|
||||
import jadx.api.plugins.input.data.IClassData;
|
||||
import jadx.api.plugins.input.data.IFieldData;
|
||||
import jadx.api.plugins.input.data.IMethodData;
|
||||
@@ -312,6 +314,8 @@ public class ClassNode extends NotificationAttrNode
|
||||
return decompile(true);
|
||||
}
|
||||
|
||||
private static final Object DECOMPILE_WITH_MODE_SYNC = new Object();
|
||||
|
||||
/**
|
||||
* WARNING: Slow operation! Use with caution!
|
||||
*/
|
||||
@@ -320,15 +324,18 @@ public class ClassNode extends NotificationAttrNode
|
||||
if (mode == baseMode) {
|
||||
return decompile(true);
|
||||
}
|
||||
JadxArgs args = root.getArgs();
|
||||
try {
|
||||
unload();
|
||||
args.setDecompilationMode(mode);
|
||||
ProcessClass process = new ProcessClass(args);
|
||||
process.initPasses(root);
|
||||
return process.generateCode(this);
|
||||
} finally {
|
||||
args.setDecompilationMode(baseMode);
|
||||
synchronized (DECOMPILE_WITH_MODE_SYNC) {
|
||||
JadxArgs args = root.getArgs();
|
||||
try {
|
||||
unload();
|
||||
args.setDecompilationMode(mode);
|
||||
ProcessClass process = new ProcessClass(args);
|
||||
process.initPasses(root);
|
||||
return process.generateCode(this);
|
||||
} finally {
|
||||
args.setDecompilationMode(baseMode);
|
||||
unload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,22 +390,46 @@ public class ClassNode extends NotificationAttrNode
|
||||
return code;
|
||||
}
|
||||
}
|
||||
ICodeInfo codeInfo;
|
||||
try {
|
||||
if (Consts.DEBUG) {
|
||||
LOG.debug("Decompiling class: {}", this);
|
||||
}
|
||||
codeInfo = root.getProcessClasses().generateCode(this);
|
||||
} catch (Throwable e) {
|
||||
addError("Code generation failed", e);
|
||||
codeInfo = new SimpleCodeInfo(Utils.getStackTrace(e));
|
||||
}
|
||||
ICodeInfo codeInfo = generateClassCode();
|
||||
if (codeInfo != ICodeInfo.EMPTY) {
|
||||
codeCache.add(clsRawName, codeInfo);
|
||||
}
|
||||
return codeInfo;
|
||||
}
|
||||
|
||||
private ICodeInfo generateClassCode() {
|
||||
try {
|
||||
if (Consts.DEBUG) {
|
||||
LOG.debug("Decompiling class: {}", this);
|
||||
}
|
||||
ICodeInfo codeInfo = root.getProcessClasses().generateCode(this);
|
||||
processDefinitionAnnotations(codeInfo);
|
||||
return codeInfo;
|
||||
} catch (Throwable e) {
|
||||
addError("Code generation failed", e);
|
||||
return new SimpleCodeInfo(Utils.getStackTrace(e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save node definition positions found in code
|
||||
*/
|
||||
private static void processDefinitionAnnotations(ICodeInfo codeInfo) {
|
||||
Map<Integer, ICodeAnnotation> annotations = codeInfo.getCodeMetadata().getAsMap();
|
||||
if (annotations.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<Integer, ICodeAnnotation> entry : annotations.entrySet()) {
|
||||
ICodeAnnotation ann = entry.getValue();
|
||||
if (ann.getAnnType() == AnnType.DECLARATION) {
|
||||
NodeDeclareRef declareRef = (NodeDeclareRef) ann;
|
||||
int pos = entry.getKey();
|
||||
declareRef.setDefPos(pos);
|
||||
declareRef.getNode().setDefPosition(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ICodeInfo getCodeFromCache() {
|
||||
ICodeCache codeCache = root().getCodeCache();
|
||||
|
||||
@@ -134,10 +134,22 @@ public class CodePanel extends JPanel {
|
||||
codeScrollPane.setLineNumbersEnabled(true);
|
||||
}
|
||||
|
||||
private static final LineNumberFormatter SIMPLE_LINE_FORMATTER = new LineNumberFormatter() {
|
||||
@Override
|
||||
public String format(int lineNumber) {
|
||||
return Integer.toString(lineNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLength(int maxLineNumber) {
|
||||
return SourceLineFormatter.getNumberLength(maxLineNumber);
|
||||
}
|
||||
};
|
||||
|
||||
private synchronized void applyLineFormatter() {
|
||||
LineNumberFormatter linesFormatter = useSourceLines
|
||||
? new SourceLineFormatter(codeArea.getCodeInfo())
|
||||
: LineNumberList.DEFAULT_LINE_NUMBER_FORMATTER;
|
||||
: SIMPLE_LINE_FORMATTER;
|
||||
codeScrollPane.getGutter().setLineNumberFormatter(linesFormatter);
|
||||
}
|
||||
|
||||
@@ -170,15 +182,13 @@ public class CodePanel extends JPanel {
|
||||
}
|
||||
|
||||
private void initLinesModeSwitch() {
|
||||
if (canShowDebugLines()) {
|
||||
MousePressedHandler lineModeSwitch = new MousePressedHandler(ev -> {
|
||||
useSourceLines = !useSourceLines;
|
||||
applyLineFormatter();
|
||||
});
|
||||
for (Component gutterComp : codeScrollPane.getGutter().getComponents()) {
|
||||
if (gutterComp instanceof LineNumberList) {
|
||||
gutterComp.addMouseListener(lineModeSwitch);
|
||||
}
|
||||
MousePressedHandler lineModeSwitch = new MousePressedHandler(ev -> {
|
||||
useSourceLines = !useSourceLines;
|
||||
applyLineFormatter();
|
||||
});
|
||||
for (Component gutterComp : codeScrollPane.getGutter().getComponents()) {
|
||||
if (gutterComp instanceof LineNumberList) {
|
||||
gutterComp.addMouseListener(lineModeSwitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,10 @@ public class SourceLineFormatter implements LineNumberFormatter {
|
||||
.values().stream()
|
||||
.mapToInt(Integer::intValue)
|
||||
.max().orElse(1);
|
||||
// maxLine can be anything including zero and negative numbers,
|
||||
// so use safe 'stringify' method instead faster 'Math.log10'
|
||||
return Integer.toString(maxLine).length();
|
||||
return getNumberLength(maxLine);
|
||||
}
|
||||
|
||||
public static int getNumberLength(int num) {
|
||||
return num < 10 ? 1 : 1 + (int) Math.log10(num);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user