mirror of
https://github.com/revanced/smali.git
synced 2025-05-14 21:27:06 +02:00
Unified interface table creation logic. No more duplication.
This commit is contained in:
parent
389c3a6afa
commit
e3b5efd7d8
@ -34,7 +34,6 @@ package org.jf.dexlib2.analysis;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import org.jf.dexlib2.AccessFlags;
|
import org.jf.dexlib2.AccessFlags;
|
||||||
import org.jf.dexlib2.analysis.util.TypeProtoUtils;
|
import org.jf.dexlib2.analysis.util.TypeProtoUtils;
|
||||||
import org.jf.dexlib2.iface.ClassDef;
|
import org.jf.dexlib2.iface.ClassDef;
|
||||||
@ -43,7 +42,6 @@ import org.jf.dexlib2.iface.Method;
|
|||||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||||
import org.jf.dexlib2.util.FieldUtil;
|
import org.jf.dexlib2.util.FieldUtil;
|
||||||
import org.jf.dexlib2.util.MethodUtil;
|
|
||||||
import org.jf.util.ExceptionWithContext;
|
import org.jf.util.ExceptionWithContext;
|
||||||
import org.jf.util.SparseArray;
|
import org.jf.util.SparseArray;
|
||||||
|
|
||||||
@ -59,8 +57,7 @@ public class ClassProto implements TypeProto {
|
|||||||
@Nonnull protected final ClassPath classPath;
|
@Nonnull protected final ClassPath classPath;
|
||||||
@Nonnull protected final String type;
|
@Nonnull protected final String type;
|
||||||
@Nullable protected ClassDef classDef;
|
@Nullable protected ClassDef classDef;
|
||||||
@Nullable protected Set<String> interfaces;
|
@Nullable protected LinkedHashMap<String, ClassDef> interfaces;
|
||||||
@Nullable protected LinkedHashMap<String, ClassDef> interfaceTable;
|
|
||||||
@Nullable protected Method[] vtable;
|
@Nullable protected Method[] vtable;
|
||||||
@Nullable protected SparseArray<FieldReference> instanceFields;
|
@Nullable protected SparseArray<FieldReference> instanceFields;
|
||||||
protected boolean interfacesFullyResolved = true;
|
protected boolean interfacesFullyResolved = true;
|
||||||
@ -99,13 +96,6 @@ public class ClassProto implements TypeProto {
|
|||||||
return instanceFields;
|
return instanceFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedHashMap<String, ClassDef> getInterfaceTable() {
|
|
||||||
if (interfaceTable == null) {
|
|
||||||
interfaceTable = loadInterfaceTable();
|
|
||||||
}
|
|
||||||
return interfaceTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this class is an interface.
|
* Returns true if this class is an interface.
|
||||||
*
|
*
|
||||||
@ -118,47 +108,31 @@ public class ClassProto implements TypeProto {
|
|||||||
return (classDef.getAccessFlags() & AccessFlags.INTERFACE.getValue()) != 0;
|
return (classDef.getAccessFlags() & AccessFlags.INTERFACE.getValue()) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addInterfacesRecursively(@Nonnull ClassDef classDef) {
|
|
||||||
assert interfaces != null;
|
|
||||||
for (String iface: classDef.getInterfaces()) {
|
|
||||||
interfaces.add(iface);
|
|
||||||
addInterfacesRecursively(iface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addInterfacesRecursively(@Nonnull String cls) {
|
|
||||||
ClassDef classDef;
|
|
||||||
try {
|
|
||||||
classDef = classPath.getClassDef(cls);
|
|
||||||
addInterfacesRecursively(classDef);
|
|
||||||
} catch (UnresolvedClassException ex) {
|
|
||||||
interfacesFullyResolved = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
protected Set<String> getInterfaces() {
|
protected LinkedHashMap<String, ClassDef> getInterfaces() {
|
||||||
if (interfaces != null) {
|
if (interfaces != null) {
|
||||||
return interfaces;
|
return interfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
interfaces = Sets.newHashSet();
|
interfaces = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ClassDef classDef = getClassDef();
|
for (String interfaceType: getClassDef().getInterfaces()) {
|
||||||
|
if (!interfaces.containsKey(interfaceType)) {
|
||||||
|
ClassDef interfaceDef;
|
||||||
|
try {
|
||||||
|
interfaceDef = classPath.getClassDef(interfaceType);
|
||||||
|
interfaces.put(interfaceType, interfaceDef);
|
||||||
|
} catch (UnresolvedClassException ex) {
|
||||||
|
interfacesFullyResolved = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (isInterface()) {
|
ClassProto interfaceProto = (ClassProto) classPath.getClass(interfaceType);
|
||||||
interfaces.add(getType());
|
for (ClassDef superInterface: interfaceProto.getInterfaces().values()) {
|
||||||
}
|
if (!interfaces.containsKey(superInterface.getType())) {
|
||||||
|
interfaces.put(superInterface.getType(), superInterface);
|
||||||
while (true) {
|
}
|
||||||
addInterfacesRecursively(classDef);
|
}
|
||||||
|
|
||||||
String superclass = classDef.getSuperclass();
|
|
||||||
if (superclass != null) {
|
|
||||||
classDef = classPath.getClassDef(superclass);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (UnresolvedClassException ex) {
|
} catch (UnresolvedClassException ex) {
|
||||||
@ -179,10 +153,8 @@ public class ClassProto implements TypeProto {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean implementsInterface(@Nonnull String iface) {
|
public boolean implementsInterface(@Nonnull String iface) {
|
||||||
for (String implementIface: getInterfaces()) {
|
if (getInterfaces().containsKey(iface)) {
|
||||||
if (implementIface.equals(iface)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!interfacesFullyResolved) {
|
if (!interfacesFullyResolved) {
|
||||||
throw new UnresolvedClassException("Interfaces for class %s not fully resolved", getType());
|
throw new UnresolvedClassException("Interfaces for class %s not fully resolved", getType());
|
||||||
@ -541,11 +513,8 @@ public class ClassProto implements TypeProto {
|
|||||||
if (!isInterface()) {
|
if (!isInterface()) {
|
||||||
addToVtable(getClassDef().getVirtualMethods(), virtualMethodList);
|
addToVtable(getClassDef().getVirtualMethods(), virtualMethodList);
|
||||||
|
|
||||||
LinkedHashMap<String, ClassDef> interfaceTable = loadInterfaceTable();
|
for (ClassDef interfaceDef: getInterfaces().values()) {
|
||||||
if (interfaceTable != null) {
|
addToVtable(interfaceDef.getVirtualMethods(), virtualMethodList);
|
||||||
for (ClassDef interfaceDef: interfaceTable.values()) {
|
|
||||||
addToVtable(interfaceDef.getVirtualMethods(), virtualMethodList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,32 +526,6 @@ public class ClassProto implements TypeProto {
|
|||||||
return vtable;
|
return vtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkedHashMap<String, ClassDef> loadInterfaceTable() {
|
|
||||||
LinkedHashMap<String, ClassDef> interfaceTable = Maps.newLinkedHashMap();
|
|
||||||
|
|
||||||
for (String interfaceType: getClassDef().getInterfaces()) {
|
|
||||||
if (!interfaceTable.containsKey(interfaceType)) {
|
|
||||||
ClassDef interfaceDef;
|
|
||||||
try {
|
|
||||||
interfaceDef = classPath.getClassDef(interfaceType);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw ExceptionWithContext.withContext(ex,
|
|
||||||
String.format("Could not find interface %s", interfaceType));
|
|
||||||
}
|
|
||||||
interfaceTable.put(interfaceType, interfaceDef);
|
|
||||||
|
|
||||||
ClassProto interfaceProto = (ClassProto) classPath.getClass(interfaceType);
|
|
||||||
for (ClassDef superInterface: interfaceProto.getInterfaceTable().values()) {
|
|
||||||
if (!interfaceTable.containsKey(superInterface.getType())) {
|
|
||||||
interfaceTable.put(superInterface.getType(), superInterface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return interfaceTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addToVtable(Iterable<? extends Method> localMethods, List<Method> vtable) {
|
private void addToVtable(Iterable<? extends Method> localMethods, List<Method> vtable) {
|
||||||
for (Method virtualMethod: localMethods) {
|
for (Method virtualMethod: localMethods) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user