fix: restore fields order if init use other fields (#1235)
This commit is contained in:
@@ -2,8 +2,10 @@ package jadx.core.dex.visitors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -269,9 +271,70 @@ public class ExtractFieldInit extends AbstractVisitor {
|
||||
return Objects.equals(exclude, Boolean.TRUE);
|
||||
}
|
||||
|
||||
private static void fixFieldsOrder(ClassNode cls, List<FieldInitInfo> fieldsInit) {
|
||||
private static void fixFieldsOrder(ClassNode cls, List<FieldInitInfo> inits) {
|
||||
List<FieldNode> orderedFields = processFieldsDependencies(cls, inits);
|
||||
applyFieldsOrder(cls, orderedFields);
|
||||
}
|
||||
|
||||
private static List<FieldNode> processFieldsDependencies(ClassNode cls, List<FieldInitInfo> inits) {
|
||||
List<FieldNode> orderedFields = Utils.collectionMap(inits, v -> v.fieldNode);
|
||||
// collect dependant fields
|
||||
Map<FieldNode, List<FieldNode>> deps = new HashMap<>(inits.size());
|
||||
for (FieldInitInfo initInfo : inits) {
|
||||
IndexInsnNode insn = initInfo.putInsn;
|
||||
boolean staticField = insn.getType() == InsnType.SPUT;
|
||||
InsnType useType = staticField ? InsnType.SGET : InsnType.IGET;
|
||||
insn.visitInsns(subInsn -> {
|
||||
if (subInsn.getType() == useType) {
|
||||
FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) subInsn).getIndex();
|
||||
if (fieldInfo.getDeclClass().equals(cls.getClassInfo())) {
|
||||
FieldNode depField = cls.searchField(fieldInfo);
|
||||
if (depField != null) {
|
||||
deps.computeIfAbsent(initInfo.fieldNode, k -> new ArrayList<>())
|
||||
.add(depField);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (deps.isEmpty()) {
|
||||
return orderedFields;
|
||||
}
|
||||
// build new list with deps fields before usage field
|
||||
List<FieldNode> result = new ArrayList<>();
|
||||
for (FieldNode field : orderedFields) {
|
||||
int idx = result.indexOf(field);
|
||||
List<FieldNode> fieldDeps = deps.get(field);
|
||||
if (fieldDeps == null) {
|
||||
if (idx == -1) {
|
||||
result.add(field);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (idx == -1) {
|
||||
for (FieldNode depField : fieldDeps) {
|
||||
if (!result.contains(depField)) {
|
||||
result.add(depField);
|
||||
}
|
||||
}
|
||||
result.add(field);
|
||||
continue;
|
||||
}
|
||||
for (FieldNode depField : fieldDeps) {
|
||||
int depIdx = result.indexOf(depField);
|
||||
if (depIdx == -1) {
|
||||
result.add(idx, depField);
|
||||
} else if (depIdx > idx) {
|
||||
result.remove(depIdx);
|
||||
result.add(idx, depField);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void applyFieldsOrder(ClassNode cls, List<FieldNode> orderedFields) {
|
||||
List<FieldNode> clsFields = cls.getFields();
|
||||
List<FieldNode> orderedFields = Utils.collectionMap(fieldsInit, v -> v.fieldNode);
|
||||
// check if already ordered
|
||||
boolean ordered = Collections.indexOfSubList(clsFields, orderedFields) != -1;
|
||||
if (!ordered) {
|
||||
|
||||
Reference in New Issue
Block a user