diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt index c4289b6c..c7fe7be0 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt @@ -65,19 +65,6 @@ class ConstructorFinder( /** [ModifierRules] 实例 */ private var modifiers: ModifierRules? = null - /** - * [Constructor] 在当前类中的位置 - * - * - 设置后将筛选 [Class.getDeclaredConstructors] 的数组下标 - * - * - ❗受到字节码顺序影响 - 请勿完全依赖于此功能 - * - * 若 index 小于零则忽略此条件 (等于 -2 为取最后一个) - * - * 可使用 [firstIndex] 和 [lastIndex] 设置首位和末位筛选条件 - */ - var index = -1 - /** * [Constructor] 参数个数 * @@ -87,24 +74,16 @@ class ConstructorFinder( */ var paramCount = -1 - /** 设置 [Constructor] 在当前类中的位置为首位 */ - fun firstIndex() { - index = 0 - } - - /** 设置 [Constructor] 在当前类中的位置为末位 */ - fun lastIndex() { - index = -2 - } - /** * [Constructor] 筛选条件 * - * 可不设置筛选条件 - 默认模糊查找并取第一个匹配的 [Constructor] + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * @param initiate 方法体 + * @return [BaseFinder.IndexTypeCondition] */ - fun modifiers(initiate: ModifierRules.() -> Unit) { + fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition { modifiers = ModifierRules().apply(initiate) + return IndexTypeCondition(IndexConfigType.MATCH) } /** @@ -115,11 +94,37 @@ class ConstructorFinder( * - ❗无参 [Constructor] 不要使用此方法 * * - ❗有参 [Constructor] 必须使用此方法设定参数或使用 [paramCount] 指定个数 + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * @param paramType 参数类型数组 + * @return [BaseFinder.IndexTypeCondition] */ - fun param(vararg paramType: Class<*>) { + fun param(vararg paramType: Class<*>): IndexTypeCondition { if (paramType.isEmpty()) error("paramTypes is empty, please delete param() method") paramTypes = paramType + return IndexTypeCondition(IndexConfigType.MATCH) + } + + /** + * 顺序筛选字节码的下标 + * @return [BaseFinder.IndexTypeCondition] + */ + fun order() = IndexTypeCondition(IndexConfigType.ORDER) + + /** + * [Constructor] 参数个数 + * + * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数 + * + * 若参数个数小于零则忽略并使用 [param] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 + * @param num 个数 + * @return [BaseFinder.IndexTypeCondition] + */ + fun paramCount(num: Int): IndexTypeCondition { + paramCount = num + return IndexTypeCondition(IndexConfigType.MATCH) } /** @@ -127,7 +132,7 @@ class ConstructorFinder( * @return [Constructor] * @throws NoSuchMethodError 如果找不到构造方法 */ - private val result get() = ReflectionTool.findConstructor(classSet, index, modifiers, paramCount, paramTypes) + private val result get() = ReflectionTool.findConstructor(classSet, orderIndex, matchIndex, modifiers, paramCount, paramTypes) /** * 设置实例 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt index e8d669fa..2d4f5eee 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt @@ -53,21 +53,6 @@ class FieldFinder( /** [ModifierRules] 实例 */ private var modifiers: ModifierRules? = null - /** - * [Field] 在当前类中的位置 - * - * - 设置后将筛选 [Class.getDeclaredFields] 的数组下标 - * - * - ❗若你同时设置了 [type] 将仅过滤类型为 [type] 的数组下标 - * - * - ❗受到字节码顺序影响 - 请勿完全依赖于此功能 - * - * 若 index 小于零则忽略此条件 (等于 -2 为取最后一个) - * - * 可使用 [firstIndex] 和 [lastIndex] 设置首位和末位筛选条件 - */ - var index = -1 - /** * [Field] 名称 * @@ -83,39 +68,51 @@ class FieldFinder( var type: Class<*>? = null /** - * 设置 [Field] 在当前类中的位置为首位 - * - * - ❗若你同时设置了 [type] 将仅过滤类型为 [type] 的数组下标 + * 顺序筛选字节码的下标 + * @return [BaseFinder.IndexTypeCondition] */ - fun firstIndex() { - index = 0 + fun order() = IndexTypeCondition(IndexConfigType.ORDER) + + /** + * [Field] 名称 + * + * - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Field] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 + * @param value 名称 + * @return [BaseFinder.IndexTypeCondition] + */ + fun name(value: String): IndexTypeCondition { + name = value + return IndexTypeCondition(IndexConfigType.MATCH) } /** - * 设置 [Field] 在当前类中的位置为末位 + * [Field] 类型 * - * - ❗若你同时设置了 [type] 将仅过滤类型为 [type] 的数组下标 + * - 可不填写类型 - 默认模糊查找并取第一个匹配的 [Field] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 + * @param value 类型 + * @return [BaseFinder.IndexTypeCondition] */ - fun lastIndex() { - index = -2 - } - - fun name(value: String) { - - } - - fun type(value: Class<*>) { - + fun type(value: Class<*>): IndexTypeCondition { + type = value + return IndexTypeCondition(IndexConfigType.MATCH) } /** * [Field] 筛选条件 * * 可不设置筛选条件 - 默认模糊查找并取第一个匹配的 [Field] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * @param initiate 方法体 + * @return [BaseFinder.IndexTypeCondition] */ - fun modifiers(initiate: ModifierRules.() -> Unit) { + fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition { modifiers = ModifierRules().apply(initiate) + return IndexTypeCondition(IndexConfigType.MATCH) } /** @@ -130,7 +127,7 @@ class FieldFinder( override fun build(isBind: Boolean) = try { if (classSet != null) { runBlocking { - memberInstance = ReflectionTool.findField(classSet, index, name, modifiers, type) + memberInstance = ReflectionTool.findField(classSet, orderIndex, matchIndex, name, modifiers, type) }.result { onHookLogMsg(msg = "Find Field [${memberInstance}] takes ${it}ms [${hookTag}]") } Result() } else Result(isNoSuch = true, Throwable("classSet is null")) @@ -153,10 +150,6 @@ class FieldFinder( @DoNotUseMethod override fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable) - inner class IndexTypeCondition { - - } - /** * [Field] 查找结果实现类 * diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt index f557b930..00dd6267 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt @@ -65,19 +65,6 @@ class MethodFinder( /** [ModifierRules] 实例 */ private var modifiers: ModifierRules? = null - /** - * [Method] 在当前类中的位置 - * - * - 设置后将筛选 [Class.getDeclaredMethods] 的数组下标 - * - * - ❗受到字节码顺序影响 - 请勿完全依赖于此功能 - * - * 若 index 小于零则忽略此条件 (等于 -2 为取最后一个) - * - * 可使用 [firstIndex] 和 [lastIndex] 设置首位和末位筛选条件 - */ - var index = -1 - /** * [Method] 名称 * @@ -101,24 +88,18 @@ class MethodFinder( */ var returnType: Class<*>? = null - /** 设置 [Method] 在当前类中的位置为首位 */ - fun firstIndex() { - index = 0 - } - - /** 设置 [Method] 在当前类中的位置为末位 */ - fun lastIndex() { - index = -2 - } - /** * [Method] 筛选条件 * * 可不设置筛选条件 - 默认模糊查找并取第一个匹配的 [Method] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * @param initiate 方法体 + * @return [BaseFinder.IndexTypeCondition] */ - fun modifiers(initiate: ModifierRules.() -> Unit) { + fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition { modifiers = ModifierRules().apply(initiate) + return IndexTypeCondition(IndexConfigType.MATCH) } /** @@ -129,11 +110,65 @@ class MethodFinder( * - ❗无参 [Method] 不要使用此方法 * * - ❗有参 [Method] 必须使用此方法设定参数或使用 [paramCount] 指定个数 + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * @param paramType 参数类型数组 + * @return [BaseFinder.IndexTypeCondition] */ - fun param(vararg paramType: Class<*>) { + fun param(vararg paramType: Class<*>): IndexTypeCondition { if (paramType.isEmpty()) error("paramTypes is empty, please delete param() method") paramTypes = paramType + return IndexTypeCondition(IndexConfigType.MATCH) + } + + /** + * 顺序筛选字节码的下标 + * @return [BaseFinder.IndexTypeCondition] + */ + fun order() = IndexTypeCondition(IndexConfigType.ORDER) + + /** + * [Method] 名称 + * + * - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Method] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 + * @param value 名称 + * @return [BaseFinder.IndexTypeCondition] + */ + fun name(value: String): IndexTypeCondition { + name = value + return IndexTypeCondition(IndexConfigType.MATCH) + } + + /** + * [Method] 参数个数 + * + * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数 + * + * 若参数个数小于零则忽略并使用 [param] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 + * @param num 个数 + * @return [BaseFinder.IndexTypeCondition] + */ + fun paramCount(num: Int): IndexTypeCondition { + paramCount = num + return IndexTypeCondition(IndexConfigType.MATCH) + } + + /** + * [Method] 返回值 + * + * 可不填写返回值 - 默认模糊查找并取第一个匹配的 [Method] + * + * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 + * @param value 个数 + * @return [BaseFinder.IndexTypeCondition] + */ + fun returnType(value: Class<*>): IndexTypeCondition { + returnType = value + return IndexTypeCondition(IndexConfigType.MATCH) } /** @@ -141,7 +176,7 @@ class MethodFinder( * @return [Method] * @throws NoSuchMethodError 如果找不到方法 */ - private val result get() = ReflectionTool.findMethod(classSet, index, name, modifiers, returnType, paramCount, paramTypes) + private val result get() = ReflectionTool.findMethod(classSet, orderIndex, matchIndex, name, modifiers, returnType, paramCount, paramTypes) /** * 设置实例 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt index dcfad44e..2f9a222a 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt @@ -34,6 +34,7 @@ import com.highcapable.yukihookapi.hook.core.YukiHookCreater import com.highcapable.yukihookapi.hook.log.yLoggerE import com.highcapable.yukihookapi.hook.log.yLoggerI import java.lang.reflect.Member +import kotlin.math.abs /** * 这是查找类功能的基本类实现 @@ -47,6 +48,70 @@ abstract class BaseFinder( open val classSet: Class<*>? = null ) { + /** + * 字节码下标筛选数据类型 + */ + enum class IndexConfigType { ORDER, MATCH } + + /** 字节码顺序下标 */ + internal var orderIndex: Pair? = null + + /** 字节码筛选下标 */ + internal var matchIndex: Pair? = null + + /** + * 字节码下标筛选实现类 + * @param type 类型 + */ + inner class IndexTypeCondition(private val type: IndexConfigType) { + + /** + * 设置下标 + * + * 若 index 小于零则为倒序 - 此时可以使用 [IndexTypeConditionSort.reverse] 方法实现 + * + * 可使用 [IndexTypeConditionSort.first] 和 [IndexTypeConditionSort.last] 设置首位和末位筛选条件 + * @param num 下标 + */ + fun index(num: Int) = when (type) { + IndexConfigType.ORDER -> orderIndex = Pair(num, true) + IndexConfigType.MATCH -> matchIndex = Pair(num, true) + } + + /** + * 得到下标 + * @return [IndexTypeConditionSort] + */ + fun index() = IndexTypeConditionSort() + + /** + * 字节码下标排序实现类 + * + * - ❗请使用 [index] 方法来获取 [IndexTypeConditionSort] + */ + inner class IndexTypeConditionSort { + + /** 设置满足条件的第一个*/ + fun first() = index(num = 0) + + /** 设置满足条件的最后一个*/ + fun last() = when (type) { + IndexConfigType.ORDER -> orderIndex = Pair(0, false) + IndexConfigType.MATCH -> matchIndex = Pair(0, false) + } + + /** + * 设置倒序下标 + * @param num 下标 + */ + fun reverse(num: Int) = when { + num < 0 -> index(abs(num)) + num == 0 -> index().last() + else -> index(-num) + } + } + } + /** 是否开启忽略错误警告功能 */ internal var isShutErrorPrinting = false diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt index 45075368..c6aa7d21 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt @@ -35,7 +35,10 @@ import com.highcapable.yukihookapi.hook.core.finder.FieldFinder import com.highcapable.yukihookapi.hook.core.finder.MethodFinder import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.store.MemberCacheStore +import java.lang.reflect.Constructor +import java.lang.reflect.Field import java.lang.reflect.Member +import java.lang.reflect.Method /** * [Class] 转换为 [HookClass] @@ -131,4 +134,25 @@ fun Class<*>.method(initiate: MethodFinder.() -> Unit) = MethodFinder(classSet = * @param initiate 查找方法体 * @return [ConstructorFinder.Result] */ -fun Class<*>.constructor(initiate: ConstructorFinder.() -> Unit) = ConstructorFinder(classSet = this).apply(initiate).build() \ No newline at end of file +fun Class<*>.constructor(initiate: ConstructorFinder.() -> Unit) = ConstructorFinder(classSet = this).apply(initiate).build() + +/** + * 遍历当前类中的所有方法 + * @param callback 回调 - ([Int] 下标,[Method] 实例) + */ +fun Class<*>.allMethods(callback: (index: Int, method: Method) -> Unit) = + declaredMethods.forEachIndexed { p, it -> callback(p, it.apply { isAccessible = true }) } + +/** + * 遍历当前类中的所有构造方法 + * @param callback 回调 - ([Int] 下标,[Constructor] 实例) + */ +fun Class<*>.allConstructors(callback: (index: Int, constructor: Constructor<*>) -> Unit) = + declaredConstructors.forEachIndexed { p, it -> callback(p, it.apply { isAccessible = true }) } + +/** + * 遍历当前类中的所有变量 + * @param callback 回调 - ([Int] 下标,[Field] 实例) + */ +fun Class<*>.allFields(callback: (index: Int, field: Field) -> Unit) = + declaredFields.forEachIndexed { p, it -> callback(p, it.apply { isAccessible = true }) } \ No newline at end of file diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionTool.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionTool.kt index b2aa9c94..6e8aed56 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionTool.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionTool.kt @@ -33,6 +33,7 @@ import java.lang.reflect.Constructor import java.lang.reflect.Field import java.lang.reflect.Member import java.lang.reflect.Method +import kotlin.math.abs /** * 这是一个对 [Member] 查找的工具实现类 @@ -45,7 +46,8 @@ internal object ReflectionTool { /** * 查找任意变量 * @param classSet 变量所在类 - * @param index 下标 + * @param orderIndex 字节码顺序下标 + * @param matchIndex 字节码筛选下标 * @param name 变量名称 * @param modifiers 变量描述 * @param type 变量类型 @@ -53,19 +55,63 @@ internal object ReflectionTool { * @throws IllegalStateException 如果 [classSet] 为 null * @throws NoSuchFieldError 如果找不到变量 */ - internal fun findField(classSet: Class<*>?, index: Int, name: String, modifiers: ModifierRules?, type: Class<*>?): Field { - val hashCode = ("[$index][$name][$type][$modifiers][$classSet]").hashCode() + internal fun findField( + classSet: Class<*>?, + orderIndex: Pair?, + matchIndex: Pair?, + name: String, + modifiers: ModifierRules?, + type: Class<*>? + ): Field { + val hashCode = ("[$orderIndex][$matchIndex][$name][$type][$modifiers][$classSet]").hashCode() return MemberCacheStore.findField(hashCode) ?: let { var field: Field? = null + if (orderIndex == null && matchIndex != null && name.isBlank() && modifiers == null && type == null) + error("You must set a condition when finding a Field") classSet?.declaredFields?.apply { - filter { type == null || type == it.type }.takeIf { it.isNotEmpty() }?.forEachIndexed { p, it -> + var typeIndex = -1 + var nameIndex = -1 + var modifyIndex = -1 + val typeLastIndex = if (type != null && matchIndex != null) filter { type == it.type }.lastIndex else -1 + val nameLastIndex = if (name.isNotBlank() && matchIndex != null) filter { name == it.name }.lastIndex else -1 + val modifyLastIndex = if (modifiers != null && matchIndex != null) filter { modifiers.contains(it) }.lastIndex else -1 + forEachIndexed { p, it -> var isMatched = false var conditions = true - if (type != null) isMatched = true - if (name.isNotBlank()) conditions = (name == it.name).also { isMatched = true } - if (modifiers != null) conditions = (conditions && modifiers.contains(it)).also { isMatched = true } - if (index == -2) conditions = (conditions && p == lastIndex).also { isMatched = true } - if (index >= 0) conditions = (conditions && p == index).also { isMatched = true } + if (type != null) + conditions = (type == it.type).let { + if (it) typeIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == typeIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (typeLastIndex - typeIndex) && matchIndex.second) || + (typeLastIndex == typeIndex && matchIndex.second.not())) + } + if (name.isNotBlank()) + conditions = (conditions && name == it.name).let { + if (it) nameIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == nameIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) || + (nameLastIndex == nameIndex && matchIndex.second.not())) + } + if (modifiers != null) + conditions = (conditions && modifiers.contains(it)).let { + if (it) modifyIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == modifyIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) || + (modifyLastIndex == modifyIndex && matchIndex.second.not())) + } + if (orderIndex != null) conditions = + (conditions && ((orderIndex.first >= 0 && orderIndex.first == p && orderIndex.second) || + (orderIndex.first < 0 && abs(orderIndex.first) == (lastIndex - p) && orderIndex.second) || + (lastIndex == p && orderIndex.second.not()))).also { isMatched = true } if (conditions && isMatched) { field = it.apply { isAccessible = true } return@apply @@ -75,9 +121,19 @@ internal object ReflectionTool { field?.also { MemberCacheStore.putField(hashCode, field) } ?: throw NoSuchFieldError( "Can't find this Field --> " + - "index:[${ - index.takeIf { it >= 0 || it == -2 }?.toString() - ?.replace(oldValue = "-2", newValue = "last") ?: "unspecified" + "orderIndex:[${ + when { + orderIndex == null -> "unspecified" + orderIndex.second.not() -> "last" + else -> orderIndex.first + } + }] " + + "matchIndex:[${ + when { + matchIndex == null -> "unspecified" + matchIndex.second.not() -> "last" + else -> matchIndex.first + } }] " + "name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " + "type:[${type ?: "unspecified"}] " + @@ -91,7 +147,8 @@ internal object ReflectionTool { /** * 查找任意方法 * @param classSet 方法所在类 - * @param index 下标 + * @param orderIndex 字节码顺序下标 + * @param matchIndex 字节码筛选下标 * @param name 方法名称 * @param modifiers 方法描述 * @param returnType 方法返回值 @@ -103,28 +160,89 @@ internal object ReflectionTool { */ internal fun findMethod( classSet: Class<*>?, - index: Int, + orderIndex: Pair?, + matchIndex: Pair?, name: String, modifiers: ModifierRules?, returnType: Class<*>?, paramCount: Int, paramTypes: Array>? ): Method { - val hashCode = ("[$index][$name][$paramCount][${paramTypes.typeOfString()}][$returnType][$modifiers][$classSet]").hashCode() + val hashCode = + ("[$orderIndex][$matchIndex][$name][$paramCount][${paramTypes.typeOfString()}][$returnType][$modifiers][$classSet]").hashCode() return MemberCacheStore.findMethod(hashCode) ?: let { var method: Method? = null classSet?.declaredMethods?.apply { + var returnTypeIndex = -1 + var paramTypeIndex = -1 + var paramCountIndex = -1 + var nameIndex = -1 + var modifyIndex = -1 + val returnTypeLastIndex = + if (returnType != null && matchIndex != null) filter { returnType == it.returnType }.lastIndex else -1 + val paramCountLastIndex = + if (paramCount >= 0 && matchIndex != null) filter { paramCount == it.parameterTypes.size }.lastIndex else -1 + val paramTypeLastIndex = + if (paramTypes != null && matchIndex != null) filter { arrayContentsEq(paramTypes, it.parameterTypes) }.lastIndex else -1 + val nameLastIndex = if (name.isNotBlank() && matchIndex != null) filter { name == it.name }.lastIndex else -1 + val modifyLastIndex = if (modifiers != null && matchIndex != null) filter { modifiers.contains(it) }.lastIndex else -1 forEachIndexed { p, it -> var isMatched = false var conditions = true - if (name.isNotBlank()) conditions = (name == it.name).also { isMatched = true } - if (returnType != null) conditions = (conditions && it.returnType == returnType).also { isMatched = true } - if (paramCount >= 0) conditions = (conditions && it.parameterTypes.size == paramCount).also { isMatched = true } - if (paramTypes != null) conditions = - (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).also { isMatched = true } - if (modifiers != null) conditions = (conditions && modifiers.contains(it)).also { isMatched = true } - if (index == -2) conditions = (conditions && p == lastIndex).also { isMatched = true } - if (index >= 0) conditions = (conditions && p == index).also { isMatched = true } + if (name.isNotBlank()) + conditions = (name == it.name).let { + if (it) nameIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == nameIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) || + (nameLastIndex == nameIndex && matchIndex.second.not())) + } + if (returnType != null) + conditions = (conditions && returnType == it.returnType).let { + if (it) returnTypeIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == returnTypeIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (returnTypeLastIndex - returnTypeIndex) && matchIndex.second) || + (returnTypeLastIndex == returnTypeIndex && matchIndex.second.not())) + } + if (paramCount >= 0) + conditions = (conditions && it.parameterTypes.size == paramCount).let { + if (it) paramCountIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == paramCountIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) || + (paramCountLastIndex == paramCountIndex && matchIndex.second.not())) + } + if (paramTypes != null) + conditions = (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).let { + if (it) paramTypeIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == paramTypeIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) || + (paramTypeLastIndex == paramTypeIndex && matchIndex.second.not())) + } + if (modifiers != null) + conditions = (conditions && modifiers.contains(it)).let { + if (it) modifyIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == modifyIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) || + (modifyLastIndex == modifyIndex && matchIndex.second.not())) + } + if (orderIndex != null) conditions = + (conditions && ((orderIndex.first >= 0 && orderIndex.first == p && orderIndex.second) || + (orderIndex.first < 0 && abs(orderIndex.first) == (lastIndex - p) && orderIndex.second) || + (lastIndex == p && orderIndex.second.not()))).also { isMatched = true } if (conditions && isMatched) { method = it.apply { isAccessible = true } return@apply @@ -134,9 +252,19 @@ internal object ReflectionTool { method?.also { MemberCacheStore.putMethod(hashCode, method) } ?: throw NoSuchMethodError( "Can't find this Method --> " + - "index:[${ - index.takeIf { it >= 0 || it == -2 } - ?.toString()?.replace(oldValue = "-2", newValue = "last") ?: "unspecified" + "orderIndex:[${ + when { + orderIndex == null -> "unspecified" + orderIndex.second.not() -> "last" + else -> orderIndex.first + } + }] " + + "matchIndex:[${ + when { + matchIndex == null -> "unspecified" + matchIndex.second.not() -> "last" + else -> matchIndex.first + } }] " + "name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " + "paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " + @@ -152,7 +280,8 @@ internal object ReflectionTool { /** * 查找任意构造方法 * @param classSet 构造方法所在类 - * @param index 下标 + * @param orderIndex 字节码顺序下标 + * @param matchIndex 字节码筛选下标 * @param modifiers 构造方法描述 * @param paramCount 构造方法参数个数 * @param paramTypes 构造方法参数类型 @@ -162,24 +291,61 @@ internal object ReflectionTool { */ internal fun findConstructor( classSet: Class<*>?, - index: Int, + orderIndex: Pair?, + matchIndex: Pair?, modifiers: ModifierRules?, paramCount: Int, paramTypes: Array>? ): Constructor<*> { - val hashCode = ("[$index][$paramCount][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode() + val hashCode = ("[$orderIndex][$matchIndex][$paramCount][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode() return MemberCacheStore.findConstructor(hashCode) ?: let { var constructor: Constructor<*>? = null classSet?.declaredConstructors?.apply { + var paramTypeIndex = -1 + var paramCountIndex = -1 + var modifyIndex = -1 + val paramCountLastIndex = + if (paramCount >= 0 && matchIndex != null) filter { paramCount == it.parameterTypes.size }.lastIndex else -1 + val paramTypeLastIndex = + if (paramTypes != null && matchIndex != null) filter { arrayContentsEq(paramTypes, it.parameterTypes) }.lastIndex else -1 + val modifyLastIndex = if (modifiers != null && matchIndex != null) filter { modifiers.contains(it) }.lastIndex else -1 forEachIndexed { p, it -> var isMatched = false var conditions = true - if (paramCount >= 0) conditions = (it.parameterTypes.size == paramCount).also { isMatched = true } - if (paramTypes != null) conditions = - (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).also { isMatched = true } - if (modifiers != null) conditions = (conditions && modifiers.contains(it)).also { isMatched = true } - if (index == -2) conditions = (conditions && p == lastIndex).also { isMatched = true } - if (index >= 0) conditions = (conditions && p == index).also { isMatched = true } + if (paramCount >= 0) + conditions = (it.parameterTypes.size == paramCount).let { + if (it) paramCountIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == paramCountIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) || + (paramCountLastIndex == paramCountIndex && matchIndex.second.not())) + } + if (paramTypes != null) + conditions = (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).let { + if (it) paramTypeIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == paramTypeIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) || + (paramTypeLastIndex == paramTypeIndex && matchIndex.second.not())) + } + if (modifiers != null) + conditions = (conditions && modifiers.contains(it)).let { + if (it) modifyIndex++ + isMatched = true + it && (matchIndex == null || + (matchIndex.first >= 0 && matchIndex.first == modifyIndex && matchIndex.second) || + (matchIndex.first < 0 && + abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) || + (modifyLastIndex == modifyIndex && matchIndex.second.not())) + } + if (orderIndex != null) conditions = + (conditions && ((orderIndex.first >= 0 && orderIndex.first == p && orderIndex.second) || + (orderIndex.first < 0 && abs(orderIndex.first) == (lastIndex - p) && orderIndex.second) || + (lastIndex == p && orderIndex.second.not()))).also { isMatched = true } if (conditions && isMatched) { constructor = it.apply { isAccessible = true } return@apply @@ -189,7 +355,20 @@ internal object ReflectionTool { return constructor?.also { MemberCacheStore.putConstructor(hashCode, constructor) } ?: throw NoSuchMethodError( "Can't find this Constructor --> " + - "index:[${index.takeIf { it >= 0 } ?: "unspecified"}] " + + "orderIndex:[${ + when { + orderIndex == null -> "unspecified" + orderIndex.second.not() -> "last" + else -> orderIndex.first + } + }] " + + "matchIndex:[${ + when { + matchIndex == null -> "unspecified" + matchIndex.second.not() -> "last" + else -> matchIndex.first + } + }] " + "paramCount:[${ paramCount.takeIf { it >= 0 || it == -2 } ?.toString()?.replace(oldValue = "-2", newValue = "last") ?: "unspecified"