提交 e4e6f379 编写于 作者: S Skylot

fix: sort inner classes and methods by source lines

上级 4b314e9d
......@@ -10,6 +10,7 @@ import java.util.Objects;
import java.util.Set;
import com.android.dx.rop.code.AccessFlags;
import com.google.common.collect.Streams;
import jadx.api.JadxArgs;
import jadx.core.dex.attributes.AFlag;
......@@ -130,7 +131,8 @@ public class ClassGen {
annotationGen.addForClass(clsCode);
insertRenameInfo(clsCode, cls);
CodeGenUtils.addSourceFileInfo(clsCode, cls);
clsCode.startLine(af.makeString());
clsCode.startLineWithNum(cls.getSourceLine());
clsCode.add(af.makeString());
if (af.isInterface()) {
if (af.isAnnotation()) {
clsCode.add('@');
......@@ -222,21 +224,32 @@ public class ClassGen {
clsDeclLine = clsCode.getLine();
clsCode.incIndent();
addFields(clsCode);
addInnerClasses(clsCode, cls);
addMethods(clsCode);
addInnerClsAndMethods(clsCode);
clsCode.decIndent();
clsCode.startLine('}');
}
private void addInnerClasses(CodeWriter code, ClassNode cls) throws CodegenException {
for (ClassNode innerCls : cls.getInnerClasses()) {
if (innerCls.contains(AFlag.DONT_GENERATE)) {
continue;
}
private void addInnerClsAndMethods(CodeWriter clsCode) {
Streams.concat(cls.getInnerClasses().stream(), cls.getMethods().stream())
.filter(node -> !node.contains(AFlag.DONT_GENERATE))
.sorted(Comparator.comparingInt(LineAttrNode::getSourceLine))
.forEach(node -> {
if (node instanceof ClassNode) {
addInnerClass(clsCode, (ClassNode) node);
} else {
addMethod(clsCode, (MethodNode) node);
}
});
}
private void addInnerClass(CodeWriter code, ClassNode innerCls) {
try {
ClassGen inClGen = new ClassGen(innerCls, getParentGen());
code.newLine();
inClGen.addClassCode(code);
imports.addAll(inClGen.getImports());
} catch (Exception e) {
ErrorsCounter.classError(innerCls, "Inner class code generation error", e);
}
}
......@@ -249,38 +262,26 @@ public class ClassGen {
return false;
}
private void addMethods(CodeWriter code) {
List<MethodNode> methods = sortMethodsByLine(cls.getMethods());
for (MethodNode mth : methods) {
if (mth.contains(AFlag.DONT_GENERATE)) {
continue;
}
if (code.getLine() != clsDeclLine) {
code.newLine();
}
int savedIndent = code.getIndent();
try {
addMethod(code, mth);
} catch (Exception e) {
if (mth.getParentClass().getTopParentClass().contains(AFlag.RESTART_CODEGEN)) {
throw new JadxRuntimeException("Method generation error", e);
}
code.newLine().add("/*");
code.newLine().addMultiLine(ErrorsCounter.methodError(mth, "Method generation error", e));
Utils.appendStackTrace(code, e);
code.newLine().add("*/");
code.setIndent(savedIndent);
mth.addError("Method generation error: " + e.getMessage(), e);
private void addMethod(CodeWriter code, MethodNode mth) {
if (code.getLine() != clsDeclLine) {
code.newLine();
}
int savedIndent = code.getIndent();
try {
addMethodCode(code, mth);
} catch (Exception e) {
if (mth.getParentClass().getTopParentClass().contains(AFlag.RESTART_CODEGEN)) {
throw new JadxRuntimeException("Method generation error", e);
}
code.newLine().add("/*");
code.newLine().addMultiLine(ErrorsCounter.methodError(mth, "Method generation error", e));
Utils.appendStackTrace(code, e);
code.newLine().add("*/");
code.setIndent(savedIndent);
mth.addError("Method generation error: " + e.getMessage(), e);
}
}
private static List<MethodNode> sortMethodsByLine(List<MethodNode> methods) {
List<MethodNode> out = new ArrayList<>(methods);
out.sort(Comparator.comparingInt(LineAttrNode::getSourceLine));
return out;
}
private boolean isMethodsPresents() {
for (MethodNode mth : cls.getMethods()) {
if (!mth.contains(AFlag.DONT_GENERATE)) {
......@@ -290,7 +291,7 @@ public class ClassGen {
return false;
}
public void addMethod(CodeWriter code, MethodNode mth) throws CodegenException {
public void addMethodCode(CodeWriter code, MethodNode mth) throws CodegenException {
CodeGenUtils.addComments(code, mth);
if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
MethodGen mthGen = new MethodGen(this, mth);
......
......@@ -8,9 +8,12 @@ import java.util.Set;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Streams;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.DeclareVariablesAttr;
import jadx.core.dex.attributes.nodes.LineAttrNode;
import jadx.core.dex.instructions.ArithNode;
import jadx.core.dex.instructions.ArithOp;
import jadx.core.dex.instructions.InsnType;
......@@ -20,6 +23,7 @@ import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.instructions.mods.TernaryInsn;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.InsnContainer;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
......@@ -44,6 +48,14 @@ import jadx.core.utils.exceptions.JadxException;
)
public class PrepareForCodeGen extends AbstractVisitor {
@Override
public boolean visit(ClassNode cls) throws JadxException {
if (cls.root().getArgs().isDebugInfo()) {
setClassSourceLine(cls);
}
return true;
}
@Override
public void visit(MethodNode mth) throws JadxException {
List<BlockNode> blocks = mth.getBasicBlocks();
......@@ -246,4 +258,26 @@ public class PrepareForCodeGen extends AbstractVisitor {
}
return null;
}
/**
* Use source line from top method
*/
private void setClassSourceLine(ClassNode cls) {
for (ClassNode innerClass : cls.getInnerClasses()) {
setClassSourceLine(innerClass);
}
int minLine = Streams.concat(
cls.getMethods().stream(),
cls.getInnerClasses().stream(),
cls.getFields().stream())
.filter(mth -> !mth.contains(AFlag.DONT_GENERATE))
.filter(mth -> mth.getSourceLine() != 0)
.mapToInt(LineAttrNode::getSourceLine)
.min()
.orElse(0);
if (minLine != 0) {
cls.setSourceLine(minLine - 1);
}
}
}
......@@ -39,7 +39,7 @@ public class TestLineNumbers2 extends IntegrationTest {
ClassNode cls = getClassNode(TestCls.class);
Map<Integer, Integer> lineMapping = cls.getCode().getLineMapping();
assertEquals("{8=18, 11=22, 12=23, 13=24, 14=28, 16=25, 17=26, 18=28, 21=31, 22=32}",
assertEquals("{5=17, 8=18, 11=22, 12=23, 13=24, 14=28, 16=25, 17=26, 18=28, 21=31, 22=32}",
lineMapping.toString());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册