This commit is contained in:
@@ -181,7 +181,7 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails,
|
||||
this.retType = mthInfo.getReturnType();
|
||||
this.argTypes = mthInfo.getArgumentsTypes();
|
||||
} else {
|
||||
this.argTypes = types;
|
||||
this.argTypes = Collections.unmodifiableList(types);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,9 @@ public class TypeUtils {
|
||||
|
||||
@Nullable
|
||||
public ArgType replaceTypeVariablesUsingMap(ArgType replaceType, Map<ArgType, ArgType> replaceMap) {
|
||||
if (replaceMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (replaceType.isGenericType()) {
|
||||
return replaceMap.get(replaceType);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import jadx.core.dex.nodes.IMethodDetails;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.dex.visitors.methods.MutableMethodDetails;
|
||||
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
|
||||
import jadx.core.dex.visitors.typeinference.TypeCompare;
|
||||
import jadx.core.dex.visitors.typeinference.TypeCompareEnum;
|
||||
@@ -111,12 +112,19 @@ public class MethodInvokeVisitor extends AbstractVisitor {
|
||||
return;
|
||||
}
|
||||
|
||||
overloadMethods.add(mthDetails);
|
||||
resolveTypeVariablesInMethodArgs(invokeInsn, mthDetails, overloadMethods);
|
||||
// resolve generic type variables
|
||||
Map<ArgType, ArgType> typeVarsMapping = getTypeVarsMapping(invokeInsn);
|
||||
IMethodDetails effectiveMthDetails = resolveTypeVars(mthDetails, typeVarsMapping);
|
||||
List<IMethodDetails> effectiveOverloadMethods = new ArrayList<>(overloadMethods.size() + 1);
|
||||
for (IMethodDetails overloadMethod : overloadMethods) {
|
||||
effectiveOverloadMethods.add(resolveTypeVars(overloadMethod, typeVarsMapping));
|
||||
}
|
||||
effectiveOverloadMethods.add(effectiveMthDetails);
|
||||
|
||||
// search cast types to resolve overloading
|
||||
int argsOffset = invokeInsn.getFirstArgOffset();
|
||||
List<ArgType> compilerVarTypes = collectCompilerVarTypes(invokeInsn, argsOffset);
|
||||
List<ArgType> castTypes = searchCastTypes(parentMth, mthDetails, overloadMethods, compilerVarTypes);
|
||||
List<ArgType> castTypes = searchCastTypes(parentMth, effectiveMthDetails, effectiveOverloadMethods, compilerVarTypes);
|
||||
applyArgsCast(invokeInsn, argsOffset, compilerVarTypes, castTypes);
|
||||
}
|
||||
|
||||
@@ -147,8 +155,7 @@ public class MethodInvokeVisitor extends AbstractVisitor {
|
||||
return callMth.getDeclClass().getType();
|
||||
}
|
||||
|
||||
private void resolveTypeVariablesInMethodArgs(BaseInvokeNode invokeInsn, IMethodDetails mthDetails,
|
||||
List<IMethodDetails> overloadedMethods) {
|
||||
private Map<ArgType, ArgType> getTypeVarsMapping(BaseInvokeNode invokeInsn) {
|
||||
MethodInfo callMth = invokeInsn.getCallMth();
|
||||
ArgType declClsType = callMth.getDeclClass().getType();
|
||||
ArgType callClsType;
|
||||
@@ -158,12 +165,7 @@ public class MethodInvokeVisitor extends AbstractVisitor {
|
||||
} else {
|
||||
callClsType = declClsType;
|
||||
}
|
||||
|
||||
Map<ArgType, ArgType> typeVarsMapping = root.getTypeUtils().getTypeVariablesMapping(callClsType);
|
||||
resolveTypeVars(mthDetails, typeVarsMapping);
|
||||
for (IMethodDetails m : overloadedMethods) {
|
||||
resolveTypeVars(m, typeVarsMapping);
|
||||
}
|
||||
return root.getTypeUtils().getTypeVariablesMapping(callClsType);
|
||||
}
|
||||
|
||||
private void applyArgsCast(BaseInvokeNode invokeInsn, int argsOffset, List<ArgType> compilerVarTypes, List<ArgType> castTypes) {
|
||||
@@ -199,9 +201,11 @@ public class MethodInvokeVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveTypeVars(IMethodDetails mthDetails, Map<ArgType, ArgType> typeVarsMapping) {
|
||||
private IMethodDetails resolveTypeVars(IMethodDetails mthDetails, Map<ArgType, ArgType> typeVarsMapping) {
|
||||
List<ArgType> argTypes = mthDetails.getArgTypes();
|
||||
int argsCount = argTypes.size();
|
||||
boolean fixed = false;
|
||||
List<ArgType> fixedArgTypes = new ArrayList<>(argsCount);
|
||||
for (int argNum = 0; argNum < argsCount; argNum++) {
|
||||
ArgType argType = argTypes.get(argNum);
|
||||
if (argType == null) {
|
||||
@@ -213,9 +217,28 @@ public class MethodInvokeVisitor extends AbstractVisitor {
|
||||
// type variables erased from method info by compiler
|
||||
resolvedType = mthDetails.getMethodInfo().getArgumentsTypes().get(argNum);
|
||||
}
|
||||
argTypes.set(argNum, resolvedType);
|
||||
fixedArgTypes.add(resolvedType);
|
||||
fixed = true;
|
||||
} else {
|
||||
fixedArgTypes.add(argType);
|
||||
}
|
||||
}
|
||||
ArgType returnType = mthDetails.getReturnType();
|
||||
if (returnType.containsTypeVariable()) {
|
||||
ArgType resolvedType = root.getTypeUtils().replaceTypeVariablesUsingMap(returnType, typeVarsMapping);
|
||||
if (resolvedType == null || resolvedType.containsTypeVariable()) {
|
||||
returnType = mthDetails.getMethodInfo().getReturnType();
|
||||
fixed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fixed) {
|
||||
return mthDetails;
|
||||
}
|
||||
MutableMethodDetails mutableMethodDetails = new MutableMethodDetails(mthDetails);
|
||||
mutableMethodDetails.setArgTypes(fixedArgTypes);
|
||||
mutableMethodDetails.setRetType(returnType);
|
||||
return mutableMethodDetails;
|
||||
}
|
||||
|
||||
private List<ArgType> searchCastTypes(MethodNode parentMth, IMethodDetails mthDetails, List<IMethodDetails> overloadedMethods,
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package jadx.core.dex.visitors.methods;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import jadx.core.dex.info.MethodInfo;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.nodes.GenericTypeParameter;
|
||||
import jadx.core.dex.nodes.IMethodDetails;
|
||||
|
||||
public class MutableMethodDetails implements IMethodDetails {
|
||||
|
||||
private final MethodInfo mthInfo;
|
||||
private ArgType retType;
|
||||
private List<ArgType> argTypes;
|
||||
private List<GenericTypeParameter> typeParams;
|
||||
private List<ArgType> throwTypes;
|
||||
private boolean varArg;
|
||||
|
||||
public MutableMethodDetails(IMethodDetails base) {
|
||||
this.mthInfo = base.getMethodInfo();
|
||||
this.retType = base.getReturnType();
|
||||
this.argTypes = Collections.unmodifiableList(base.getArgTypes());
|
||||
this.typeParams = Collections.unmodifiableList(base.getTypeParameters());
|
||||
this.throwTypes = Collections.unmodifiableList(base.getThrows());
|
||||
this.varArg = base.isVarArg();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodInfo getMethodInfo() {
|
||||
return mthInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArgType getReturnType() {
|
||||
return retType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArgType> getArgTypes() {
|
||||
return argTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GenericTypeParameter> getTypeParameters() {
|
||||
return typeParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArgType> getThrows() {
|
||||
return throwTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVarArg() {
|
||||
return varArg;
|
||||
}
|
||||
|
||||
public void setRetType(ArgType retType) {
|
||||
this.retType = retType;
|
||||
}
|
||||
|
||||
public void setArgTypes(List<ArgType> argTypes) {
|
||||
this.argTypes = argTypes;
|
||||
}
|
||||
|
||||
public void setTypeParams(List<GenericTypeParameter> typeParams) {
|
||||
this.typeParams = typeParams;
|
||||
}
|
||||
|
||||
public void setThrowTypes(List<ArgType> throwTypes) {
|
||||
this.throwTypes = throwTypes;
|
||||
}
|
||||
|
||||
public void setVarArg(boolean varArg) {
|
||||
this.varArg = varArg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Mutable" + toAttrString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user