Modify move MethodFinder, ConstructorFinder, FieldFinder rules data to MethodRulesData, ConstructorRulesData, FieldRulesData and separate BaseFinder

This commit is contained in:
2022-09-05 01:13:29 +08:00
parent 1521c6be25
commit 17fe436760
16 changed files with 569 additions and 378 deletions

View File

@@ -64,7 +64,7 @@
[filename](public/FieldFinder.md ':include') [filename](public/FieldFinder.md ':include')
[filename](public/MemberBaseFinder-IndexTypeCondition.md ':include') [filename](public/BaseFinder-IndexTypeCondition.md ':include')
[filename](public/ModifierRules.md ':include') [filename](public/ModifierRules.md ':include')

View File

@@ -1,4 +1,4 @@
## MemberBaseFinder.IndexTypeCondition *- class* ## BaseFinder.IndexTypeCondition *- class*
```kotlin ```kotlin
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType) inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
@@ -8,10 +8,6 @@ inner class IndexTypeCondition internal constructor(private val type: IndexConfi
`v1.0.70` `新增` `v1.0.70` `新增`
`v1.0.93` `修改`
重命名 `BaseFinder``MemberBaseFinder`
**功能描述** **功能描述**
> 字节码下标筛选实现类。 > 字节码下标筛选实现类。

View File

@@ -1,7 +1,7 @@
## ConstructorFinder *- class* ## ConstructorFinder *- class*
```kotlin ```kotlin
class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : BaseFinder() class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
``` ```
**变更记录** **变更记录**
@@ -14,7 +14,7 @@ class ConstructorFinder internal constructor(override val hookInstance: YukiMemb
`v1.0.93` `修改` `v1.0.93` `修改`
修正拼写错误的 **Creater** 命名到 **Creator** 合并到 `MemberBaseFinder`
**功能描述** **功能描述**
@@ -90,7 +90,7 @@ fun param(vararg paramType: Any): IndexTypeCondition
> 设置 `Constructor` 参数。 > 设置 `Constructor` 参数。
如果同时使用了 `paramCount``paramTypes` 的数量必须与 `paramCount` 完全匹配。 如果同时使用了 `paramCount``paramType` 的数量必须与 `paramCount` 完全匹配。
!> 无参 `Constructor` 请使用 `emptyParam` 设置查询条件。 !> 无参 `Constructor` 请使用 `emptyParam` 设置查询条件。

View File

@@ -1,7 +1,7 @@
## FieldFinder *- class* ## FieldFinder *- class*
```kotlin ```kotlin
class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : BaseFinder() class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : MemberBaseFinder
``` ```
**变更记录** **变更记录**
@@ -12,6 +12,10 @@ class FieldFinder internal constructor(override val hookInstance: YukiMemberHook
合并到 `BaseFinder` 合并到 `BaseFinder`
`v1.0.93` `修改`
合并到 `MemberBaseFinder`
**功能描述** **功能描述**
> `Field` 查找类。 > `Field` 查找类。

View File

@@ -1,7 +1,7 @@
## MethodFinder *- class* ## MethodFinder *- class*
```kotlin ```kotlin
class MethodFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : BaseFinder() class MethodFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
``` ```
**变更记录** **变更记录**
@@ -12,6 +12,10 @@ class MethodFinder internal constructor(override val hookInstance: YukiMemberHoo
合并到 `BaseFinder` 合并到 `BaseFinder`
`v1.0.93` `修改`
合并到 `MemberBaseFinder`
**功能描述** **功能描述**
> `Method` 查找类。 > `Method` 查找类。
@@ -120,7 +124,7 @@ fun param(vararg paramType: Any): IndexTypeCondition
> 设置 `Method` 参数。 > 设置 `Method` 参数。
如果同时使用了 `paramCount``paramTypes` 的数量必须与 `paramCount` 完全匹配。 如果同时使用了 `paramCount``paramType` 的数量必须与 `paramCount` 完全匹配。
!> 无参 `Method` 请使用 `emptyParam` 设置查询条件。 !> 无参 `Method` 请使用 `emptyParam` 设置查询条件。

View File

@@ -0,0 +1,147 @@
/*
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
* Copyright (C) 2019-2022 HighCapable
* https://github.com/fankes/YukiHookAPI
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This file is Created by fankes on 2022/9/4.
*/
package com.highcapable.yukihookapi.hook.core.finder.base
import com.highcapable.yukihookapi.annotation.YukiPrivateApi
import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.factory.classOf
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
import java.lang.reflect.Member
import kotlin.math.abs
/**
* 这是 [Class] 与 [Member] 查找类功能的基本类实现
*/
abstract class BaseFinder {
/**
* 字节码、数组下标筛选数据类型
*/
@PublishedApi
internal enum class IndexConfigType { ORDER, MATCH }
/** 字节码、数组顺序下标 */
internal var orderIndex: Pair<Int, Boolean>? = null
/** 字节码、数组筛选下标 */
internal var matchIndex: Pair<Int, Boolean>? = null
/**
* 字节码、数组下标筛选实现类
* @param type 类型
*/
inner class IndexTypeCondition @PublishedApi internal constructor(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 internal constructor() {
/** 设置满足条件的第一个*/
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)
}
}
}
/**
* 将目标类型转换为可识别的兼容类型
* @param tag 当前查找类的标识
* @param loader 使用的 [ClassLoader]
* @return [Class] or null
*/
internal fun Any?.compat(tag: String, loader: ClassLoader?) = when (this) {
null -> null
is Class<*> -> this
is String -> runCatching { classOf(name = this, loader) }.getOrNull() ?: UndefinedType
is VariousClass -> runCatching { get(loader) }.getOrNull() ?: UndefinedType
else -> error("$tag match type \"$javaClass\" not allowed")
} as Class<*>?
/**
* 返回结果实现类
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun build(): BaseResult
/**
* 返回只有异常的结果实现类
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param throwable 异常
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun failure(throwable: Throwable?): BaseResult
/**
* 查找结果实现、处理类接口
*
* - ❗此功能交由方法体自动完成 - 你不应该手动继承此接口
*/
@YukiPrivateApi
interface BaseResult
}

View File

@@ -29,12 +29,9 @@ package com.highcapable.yukihookapi.hook.core.finder.base
import com.highcapable.yukihookapi.YukiHookAPI import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.annotation.YukiPrivateApi import com.highcapable.yukihookapi.annotation.YukiPrivateApi
import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator
import com.highcapable.yukihookapi.hook.factory.classOf
import com.highcapable.yukihookapi.hook.log.yLoggerE import com.highcapable.yukihookapi.hook.log.yLoggerE
import com.highcapable.yukihookapi.hook.log.yLoggerI import com.highcapable.yukihookapi.hook.log.yLoggerI
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
import com.highcapable.yukihookapi.hook.utils.await import com.highcapable.yukihookapi.hook.utils.await
import com.highcapable.yukihookapi.hook.utils.unit import com.highcapable.yukihookapi.hook.utils.unit
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
@@ -42,7 +39,6 @@ import java.lang.reflect.Constructor
import java.lang.reflect.Field import java.lang.reflect.Field
import java.lang.reflect.Member import java.lang.reflect.Member
import java.lang.reflect.Method import java.lang.reflect.Method
import kotlin.math.abs
/** /**
* 这是 [Member] 查找类功能的基本类实现 * 这是 [Member] 查找类功能的基本类实现
@@ -56,72 +52,7 @@ abstract class MemberBaseFinder internal constructor(
internal open val hookInstance: YukiMemberHookCreator.MemberHookCreator? = null, internal open val hookInstance: YukiMemberHookCreator.MemberHookCreator? = null,
@PublishedApi @PublishedApi
internal open val classSet: Class<*>? = null internal open val classSet: Class<*>? = null
) { ) : BaseFinder() {
/**
* 字节码下标筛选数据类型
*/
@PublishedApi
internal enum class IndexConfigType { ORDER, MATCH }
/** 字节码顺序下标 */
internal var orderIndex: Pair<Int, Boolean>? = null
/** 字节码筛选下标 */
internal var matchIndex: Pair<Int, Boolean>? = null
/**
* 字节码下标筛选实现类
* @param type 类型
*/
inner class IndexTypeCondition @PublishedApi internal constructor(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 internal constructor() {
/** 设置满足条件的第一个*/
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)
}
}
}
/** 是否使用了重查找功能 */ /** 是否使用了重查找功能 */
@PublishedApi @PublishedApi
@@ -176,13 +107,7 @@ abstract class MemberBaseFinder internal constructor(
* 将目标类型转换为可识别的兼容类型 * 将目标类型转换为可识别的兼容类型
* @return [Class] or null * @return [Class] or null
*/ */
internal fun Any?.compat() = when (this) { internal fun Any?.compat() = compat(tag, classSet?.classLoader)
null -> null
is Class<*> -> this
is String -> runCatching { classOf(name = this, classSet!!.classLoader) }.getOrNull() ?: UndefinedType
is VariousClass -> runCatching { get(classSet!!.classLoader) }.getOrNull() ?: UndefinedType
else -> error("$tag match type \"$javaClass\" not allowed")
} as Class<*>?
/** /**
* 发生错误时输出日志 * 发生错误时输出日志
@@ -221,49 +146,22 @@ abstract class MemberBaseFinder internal constructor(
if (YukiHookAPI.Configs.isDebug && YukiHookBridge.hasXposedBridge && hookInstance != null) yLoggerI(msg = msg) if (YukiHookAPI.Configs.isDebug && YukiHookBridge.hasXposedBridge && hookInstance != null) yLoggerI(msg = msg)
} }
/**
* 返回结果实现类
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun build(): BaseResult
/** /**
* 返回结果处理类并设置到目标 [YukiMemberHookCreator.MemberHookCreator] * 返回结果处理类并设置到目标 [YukiMemberHookCreator.MemberHookCreator]
* *
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法 * - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [BaseResult] * @return [BaseFinder.BaseResult]
*/ */
@YukiPrivateApi @YukiPrivateApi
abstract fun process(): BaseResult abstract fun process(): BaseResult
/**
* 返回只有异常的结果实现类
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param throwable 异常
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun failure(throwable: Throwable?): BaseResult
/** /**
* 返回只有异常的结果处理类并作用于目标 [YukiMemberHookCreator.MemberHookCreator] * 返回只有异常的结果处理类并作用于目标 [YukiMemberHookCreator.MemberHookCreator]
* *
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法 * - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param throwable 异常 * @param throwable 异常
* @return [BaseResult] * @return [BaseFinder.BaseResult]
*/ */
@YukiPrivateApi @YukiPrivateApi
abstract fun denied(throwable: Throwable?): BaseResult abstract fun denied(throwable: Throwable?): BaseResult
/**
* 查找结果实现、处理类接口
*
* - ❗此功能交由方法体自动完成 - 你不应该手动继承此接口
*/
@YukiPrivateApi
interface BaseResult
} }

