package app.revanced.extensions import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.MethodFingerprintExtensions.name import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import org.jf.dexlib2.iface.Method import org.jf.dexlib2.util.MethodUtil import org.w3c.dom.Node // TODO: populate this to all patches /** * Convert a [MethodFingerprint] to a [PatchResultError]. * * @return A [PatchResultError] for the [MethodFingerprint]. */ fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name") /** * Find the [MutableMethod] from a given [Method] in a [MutableClass]. * * @param method The [Method] to find. * @return The [MutableMethod]. */ fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first { MethodUtil.methodSignaturesMatch(it, method) } /** * traverse the class hierarchy starting from the given root class * * @param targetClass the class to start traversing the class hierarchy from * @param callback function that is called for every class in the hierarchy */ fun BytecodeContext.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) { callback(targetClass) this.findClass(targetClass.superclass ?: return)?.mutableClass?.let { traverseClassHierarchy(it, callback) } } /** * apply a transform to all methods of the class * * @param transform the transformation function. original method goes in, transformed method goes out */ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) { val transformedMethods = methods.map { it.transform() } methods.clear() methods.addAll(transformedMethods) } internal fun Node.doRecursively(action: (Node) -> Unit) { action(this) for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action) }