use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class ShadowFieldVisitor method collectAllInstanceFields.
private static List<FieldNode> collectAllInstanceFields(ClassNode cls) {
List<FieldNode> fieldsList = new ArrayList<>();
ClassNode currentClass = cls;
while (currentClass != null) {
for (FieldNode field : currentClass.getFields()) {
if (!field.getAccessFlags().isStatic()) {
fieldsList.add(field);
}
}
ArgType superClass = currentClass.getSuperClass();
if (superClass == null) {
break;
}
currentClass = cls.root().resolveClass(superClass);
}
return fieldsList;
}
use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class ShadowFieldVisitor method searchShadowedFields.
private static Map<FieldInfo, FieldFixType> searchShadowedFields(ClassNode thisCls) {
List<FieldNode> allFields = collectAllInstanceFields(thisCls);
if (allFields.isEmpty()) {
return Collections.emptyMap();
}
Map<String, List<FieldNode>> mapByName = groupByName(allFields);
mapByName.entrySet().removeIf(entry -> entry.getValue().size() == 1);
if (mapByName.isEmpty()) {
return Collections.emptyMap();
}
Map<FieldInfo, FieldFixType> fixMap = new HashMap<>();
for (List<FieldNode> fields : mapByName.values()) {
boolean fromThisCls = fields.get(0).getParentClass() == thisCls;
if (fromThisCls && fields.size() == 2) {
// only one super class contains same field => can use super
FieldNode otherField = fields.get(1);
if (otherField.getParentClass() != thisCls) {
fixMap.put(otherField.getFieldInfo(), FieldFixType.SUPER);
}
} else {
// several super classes contains same field => can't use super, need cast to exact class
for (FieldNode field : fields) {
if (field.getParentClass() != thisCls) {
fixMap.put(field.getFieldInfo(), FieldFixType.CAST);
}
}
}
}
return fixMap;
}
use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class ReSugarCode method processEnumSwitch.
private static boolean processEnumSwitch(MethodNode mth, SwitchInsn insn) {
InsnArg arg = insn.getArg(0);
if (!arg.isInsnWrap()) {
return false;
}
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
if (wrapInsn.getType() != InsnType.AGET) {
return false;
}
EnumMapInfo enumMapInfo = checkEnumMapAccess(mth.root(), wrapInsn);
if (enumMapInfo == null) {
return false;
}
FieldNode enumMapField = enumMapInfo.getMapField();
InsnArg invArg = enumMapInfo.getArg();
EnumMapAttr.KeyValueMap valueMap = getEnumMap(mth, enumMapField);
if (valueMap == null) {
return false;
}
int caseCount = insn.getKeys().length;
for (int i = 0; i < caseCount; i++) {
Object key = insn.getKey(i);
Object newKey = valueMap.get(key);
if (newKey == null) {
return false;
}
}
// replace confirmed
if (!insn.replaceArg(arg, invArg)) {
return false;
}
for (int i = 0; i < caseCount; i++) {
insn.modifyKey(i, valueMap.get(insn.getKey(i)));
}
enumMapField.add(AFlag.DONT_GENERATE);
checkAndHideClass(enumMapField.getParentClass());
return true;
}
use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class ProcessAnonymous method checkUsage.
/**
* Checks:
* - class have only one constructor which used only once (allow common code for field init)
* - methods or fields not used outside (allow only nested inner classes with synthetic usage)
*
* @return anonymous constructor method
*/
private static MethodNode checkUsage(ClassNode cls) {
MethodNode ctr = ListUtils.filterOnlyOne(cls.getMethods(), MethodNode::isConstructor);
if (ctr == null) {
return null;
}
if (ctr.getUseIn().size() != 1) {
// check if used in common field init in all constructors
if (!checkForCommonFieldInit(ctr)) {
return null;
}
}
MethodNode ctrUseMth = ctr.getUseIn().get(0);
ClassNode ctrUseCls = ctrUseMth.getParentClass();
if (ctrUseCls.equals(cls)) {
// exclude self usage
return null;
}
for (MethodNode mth : cls.getMethods()) {
if (mth == ctr) {
continue;
}
for (MethodNode useMth : mth.getUseIn()) {
if (useMth.equals(ctrUseMth)) {
continue;
}
if (badMethodUsage(cls, useMth, mth.getAccessFlags())) {
return null;
}
}
}
for (FieldNode field : cls.getFields()) {
for (MethodNode useMth : field.getUseIn()) {
if (badMethodUsage(cls, useMth, field.getAccessFlags())) {
return null;
}
}
}
return ctr;
}
use of jadx.core.dex.nodes.FieldNode in project jadx by skylot.
the class ConstInlineVisitor method replaceArg.
private static boolean replaceArg(MethodNode mth, RegisterArg arg, InsnArg constArg, InsnNode constInsn) {
InsnNode useInsn = arg.getParentInsn();
if (useInsn == null) {
return false;
}
InsnType insnType = useInsn.getType();
if (insnType == InsnType.PHI) {
return false;
}
if (constArg.isLiteral()) {
long literal = ((LiteralArg) constArg).getLiteral();
ArgType argType = arg.getType();
if (argType == ArgType.UNKNOWN) {
argType = arg.getInitType();
}
if (argType.isObject() && literal != 0) {
argType = ArgType.NARROW_NUMBERS;
}
LiteralArg litArg = InsnArg.lit(literal, argType);
litArg.copyAttributesFrom(constArg);
if (!useInsn.replaceArg(arg, litArg)) {
return false;
}
// arg replaced, made some optimizations
FieldNode fieldNode = null;
ArgType litArgType = litArg.getType();
if (litArgType.isTypeKnown()) {
fieldNode = mth.getParentClass().getConstFieldByLiteralArg(litArg);
} else if (litArgType.contains(PrimitiveType.INT)) {
fieldNode = mth.getParentClass().getConstField((int) literal, false);
}
if (fieldNode != null) {
IndexInsnNode sgetInsn = new IndexInsnNode(InsnType.SGET, fieldNode.getFieldInfo(), 0);
if (litArg.wrapInstruction(mth, sgetInsn) != null) {
fieldNode.addUseIn(mth);
}
} else {
if (needExplicitCast(useInsn, litArg)) {
litArg.add(AFlag.EXPLICIT_PRIMITIVE_TYPE);
}
}
} else {
if (!useInsn.replaceArg(arg, constArg.duplicate())) {
return false;
}
}
useInsn.inheritMetadata(constInsn);
return true;
}
Aggregations