use of jadx.core.dex.nodes.IMethodDetails in project jadx by skylot.
the class OverrideMethodVisitor method processOverrideMethods.
private MethodOverrideAttr processOverrideMethods(MethodNode mth, SuperTypesData superData) {
MethodOverrideAttr result = mth.get(AType.METHOD_OVERRIDE);
if (result != null) {
return result;
}
ClassNode cls = mth.getParentClass();
String signature = mth.getMethodInfo().makeSignature(false);
List<IMethodDetails> overrideList = new ArrayList<>();
Set<IMethodDetails> baseMethods = new HashSet<>();
for (ArgType superType : superData.getSuperTypes()) {
ClassNode classNode = mth.root().resolveClass(superType);
if (classNode != null) {
MethodNode ovrdMth = searchOverriddenMethod(classNode, signature);
if (ovrdMth != null) {
if (isMethodVisibleInCls(ovrdMth, cls)) {
overrideList.add(ovrdMth);
MethodOverrideAttr attr = ovrdMth.get(AType.METHOD_OVERRIDE);
if (attr != null) {
addBaseMethod(superData, overrideList, baseMethods, superType);
return buildOverrideAttr(mth, overrideList, baseMethods, attr);
}
}
}
} else {
ClspClass clsDetails = mth.root().getClsp().getClsDetails(superType);
if (clsDetails != null) {
Map<String, ClspMethod> methodsMap = clsDetails.getMethodsMap();
for (Map.Entry<String, ClspMethod> entry : methodsMap.entrySet()) {
String mthShortId = entry.getKey();
if (mthShortId.startsWith(signature)) {
overrideList.add(entry.getValue());
break;
}
}
}
}
addBaseMethod(superData, overrideList, baseMethods, superType);
}
return buildOverrideAttr(mth, overrideList, baseMethods, null);
}
use of jadx.core.dex.nodes.IMethodDetails in project jadx by skylot.
the class TypeBoundInvokeAssign method getReturnType.
private ArgType getReturnType(ArgType instanceType) {
ArgType mthDeclType;
IMethodDetails methodDetails = root.getMethodUtils().getMethodDetails(invokeNode);
if (methodDetails != null) {
// use methods detail to resolve declaration class for virtual invokes
mthDeclType = methodDetails.getMethodInfo().getDeclClass().getType();
} else {
mthDeclType = instanceType;
}
ArgType resultGeneric = root.getTypeUtils().replaceClassGenerics(instanceType, mthDeclType, genericReturnType);
if (resultGeneric != null && !resultGeneric.isWildcard()) {
return resultGeneric;
}
return invokeNode.getCallMth().getReturnType();
}
use of jadx.core.dex.nodes.IMethodDetails in project jadx by skylot.
the class TypeUpdate method invokeListener.
private TypeUpdateResult invokeListener(TypeUpdateInfo updateInfo, InsnNode insn, InsnArg arg, ArgType candidateType) {
BaseInvokeNode invoke = (BaseInvokeNode) insn;
if (isAssign(invoke, arg)) {
// TODO: implement backward type propagation (from result to instance)
return SAME;
}
if (invoke.getInstanceArg() == arg) {
IMethodDetails methodDetails = root.getMethodUtils().getMethodDetails(invoke);
if (methodDetails == null) {
return SAME;
}
TypeUtils typeUtils = root.getTypeUtils();
Set<ArgType> knownTypeVars = typeUtils.getKnownTypeVarsAtMethod(updateInfo.getMth());
Map<ArgType, ArgType> typeVarsMap = typeUtils.getTypeVariablesMapping(candidateType);
ArgType returnType = methodDetails.getReturnType();
List<ArgType> argTypes = methodDetails.getArgTypes();
int argsCount = argTypes.size();
if (typeVarsMap.isEmpty()) {
// generics can't be resolved => use as is
return applyInvokeTypes(updateInfo, invoke, argsCount, knownTypeVars, () -> returnType, argTypes::get);
}
// resolve types before apply
return applyInvokeTypes(updateInfo, invoke, argsCount, knownTypeVars, () -> typeUtils.replaceTypeVariablesUsingMap(returnType, typeVarsMap), argNum -> typeUtils.replaceClassGenerics(candidateType, argTypes.get(argNum)));
}
return SAME;
}
use of jadx.core.dex.nodes.IMethodDetails in project jadx by skylot.
the class MethodUtils method getMethodOriginDeclClass.
public ClassInfo getMethodOriginDeclClass(MethodNode mth) {
IMethodDetails baseMth = getOverrideBaseMth(mth);
if (baseMth != null) {
return baseMth.getMethodInfo().getDeclClass();
}
MethodBridgeAttr bridgeAttr = mth.get(AType.BRIDGED_BY);
if (bridgeAttr != null) {
return getMethodOriginDeclClass(bridgeAttr.getBridgeMth());
}
return mth.getMethodInfo().getDeclClass();
}
use of jadx.core.dex.nodes.IMethodDetails in project jadx by skylot.
the class InlineMethods method inlineMethod.
private void inlineMethod(MethodNode mth, MethodNode callMth, MethodInlineAttr mia, BlockNode block, InvokeNode insn) {
InsnNode inlCopy = mia.getInsn().copyWithoutResult();
RegisterArg resultArg = insn.getResult();
if (resultArg != null) {
inlCopy.setResult(resultArg.duplicate());
} else if (isAssignNeeded(mia.getInsn(), insn, callMth)) {
// add fake result to make correct java expression (see test TestGetterInlineNegative)
inlCopy.setResult(makeFakeArg(mth, callMth.getReturnType(), "unused"));
}
if (!callMth.getMethodInfo().getArgumentsTypes().isEmpty()) {
// remap args
InsnArg[] regs = new InsnArg[callMth.getRegsCount()];
int[] regNums = mia.getArgsRegNums();
for (int i = 0; i < regNums.length; i++) {
InsnArg arg = insn.getArg(i);
regs[regNums[i]] = arg;
}
// replace args
List<RegisterArg> inlArgs = new ArrayList<>();
inlCopy.getRegisterArgs(inlArgs);
for (RegisterArg r : inlArgs) {
int regNum = r.getRegNum();
if (regNum >= regs.length) {
LOG.warn("Unknown register number {} in method call: {} from {}", r, callMth, mth);
} else {
InsnArg repl = regs[regNum];
if (repl == null) {
LOG.warn("Not passed register {} in method call: {} from {}", r, callMth, mth);
} else {
inlCopy.replaceArg(r, repl);
}
}
}
}
IMethodDetails methodDetailsAttr = inlCopy.get(AType.METHOD_DETAILS);
if (!BlockUtils.replaceInsn(mth, block, insn, inlCopy)) {
mth.addWarnComment("Failed to inline method: " + callMth);
}
// replaceInsn replaces the attributes as well, make sure to preserve METHOD_DETAILS
if (methodDetailsAttr != null) {
inlCopy.addAttr(methodDetailsAttr);
}
updateUsageInfo(mth, callMth, mia.getInsn());
}
Aggregations