View File

@@ -32,7 +32,9 @@ package com.highcapable.yukihookapi.hook.core.finder.members
import com.highcapable.yukihookapi.annotation.YukiPrivateApi import com.highcapable.yukihookapi.annotation.YukiPrivateApi
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder
import com.highcapable.yukihookapi.hook.core.finder.members.data.ConstructorRulesData
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool
import com.highcapable.yukihookapi.hook.factory.ConstructorCondition import com.highcapable.yukihookapi.hook.factory.ConstructorCondition
@@ -62,21 +64,12 @@ class ConstructorFinder @PublishedApi internal constructor(
/** 当前使用的 [classSet] */ /** 当前使用的 [classSet] */
private var usedClassSet = classSet private var usedClassSet = classSet
/** 是否在未找到后继续在当前 [classSet] 的父类中查找 */
private var isFindInSuperClass = false
/** 当前重查找结果回调 */ /** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null private var remedyPlansCallback: (() -> Unit)? = null
/** [Constructor] 参数数组 */ /** 当前查询条件规则数据 */
private var paramTypes: Array<out Class<*>>? = null
/** [Constructor] 参数个数范围 */
private var paramCountRange = IntRange.EMPTY
/** [ModifierRules] 实例 */
@PublishedApi @PublishedApi
internal var modifiers: ModifierRules? = null internal var rulesData = ConstructorRulesData()
/** /**
* 设置 [Constructor] 参数个数 * 设置 [Constructor] 参数个数
@@ -84,50 +77,55 @@ class ConstructorFinder @PublishedApi internal constructor(
* 你可以不使用 [param] 指定参数类型而是仅使用此变量指定参数个数 * 你可以不使用 [param] 指定参数类型而是仅使用此变量指定参数个数
* *
* 若参数个数小于零则忽略并使用 [param] * 若参数个数小于零则忽略并使用 [param]
* @return [Int]
*/ */
var paramCount = -1 var paramCount
get() = rulesData.paramCount
set(value) {
rulesData.paramCount = value
}
/** /**
* 设置 [Constructor] 标识符筛选条件 * 设置 [Constructor] 标识符筛选条件
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体 * @param initiate 方法体
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition { inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition {
modifiers = ModifierRules().apply(initiate) rulesData.modifiers = ModifierRules().apply(initiate)
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
/** /**
* 设置 [Constructor] 空参数、无参数 * 设置 [Constructor] 空参数、无参数
* *
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun emptyParam() = paramCount(num = 0) fun emptyParam() = paramCount(num = 0)
/** /**
* 设置 [Constructor] 参数 * 设置 [Constructor] 参数
* *
* 如果同时使用了 [paramCount] 则 [paramTypes] 的数量必须与 [paramCount] 完全匹配 * 如果同时使用了 [paramCount] 则 [paramType] 的数量必须与 [paramCount] 完全匹配
* *
* - ❗无参 [Constructor] 请使用 [emptyParam] 设置查询条件 * - ❗无参 [Constructor] 请使用 [emptyParam] 设置查询条件
* *
* - ❗有参 [Constructor] 必须使用此方法设定参数或使用 [paramCount] 指定个数 * - ❗有参 [Constructor] 必须使用此方法设定参数或使用 [paramCount] 指定个数
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass] * @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass]
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun param(vararg paramType: Any): IndexTypeCondition { fun param(vararg paramType: Any): IndexTypeCondition {
if (paramType.isEmpty()) error("paramTypes is empty, please use emptyParam() instead") if (paramType.isEmpty()) error("paramTypes is empty, please use emptyParam() instead")
paramTypes = ArrayList<Class<*>>().apply { paramType.forEach { add(it.compat() ?: UndefinedType) } }.toTypedArray() rulesData.paramTypes = arrayListOf<Class<*>>().apply { paramType.forEach { add(it.compat() ?: UndefinedType) } }.toTypedArray()
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
/** /**
* 顺序筛选字节码的下标 * 顺序筛选字节码的下标
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun order() = IndexTypeCondition(IndexConfigType.ORDER) fun order() = IndexTypeCondition(IndexConfigType.ORDER)
@@ -138,12 +136,12 @@ class ConstructorFinder @PublishedApi internal constructor(
* *
* 若参数个数小于零则忽略并使用 [param] * 若参数个数小于零则忽略并使用 [param]
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param num 个数 * @param num 个数
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun paramCount(num: Int): IndexTypeCondition { fun paramCount(num: Int): IndexTypeCondition {
paramCount = num rulesData.paramCount = num
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -152,12 +150,12 @@ class ConstructorFinder @PublishedApi internal constructor(
* *
* 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围 * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param numRange 个数范围 * @param numRange 个数范围
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun paramCount(numRange: IntRange): IndexTypeCondition { fun paramCount(numRange: IntRange): IndexTypeCondition {
paramCountRange = numRange rulesData.paramCountRange = numRange
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -168,7 +166,7 @@ class ConstructorFinder @PublishedApi internal constructor(
* @param isOnlySuperClass 是否仅在当前 [classSet] 的父类中查找 - 若父类是 [Any] 则不会生效 * @param isOnlySuperClass 是否仅在当前 [classSet] 的父类中查找 - 若父类是 [Any] 则不会生效
*/ */
fun superClass(isOnlySuperClass: Boolean = false) { fun superClass(isOnlySuperClass: Boolean = false) {
isFindInSuperClass = true rulesData.isFindInSuper = true
if (isOnlySuperClass && classSet?.hasExtends == true) usedClassSet = classSet.superclass if (isOnlySuperClass && classSet?.hasExtends == true) usedClassSet = classSet.superclass
} }
@@ -177,11 +175,7 @@ class ConstructorFinder @PublishedApi internal constructor(
* @return [HashSet]<[Constructor]> * @return [HashSet]<[Constructor]>
* @throws NoSuchMethodError 如果找不到构造方法 * @throws NoSuchMethodError 如果找不到构造方法
*/ */
private val result private val result get() = ReflectionTool.findConstructors(usedClassSet, orderIndex, matchIndex, rulesData)
get() = ReflectionTool.findConstructors(
usedClassSet, orderIndex, matchIndex, modifiers,
paramCount, paramCountRange, paramTypes, isFindInSuperClass
)
/** /**
* 设置实例 * 设置实例

View File

@@ -33,7 +33,9 @@ import com.highcapable.yukihookapi.annotation.YukiPrivateApi
import com.highcapable.yukihookapi.hook.bean.CurrentClass import com.highcapable.yukihookapi.hook.bean.CurrentClass
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder
import com.highcapable.yukihookapi.hook.core.finder.members.data.FieldRulesData
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions
import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool
@@ -63,26 +65,24 @@ class FieldFinder @PublishedApi internal constructor(
/** 当前使用的 [classSet] */ /** 当前使用的 [classSet] */
private var usedClassSet = classSet private var usedClassSet = classSet
/** 是否在未找到后继续在当前 [classSet] 的父类中查找 */
private var isFindInSuperClass = false
/** 当前重查找结果回调 */ /** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null private var remedyPlansCallback: (() -> Unit)? = null
/** [ModifierRules] 实例 */ /** 当前查询条件规则数据 */
@PublishedApi @PublishedApi
internal var modifiers: ModifierRules? = null internal var rulesData = FieldRulesData()
/** [NameConditions] 实例 */
@PublishedApi
internal var nameConditions: NameConditions? = null
/** /**
* 设置 [Field] 名称 * 设置 [Field] 名称
* *
* - ❗若不填写名称则必须存在一个其它条件 * - ❗若不填写名称则必须存在一个其它条件
* @return [String]
*/ */
var name = "" var name
get() = rulesData.name
set(value) {
rulesData.name = value
}
/** /**
* 设置 [Field] 类型 * 设置 [Field] 类型
@@ -90,26 +90,31 @@ class FieldFinder @PublishedApi internal constructor(
* - ❗只能是 [Class]、[String]、[VariousClass] * - ❗只能是 [Class]、[String]、[VariousClass]
* *
* - 可不填写类型 * - 可不填写类型
* @return [Any] or null
*/ */
var type: Any? = null var type
get() = rulesData.type
set(value) {
rulesData.type = value.compat()
}
/** /**
* 设置 [Field] 标识符筛选条件 * 设置 [Field] 标识符筛选条件
* *
* - 可不设置筛选条件 * - 可不设置筛选条件
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体 * @param initiate 方法体
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition { inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition {
modifiers = ModifierRules().apply(initiate) rulesData.modifiers = ModifierRules().apply(initiate)
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
/** /**
* 顺序筛选字节码的下标 * 顺序筛选字节码的下标
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun order() = IndexTypeCondition(IndexConfigType.ORDER) fun order() = IndexTypeCondition(IndexConfigType.ORDER)
@@ -118,12 +123,12 @@ class FieldFinder @PublishedApi internal constructor(
* *
* - ❗若不填写名称则必须存在一个其它条件 * - ❗若不填写名称则必须存在一个其它条件
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 名称 * @param value 名称
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun name(value: String): IndexTypeCondition { fun name(value: String): IndexTypeCondition {
name = value rulesData.name = value
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -132,12 +137,12 @@ class FieldFinder @PublishedApi internal constructor(
* *
* - ❗若不填写名称则必须存在一个其它条件 * - ❗若不填写名称则必须存在一个其它条件
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体 * @param initiate 方法体
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
inline fun name(initiate: NameConditions.() -> Unit): IndexTypeCondition { inline fun name(initiate: NameConditions.() -> Unit): IndexTypeCondition {
nameConditions = NameConditions().apply(initiate) rulesData.nameConditions = NameConditions().apply(initiate)
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -146,12 +151,12 @@ class FieldFinder @PublishedApi internal constructor(
* *
* - 可不填写类型 * - 可不填写类型
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 类型 - ❗只能是 [Class]、[String]、[VariousClass] * @param value 类型 - ❗只能是 [Class]、[String]、[VariousClass]
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun type(value: Any): IndexTypeCondition { fun type(value: Any): IndexTypeCondition {
type = value rulesData.type = value.compat()
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -162,7 +167,7 @@ class FieldFinder @PublishedApi internal constructor(
* @param isOnlySuperClass 是否仅在当前 [classSet] 的父类中查找 - 若父类是 [Any] 则不会生效 * @param isOnlySuperClass 是否仅在当前 [classSet] 的父类中查找 - 若父类是 [Any] 则不会生效
*/ */
fun superClass(isOnlySuperClass: Boolean = false) { fun superClass(isOnlySuperClass: Boolean = false) {
isFindInSuperClass = true rulesData.isFindInSuper = true
if (isOnlySuperClass && classSet?.hasExtends == true) usedClassSet = classSet.superclass if (isOnlySuperClass && classSet?.hasExtends == true) usedClassSet = classSet.superclass
} }
@@ -171,13 +176,7 @@ class FieldFinder @PublishedApi internal constructor(
* @return [HashSet]<[Field]> * @return [HashSet]<[Field]>
* @throws NoSuchFieldError 如果找不到变量 * @throws NoSuchFieldError 如果找不到变量
*/ */
private val result private val result get() = ReflectionTool.findFields(usedClassSet, orderIndex, matchIndex, rulesData)
get() = ReflectionTool.findFields(
usedClassSet, orderIndex,
matchIndex, name,
modifiers, nameConditions,
type.compat(), isFindInSuperClass
)
/** /**
* 设置实例 * 设置实例

View File

@@ -32,7 +32,9 @@ package com.highcapable.yukihookapi.hook.core.finder.members
import com.highcapable.yukihookapi.annotation.YukiPrivateApi import com.highcapable.yukihookapi.annotation.YukiPrivateApi
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder
import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions
import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool
@@ -64,32 +66,24 @@ class MethodFinder @PublishedApi internal constructor(
/** 当前使用的 [classSet] */ /** 当前使用的 [classSet] */
private var usedClassSet = classSet private var usedClassSet = classSet
/** 是否在未找到后继续在当前 [classSet] 的父类中查找 */
private var isFindInSuperClass = false
/** 当前重查找结果回调 */ /** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null private var remedyPlansCallback: (() -> Unit)? = null
/** [Method] 参数数组 */ /** 当前查询条件规则数据 */
private var paramTypes: Array<out Class<*>>? = null
/** [Method] 参数个数范围 */
private var paramCountRange = IntRange.EMPTY
/** [ModifierRules] 实例 */
@PublishedApi @PublishedApi
internal var modifiers: ModifierRules? = null internal var rulesData = MethodRulesData()
/** [NameConditions] 实例 */
@PublishedApi
internal var nameConditions: NameConditions? = null
/** /**
* 设置 [Method] 名称 * 设置 [Method] 名称
* *
* - ❗若不填写名称则必须存在一个其它条件 * - ❗若不填写名称则必须存在一个其它条件
* @return [String]
*/ */
var name = "" var name
get() = rulesData.name
set(value) {
rulesData.name = value
}
/** /**
* 设置 [Method] 参数个数 * 设置 [Method] 参数个数
@@ -97,8 +91,13 @@ class MethodFinder @PublishedApi internal constructor(
* 你可以不使用 [param] 指定参数类型而是仅使用此变量指定参数个数 * 你可以不使用 [param] 指定参数类型而是仅使用此变量指定参数个数
* *
* 若参数个数小于零则忽略并使用 [param] * 若参数个数小于零则忽略并使用 [param]
* @return [Int]
*/ */
var paramCount = -1 var paramCount
get() = rulesData.paramCount
set(value) {
rulesData.paramCount = value
}
/** /**
* 设置 [Method] 返回值 * 设置 [Method] 返回值
@@ -106,52 +105,57 @@ class MethodFinder @PublishedApi internal constructor(
* - ❗只能是 [Class]、[String]、[VariousClass] * - ❗只能是 [Class]、[String]、[VariousClass]
* *
* - 可不填写返回值 * - 可不填写返回值
* @return [Any] or null
*/ */
var returnType: Any? = null var returnType
get() = rulesData.returnType
set(value) {
rulesData.returnType = value.compat()
}
/** /**
* 设置 [Method] 标识符筛选条件 * 设置 [Method] 标识符筛选条件
* *
* - 可不设置筛选条件 * - 可不设置筛选条件
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体 * @param initiate 方法体
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition { inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition {
modifiers = ModifierRules().apply(initiate) rulesData.modifiers = ModifierRules().apply(initiate)
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
/** /**
* 设置 [Method] 空参数、无参数 * 设置 [Method] 空参数、无参数
* *
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun emptyParam() = paramCount(num = 0) fun emptyParam() = paramCount(num = 0)
/** /**
* 设置 [Method] 参数 * 设置 [Method] 参数
* *
* 如果同时使用了 [paramCount] 则 [paramTypes] 的数量必须与 [paramCount] 完全匹配 * 如果同时使用了 [paramCount] 则 [paramType] 的数量必须与 [paramCount] 完全匹配
* *
* - ❗无参 [Method] 请使用 [emptyParam] 设置查询条件 * - ❗无参 [Method] 请使用 [emptyParam] 设置查询条件
* *
* - ❗有参 [Method] 必须使用此方法设定参数或使用 [paramCount] 指定个数 * - ❗有参 [Method] 必须使用此方法设定参数或使用 [paramCount] 指定个数
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass] * @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass]
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun param(vararg paramType: Any): IndexTypeCondition { fun param(vararg paramType: Any): IndexTypeCondition {
if (paramType.isEmpty()) error("paramTypes is empty, please use emptyParam() instead") if (paramType.isEmpty()) error("paramTypes is empty, please use emptyParam() instead")
paramTypes = ArrayList<Class<*>>().apply { paramType.forEach { add(it.compat() ?: UndefinedType) } }.toTypedArray() rulesData.paramTypes = arrayListOf<Class<*>>().apply { paramType.forEach { add(it.compat() ?: UndefinedType) } }.toTypedArray()
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
/** /**
* 顺序筛选字节码的下标 * 顺序筛选字节码的下标
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun order() = IndexTypeCondition(IndexConfigType.ORDER) fun order() = IndexTypeCondition(IndexConfigType.ORDER)
@@ -160,12 +164,12 @@ class MethodFinder @PublishedApi internal constructor(
* *
* - ❗若不填写名称则必须存在一个其它条件 * - ❗若不填写名称则必须存在一个其它条件
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 名称 * @param value 名称
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun name(value: String): IndexTypeCondition { fun name(value: String): IndexTypeCondition {
name = value rulesData.name = value
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -174,12 +178,12 @@ class MethodFinder @PublishedApi internal constructor(
* *
* - ❗若不填写名称则必须存在一个其它条件 * - ❗若不填写名称则必须存在一个其它条件
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体 * @param initiate 方法体
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
inline fun name(initiate: NameConditions.() -> Unit): IndexTypeCondition { inline fun name(initiate: NameConditions.() -> Unit): IndexTypeCondition {
nameConditions = NameConditions().apply(initiate) rulesData.nameConditions = NameConditions().apply(initiate)
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -190,12 +194,12 @@ class MethodFinder @PublishedApi internal constructor(
* *
* 若参数个数小于零则忽略并使用 [param] * 若参数个数小于零则忽略并使用 [param]
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param num 个数 * @param num 个数
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun paramCount(num: Int): IndexTypeCondition { fun paramCount(num: Int): IndexTypeCondition {
paramCount = num rulesData.paramCount = num
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -204,12 +208,12 @@ class MethodFinder @PublishedApi internal constructor(
* *
* 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围 * 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param numRange 个数范围 * @param numRange 个数范围
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun paramCount(numRange: IntRange): IndexTypeCondition { fun paramCount(numRange: IntRange): IndexTypeCondition {
paramCountRange = numRange rulesData.paramCountRange = numRange
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -218,12 +222,12 @@ class MethodFinder @PublishedApi internal constructor(
* *
* - 可不填写返回值 * - 可不填写返回值
* *
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个 * - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 个数 * @param value 个数
* @return [MemberBaseFinder.IndexTypeCondition] * @return [BaseFinder.IndexTypeCondition]
*/ */
fun returnType(value: Any): IndexTypeCondition { fun returnType(value: Any): IndexTypeCondition {
returnType = value rulesData.returnType = value.compat()
return IndexTypeCondition(IndexConfigType.MATCH) return IndexTypeCondition(IndexConfigType.MATCH)
} }
@@ -234,7 +238,7 @@ class MethodFinder @PublishedApi internal constructor(
* @param isOnlySuperClass 是否仅在当前 [classSet] 的父类中查找 - 若父类是 [Any] 则不会生效 * @param isOnlySuperClass 是否仅在当前 [classSet] 的父类中查找 - 若父类是 [Any] 则不会生效
*/ */
fun superClass(isOnlySuperClass: Boolean = false) { fun superClass(isOnlySuperClass: Boolean = false) {
isFindInSuperClass = true rulesData.isFindInSuper = true
if (isOnlySuperClass && classSet?.hasExtends == true) usedClassSet = classSet.superclass if (isOnlySuperClass && classSet?.hasExtends == true) usedClassSet = classSet.superclass
} }
@@ -243,12 +247,7 @@ class MethodFinder @PublishedApi internal constructor(
* @return [HashSet]<[Method]> * @return [HashSet]<[Method]>
* @throws NoSuchMethodError 如果找不到方法 * @throws NoSuchMethodError 如果找不到方法
*/ */
private val result private val result get() = ReflectionTool.findMethods(usedClassSet, orderIndex, matchIndex, rulesData)
get() = ReflectionTool.findMethods(
usedClassSet, orderIndex, matchIndex, name,
modifiers, nameConditions, returnType.compat(),
paramCount, paramCountRange, paramTypes, isFindInSuperClass
)
/** /**
* 设置实例 * 设置实例

View File

@@ -0,0 +1,43 @@
/*
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
* Copyright (C) 2019-2022 HighCapable
* https://github.com/fankes/YukiHookAPI
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This file is Created by fankes on 2022/9/4.
*/
package com.highcapable.yukihookapi.hook.core.finder.members.data
import java.lang.reflect.Constructor
/**
* [Constructor] 规则查询数据类
* @param paramTypes 参数类型数组
* @param paramCount 参数个数
* @param paramCountRange 参数个数范围
*/
@PublishedApi
internal class ConstructorRulesData internal constructor(
var paramTypes: Array<out Class<*>>? = null,
var paramCount: Int = -1,
var paramCountRange: IntRange = IntRange.EMPTY
) : MemberRulesData()

View File

@@ -0,0 +1,44 @@
/*
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
* Copyright (C) 2019-2022 HighCapable
* https://github.com/fankes/YukiHookAPI
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This file is Created by fankes on 2022/9/4.
*/
package com.highcapable.yukihookapi.hook.core.finder.members.data
import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions
import java.lang.reflect.Field
/**
* [Field] 规则查询数据类
* @param name 名称
* @param nameConditions 名称规则
* @param type 类型
*/
@PublishedApi
internal class FieldRulesData internal constructor(
var name: String = "",
var nameConditions: NameConditions? = null,
var type: Any? = null
) : MemberRulesData()

View File

@@ -0,0 +1,46 @@
/*
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
* Copyright (C) 2019-2022 HighCapable
* https://github.com/fankes/YukiHookAPI
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This file is Created by fankes on 2022/9/4.
*/
package com.highcapable.yukihookapi.hook.core.finder.members.data
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import java.lang.reflect.Member
/**
* [Member] 规则查询数据类
* @param modifiers 描述符
* @param isFindInSuper 是否在未找到后继续在父类中查找
* @param matchCount 匹配的字节码个数
* @param matchCountRange 匹配的字节码个数范围
*/
@PublishedApi
internal open class MemberRulesData internal constructor(
var modifiers: ModifierRules? = null,
var isFindInSuper: Boolean = false,
var matchCount: Int = -1,
var matchCountRange: IntRange = IntRange.EMPTY
)

View File

@@ -0,0 +1,50 @@
/*
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
* Copyright (C) 2019-2022 HighCapable
* https://github.com/fankes/YukiHookAPI
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This file is Created by fankes on 2022/9/4.
*/
package com.highcapable.yukihookapi.hook.core.finder.members.data
import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions
import java.lang.reflect.Method
/**
* [Method] 规则查询数据类
* @param name 名称
* @param nameConditions 名称规则
* @param paramTypes 参数类型数组
* @param paramCount 参数个数
* @param paramCountRange 参数个数范围
* @param returnType 返回值类型
*/
@PublishedApi
internal class MethodRulesData internal constructor(
var name: String = "",
var nameConditions: NameConditions? = null,
var paramTypes: Array<out Class<*>>? = null,
var paramCount: Int = -1,
var paramCountRange: IntRange = IntRange.EMPTY,
var returnType: Any? = null
) : MemberRulesData()

View File

@@ -27,8 +27,9 @@
*/ */
package com.highcapable.yukihookapi.hook.core.reflex.tools package com.highcapable.yukihookapi.hook.core.reflex.tools
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.core.finder.members.data.ConstructorRulesData
import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions import com.highcapable.yukihookapi.hook.core.finder.members.data.FieldRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
import com.highcapable.yukihookapi.hook.factory.hasExtends import com.highcapable.yukihookapi.hook.factory.hasExtends
import com.highcapable.yukihookapi.hook.store.ReflectsCacheStore import com.highcapable.yukihookapi.hook.store.ReflectsCacheStore
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
@@ -51,29 +52,21 @@ internal object ReflectionTool {
* @param classSet 变量所在类 * @param classSet 变量所在类
* @param orderIndex 字节码顺序下标 * @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标 * @param matchIndex 字节码筛选下标
* @param name 变量名称 * @param rulesData 规则查询数据
* @param modifiers 变量描述
* @param nameConditions 名称查找条件
* @param type 变量类型
* @param isFindInSuperClass 是否在未找到后继续在当前 [classSet] 的父类中查找
* @return [HashSet]<[Field]> * @return [HashSet]<[Field]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [type] 目标类不存在 * @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [FieldRulesData.type] 目标类不存在
* @throws NoSuchFieldError 如果找不到变量 * @throws NoSuchFieldError 如果找不到变量
*/ */
internal fun findFields( internal fun findFields(
classSet: Class<*>?, classSet: Class<*>?,
orderIndex: Pair<Int, Boolean>?, orderIndex: Pair<Int, Boolean>?,
matchIndex: Pair<Int, Boolean>?, matchIndex: Pair<Int, Boolean>?,
name: String, rulesData: FieldRulesData
modifiers: ModifierRules?,
nameConditions: NameConditions?,
type: Class<*>?,
isFindInSuperClass: Boolean
): HashSet<Field> { ): HashSet<Field> {
if (type == UndefinedType) error("Field match type class is not found") if (rulesData.type == UndefinedType) error("Field match type class is not found")
if (orderIndex == null && matchIndex == null && name.isBlank() && modifiers == null && type == null) if (orderIndex == null && matchIndex == null && rulesData.name.isBlank() && rulesData.modifiers == null && rulesData.type == null)
error("You must set a condition when finding a Field") error("You must set a condition when finding a Field")
val hashCode = ("[$orderIndex][$matchIndex][$name][$type][$modifiers][$classSet]").hashCode() val hashCode = ("[$orderIndex][$matchIndex][${rulesData.name}][${rulesData.type}][${rulesData.modifiers}][$classSet]").hashCode()
return ReflectsCacheStore.findFields(hashCode) ?: let { return ReflectsCacheStore.findFields(hashCode) ?: let {
val fields = HashSet<Field>() val fields = HashSet<Field>()
classSet?.declaredFields?.apply { classSet?.declaredFields?.apply {
@@ -81,15 +74,19 @@ internal object ReflectionTool {
var nameIndex = -1 var nameIndex = -1
var modifyIndex = -1 var modifyIndex = -1
var nameCdsIndex = -1 var nameCdsIndex = -1
val typeLastIndex = if (type != null && matchIndex != null) filter { type == it.type }.lastIndex else -1 val typeLastIndex =
val nameLastIndex = if (name.isNotBlank() && matchIndex != null) filter { name == it.name }.lastIndex else -1 if (rulesData.type != null && matchIndex != null) filter { rulesData.type == it.type }.lastIndex else -1
val modifyLastIndex = if (modifiers != null && matchIndex != null) filter { modifiers.contains(it) }.lastIndex else -1 val nameLastIndex =
val nameCdsLastIndex = if (nameConditions != null && matchIndex != null) filter { nameConditions.contains(it) }.lastIndex else -1 if (rulesData.name.isNotBlank() && matchIndex != null) filter { rulesData.name == it.name }.lastIndex else -1
val modifyLastIndex =
if (rulesData.modifiers != null && matchIndex != null) filter { rulesData.modifiers!!.contains(it) }.lastIndex else -1
val nameCdsLastIndex =
if (rulesData.nameConditions != null && matchIndex != null) filter { rulesData.nameConditions!!.contains(it) }.lastIndex else -1
forEachIndexed { p, it -> forEachIndexed { p, it ->
var isMatched = false var isMatched = false
var conditions = true var conditions = true
if (type != null) if (rulesData.type != null)
conditions = (type == it.type).let { conditions = (rulesData.type == it.type).let {
if (it) typeIndex++ if (it) typeIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -98,8 +95,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (typeLastIndex - typeIndex) && matchIndex.second) || abs(matchIndex.first) == (typeLastIndex - typeIndex) && matchIndex.second) ||
(typeLastIndex == typeIndex && matchIndex.second.not())) (typeLastIndex == typeIndex && matchIndex.second.not()))
} }
if (name.isNotBlank()) if (rulesData.name.isNotBlank())
conditions = (conditions && name == it.name).let { conditions = (conditions && rulesData.name == it.name).let {
if (it) nameIndex++ if (it) nameIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -108,8 +105,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) || abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) ||
(nameLastIndex == nameIndex && matchIndex.second.not())) (nameLastIndex == nameIndex && matchIndex.second.not()))
} }
if (modifiers != null) if (rulesData.modifiers != null)
conditions = (conditions && modifiers.contains(it)).let { conditions = (conditions && rulesData.modifiers!!.contains(it)).let {
if (it) modifyIndex++ if (it) modifyIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -118,8 +115,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) || abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) ||
(modifyLastIndex == modifyIndex && matchIndex.second.not())) (modifyLastIndex == modifyIndex && matchIndex.second.not()))
} }
if (nameConditions != null) if (rulesData.nameConditions != null)
conditions = (conditions && nameConditions.contains(it)).let { conditions = (conditions && rulesData.nameConditions!!.contains(it)).let {
if (it) nameCdsIndex++ if (it) nameCdsIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -134,15 +131,10 @@ internal object ReflectionTool {
(lastIndex == p && orderIndex.second.not()))).also { isMatched = true } (lastIndex == p && orderIndex.second.not()))).also { isMatched = true }
if (conditions && isMatched) fields.add(it.apply { isAccessible = true }) if (conditions && isMatched) fields.add(it.apply { isAccessible = true })
} }
} ?: error("Can't find this Field [$name] because classSet is null") } ?: error("Can't find this Field [${rulesData.name}] because classSet is null")
fields.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putFields(hashCode, fields) } fields.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putFields(hashCode, fields) }
?: if (isFindInSuperClass && classSet.hasExtends) ?: if (rulesData.isFindInSuper && classSet.hasExtends)
findFields( findFields(classSet.superclass, orderIndex, matchIndex, rulesData)
classSet.superclass,
orderIndex, matchIndex,
name, modifiers, nameConditions,
type, isFindInSuperClass = true
)
else throw NoSuchFieldError( else throw NoSuchFieldError(
"Can't find this Field --> " + "Can't find this Field --> " +
when { when {
@@ -155,13 +147,13 @@ internal object ReflectionTool {
matchIndex.second.not() -> "matchIndex:[last] " matchIndex.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex.first}] " else -> "matchIndex:[${matchIndex.first}] "
} + } +
when (nameConditions) { when (rulesData.nameConditions) {
null -> "" null -> ""
else -> "nameConditions:$nameConditions " else -> "nameConditions:${rulesData.nameConditions} "
} + } +
"name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " + "name:[${rulesData.name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"type:[${type ?: "unspecified"}] " + "type:[${rulesData.type ?: "unspecified"}] " +
"modifiers:${modifiers ?: "[]"} " + "modifiers:${rulesData.modifiers ?: "[]"} " +
"in [$classSet] " + "in [$classSet] " +
"by $TAG" "by $TAG"
) )
@@ -173,41 +165,28 @@ internal object ReflectionTool {
* @param classSet 方法所在类 * @param classSet 方法所在类
* @param orderIndex 字节码顺序下标 * @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标 * @param matchIndex 字节码筛选下标
* @param name 方法名称 * @param rulesData 规则查询数据
* @param modifiers 方法描述
* @param nameConditions 名称查找条件
* @param returnType 方法返回值
* @param paramCount 方法参数个数
* @param paramCountRange 方法参数个数范围
* @param paramTypes 方法参数类型
* @param isFindInSuperClass 是否在未找到后继续在当前 [classSet] 的父类中查找
* @return [HashSet]<[Method]> * @return [HashSet]<[Method]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [paramTypes] 以及 [returnType] 目标类不存在 * @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [MethodRulesData.paramTypes] 以及 [MethodRulesData.returnType] 目标类不存在
* @throws NoSuchMethodError 如果找不到方法 * @throws NoSuchMethodError 如果找不到方法
*/ */
internal fun findMethods( internal fun findMethods(
classSet: Class<*>?, classSet: Class<*>?,
orderIndex: Pair<Int, Boolean>?, orderIndex: Pair<Int, Boolean>?,
matchIndex: Pair<Int, Boolean>?, matchIndex: Pair<Int, Boolean>?,
name: String, rulesData: MethodRulesData
modifiers: ModifierRules?,
nameConditions: NameConditions?,
returnType: Class<*>?,
paramCount: Int,
paramCountRange: IntRange,
paramTypes: Array<out Class<*>>?,
isFindInSuperClass: Boolean
): HashSet<Method> { ): HashSet<Method> {
if (returnType == UndefinedType) error("Method match returnType class is not found") if (rulesData.returnType == UndefinedType) error("Method match returnType class is not found")
paramTypes?.takeIf { it.isNotEmpty() } rulesData.paramTypes?.takeIf { it.isNotEmpty() }
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Method match paramType[$p] class is not found") } ?.forEachIndexed { p, it -> if (it == UndefinedType) error("Method match paramType[$p] class is not found") }
if (orderIndex == null && matchIndex == null && if (orderIndex == null && matchIndex == null &&
name.isBlank() && modifiers == null && rulesData.name.isBlank() && rulesData.modifiers == null &&
paramCount < 0 && paramCountRange.isEmpty() && rulesData.paramCount < 0 && rulesData.paramCountRange.isEmpty() &&
paramTypes == null && returnType == null rulesData.paramTypes == null && rulesData.returnType == null
) error("You must set a condition when finding a Method") ) error("You must set a condition when finding a Method")
val hashCode = val hashCode =
("[$orderIndex][$matchIndex][$name][$paramCount][${paramTypes.typeOfString()}][$returnType][$modifiers][$classSet]").hashCode() ("[$orderIndex][$matchIndex][${rulesData.name}][${rulesData.paramCount}][${rulesData.paramTypes.typeOfString()}]" +
"[${rulesData.returnType}][${rulesData.modifiers}][$classSet]").hashCode()
return ReflectsCacheStore.findMethods(hashCode) ?: let { return ReflectsCacheStore.findMethods(hashCode) ?: let {
val methods = HashSet<Method>() val methods = HashSet<Method>()
classSet?.declaredMethods?.apply { classSet?.declaredMethods?.apply {
@@ -219,21 +198,25 @@ internal object ReflectionTool {
var modifyIndex = -1 var modifyIndex = -1
var nameCdsIndex = -1 var nameCdsIndex = -1
val returnTypeLastIndex = val returnTypeLastIndex =
if (returnType != null && matchIndex != null) filter { returnType == it.returnType }.lastIndex else -1 if (rulesData.returnType != null && matchIndex != null) filter { rulesData.returnType == it.returnType }.lastIndex else -1
val paramCountLastIndex = val paramCountLastIndex =
if (paramCount >= 0 && matchIndex != null) filter { paramCount == it.parameterTypes.size }.lastIndex else -1 if (rulesData.paramCount >= 0 && matchIndex != null) filter { rulesData.paramCount == it.parameterTypes.size }.lastIndex else -1
val paramCountRangeLastIndex = if (paramCountRange.isEmpty().not() && matchIndex != null) val paramCountRangeLastIndex = if (rulesData.paramCountRange.isEmpty().not() && matchIndex != null)
filter { it.parameterTypes.size in paramCountRange }.lastIndex else -1 filter { it.parameterTypes.size in rulesData.paramCountRange }.lastIndex else -1
val paramTypeLastIndex = val paramTypeLastIndex =
if (paramTypes != null && matchIndex != null) filter { arrayContentsEq(paramTypes, it.parameterTypes) }.lastIndex else -1 if (rulesData.paramTypes != null && matchIndex != null)
val nameLastIndex = if (name.isNotBlank() && matchIndex != null) filter { name == it.name }.lastIndex else -1 filter { arrayContentsEq(rulesData.paramTypes, it.parameterTypes) }.lastIndex else -1
val modifyLastIndex = if (modifiers != null && matchIndex != null) filter { modifiers.contains(it) }.lastIndex else -1 val nameLastIndex =
val nameCdsLastIndex = if (nameConditions != null && matchIndex != null) filter { nameConditions.contains(it) }.lastIndex else -1 if (rulesData.name.isNotBlank() && matchIndex != null) filter { rulesData.name == it.name }.lastIndex else -1
val modifyLastIndex =
if (rulesData.modifiers != null && matchIndex != null) filter { rulesData.modifiers!!.contains(it) }.lastIndex else -1
val nameCdsLastIndex =
if (rulesData.nameConditions != null && matchIndex != null) filter { rulesData.nameConditions!!.contains(it) }.lastIndex else -1
forEachIndexed { p, it -> forEachIndexed { p, it ->
var isMatched = false var isMatched = false
var conditions = true var conditions = true
if (name.isNotBlank()) if (rulesData.name.isNotBlank())
conditions = (name == it.name).let { conditions = (rulesData.name == it.name).let {
if (it) nameIndex++ if (it) nameIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -242,8 +225,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) || abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) ||
(nameLastIndex == nameIndex && matchIndex.second.not())) (nameLastIndex == nameIndex && matchIndex.second.not()))
} }
if (returnType != null) if (rulesData.returnType != null)
conditions = (conditions && returnType == it.returnType).let { conditions = (conditions && rulesData.returnType == it.returnType).let {
if (it) returnTypeIndex++ if (it) returnTypeIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -252,8 +235,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (returnTypeLastIndex - returnTypeIndex) && matchIndex.second) || abs(matchIndex.first) == (returnTypeLastIndex - returnTypeIndex) && matchIndex.second) ||
(returnTypeLastIndex == returnTypeIndex && matchIndex.second.not())) (returnTypeLastIndex == returnTypeIndex && matchIndex.second.not()))
} }
if (paramCount >= 0) if (rulesData.paramCount >= 0)
conditions = (conditions && it.parameterTypes.size == paramCount).let { conditions = (conditions && it.parameterTypes.size == rulesData.paramCount).let {
if (it) paramCountIndex++ if (it) paramCountIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -262,8 +245,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) || abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) ||
(paramCountLastIndex == paramCountIndex && matchIndex.second.not())) (paramCountLastIndex == paramCountIndex && matchIndex.second.not()))
} }
if (paramCountRange.isEmpty().not()) if (rulesData.paramCountRange.isEmpty().not())
conditions = (conditions && it.parameterTypes.size in paramCountRange).let { conditions = (conditions && it.parameterTypes.size in rulesData.paramCountRange).let {
if (it) paramCountRangeIndex++ if (it) paramCountRangeIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -272,8 +255,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) || abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) ||
(paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not())) (paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not()))
} }
if (paramTypes != null) if (rulesData.paramTypes != null)
conditions = (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).let { conditions = (conditions && arrayContentsEq(rulesData.paramTypes, it.parameterTypes)).let {
if (it) paramTypeIndex++ if (it) paramTypeIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -282,8 +265,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) || abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) ||
(paramTypeLastIndex == paramTypeIndex && matchIndex.second.not())) (paramTypeLastIndex == paramTypeIndex && matchIndex.second.not()))
} }
if (modifiers != null) if (rulesData.modifiers != null)
conditions = (conditions && modifiers.contains(it)).let { conditions = (conditions && rulesData.modifiers!!.contains(it)).let {
if (it) modifyIndex++ if (it) modifyIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -292,8 +275,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) || abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) ||
(modifyLastIndex == modifyIndex && matchIndex.second.not())) (modifyLastIndex == modifyIndex && matchIndex.second.not()))
} }
if (nameConditions != null) if (rulesData.nameConditions != null)
conditions = (conditions && nameConditions.contains(it)).let { conditions = (conditions && rulesData.nameConditions!!.contains(it)).let {
if (it) nameCdsIndex++ if (it) nameCdsIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -308,16 +291,10 @@ internal object ReflectionTool {
(lastIndex == p && orderIndex.second.not()))).also { isMatched = true } (lastIndex == p && orderIndex.second.not()))).also { isMatched = true }
if (conditions && isMatched) methods.add(it.apply { isAccessible = true }) if (conditions && isMatched) methods.add(it.apply { isAccessible = true })
} }
} ?: error("Can't find this Method [$name] because classSet is null") } ?: error("Can't find this Method [${rulesData.name}] because classSet is null")
methods.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putMethods(hashCode, methods) } methods.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putMethods(hashCode, methods) }
?: if (isFindInSuperClass && classSet.hasExtends) ?: if (rulesData.isFindInSuper && classSet.hasExtends)
findMethods( findMethods(classSet.superclass, orderIndex, matchIndex, rulesData)
classSet.superclass,
orderIndex, matchIndex,
name, modifiers, nameConditions,
returnType, paramCount, paramCountRange,
paramTypes, isFindInSuperClass = true
)
else throw NoSuchMethodError( else throw NoSuchMethodError(
"Can't find this Method --> " + "Can't find this Method --> " +
when { when {
@@ -330,16 +307,16 @@ internal object ReflectionTool {
matchIndex.second.not() -> "matchIndex:[last] " matchIndex.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex.first}] " else -> "matchIndex:[${matchIndex.first}] "
} + } +
when (nameConditions) { when (rulesData.nameConditions) {
null -> "" null -> ""
else -> "nameConditions:$nameConditions " else -> "nameConditions:${rulesData.nameConditions} "
} + } +
"name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " + "name:[${rulesData.name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " + "paramCount:[${rulesData.paramCount.takeIf { it >= 0 } ?: "unspecified"}] " +
"paramCountRange:[${paramCountRange.takeIf { it.isEmpty().not() } ?: "unspecified"}] " + "paramCountRange:[${rulesData.paramCountRange.takeIf { it.isEmpty().not() } ?: "unspecified"}] " +
"paramTypes:[${paramTypes.typeOfString()}] " + "paramTypes:[${rulesData.paramTypes.typeOfString()}] " +
"returnType:[${returnType ?: "unspecified"}] " + "returnType:[${rulesData.returnType ?: "unspecified"}] " +
"modifiers:${modifiers ?: "[]"} " + "modifiers:${rulesData.modifiers ?: "[]"} " +
"in [$classSet] " + "in [$classSet] " +
"by $TAG" "by $TAG"
) )
@@ -351,32 +328,25 @@ internal object ReflectionTool {
* @param classSet 构造方法所在类 * @param classSet 构造方法所在类
* @param orderIndex 字节码顺序下标 * @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标 * @param matchIndex 字节码筛选下标
* @param modifiers 构造方法描述 * @param rulesData 规则查询数据
* @param paramCount 构造方法参数个数
* @param paramCountRange 构造方法参数个数范围
* @param paramTypes 构造方法参数类型
* @param isFindInSuperClass 是否在未找到后继续在当前 [classSet] 的父类中查找
* @return [HashSet]<[Constructor]> * @return [HashSet]<[Constructor]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [paramTypes] 目标类不存在 * @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [ConstructorRulesData.paramTypes] 目标类不存在
* @throws NoSuchMethodError 如果找不到构造方法 * @throws NoSuchMethodError 如果找不到构造方法
*/ */
internal fun findConstructors( internal fun findConstructors(
classSet: Class<*>?, classSet: Class<*>?,
orderIndex: Pair<Int, Boolean>?, orderIndex: Pair<Int, Boolean>?,
matchIndex: Pair<Int, Boolean>?, matchIndex: Pair<Int, Boolean>?,
modifiers: ModifierRules?, rulesData: ConstructorRulesData
paramCount: Int,
paramCountRange: IntRange,
paramTypes: Array<out Class<*>>?,
isFindInSuperClass: Boolean
): HashSet<Constructor<*>> { ): HashSet<Constructor<*>> {
paramTypes?.takeIf { it.isNotEmpty() } rulesData.paramTypes?.takeIf { it.isNotEmpty() }
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Constructor match paramType[$p] class is not found") } ?.forEachIndexed { p, it -> if (it == UndefinedType) error("Constructor match paramType[$p] class is not found") }
if (orderIndex == null && matchIndex == null && if (orderIndex == null && matchIndex == null &&
modifiers == null && paramCount < 0 && rulesData.modifiers == null && rulesData.paramCount < 0 &&
paramCountRange.isEmpty() && paramTypes == null rulesData.paramCountRange.isEmpty() && rulesData.paramTypes == null
) error("You must set a condition when finding a Constructor") ) error("You must set a condition when finding a Constructor")
val hashCode = ("[$orderIndex][$matchIndex][$paramCount][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode() val hashCode = ("[$orderIndex][$matchIndex][${rulesData.paramCount}][${rulesData.paramTypes.typeOfString()}]" +
"[${rulesData.modifiers}][$classSet]").hashCode()
return ReflectsCacheStore.findConstructors(hashCode) ?: let { return ReflectsCacheStore.findConstructors(hashCode) ?: let {
val constructors = HashSet<Constructor<*>>() val constructors = HashSet<Constructor<*>>()
classSet?.declaredConstructors?.apply { classSet?.declaredConstructors?.apply {
@@ -385,17 +355,19 @@ internal object ReflectionTool {
var paramCountRangeIndex = -1 var paramCountRangeIndex = -1
var modifyIndex = -1 var modifyIndex = -1
val paramCountLastIndex = val paramCountLastIndex =
if (paramCount >= 0 && matchIndex != null) filter { paramCount == it.parameterTypes.size }.lastIndex else -1 if (rulesData.paramCount >= 0 && matchIndex != null) filter { rulesData.paramCount == it.parameterTypes.size }.lastIndex else -1
val paramCountRangeLastIndex = if (paramCountRange.isEmpty().not() && matchIndex != null) val paramCountRangeLastIndex = if (rulesData.paramCountRange.isEmpty().not() && matchIndex != null)
filter { it.parameterTypes.size in paramCountRange }.lastIndex else -1 filter { it.parameterTypes.size in rulesData.paramCountRange }.lastIndex else -1
val paramTypeLastIndex = val paramTypeLastIndex =
if (paramTypes != null && matchIndex != null) filter { arrayContentsEq(paramTypes, it.parameterTypes) }.lastIndex else -1 if (rulesData.paramTypes != null && matchIndex != null)
val modifyLastIndex = if (modifiers != null && matchIndex != null) filter { modifiers.contains(it) }.lastIndex else -1 filter { arrayContentsEq(rulesData.paramTypes, it.parameterTypes) }.lastIndex else -1
val modifyLastIndex =
if (rulesData.modifiers != null && matchIndex != null) filter { rulesData.modifiers!!.contains(it) }.lastIndex else -1
forEachIndexed { p, it -> forEachIndexed { p, it ->
var isMatched = false var isMatched = false
var conditions = true var conditions = true
if (paramCount >= 0) if (rulesData.paramCount >= 0)
conditions = (it.parameterTypes.size == paramCount).let { conditions = (it.parameterTypes.size == rulesData.paramCount).let {
if (it) paramCountIndex++ if (it) paramCountIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -404,8 +376,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) || abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) ||
(paramCountLastIndex == paramCountIndex && matchIndex.second.not())) (paramCountLastIndex == paramCountIndex && matchIndex.second.not()))
} }
if (paramCountRange.isEmpty().not()) if (rulesData.paramCountRange.isEmpty().not())
conditions = (conditions && it.parameterTypes.size in paramCountRange).let { conditions = (conditions && it.parameterTypes.size in rulesData.paramCountRange).let {
if (it) paramCountRangeIndex++ if (it) paramCountRangeIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -414,8 +386,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) || abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) ||
(paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not())) (paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not()))
} }
if (paramTypes != null) if (rulesData.paramTypes != null)
conditions = (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).let { conditions = (conditions && arrayContentsEq(rulesData.paramTypes, it.parameterTypes)).let {
if (it) paramTypeIndex++ if (it) paramTypeIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -424,8 +396,8 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) || abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) ||
(paramTypeLastIndex == paramTypeIndex && matchIndex.second.not())) (paramTypeLastIndex == paramTypeIndex && matchIndex.second.not()))
} }
if (modifiers != null) if (rulesData.modifiers != null)
conditions = (conditions && modifiers.contains(it)).let { conditions = (conditions && rulesData.modifiers!!.contains(it)).let {
if (it) modifyIndex++ if (it) modifyIndex++
isMatched = true isMatched = true
it && (matchIndex == null || it && (matchIndex == null ||
@@ -442,13 +414,8 @@ internal object ReflectionTool {
} }
} ?: error("Can't find this Constructor because classSet is null") } ?: error("Can't find this Constructor because classSet is null")
return constructors.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putConstructors(hashCode, constructors) } return constructors.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putConstructors(hashCode, constructors) }
?: if (isFindInSuperClass && classSet.hasExtends) ?: if (rulesData.isFindInSuper && classSet.hasExtends)
findConstructors( findConstructors(classSet.superclass, orderIndex, matchIndex, rulesData)
classSet.superclass,
orderIndex, matchIndex,
modifiers, paramCount, paramCountRange,
paramTypes, isFindInSuperClass = true
)
else throw NoSuchMethodError( else throw NoSuchMethodError(
"Can't find this Constructor --> " + "Can't find this Constructor --> " +
when { when {
@@ -461,10 +428,10 @@ internal object ReflectionTool {
matchIndex.second.not() -> "matchIndex:[last] " matchIndex.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex.first}] " else -> "matchIndex:[${matchIndex.first}] "
} + } +
"paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " + "paramCount:[${rulesData.paramCount.takeIf { it >= 0 } ?: "unspecified"}] " +
"paramCountRange:[${paramCountRange.takeIf { it.isEmpty().not() } ?: "unspecified"}] " + "paramCountRange:[${rulesData.paramCountRange.takeIf { it.isEmpty().not() } ?: "unspecified"}] " +
"paramTypes:[${paramTypes.typeOfString()}] " + "paramTypes:[${rulesData.paramTypes.typeOfString()}] " +
"modifiers:${modifiers ?: "[]"} " + "modifiers:${rulesData.modifiers ?: "[]"} " +
"in [$classSet] " + "in [$classSet] " +
"by $TAG" "by $TAG"
) )

View File

@@ -29,9 +29,9 @@
package com.highcapable.yukihookapi.hook.xposed.bridge.factory package com.highcapable.yukihookapi.hook.xposed.bridge.factory
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
import com.highcapable.yukihookapi.hook.core.finder.members.ConstructorFinder import com.highcapable.yukihookapi.hook.core.finder.members.ConstructorFinder
import com.highcapable.yukihookapi.hook.core.finder.members.MethodFinder import com.highcapable.yukihookapi.hook.core.finder.members.MethodFinder
import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder
import com.highcapable.yukihookapi.hook.log.yLoggerE import com.highcapable.yukihookapi.hook.log.yLoggerE
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodHook
@@ -81,12 +81,12 @@ internal object YukiHookHelper {
if (YukiHookBridge.hasXposedBridge) XposedHelpers.findClass(name, loader) else null if (YukiHookBridge.hasXposedBridge) XposedHelpers.findClass(name, loader) else null
/** /**
* Hook [MemberBaseFinder.BaseResult] * Hook [BaseFinder.BaseResult]
* @param traction 直接调用 [MemberBaseFinder.BaseResult] * @param traction 直接调用 [BaseFinder.BaseResult]
* @param callback 回调 * @param callback 回调
* @return [Pair] - ([YukiMemberHook.Unhook] or null,[Boolean] 是否已经 Hook) * @return [Pair] - ([YukiMemberHook.Unhook] or null,[Boolean] 是否已经 Hook)
*/ */
internal fun hook(traction: MemberBaseFinder.BaseResult, callback: YukiHookCallback) = runCatching { internal fun hook(traction: BaseFinder.BaseResult, callback: YukiHookCallback) = runCatching {
hookMember( hookMember(
when (traction) { when (traction) {
is MethodFinder.Result -> traction.ignored().give() is MethodFinder.Result -> traction.ignored().give()