Added more function in MethodFinder, ConstructorFinder, FieldFinder

This commit is contained in:
2022-08-06 03:24:03 +08:00
parent 95897a2621
commit 832245d4a3
10 changed files with 1191 additions and 284 deletions

View File

@@ -16,6 +16,8 @@ class ConstructorFinder internal constructor(override val hookInstance: YukiMemb
> `Constructor` 查找类。
可通过指定类型查找指定构造方法或一组构造方法。
### paramCount [field]
```kotlin
@@ -112,6 +114,24 @@ fun paramCount(num: Int): IndexTypeCondition
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
### paramCount [method]
```kotlin
fun paramCount(numRange: IntRange): IndexTypeCondition
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 设置 `Constructor` 参数个数范围。
你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数范围。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
### superClass [method]
```kotlin
@@ -160,7 +180,7 @@ inline fun constructor(initiate: ConstructorFinder.() -> Unit)
> 创建需要重新查找的 `Constructor`。
你可以添加多个备选构造方法,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
你可以添加多个备选 `Constructor`,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
#### Result [class]
@@ -179,13 +199,17 @@ inner class Result internal constructor()
##### onFind [method]
```kotlin
fun onFind(initiate: Constructor<*>.() -> Unit)
fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit)
```
**变更记录**
`v1.0.1` `新增`
`v1.0.93` `修改`
`initiate` 参数 `Constructor` 变为 `HashSet<Constructor>`
**功能描述**
> 当在 `RemedyPlan` 中找到结果时。
@@ -207,13 +231,17 @@ constructor {
### Result [class]
```kotlin
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val e: Throwable?)
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
```
**变更记录**
`v1.0` `添加`
`v1.0.93` `修改`
继承到接口 `BaseResult`
**功能描述**
> `Constructor` 查找结果实现类。
@@ -247,6 +275,7 @@ constructor {
// Your code here.
}.result {
get().call()
all()
remedys {}
onNoSuchConstructor {}
}
@@ -266,6 +295,8 @@ fun get(): Instance
> 获得 `Constructor` 实例处理类。
若有多个 `Constructor` 结果只会返回第一个。
!> 若你设置了 `remedys` 请使用 `wait` 回调结果方法。
**功能示例**
@@ -300,6 +331,36 @@ constructor {
}.get().newInstance<TestClass>("param1", "param2")
```
#### all [method]
```kotlin
fun all(): ArrayList<Instance>
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获得 `Constructor` 实例处理类数组。
返回全部查询条件匹配的多个 `Constructor` 实例结果并在 `isBindToHooker` 时设置到 `hookInstance`
**功能示例**
你可以通过此方法来获得当前条件结果中匹配的全部 `Constructor`
> 示例如下
```kotlin
constructor {
// Your code here.
}.all().forEach { instance ->
instance.call(...)
}
```
#### give [method]
```kotlin
@@ -314,6 +375,28 @@ fun give(): Constructor<*>?
> 得到构造方法本身。
若有多个 `Constructor` 结果只会返回第一个。
在查询条件找不到任何结果的时候将返回 `null`
#### giveAll [method]
```kotlin
fun giveAll(): HashSet<Constructor<*>>
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 得到 `Constructor` 本身数组。
返回全部查询条件匹配的多个 `Constructor` 实例。
在查询条件找不到任何结果的时候将返回空的 `HashSet`
#### wait [method]
```kotlin
@@ -328,6 +411,28 @@ fun wait(initiate: Instance.() -> Unit)
> 获得 `Constructor` 实例处理类,配合 `RemedyPlan` 使用。
若有多个 `Constructor` 结果只会返回第一个。
!> 若你设置了 `remedys` 必须使用此方法才能获得结果。
!> 若你没有设置 `remedys` 此方法将不会被回调。
#### waitAll [method]
```kotlin
fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获得 `Constructor` 实例处理类数组,配合 `RemedyPlan` 使用。
返回全部查询条件匹配的多个 `Constructor` 实例结果。
!> 若你设置了 `remedys` 必须使用此方法才能获得结果。
!> 若你没有设置 `remedys` 此方法将不会被回调。
@@ -348,11 +453,11 @@ inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
**功能描述**
> 创建构造方法重查找功能。
> 创建 `Constructor` 重查找功能。
**功能示例**
当你遇到一种构造方法可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchConstructor` 捕获异常二次查找构造方法
当你遇到一种 `Constructor` 可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchConstructor` 捕获异常二次查找 `Constructor`
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
@@ -387,7 +492,7 @@ inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
**功能描述**
> 监听找不到构造方法时。
> 监听找不到 `Constructor` 时。
只会返回第一次的错误信息,不会返回 `RemedyPlan` 的错误信息。
@@ -410,13 +515,17 @@ fun ignoredError(): Result
#### Instance [class]
```kotlin
inner class Instance internal constructor()
inner class Instance internal constructor(private val constructor: Constructor<*>?)
```
**变更记录**
`v1.0.2` `新增`
`v1.0.93` `修改`
新增 `constructor` 参数
**功能描述**
> `Constructor` 实例处理类。
@@ -433,7 +542,7 @@ fun call(vararg param: Any?): Any?
**功能描述**
> 执行构造方法创建目标实例,不指定目标实例类型。
> 执行 `Constructor` 创建目标实例,不指定目标实例类型。
##### newInstance [method]
@@ -447,4 +556,4 @@ fun <T> newInstance(vararg param: Any?): T?
**功能描述**
> 执行构造方法创建目标实例 ,指定 `T` 目标实例类型。
> 执行 `Constructor` 创建目标实例 ,指定 `T` 目标实例类型。

View File

@@ -16,6 +16,8 @@ class FieldFinder internal constructor(override val hookInstance: YukiMemberHook
> `Field` 查找类。
可通过指定类型查找指定变量或一组变量。
### ~~classSet [field]~~ <!-- {docsify-ignore} -->
**变更记录**
@@ -58,7 +60,7 @@ var type: Any?
> 设置 `Field` 类型。
可不填写类型,默认模糊查找并取第一个匹配的 `Field`
可不填写类型。
### modifiers [method]
@@ -78,7 +80,7 @@ inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition
> 设置 `Field` 标识符筛选条件。
可不设置筛选条件,默认模糊查找并取第一个匹配的 `Field`
可不设置筛选条件。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -110,7 +112,7 @@ fun name(value: String): IndexTypeCondition
> 设置 `Field` 名称。
!> 若不填写名称则必须存在一个其它条件,默认模糊查找并取第一个匹配的 `Field`
!> 若不填写名称则必须存在一个其它条件。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -128,7 +130,7 @@ inline fun name(initiate: NameConditions.() -> Unit): IndexTypeCondition
> 设置 `Field` 名称条件。
!> 若不填写名称则必须存在一个其它条件,默认模糊查找并取第一个匹配的 `Field`
!> 若不填写名称则必须存在一个其它条件。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -146,7 +148,7 @@ fun type(value: Any): IndexTypeCondition
> 设置 `Field` 类型。
!> 可不填写类型,默认模糊查找并取第一个匹配的 `Field`
!> 可不填写类型。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -166,16 +168,92 @@ fun superClass(isOnlySuperClass: Boolean)
!> 若当前 `classSet` 的父类较多可能会耗时API 会自动循环到父类继承是 `Any` 前的最后一个类。
### RemedyPlan [class]
```kotlin
inner class RemedyPlan internal constructor()
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> `Field` 重查找实现类,可累计失败次数直到查找成功。
#### field [method]
```kotlin
inline fun field(initiate: FieldFinder.() -> Unit): Result
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 创建需要重新查找的 `Field`。
你可以添加多个备选 `Field`,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
#### Result [class]
```kotlin
inner class Result internal constructor()
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> `RemedyPlan` 结果实现类。
##### onFind [method]
```kotlin
fun onFind(initiate: HashSet<Field>.() -> Unit)
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 当在 `RemedyPlan` 中找到结果时。
**功能示例**
你可以方便地对重查找的 `Field` 实现 `onFind` 方法。
> 示例如下
```kotlin
field {
// Your code here.
}.onFind {
// Your code here.
}
```
### Result [class]
```kotlin
inner class Result internal constructor(internal val isNoSuch: Boolean, private val e: Throwable?)
inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
```
**变更记录**
`v1.0` `添加`
`v1.0.93` `修改`
继承到接口 `BaseResult`
**功能描述**
> `Field` 查找结果实现类。
@@ -212,22 +290,28 @@ field {
get(instance).string()
get(instance).cast<CustomClass>()
get().boolean()
all(instance)
give()
giveAll()
onNoSuchField {}
}
```
#### get [method]
```kotlin
fun get(instance: Any?): Instance
```
**变更记录**
`v1.0` `添加`
**功能描述**
> 得到变量实例处理类。
> 获得 `Field` 实例处理类。
若有多个 `Field` 结果只会返回第一个。
**功能示例**
@@ -251,6 +335,36 @@ field {
}.get().set("something")
```
#### all [method]
```kotlin
fun all(instance: Any?): ArrayList<Instance>
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获得 `Field` 实例处理类数组。
返回全部查询条件匹配的多个 `Field` 实例结果。
**功能示例**
你可以通过此方法来获得当前条件结果中匹配的全部 `Field`,其变量所在实例用法与 `get` 相同。
> 示例如下
```kotlin
field {
// Your code here.
}.all(instance).forEach { instance ->
instance.self
}
```
#### give [method]
```kotlin
@@ -263,7 +377,104 @@ fun give(): Field?
**功能描述**
> 得到变量本身。
> 得到 `Field` 本身。
若有多个 Field 结果只会返回第一个。
在查询条件找不到任何结果的时候将返回 `null`
#### giveAll [method]
```kotlin
fun giveAll(): HashSet<Field>
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 得到 `Field` 本身数组。
返回全部查询条件匹配的多个 `Field` 实例。
在查询条件找不到任何结果的时候将返回空的 `HashSet`
#### wait [method]
```kotlin
fun wait(instance: Any?, initiate: Instance.() -> Unit)
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获得 `Field` 实例处理类,配合 `RemedyPlan` 使用。
若有多个 `Field` 结果只会返回第一个。
!> 若你设置了 `remedys` 必须使用此方法才能获得结果。
!> 若你没有设置 `remedys` 此方法将不会被回调。
#### waitAll [method]
```kotlin
fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获得 `Field` 实例处理类数组,配合 `RemedyPlan` 使用。
返回全部查询条件匹配的多个 `Field` 实例结果。
!> 若你设置了 `remedys` 必须使用此方法才能获得结果。
!> 若你没有设置 `remedys` 此方法将不会被回调。
#### remedys [method]
```kotlin
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 创建 `Field` 重查找功能。
**功能示例**
当你遇到一种 `Field` 可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchField` 捕获异常二次查找 `Field`
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
> 示例如下
```kotlin
field {
// Your code here.
}.remedys {
field {
// Your code here.
}
field {
// Your code here.
}
}
```
#### onNoSuchField [method]
@@ -277,7 +488,7 @@ fun onNoSuchField(result: (Throwable) -> Unit): Result
**功能描述**
> 监听找不到变量时。
> 监听找不到 `Field` 时。
#### ignoredError [method]
@@ -298,17 +509,37 @@ fun ignoredError(): Result
#### Instance [class]
```kotlin
inner class Instance internal constructor(private val instance: Any?, val self: Any?)
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
```
**变更记录**
`v1.0` `添加`
`v1.0.93` `修改`
新增 `field` 参数
移动 `self` 参数到类变量
**功能描述**
> `Field` 实例变量处理类。
##### self [field]
```kotlin
val self: Any?
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获取当前 `Field` 自身的实例化对象。
##### cast [method]
```kotlin
@@ -327,7 +558,7 @@ fun <T> cast(): T?
**功能描述**
> 得到变量实例。
> 得到当前 `Field` 实例。
##### byte [method]
@@ -341,7 +572,7 @@ fun byte(): Byte?
**功能描述**
> 得到变量 Byte 实例。
> 得到当前 `Field` Byte 实例。
##### int [method]
@@ -361,7 +592,7 @@ fun int(): Int
**功能描述**
> 得到变量 Int 实例。
> 得到当前 `Field` Int 实例。
##### long [method]
@@ -381,7 +612,7 @@ fun long(): Long
**功能描述**
> 得到变量 Long 实例。
> 得到当前 `Field` Long 实例。
##### short [method]
@@ -400,7 +631,7 @@ fun short(): Short
**功能描述**
> 得到变量 Short 实例。
> 得到当前 `Field` Short 实例。
##### double [method]
@@ -420,7 +651,7 @@ fun double(): Double
**功能描述**
> 得到变量 Double 实例。
> 得到当前 `Field` Double 实例。
##### float [method]
@@ -439,7 +670,7 @@ fun float(): Float
**功能描述**
> 得到变量 Float 实例。
> 得到当前 `Field` Float 实例。
##### string [method]
@@ -459,7 +690,7 @@ fun string(): String
**功能描述**
> 得到变量 String 实例。
> 得到当前 `Field` String 实例。
##### char [method]
@@ -473,7 +704,7 @@ fun char(): Char
**功能描述**
> 得到变量 Char 实例。
> 得到当前 `Field` Char 实例。
##### boolean [method]
@@ -493,7 +724,7 @@ fun boolean(): Boolean
**功能描述**
> 得到变量 Boolean 实例。
> 得到当前 `Field` Boolean 实例。
##### any [method]
@@ -512,7 +743,7 @@ fun any(): Any?
**功能描述**
> 得到变量 Any 实例。
> 得到当前 `Field` Any 实例。
##### array [method]
@@ -526,7 +757,7 @@ inline fun <reified T> array(): Array<T>
**功能描述**
> 得到变量 Array 实例。
> 得到当前 `Field` Array 实例。
##### list [method]
@@ -540,7 +771,7 @@ inline fun <reified T> list(): List<T>
**功能描述**
> 得到变量 List 实例。
> 得到当前 `Field` List 实例。
##### set [method]
@@ -554,7 +785,7 @@ fun set(any: Any?)
**功能描述**
> 设置变量实例。
> 设置当前 `Field` 实例。
##### setTrue [method]
@@ -567,7 +798,7 @@ fun setTrue()
**功能描述**
> 设置变量实例为 `true`。
> 设置当前 `Field` 实例为 `true`。
!> 请确保实例对象类型为 `Boolean`
@@ -583,7 +814,7 @@ fun setFalse()
**功能描述**
> 设置变量实例为 `false`。
> 设置当前 `Field` 实例为 `false`。
!> 请确保实例对象类型为 `Boolean`
@@ -599,4 +830,4 @@ fun setNull()
**功能描述**
> 设置变量实例为 `null`
> 设置当前 `Field` 实例为 `null`

View File

@@ -16,6 +16,8 @@ class MethodFinder internal constructor(override val hookInstance: YukiMemberHoo
> `Method` 查找类。
可通过指定类型查找指定方法或一组方法。
### name [field]
```kotlin
@@ -66,7 +68,7 @@ var returnType: Any?
**功能描述**
> 设置 `Method` 返回值,可不填写返回值,默认模糊查找并取第一个匹配的 `Method`
> 设置 `Method` 返回值,可不填写返回值。
### modifiers [method]
@@ -86,7 +88,7 @@ inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition
> 设置 `Method` 标识符筛选条件。
可不设置筛选条件,默认模糊查找并取第一个匹配的 `Method`
可不设置筛选条件。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -154,7 +156,7 @@ fun name(value: String): IndexTypeCondition
> 设置 `Method` 名称。
!> 若不填写名称则必须存在一个其它条件,默认模糊查找并取第一个匹配的 `Method`
!> 若不填写名称则必须存在一个其它条件。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -172,7 +174,7 @@ inline fun name(initiate: NameConditions.() -> Unit): IndexTypeCondition
> 设置 `Method` 名称条件。
!> 若不填写名称则必须存在一个其它条件,默认模糊查找并取第一个匹配的 `Method`
!> 若不填写名称则必须存在一个其它条件。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -196,6 +198,24 @@ fun paramCount(num: Int): IndexTypeCondition
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
### paramCount [method]
```kotlin
fun paramCount(numRange: IntRange): IndexTypeCondition
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 设置 `Method` 参数个数范围。
你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数范围。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
### returnType [method]
```kotlin
@@ -210,7 +230,7 @@ fun returnType(value: Any): IndexTypeCondition
> 设置 `Method` 返回值。
可不填写返回值,默认模糊查找并取第一个匹配的 `Method`
可不填写返回值。
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
@@ -262,7 +282,7 @@ inline fun method(initiate: MethodFinder.() -> Unit): Result
> 创建需要重新查找的 `Method`。
你可以添加多个备选方法,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
你可以添加多个备选 `Method`,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
#### Result [class]
@@ -281,13 +301,17 @@ inner class Result internal constructor()
##### onFind [method]
```kotlin
fun onFind(initiate: Method.() -> Unit)
fun onFind(initiate: HashSet<Method>.() -> Unit)
```
**变更记录**
`v1.0.1` `新增`
`v1.0.93` `修改`
`initiate` 参数 `Method` 变为 `HashSet<Method>`
**功能描述**
> 当在 `RemedyPlan` 中找到结果时。
@@ -309,13 +333,17 @@ method {
### Result [class]
```kotlin
inner class Result internal constructor(internal val isNoSuch: Boolean, private val e: Throwable?)
inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
```
**变更记录**
`v1.0` `添加`
`v1.0.93` `修改`
继承到接口 `BaseResult`
**功能描述**
> `Method` 查找结果实现类。
@@ -349,6 +377,7 @@ method {
// Your code here.
}.result {
get(instance).call()
all(instance)
remedys {}
onNoSuchMethod {}
}
@@ -368,6 +397,8 @@ fun get(instance: Any?): Instance
> 获得 `Method` 实例处理类。
若有多个 `Method` 结果只会返回第一个。
!> 若你设置了 `remedys` 请使用 `wait` 回调结果方法。
**功能示例**
@@ -392,6 +423,36 @@ method {
}.get().call()
```
#### all [method]
```kotlin
fun all(instance: Any?): ArrayList<Instance>
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获得 `Method` 实例处理类数组。
返回全部查询条件匹配的多个 `Method` 实例结果并在 `isBindToHooker` 时设置到 `hookInstance`
**功能示例**
你可以通过此方法来获得当前条件结果中匹配的全部 `Method`,其方法所在实例用法与 `get` 相同。
> 示例如下
```kotlin
method {
// Your code here.
}.all(instance).forEach { instance ->
instance.call(...)
}
```
#### give [method]
```kotlin
@@ -404,7 +465,29 @@ fun give(): Method?
**功能描述**
> 得到方法本身。
> 得到 `Method` 本身。
若有多个 `Method` 结果只会返回第一个。
在查询条件找不到任何结果的时候将返回 `null`
#### giveAll [method]
```kotlin
fun giveAll(): HashSet<Method>
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 得到 `Method` 本身数组。
返回全部查询条件匹配的多个 `Method` 实例。
在查询条件找不到任何结果的时候将返回空的 `HashSet`
#### wait [method]
@@ -420,6 +503,28 @@ fun wait(instance: Any?, initiate: Instance.() -> Unit)
> 获得 `Method` 实例处理类,配合 `RemedyPlan` 使用。
若有多个 `Method` 结果只会返回第一个。
!> 若你设置了 `remedys` 必须使用此方法才能获得结果。
!> 若你没有设置 `remedys` 此方法将不会被回调。
#### waitAll [method]
```kotlin
fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
```
**变更记录**
`v1.0.93` `新增`
**功能描述**
> 获得 `Method` 实例处理类数组,配合 `RemedyPlan` 使用。
返回全部查询条件匹配的多个 `Method` 实例结果。
!> 若你设置了 `remedys` 必须使用此方法才能获得结果。
!> 若你没有设置 `remedys` 此方法将不会被回调。
@@ -440,11 +545,11 @@ inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
**功能描述**
> 创建方法重查找功能。
> 创建 `Method` 重查找功能。
**功能示例**
当你遇到一种方法可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchMethod` 捕获异常二次查找方法
当你遇到一种 `Method` 可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchMethod` 捕获异常二次查找 `Method`
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
@@ -479,7 +584,7 @@ inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
**功能描述**
> 监听找不到方法时。
> 监听找不到 `Method` 时。
只会返回第一次的错误信息,不会返回 `RemedyPlan` 的错误信息。
@@ -502,13 +607,17 @@ fun ignoredError(): Result
#### Instance [class]
```kotlin
inner class Instance internal constructor(private val instance: Any?)
inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
```
**变更记录**
`v1.0.2` `新增`
`v1.0.93` `修改`
新增 `method` 参数
**功能描述**
> `Method` 实例处理类。

View File

@@ -325,6 +325,58 @@ Test::class.java.method {
更多用法可参考 [NameConditions](api/document?id=nameconditions-class)。
### 多重查询
有些时候,我们可能需要查询一个 `Class` 中具有相同特征的一组方法、构造方法、变量,这个时候,我们就可以利用相对条件匹配来完成。
在查询条件结果的基础上,我们只需要把 `get` 换为 `all` 即可得到匹配条件的全部字节码。
假设这次我们要得到 `Class` 中方法参数个数范围在 `1..3` 的全部方法,可以使用如下实现。
> 示例如下
```kotlin
// 假设这就是这个 Class 的实例
val instance = Test()
// 使用 YukiHookAPI 调用并执行
Test::class.java.method {
paramCount(1..3)
}.all(instance).forEach { instance ->
// 调用执行每个方法
instance.call(...)
}
```
上述示例可完美匹配到如下 3 个方法。
`private void doTask(String taskName)`
`private void release(Release release, Function<boolean, String> function, Task task)`
`private void b(String a)`
通过观察 `Class` 中有两个名称为 `b` 的方法,可以使用如下实现。
> 示例如下
```kotlin
// 假设这就是这个 Class 的实例
val instance = Test()
// 使用 YukiHookAPI 调用并执行
Test::class.java.method {
name = "b"
}.all(instance).forEach { instance ->
// 调用执行每个方法
instance.call(...)
}
```
上述示例可完美匹配到如下 2 个方法。
`private void b()`
`private void b(String a)`
### 静态字节码
有些方法和变量在 `Class` 中是静态的实现,这个时候,我们不需要传入实例就可以调用它们。
@@ -625,7 +677,7 @@ Test::class.java.method {
!> 特别注意使用了 `RemedyPlan` 的方法查询结果不能再使用 `get` 的方式得到方法实例,应当使用 `wait` 方法。
更多用法可参考 [Method RemedyPlan](api/document?id=remedyplan-class) 以及 [Constructor RemedyPlan](api/document?id=remedyplan-class-1)。
更多用法可参考 [Method RemedyPlan](api/document?id=remedyplan-class)[Constructor RemedyPlan](api/document?id=remedyplan-class-1)、[Field RemedyPlan](api/document?id=remedyplan-class-2)
### 相对匹配

View File

@@ -44,8 +44,8 @@ import java.lang.reflect.Constructor
/**
* [Constructor] 查找类
*
* 可通过指定类型查找指定构造方法
* @param hookInstance 当前 Hook 实例 - 填写后将自动设置 [YukiMemberHookCreater.MemberHookCreater.member]
* 可通过指定类型查找指定构造方法或一组构造方法
* @param hookInstance 当前 Hook 实例 - 填写后将自动设置 [YukiMemberHookCreater.MemberHookCreater.members]
* @param classSet 当前需要查找的 [Class] 实例
*/
class ConstructorFinder @PublishedApi internal constructor(
@@ -67,6 +67,9 @@ class ConstructorFinder @PublishedApi internal constructor(
/** [Constructor] 参数数组 */
private var paramTypes: Array<out Class<*>>? = null
/** [Constructor] 参数个数范围 */
private var paramCountRange = IntRange.EMPTY
/** [ModifierRules] 实例 */
@PublishedApi
internal var modifiers: ModifierRules? = null
@@ -140,6 +143,20 @@ class ConstructorFinder @PublishedApi internal constructor(
return IndexTypeCondition(IndexConfigType.MATCH)
}
/**
* 设置 [Constructor] 参数个数范围
*
* 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param numRange 个数范围
* @return [BaseFinder.IndexTypeCondition]
*/
fun paramCount(numRange: IntRange): IndexTypeCondition {
paramCountRange = numRange
return IndexTypeCondition(IndexConfigType.MATCH)
}
/**
* 设置在 [classSet] 的所有父类中查找当前 [Constructor]
*
@@ -152,30 +169,35 @@ class ConstructorFinder @PublishedApi internal constructor(
}
/**
* 得到构造方法
* @return [Constructor]
* 得到构造方法或一组构造方法
* @return [HashSet]<[Constructor]>
* @throws NoSuchMethodError 如果找不到构造方法
*/
private val result
get() = ReflectionTool.findConstructor(
get() = ReflectionTool.findConstructors(
usedClassSet, orderIndex, matchIndex, modifiers,
paramCount, paramTypes, isFindInSuperClass
paramCount, paramCountRange, paramTypes, isFindInSuperClass
)
/**
* 设置实例
* @param isBind 是否将结果设置到目标 [YukiMemberHookCreater.MemberHookCreater]
* @param constructor 当前找到的 [Constructor]
* @param constructors 当前找到的 [Constructor] 数组
*/
private fun setInstance(isBind: Boolean, constructor: Constructor<*>) {
memberInstance = constructor
if (isBind) hookInstance?.member = constructor
private fun setInstance(isBind: Boolean, constructors: HashSet<Constructor<*>>) {
memberInstances.clear()
val result = constructors.takeIf { it.isNotEmpty() }?.onEach { memberInstances.add(it) }?.first()
if (isBind) hookInstance?.members?.apply {
clear()
result?.also { add(it) }
}
}
/**
* 得到构造方法结果
* 得到 [Constructor] 结果
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param isBind 是否将结果设置到目标 [YukiMemberHookCreater.MemberHookCreater]
* @return [Result]
*/
@YukiPrivateApi
@@ -184,7 +206,9 @@ class ConstructorFinder @PublishedApi internal constructor(
runBlocking {
isBindToHooker = isBind
setInstance(isBind, result)
}.result { onHookLogMsg(msg = "Find Constructor [${memberInstance}] takes ${it}ms [${hookTag}]") }
}.result { ms ->
memberInstances.takeIf { it.isNotEmpty() }?.forEach { onHookLogMsg(msg = "Find Constructor [$it] takes ${ms}ms [${hookTag}]") }
}
Result()
} else Result(isNoSuch = true, Throwable("classSet is null"))
} catch (e: Throwable) {
@@ -216,7 +240,7 @@ class ConstructorFinder @PublishedApi internal constructor(
/**
* 创建需要重新查找的 [Constructor]
*
* 你可以添加多个备选构造方法 - 直到成功为止
* 你可以添加多个备选 [Constructor] - 直到成功为止
*
* 若最后依然失败 - 将停止查找并输出错误日志
* @param initiate 方法体
@@ -235,13 +259,15 @@ class ConstructorFinder @PublishedApi internal constructor(
runCatching {
runBlocking {
setInstance(isBindToHooker, it.first.result)
}.result {
onHookLogMsg(msg = "Find Constructor [${memberInstance}] takes ${it}ms [${hookTag}]")
}.result { ms ->
memberInstances.takeIf { it.isNotEmpty() }
?.forEach { onHookLogMsg(msg = "Find Constructor [$it] takes ${ms}ms [${hookTag}]") }
}
isFindSuccess = true
it.second.onFindCallback?.invoke(memberInstance as Constructor<*>)
it.second.onFindCallback?.invoke(memberInstances.constructors())
remedyPlansCallback?.invoke()
onHookLogMsg(msg = "Constructor [${memberInstance}] trying ${p + 1} times success by RemedyPlan [${hookTag}]")
memberInstances.takeIf { it.isNotEmpty() }
?.forEach { onHookLogMsg(msg = "Constructor [$it] trying ${p + 1} times success by RemedyPlan [${hookTag}]") }
return@run
}.onFailure {
lastError = it
@@ -267,13 +293,13 @@ class ConstructorFinder @PublishedApi internal constructor(
inner class Result @PublishedApi internal constructor() {
/** 找到结果时的回调 */
internal var onFindCallback: (Constructor<*>.() -> Unit)? = null
internal var onFindCallback: (HashSet<Constructor<*>>.() -> Unit)? = null
/**
* 当找到结果时
* @param initiate 回调
*/
fun onFind(initiate: Constructor<*>.() -> Unit) {
fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit) {
onFindCallback = initiate
}
}
@@ -282,12 +308,12 @@ class ConstructorFinder @PublishedApi internal constructor(
/**
* [Constructor] 查找结果实现类
* @param isNoSuch 是否没有找到构造方法 - 默认否
* @param e 错误信息
* @param throwable 错误信息
*/
inner class Result internal constructor(
@PublishedApi internal val isNoSuch: Boolean = false,
@PublishedApi internal val e: Throwable? = null
) {
@PublishedApi internal val throwable: Throwable? = null
) : BaseResult {
/**
* 创建监听结果事件方法体
@@ -299,38 +325,89 @@ class ConstructorFinder @PublishedApi internal constructor(
/**
* 获得 [Constructor] 实例处理类
*
* - ❗在 [memberInstance] 结果为空时使用此方法将无法获得对象
* - 若有多个 [Constructor] 结果只会返回第一个
*
* - ❗在 [memberInstances] 结果为空时使用此方法将无法获得对象
*
* - ❗若你设置了 [remedys] 请使用 [wait] 回调结果方法
* @return [Instance]
*/
fun get() = Instance()
fun get() = Instance(give())
/**
* 得到构造方法本身
* 获得 [Constructor] 实例处理类数组
*
* - 返回全部查询条件匹配的多个 [Constructor] 实例结果并在 [isBindToHooker] 时设置到 [hookInstance]
*
* - ❗在 [memberInstances] 结果为空时使用此方法将无法获得对象
*
* - ❗若你设置了 [remedys] 请使用 [waitAll] 回调结果方法
* @return [ArrayList]<[Instance]>
*/
fun all(): ArrayList<Instance> {
if (isBindToHooker) memberInstances.takeIf { it.isNotEmpty() }?.apply {
hookInstance?.members?.clear()
forEach { hookInstance?.members?.add(it) }
}
return arrayListOf<Instance>().apply { giveAll().takeIf { it.isNotEmpty() }?.forEach { add(Instance(it)) } }
}
/**
* 得到 [Constructor] 本身
*
* - 若有多个 [Constructor] 结果只会返回第一个
*
* - 在查询条件找不到任何结果的时候将返回 null
* @return [Constructor] or null
*/
fun give() = memberInstance as? Constructor<*>?
fun give() = giveAll().takeIf { it.isNotEmpty() }?.first()
/**
* 得到 [Constructor] 本身数组
*
* - 返回全部查询条件匹配的多个 [Constructor] 实例
*
* - 在查询条件找不到任何结果的时候将返回空的 [HashSet]
* @return [HashSet]<[Constructor]>
*/
fun giveAll() = memberInstances.takeIf { it.isNotEmpty() }?.constructors() ?: HashSet()
/**
* 获得 [Constructor] 实例处理类
*
* - 若有多个 [Constructor] 结果只会返回第一个
*
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
*
* - ❗若你没有设置 [remedys] 此方法将不会被回调
* @param initiate 回调 [Instance]
*/
fun wait(initiate: Instance.() -> Unit) {
if (memberInstance != null) initiate(get())
if (memberInstances.isNotEmpty()) initiate(get())
else remedyPlansCallback = { initiate(get()) }
}
/**
* 创建构造方法重查找功能
* 获得 [Constructor] 实例处理类数组
*
* 当你遇到一种构造方法可能存在不同形式的存在时
* - 返回全部查询条件匹配的多个 [Constructor] 实例结果
*
* 可以使用 [RemedyPlan] 重新查找它 - 而没有必要使用 [onNoSuchConstructor] 捕获异常二次查找构造方法
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
*
* - ❗若你没有设置 [remedys] 此方法将不会被回调
* @param initiate 回调 [ArrayList]<[Instance]>
*/
fun waitAll(initiate: ArrayList<Instance>.() -> Unit) {
if (memberInstances.isNotEmpty()) initiate(all())
else remedyPlansCallback = { initiate(all()) }
}
/**
* 创建 [Constructor] 重查找功能
*
* 当你遇到一种 [Constructor] 可能存在不同形式的存在时
*
* 可以使用 [RemedyPlan] 重新查找它 - 而没有必要使用 [onNoSuchConstructor] 捕获异常二次查找 [Constructor]
* @param initiate 方法体
* @return [Result] 可继续向下监听
*/
@@ -341,14 +418,14 @@ class ConstructorFinder @PublishedApi internal constructor(
}
/**
* 监听找不到构造方法
* 监听找不到 [Constructor]
*
* 只会返回第一次的错误信息 - 不会返回 [RemedyPlan] 的错误信息
* - 只会返回第一次的错误信息 - 不会返回 [RemedyPlan] 的错误信息
* @param result 回调错误
* @return [Result] 可继续向下监听
*/
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result {
if (isNoSuch) result(e ?: Throwable())
if (isNoSuch) result(throwable ?: Throwable("Initialization Error"))
return this
}
@@ -368,32 +445,33 @@ class ConstructorFinder @PublishedApi internal constructor(
*
* 调用与创建目标实例类对象
*
* - ❗请使用 [get][wait] 方法来获取 [Instance]
* - ❗请使用 [get][wait]、[all]、[waitAll] 方法来获取 [Instance]
* @param constructor 当前 [Constructor] 实例对象
*/
inner class Instance internal constructor() {
inner class Instance internal constructor(private val constructor: Constructor<*>?) {
/**
* 执行构造方法创建目标实例
* 执行 [Constructor] 创建目标实例
* @param param 构造方法参数
* @return [Any] or null
*/
private fun baseCall(vararg param: Any?) = (memberInstance as? Constructor<*>?)?.newInstance(*param)
private fun baseCall(vararg param: Any?) = constructor?.newInstance(*param)
/**
* 执行构造方法创建目标实例 - 不指定目标实例类型
* 执行 [Constructor] 创建目标实例 - 不指定目标实例类型
* @param param 构造方法参数
* @return [Any] or null
*/
fun call(vararg param: Any?) = baseCall(*param)
/**
* 执行构造方法创建目标实例 - 指定 [T] 目标实例类型
* 执行 [Constructor] 创建目标实例 - 指定 [T] 目标实例类型
* @param param 构造方法参数
* @return [T] or null
*/
fun <T> newInstance(vararg param: Any?) = baseCall(*param) as? T?
override fun toString() = "[${(memberInstance as? Constructor<*>?)?.name ?: "<empty>"}]"
override fun toString() = "[${constructor?.name ?: "<empty>"}]"
}
}
}

View File

@@ -38,13 +38,14 @@ import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.core.finder.type.NameConditions
import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool
import com.highcapable.yukihookapi.hook.factory.hasExtends
import com.highcapable.yukihookapi.hook.log.yLoggerW
import com.highcapable.yukihookapi.hook.utils.runBlocking
import java.lang.reflect.Field
/**
* Field 查找类
*
* 可通过执行类型查找指定变量
* 可通过指定类型查找指定变量或一组变量
* @param hookInstance 当前 Hook 实例
* @param classSet 当前需要查找的 [Class] 实例
*/
@@ -61,6 +62,9 @@ class FieldFinder @PublishedApi internal constructor(
/** 是否在未找到后继续在当前 [classSet] 的父类中查找 */
private var isFindInSuperClass = false
/** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null
/** [ModifierRules] 实例 */
@PublishedApi
internal var modifiers: ModifierRules? = null
@@ -72,7 +76,7 @@ class FieldFinder @PublishedApi internal constructor(
/**
* 设置 [Field] 名称
*
* - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Field]
* - ❗若不填写名称则必须存在一个其它条件
*/
var name = ""
@@ -81,14 +85,14 @@ class FieldFinder @PublishedApi internal constructor(
*
* - ❗只能是 [Class]、[String]、[VariousClass]
*
* - 可不填写类型 - 默认模糊查找并取第一个匹配的 [Field]
* - 可不填写类型
*/
var type: Any? = null
/**
* 设置 [Field] 标识符筛选条件
*
* 可不设置筛选条件 - 默认模糊查找并取第一个匹配的 [Field]
* - 可不设置筛选条件
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体
@@ -108,7 +112,7 @@ class FieldFinder @PublishedApi internal constructor(
/**
* 设置 [Field] 名称
*
* - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Field]
* - ❗若不填写名称则必须存在一个其它条件
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 名称
@@ -122,7 +126,7 @@ class FieldFinder @PublishedApi internal constructor(
/**
* 设置 [Field] 名称条件
*
* - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Field]
* - ❗若不填写名称则必须存在一个其它条件
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体
@@ -136,7 +140,7 @@ class FieldFinder @PublishedApi internal constructor(
/**
* 设置 [Field] 类型
*
* - 可不填写类型 - 默认模糊查找并取第一个匹配的 [Field]
* - 可不填写类型
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 类型 - ❗只能是 [Class]、[String]、[VariousClass]
@@ -159,7 +163,29 @@ class FieldFinder @PublishedApi internal constructor(
}
/**
* 得到变量处理结果
* 得到变量或一组变量
* @return [HashSet]<[Field]>
* @throws NoSuchFieldError 如果找不到变量
*/
private val result
get() = ReflectionTool.findFields(
usedClassSet, orderIndex,
matchIndex, name,
modifiers, nameConditions,
type.compat(), isFindInSuperClass
)
/**
* 设置实例
* @param fields 当前找到的 [Field] 数组
*/
private fun setInstance(fields: HashSet<Field>) {
memberInstances.clear()
fields.takeIf { it.isNotEmpty() }?.forEach { memberInstances.add(it) }
}
/**
* 得到 [Field] 处理结果
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param isBind 是否将结果设置到目标 [YukiMemberHookCreater.MemberHookCreater]
@@ -170,13 +196,10 @@ class FieldFinder @PublishedApi internal constructor(
override fun build(isBind: Boolean) = try {
if (classSet != null) {
runBlocking {
memberInstance = ReflectionTool.findField(
usedClassSet, orderIndex,
matchIndex, name,
modifiers, nameConditions,
type.compat(), isFindInSuperClass
)
}.result { onHookLogMsg(msg = "Find Field [${memberInstance}] takes ${it}ms [${hookTag}]") }
setInstance(result)
}.result {
memberInstances.takeIf { it.isNotEmpty() }?.forEach { onHookLogMsg(msg = "Find Field [$it] takes ${it}ms [${hookTag}]") }
}
Result()
} else Result(isNoSuch = true, Throwable("classSet is null"))
} catch (e: Throwable) {
@@ -198,13 +221,96 @@ class FieldFinder @PublishedApi internal constructor(
@YukiPrivateApi
override fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable)
/**
* [Field] 重查找实现类
*
* 可累计失败次数直到查找成功
*/
inner class RemedyPlan @PublishedApi internal constructor() {
/** 失败尝试次数数组 */
@PublishedApi
internal val remedyPlans = HashSet<Pair<FieldFinder, Result>>()
/**
* 创建需要重新查找的 [Field]
*
* 你可以添加多个备选 [Field] - 直到成功为止
*
* 若最后依然失败 - 将停止查找并输出错误日志
* @param initiate 方法体
* @return [Result] 结果
*/
inline fun field(initiate: FieldFinder.() -> Unit) =
Result().apply { remedyPlans.add(Pair(FieldFinder(hookInstance, classSet).apply(initiate), this)) }
/** 开始重查找 */
@PublishedApi
internal fun build() {
if (classSet == null) return
if (remedyPlans.isNotEmpty()) run {
var isFindSuccess = false
var lastError: Throwable? = null
remedyPlans.forEachIndexed { p, it ->
runCatching {
runBlocking {
setInstance(it.first.result)
}.result { ms ->
memberInstances.takeIf { it.isNotEmpty() }
?.forEach { onHookLogMsg(msg = "Find Field [$it] takes ${ms}ms [${hookTag}]") }
}
isFindSuccess = true
it.second.onFindCallback?.invoke(memberInstances.fields())
remedyPlansCallback?.invoke()
memberInstances.takeIf { it.isNotEmpty() }
?.forEach { onHookLogMsg(msg = "Field [$it] trying ${p + 1} times success by RemedyPlan [${hookTag}]") }
return@run
}.onFailure {
lastError = it
onFailureMsg(msg = "Trying ${p + 1} times by RemedyPlan --> $it", isAlwaysPrint = true)
}
}
if (isFindSuccess.not()) {
onFailureMsg(
msg = "Trying ${remedyPlans.size} times and all failure by RemedyPlan",
throwable = lastError,
isAlwaysPrint = true
)
remedyPlans.clear()
}
} else yLoggerW(msg = "RemedyPlan is empty, forgot it? [${hookTag}]")
}
/**
* [RemedyPlan] 结果实现类
*
* 可在这里处理是否成功的回调
*/
inner class Result @PublishedApi internal constructor() {
/** 找到结果时的回调 */
internal var onFindCallback: (HashSet<Field>.() -> Unit)? = null
/**
* 当找到结果时
* @param initiate 回调
*/
fun onFind(initiate: HashSet<Field>.() -> Unit) {
onFindCallback = initiate
}
}
}
/**
* [Field] 查找结果实现类
*
* @param isNoSuch 是否没有找到变量 - 默认否
* @param e 错误信息
* @param throwable 错误信息
*/
inner class Result internal constructor(@PublishedApi internal val isNoSuch: Boolean = false, private val e: Throwable? = null) {
inner class Result internal constructor(
@PublishedApi internal val isNoSuch: Boolean = false,
private val throwable: Throwable? = null
) : BaseResult {
/**
* 创建监听结果事件方法体
@@ -214,32 +320,114 @@ class FieldFinder @PublishedApi internal constructor(
inline fun result(initiate: Result.() -> Unit) = apply(initiate)
/**
* 得到变量实例处理类
* 获得 [Field] 实例处理类
*
* - 若有多个 [Field] 结果只会返回第一个
*
* - ❗在 [memberInstances] 结果为空时使用此方法将无法获得对象
*
* - ❗如果目标对象不是静态 - 你必须设置 [instance]
*
* - ❗若你设置了 [remedys] 请使用 [wait] 回调结果方法
* @param instance 变量所在的实例对象 - 如果是静态可不填 - 默认 null
* @return [Instance]
*/
fun get(instance: Any? = null) = try {
Instance(instance, give()?.get(instance))
} catch (e: Throwable) {
onFailureMsg(msg = "Try to get field instance failed", throwable = e)
Instance(instance, self = null)
fun get(instance: Any? = null) = Instance(instance, give())
/**
* 获得 [Field] 实例处理类数组
*
* - 返回全部查询条件匹配的多个 [Field] 实例结果
*
* - ❗在 [memberInstances] 结果为空时使用此方法将无法获得对象
*
* - ❗如果目标对象不是静态 - 你必须设置 [instance]
*
* - ❗若你设置了 [remedys] 请使用 [waitAll] 回调结果方法
* @param instance 变量所在的实例对象 - 如果是静态可不填 - 默认 null
* @return [ArrayList]<[Instance]>
*/
fun all(instance: Any? = null) =
arrayListOf<Instance>().apply { giveAll().takeIf { it.isNotEmpty() }?.forEach { add(Instance(instance, it)) } }
/**
* 得到 [Field] 本身
*
* - 若有多个 [Field] 结果只会返回第一个
*
* - 在查询条件找不到任何结果的时候将返回 null
* @return [Field] or null
*/
fun give() = giveAll().takeIf { it.isNotEmpty() }?.first()
/**
* 得到 [Field] 本身数组
*
* - 返回全部查询条件匹配的多个 [Field] 实例
*
* - 在查询条件找不到任何结果的时候将返回空的 [HashSet]
* @return [HashSet]<[Field]>
*/
fun giveAll() = memberInstances.takeIf { it.isNotEmpty() }?.fields() ?: HashSet()
/**
* 获得 [Field] 实例处理类
*
* - 若有多个 [Field] 结果只会返回第一个
*
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
*
* - ❗若你没有设置 [remedys] 此方法将不会被回调
* @param instance 所在实例
* @param initiate 回调 [Instance]
*/
fun wait(instance: Any? = null, initiate: Instance.() -> Unit) {
if (memberInstances.isNotEmpty()) initiate(get(instance))
else remedyPlansCallback = { initiate(get(instance)) }
}
/**
* 得到变量本身
* @return [Field] or null
* 获得 [Field] 实例处理类数组
*
* - 返回全部查询条件匹配的多个 [Field] 实例结果
*
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
*
* - ❗若你没有设置 [remedys] 此方法将不会被回调
* @param instance 所在实例
* @param initiate 回调 [ArrayList]<[Instance]>
*/
fun give() = memberInstance as? Field?
fun waitAll(instance: Any? = null, initiate: ArrayList<Instance>.() -> Unit) {
if (memberInstances.isNotEmpty()) initiate(all(instance))
else remedyPlansCallback = { initiate(all(instance)) }
}
/**
* 监听找不到变量时
* 创建 [Field] 重查找功能
*
* 当你遇到一种方法可能存在不同形式的存在时
*
* 可以使用 [RemedyPlan] 重新查找它 - 而没有必要使用 [onNoSuchField] 捕获异常二次查找 [Field]
*
* 若第一次查找失败了 - 你还可以在这里继续添加此方法体直到成功为止
* @param initiate 方法体
* @return [Result] 可继续向下监听
*/
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result {
isUsingRemedyPlan = true
if (isNoSuch) RemedyPlan().apply(initiate).build()
return this
}
/**
* 监听找不到 [Field] 时
*
* - 只会返回第一次的错误信息 - 不会返回 [RemedyPlan] 的错误信息
* @param result 回调错误
* @return [Result] 可继续向下监听
*/
fun onNoSuchField(result: (Throwable) -> Unit): Result {
if (isNoSuch) result(e ?: Throwable())
if (isNoSuch) result(throwable ?: Throwable("Initialization Error"))
return this
}
@@ -255,135 +443,141 @@ class FieldFinder @PublishedApi internal constructor(
}
/**
* [Field] 实例变量处理类
* [Field] 实例处理类
*
* - ❗请使用 [get] 方法来获取 [Instance]
* - ❗请使用 [get]、[all] 方法来获取 [Instance]
* @param instance 当前 [Field] 所在类的实例对象
* @param self 当前 [Field] 自身的实例对象
* @param field 当前 [Field] 实例对象
*/
inner class Instance internal constructor(private val instance: Any?, val self: Any?) {
inner class Instance internal constructor(private val instance: Any?, private val field: Field?) {
/**
* 得到变量实例
* 获取当前 [Field] 自身的实例化对象
* @return [Any] or null
*/
val self get() = field?.get(instance)
/**
* 得到当前 [Field] 实例
* @return [T] or null
*/
fun <T> cast() = self as? T?
/**
* 得到变量的 [Byte] 实例
* 得到当前 [Field] 的 [Byte] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回 null
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回 null
* @return [Byte] or null
*/
fun byte() = cast<Byte?>()
/**
* 得到变量的 [Int] 实例
* 得到当前 [Field] 的 [Int] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [Int] 取不到返回 0
*/
fun int() = cast() ?: 0
/**
* 得到变量的 [Long] 实例
* 得到当前 [Field] 的 [Long] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [Long] 取不到返回 0L
*/
fun long() = cast() ?: 0L
/**
* 得到变量的 [Short] 实例
* 得到当前 [Field] 的 [Short] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [Short] 取不到返回 0
*/
fun short() = cast<Short?>() ?: 0
/**
* 得到变量的 [Double] 实例
* 得到当前 [Field] 的 [Double] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [Double] 取不到返回 0.0
*/
fun double() = cast() ?: 0.0
/**
* 得到变量的 [Float] 实例
* 得到当前 [Field] 的 [Float] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [Float] 取不到返回 0f
*/
fun float() = cast() ?: 0f
/**
* 得到变量的 [String] 实例
* 得到当前 [Field] 的 [String] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [String] 取不到返回 ""
*/
fun string() = cast() ?: ""
/**
* 得到变量的 [Char] 实例
* 得到当前 [Field] 的 [Char] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [Char] 取不到返回 ' '
*/
fun char() = cast() ?: ' '
/**
* 得到变量的 [Boolean] 实例
* 得到当前 [Field] 的 [Boolean] 实例
*
* - ❗请确认目标变量的类型 - 发生错误会返回默认值
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回默认值
* @return [Boolean] 取不到返回 false
*/
fun boolean() = cast() ?: false
/**
* 得到变量的 [Any] 实例
* 得到当前 [Field] 的 [Any] 实例
* @return [Any] or null
*/
fun any() = cast<Any?>()
/**
* 得到变量的 [Array] 实例 - 每项类型 [T]
* 得到当前 [Field] 的 [Array] 实例 - 每项类型 [T]
*
* - ❗请确认目标变量的类型 - 发生错误会返回空数组
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回空数组
* @return [Array] 取不到返回空数组
*/
inline fun <reified T> array() = cast() ?: arrayOf<T>()
/**
* 得到变量的 [List] 实例 - 每项类型 [T]
* 得到当前 [Field] 的 [List] 实例 - 每项类型 [T]
*
* - ❗请确认目标变量的类型 - 发生错误会返回空数组
* - ❗请确认目标 [Field] 的类型 - 发生错误会返回空数组
* @return [List] 取不到返回空数组
*/
inline fun <reified T> list() = cast() ?: listOf<T>()
/**
* 设置变量实例
* 设置当前 [Field] 实例
* @param any 设置的实例内容
*/
fun set(any: Any?) = give()?.set(instance, any)
fun set(any: Any?) = field?.set(instance, any)
/**
* 设置变量实例为 true
* 设置当前 [Field] 实例为 true
*
* - ❗请确保示例对象类型为 [Boolean]
*/
fun setTrue() = set(true)
/**
* 设置变量实例为 true
* 设置当前 [Field] 实例为 true
*
* - ❗请确保示例对象类型为 [Boolean]
*/
fun setFalse() = set(false)
/** 设置变量实例为 null */
/** 设置当前 [Field] 实例为 null */
fun setNull() = set(null)
override fun toString() =

View File

@@ -46,8 +46,8 @@ import java.lang.reflect.Method
/**
* [Method] 查找类
*
* 可通过指定类型查找指定方法
* @param hookInstance 当前 Hook 实例 - 填写后将自动设置 [YukiMemberHookCreater.MemberHookCreater.member]
* 可通过指定类型查找指定方法或一组方法
* @param hookInstance 当前 Hook 实例 - 填写后将自动设置 [YukiMemberHookCreater.MemberHookCreater.members]
* @param classSet 当前需要查找的 [Class] 实例
*/
class MethodFinder @PublishedApi internal constructor(
@@ -69,6 +69,9 @@ class MethodFinder @PublishedApi internal constructor(
/** [Method] 参数数组 */
private var paramTypes: Array<out Class<*>>? = null
/** [Method] 参数个数范围 */
private var paramCountRange = IntRange.EMPTY
/** [ModifierRules] 实例 */
@PublishedApi
internal var modifiers: ModifierRules? = null
@@ -80,7 +83,7 @@ class MethodFinder @PublishedApi internal constructor(
/**
* 设置 [Method] 名称
*
* - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Method]
* - ❗若不填写名称则必须存在一个其它条件
*/
var name = ""
@@ -98,14 +101,14 @@ class MethodFinder @PublishedApi internal constructor(
*
* - ❗只能是 [Class]、[String]、[VariousClass]
*
* - 可不填写返回值 - 默认模糊查找并取第一个匹配的 [Method]
* - 可不填写返回值
*/
var returnType: Any? = null
/**
* 设置 [Method] 标识符筛选条件
*
* 可不设置筛选条件 - 默认模糊查找并取第一个匹配的 [Method]
* - 可不设置筛选条件
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体
@@ -151,7 +154,7 @@ class MethodFinder @PublishedApi internal constructor(
/**
* 设置 [Method] 名称
*
* - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Method]
* - ❗若不填写名称则必须存在一个其它条件
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 名称
@@ -165,7 +168,7 @@ class MethodFinder @PublishedApi internal constructor(
/**
* 设置 [Method] 名称条件
*
* - ❗若不填写名称则必须存在一个其它条件 - 默认模糊查找并取第一个匹配的 [Method]
* - ❗若不填写名称则必须存在一个其它条件
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体
@@ -192,10 +195,24 @@ class MethodFinder @PublishedApi internal constructor(
return IndexTypeCondition(IndexConfigType.MATCH)
}
/**
* 设置 [Method] 参数个数范围
*
* 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param numRange 个数范围
* @return [BaseFinder.IndexTypeCondition]
*/
fun paramCount(numRange: IntRange): IndexTypeCondition {
paramCountRange = numRange
return IndexTypeCondition(IndexConfigType.MATCH)
}
/**
* 设置 [Method] 返回值
*
* 可不填写返回值 - 默认模糊查找并取第一个匹配的 [Method]
* - 可不填写返回值
*
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param value 个数
@@ -218,29 +235,33 @@ class MethodFinder @PublishedApi internal constructor(
}
/**
* 得到方法
* @return [Method]
* 得到方法或一组方法
* @return [HashSet]<[Method]>
* @throws NoSuchMethodError 如果找不到方法
*/
private val result
get() = ReflectionTool.findMethod(
get() = ReflectionTool.findMethods(
usedClassSet, orderIndex, matchIndex, name,
modifiers, nameConditions, returnType.compat(),
paramCount, paramTypes, isFindInSuperClass
paramCount, paramCountRange, paramTypes, isFindInSuperClass
)
/**
* 设置实例
* @param isBind 是否将结果设置到目标 [YukiMemberHookCreater.MemberHookCreater]
* @param method 当前找到的 [Method]
* @param methods 当前找到的 [Method] 数组
*/
private fun setInstance(isBind: Boolean, method: Method) {
memberInstance = method
if (isBind) hookInstance?.member = method
private fun setInstance(isBind: Boolean, methods: HashSet<Method>) {
memberInstances.clear()
val result = methods.takeIf { it.isNotEmpty() }?.onEach { memberInstances.add(it) }?.first()
if (isBind) hookInstance?.members?.apply {
clear()
result?.also { add(it) }
}
}
/**
* 得到方法结果
* 得到 [Method] 结果
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param isBind 是否将结果设置到目标 [YukiMemberHookCreater.MemberHookCreater]
@@ -252,7 +273,9 @@ class MethodFinder @PublishedApi internal constructor(
runBlocking {
isBindToHooker = isBind
setInstance(isBind, result)
}.result { onHookLogMsg(msg = "Find Method [${memberInstance}] takes ${it}ms [${hookTag}]") }
}.result { ms ->
memberInstances.takeIf { it.isNotEmpty() }?.forEach { onHookLogMsg(msg = "Find Method [$it] takes ${ms}ms [${hookTag}]") }
}
Result()
} else Result(isNoSuch = true, Throwable("classSet is null"))
} catch (e: Throwable) {
@@ -284,7 +307,7 @@ class MethodFinder @PublishedApi internal constructor(
/**
* 创建需要重新查找的 [Method]
*
* 你可以添加多个备选方法 - 直到成功为止
* 你可以添加多个备选 [Method] - 直到成功为止
*
* 若最后依然失败 - 将停止查找并输出错误日志
* @param initiate 方法体
@@ -304,13 +327,15 @@ class MethodFinder @PublishedApi internal constructor(
runCatching {
runBlocking {
setInstance(isBindToHooker, it.first.result)
}.result {
onHookLogMsg(msg = "Find Method [${memberInstance}] takes ${it}ms [${hookTag}]")
}.result { ms ->
memberInstances.takeIf { it.isNotEmpty() }
?.forEach { onHookLogMsg(msg = "Find Method [$it] takes ${ms}ms [${hookTag}]") }
}
isFindSuccess = true
it.second.onFindCallback?.invoke(memberInstance as Method)
it.second.onFindCallback?.invoke(memberInstances.methods())
remedyPlansCallback?.invoke()
onHookLogMsg(msg = "Method [${memberInstance}] trying ${p + 1} times success by RemedyPlan [${hookTag}]")
memberInstances.takeIf { it.isNotEmpty() }
?.forEach { onHookLogMsg(msg = "Method [$it] trying ${p + 1} times success by RemedyPlan [${hookTag}]") }
return@run
}.onFailure {
lastError = it
@@ -336,13 +361,13 @@ class MethodFinder @PublishedApi internal constructor(
inner class Result @PublishedApi internal constructor() {
/** 找到结果时的回调 */
internal var onFindCallback: (Method.() -> Unit)? = null
internal var onFindCallback: (HashSet<Method>.() -> Unit)? = null
/**
* 当找到结果时
* @param initiate 回调
*/
fun onFind(initiate: Method.() -> Unit) {
fun onFind(initiate: HashSet<Method>.() -> Unit) {
onFindCallback = initiate
}
}
@@ -351,12 +376,12 @@ class MethodFinder @PublishedApi internal constructor(
/**
* [Method] 查找结果实现类
* @param isNoSuch 是否没有找到方法 - 默认否
* @param e 错误信息
* @param throwable 错误信息
*/
inner class Result internal constructor(
@PublishedApi internal val isNoSuch: Boolean = false,
@PublishedApi internal val e: Throwable? = null
) {
@PublishedApi internal val throwable: Throwable? = null
) : BaseResult {
/**
* 创建监听结果事件方法体
@@ -368,23 +393,60 @@ class MethodFinder @PublishedApi internal constructor(
/**
* 获得 [Method] 实例处理类
*
* - ❗在 [memberInstance] 结果为空时使用此方法将无法获得对象
* - 若有多个 [Method] 结果只会返回第一个
*
* - ❗在 [memberInstances] 结果为空时使用此方法将无法获得对象
*
* - ❗若你设置了 [remedys] 请使用 [wait] 回调结果方法
* @param instance 所在实例
* @return [Instance]
*/
fun get(instance: Any? = null) = Instance(instance)
fun get(instance: Any? = null) = Instance(instance, give())
/**
* 得到方法本身
* 获得 [Method] 实例处理类数组
*
* - 返回全部查询条件匹配的多个 [Method] 实例结果并在 [isBindToHooker] 时设置到 [hookInstance]
*
* - ❗在 [memberInstances] 结果为空时使用此方法将无法获得对象
*
* - ❗若你设置了 [remedys] 请使用 [waitAll] 回调结果方法
* @param instance 所在实例
* @return [ArrayList]<[Instance]>
*/
fun all(instance: Any? = null): ArrayList<Instance> {
if (isBindToHooker) memberInstances.takeIf { it.isNotEmpty() }?.apply {
hookInstance?.members?.clear()
forEach { hookInstance?.members?.add(it) }
}
return arrayListOf<Instance>().apply { giveAll().takeIf { it.isNotEmpty() }?.forEach { add(Instance(instance, it)) } }
}
/**
* 得到 [Method] 本身
*
* - 若有多个 [Method] 结果只会返回第一个
*
* - 在查询条件找不到任何结果的时候将返回 null
* @return [Method] or null
*/
fun give() = memberInstance as? Method?
fun give() = giveAll().takeIf { it.isNotEmpty() }?.first()
/**
* 得到 [Method] 本身数组
*
* - 返回全部查询条件匹配的多个 [Method] 实例
*
* - 在查询条件找不到任何结果的时候将返回空的 [HashSet]
* @return [HashSet]<[Method]>
*/
fun giveAll() = memberInstances.takeIf { it.isNotEmpty() }?.methods() ?: HashSet()
/**
* 获得 [Method] 实例处理类
*
* - 若有多个 [Method] 结果只会返回第一个
*
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
*
* - ❗若你没有设置 [remedys] 此方法将不会被回调
@@ -392,16 +454,32 @@ class MethodFinder @PublishedApi internal constructor(
* @param initiate 回调 [Instance]
*/
fun wait(instance: Any? = null, initiate: Instance.() -> Unit) {
if (memberInstance != null) initiate(get(instance))
if (memberInstances.isNotEmpty()) initiate(get(instance))
else remedyPlansCallback = { initiate(get(instance)) }
}
/**
* 创建方法重查找功能
* 获得 [Method] 实例处理类数组
*
* 当你遇到一种方法可能存在不同形式的存在时
* - 返回全部查询条件匹配的多个 [Method] 实例结果
*
* 可以使用 [RemedyPlan] 重新查找它 - 而没有必要使用 [onNoSuchMethod] 捕获异常二次查找方法
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
*
* - ❗若你没有设置 [remedys] 此方法将不会被回调
* @param instance 所在实例
* @param initiate 回调 [ArrayList]<[Instance]>
*/
fun waitAll(instance: Any? = null, initiate: ArrayList<Instance>.() -> Unit) {
if (memberInstances.isNotEmpty()) initiate(all(instance))
else remedyPlansCallback = { initiate(all(instance)) }
}
/**
* 创建 [Method] 重查找功能
*
* 当你遇到一种 [Method] 可能存在不同形式的存在时
*
* 可以使用 [RemedyPlan] 重新查找它 - 而没有必要使用 [onNoSuchMethod] 捕获异常二次查找 [Method]
*
* 若第一次查找失败了 - 你还可以在这里继续添加此方法体直到成功为止
* @param initiate 方法体
@@ -414,14 +492,14 @@ class MethodFinder @PublishedApi internal constructor(
}
/**
* 监听找不到方法
* 监听找不到 [Method]
*
* 只会返回第一次的错误信息 - 不会返回 [RemedyPlan] 的错误信息
* - 只会返回第一次的错误信息 - 不会返回 [RemedyPlan] 的错误信息
* @param result 回调错误
* @return [Result] 可继续向下监听
*/
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result {
if (isNoSuch) result(e ?: Throwable("Initialization Error"))
if (isNoSuch) result(throwable ?: Throwable("Initialization Error"))
return this
}
@@ -439,10 +517,11 @@ class MethodFinder @PublishedApi internal constructor(
/**
* [Method] 实例处理类
*
* - ❗请使用 [get][wait] 方法来获取 [Instance]
* - ❗请使用 [get][wait]、[all]、[waitAll] 方法来获取 [Instance]
* @param instance 当前 [Method] 所在类的实例对象
* @param method 当前 [Method] 实例对象
*/
inner class Instance internal constructor(private val instance: Any?) {
inner class Instance internal constructor(private val instance: Any?, private val method: Method?) {
/** 标识需要调用当前 [Method] 未经 Hook 的原始方法 */
private var isCallOriginal = false
@@ -465,11 +544,10 @@ class MethodFinder @PublishedApi internal constructor(
* @param param 方法参数
* @return [Any] or null
*/
private fun baseCall(vararg param: Any?) = (memberInstance as? Method?)?.let {
private fun baseCall(vararg param: Any?) =
if (isCallOriginal)
YukiHookHelper.invokeOriginalMember(it, instance, *param) ?: it.invoke(instance, *param)
else it.invoke(instance, *param)
}
method?.let { YukiHookHelper.invokeOriginalMember(it, instance, *param) ?: it.invoke(instance, *param) }
else method?.invoke(instance, *param)
/**
* 执行方法 - 不指定返回值类型
@@ -578,8 +656,7 @@ class MethodFinder @PublishedApi internal constructor(
*/
inline fun <reified T> list(vararg param: Any?) = invoke(*param) ?: listOf<T>()
override fun toString() =
"[${(memberInstance as? Method?)?.name ?: "<empty>"}] in [${instance?.javaClass?.name ?: "<empty>"}]"
override fun toString() = "[${method?.name ?: "<empty>"}] in [${instance?.javaClass?.name ?: "<empty>"}]"
}
}
}

View File

@@ -37,7 +37,10 @@ import com.highcapable.yukihookapi.hook.log.yLoggerE
import com.highcapable.yukihookapi.hook.log.yLoggerI
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Member
import java.lang.reflect.Method
import kotlin.math.abs
/**
@@ -46,7 +49,7 @@ import kotlin.math.abs
* @param hookInstance 当前 Hook 实例
* @param classSet 当前需要查找的 [Class] 实例
*/
abstract class BaseFinder(
abstract class BaseFinder internal constructor(
private val tag: String,
open val hookInstance: YukiMemberHookCreater.MemberHookCreater? = null,
open val classSet: Class<*>? = null
@@ -127,8 +130,8 @@ abstract class BaseFinder(
/** 是否开启忽略错误警告功能 */
internal var isShutErrorPrinting = false
/** 当前找到的 [Member] */
internal var memberInstance: Member? = null
/** 当前找到的 [Member] 数组 */
internal var memberInstances = HashSet<Member>()
/**
* 获取当前使用的 TAG
@@ -145,6 +148,27 @@ abstract class BaseFinder(
/** 需要输出的日志内容 */
private var loggingContent: Pair<String, Throwable?>? = null
/**
* 将 [HashSet]<[Member]> 转换为 [HashSet]<[Field]>
* @return [HashSet]<[Field]>
*/
internal fun HashSet<Member>.fields() =
hashSetOf<Field>().also { takeIf { e -> e.isNotEmpty() }?.forEach { e -> (e as? Field?)?.also { f -> it.add(f) } } }
/**
* 将 [HashSet]<[Member]> 转换为 [HashSet]<[Method]>
* @return [HashSet]<[Method]>
*/
internal fun HashSet<Member>.methods() =
hashSetOf<Method>().also { takeIf { e -> e.isNotEmpty() }?.forEach { e -> (e as? Method?)?.also { m -> it.add(m) } } }
/**
* 将 [HashSet]<[Member]> 转换为 [HashSet]<[Constructor]>
* @return [HashSet]<[Constructor]>
*/
internal fun HashSet<Member>.constructors() =
hashSetOf<Constructor<*>>().also { takeIf { e -> e.isNotEmpty() }?.forEach { e -> (e as? Constructor<*>?)?.also { c -> it.add(c) } } }
/**
* 将目标类型转换为可识别的兼容类型
* @return [Class] or null
@@ -208,18 +232,26 @@ abstract class BaseFinder(
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param isBind 是否将结果设置到目标 [YukiMemberHookCreater.MemberHookCreater]
* @return [Any]
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun build(isBind: Boolean = false): Any
abstract fun build(isBind: Boolean = false): BaseResult
/**
* 创建一个异常结果
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param throwable 异常
* @return [Any]
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun failure(throwable: Throwable?): Any
abstract fun failure(throwable: Throwable?): BaseResult
/**
* 查找结果实现类接口
*
* - ❗此功能交由方法体自动完成 - 你不应该手动继承此接口
*/
@YukiPrivateApi
interface BaseResult
}

View File

@@ -47,7 +47,7 @@ internal object ReflectionTool {
private const val TAG = "YukiHookAPI#ReflectionTool"
/**
* 查找任意变量
* 查找任意变量或一组变量
* @param classSet 变量所在类
* @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标
@@ -56,11 +56,11 @@ internal object ReflectionTool {
* @param nameConditions 名称查找条件
* @param type 变量类型
* @param isFindInSuperClass 是否在未找到后继续在当前 [classSet] 的父类中查找
* @return [Field]
* @return [HashSet]<[Field]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [type] 目标类不存在
* @throws NoSuchFieldError 如果找不到变量
*/
internal fun findField(
internal fun findFields(
classSet: Class<*>?,
orderIndex: Pair<Int, Boolean>?,
matchIndex: Pair<Int, Boolean>?,
@@ -69,13 +69,13 @@ internal object ReflectionTool {
nameConditions: NameConditions?,
type: Class<*>?,
isFindInSuperClass: Boolean
): Field {
): HashSet<Field> {
if (type == UndefinedType) error("Field match type class is not found")
if (orderIndex == null && matchIndex == null && name.isBlank() && modifiers == null && type == null)
error("You must set a condition when finding a Field")
val hashCode = ("[$orderIndex][$matchIndex][$name][$type][$modifiers][$classSet]").hashCode()
return MemberCacheStore.findField(hashCode) ?: let {
var field: Field? = null
return MemberCacheStore.findFields(hashCode) ?: let {
val fields = HashSet<Field>()
classSet?.declaredFields?.apply {
var typeIndex = -1
var nameIndex = -1
@@ -132,15 +132,12 @@ internal object ReflectionTool {
(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
}
if (conditions && isMatched) fields.add(it.apply { isAccessible = true })
}
} ?: error("Can't find this Field [$name] because classSet is null")
field?.also { MemberCacheStore.putField(hashCode, field) }
fields.takeIf { it.isNotEmpty() }?.also { MemberCacheStore.putFields(hashCode, fields) }
?: if (isFindInSuperClass && classSet.hasExtends)
findField(
findFields(
classSet.superclass,
orderIndex, matchIndex,
name, modifiers, nameConditions,
@@ -165,14 +162,14 @@ internal object ReflectionTool {
"name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"type:[${type ?: "unspecified"}] " +
"modifiers:${modifiers ?: "[]"} " +
"in Class [$classSet] " +
"in [$classSet] " +
"by $TAG"
)
}
}
/**
* 查找任意方法
* 查找任意方法或一组方法
* @param classSet 方法所在类
* @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标
@@ -181,13 +178,14 @@ internal object ReflectionTool {
* @param nameConditions 名称查找条件
* @param returnType 方法返回值
* @param paramCount 方法参数个数
* @param paramCountRange 方法参数个数范围
* @param paramTypes 方法参数类型
* @param isFindInSuperClass 是否在未找到后继续在当前 [classSet] 的父类中查找
* @return [Method]
* @return [HashSet]<[Method]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [paramTypes] 以及 [returnType] 目标类不存在
* @throws NoSuchMethodError 如果找不到方法
*/
internal fun findMethod(
internal fun findMethods(
classSet: Class<*>?,
orderIndex: Pair<Int, Boolean>?,
matchIndex: Pair<Int, Boolean>?,
@@ -196,22 +194,27 @@ internal object ReflectionTool {
nameConditions: NameConditions?,
returnType: Class<*>?,
paramCount: Int,
paramCountRange: IntRange,
paramTypes: Array<out Class<*>>?,
isFindInSuperClass: Boolean
): Method {
): HashSet<Method> {
if (returnType == UndefinedType) error("Method match returnType class is not found")
paramTypes?.takeIf { it.isNotEmpty() }
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Method match paramType[$p] class is not found") }
if (orderIndex == null && matchIndex == null && name.isBlank() && modifiers == null && paramCount < 0 && paramTypes == null && returnType == null)
error("You must set a condition when finding a Method")
if (orderIndex == null && matchIndex == null &&
name.isBlank() && modifiers == null &&
paramCount < 0 && paramCountRange.isEmpty() &&
paramTypes == null && returnType == null
) error("You must set a condition when finding a Method")
val hashCode =
("[$orderIndex][$matchIndex][$name][$paramCount][${paramTypes.typeOfString()}][$returnType][$modifiers][$classSet]").hashCode()
return MemberCacheStore.findMethod(hashCode) ?: let {
var method: Method? = null
return MemberCacheStore.findMethods(hashCode) ?: let {
val methods = HashSet<Method>()
classSet?.declaredMethods?.apply {
var returnTypeIndex = -1
var paramTypeIndex = -1
var paramCountIndex = -1
var paramCountRangeIndex = -1
var nameIndex = -1
var modifyIndex = -1
var nameCdsIndex = -1
@@ -219,6 +222,8 @@ internal object ReflectionTool {
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 paramCountRangeLastIndex = if (paramCountRange.isEmpty().not() && matchIndex != null)
filter { it.parameterTypes.size in paramCountRange }.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
@@ -257,6 +262,16 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) ||
(paramCountLastIndex == paramCountIndex && matchIndex.second.not()))
}
if (paramCountRange.isEmpty().not())
conditions = (conditions && it.parameterTypes.size in paramCountRange).let {
if (it) paramCountRangeIndex++
isMatched = true
it && (matchIndex == null ||
(matchIndex.first >= 0 && matchIndex.first == paramCountRangeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) ||
(paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not()))
}
if (paramTypes != null)
conditions = (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).let {
if (it) paramTypeIndex++
@@ -291,19 +306,16 @@ internal object ReflectionTool {
(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
}
if (conditions && isMatched) methods.add(it.apply { isAccessible = true })
}
} ?: error("Can't find this Method [$name] because classSet is null")
method?.also { MemberCacheStore.putMethod(hashCode, method) }
methods.takeIf { it.isNotEmpty() }?.also { MemberCacheStore.putMethods(hashCode, methods) }
?: if (isFindInSuperClass && classSet.hasExtends)
findMethod(
findMethods(
classSet.superclass,
orderIndex, matchIndex,
name, modifiers, nameConditions,
returnType, paramCount,
returnType, paramCount, paramCountRange,
paramTypes, isFindInSuperClass = true
)
else throw NoSuchMethodError(
@@ -324,50 +336,58 @@ internal object ReflectionTool {
} +
"name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " +
"paramCountRange:[${paramCountRange.takeIf { it.isEmpty().not() } ?: "unspecified"}] " +
"paramTypes:[${paramTypes.typeOfString()}] " +
"returnType:[${returnType ?: "unspecified"}] " +
"modifiers:${modifiers ?: "[]"} " +
"in Class [$classSet] " +
"in [$classSet] " +
"by $TAG"
)
}
}
/**
* 查找任意构造方法
* 查找任意构造方法或一组构造方法
* @param classSet 构造方法所在类
* @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标
* @param modifiers 构造方法描述
* @param paramCount 构造方法参数个数
* @param paramCountRange 构造方法参数个数范围
* @param paramTypes 构造方法参数类型
* @param isFindInSuperClass 是否在未找到后继续在当前 [classSet] 的父类中查找
* @return [Constructor]
* @return [HashSet]<[Constructor]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [paramTypes] 目标类不存在
* @throws NoSuchMethodError 如果找不到构造方法
*/
internal fun findConstructor(
internal fun findConstructors(
classSet: Class<*>?,
orderIndex: Pair<Int, Boolean>?,
matchIndex: Pair<Int, Boolean>?,
modifiers: ModifierRules?,
paramCount: Int,
paramCountRange: IntRange,
paramTypes: Array<out Class<*>>?,
isFindInSuperClass: Boolean
): Constructor<*> {
): HashSet<Constructor<*>> {
paramTypes?.takeIf { it.isNotEmpty() }
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Constructor match paramType[$p] class is not found") }
val paramCountR =
if (orderIndex == null && matchIndex == null && paramCount < 0 && paramTypes == null && modifiers == null) 0 else paramCount
val hashCode = ("[$orderIndex][$matchIndex][$paramCountR][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode()
return MemberCacheStore.findConstructor(hashCode) ?: let {
var constructor: Constructor<*>? = null
if (orderIndex == null && matchIndex == null &&
modifiers == null && paramCount < 0 &&
paramCountRange.isEmpty() && paramTypes == null
) error("You must set a condition when finding a Constructor")
val hashCode = ("[$orderIndex][$matchIndex][$paramCount][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode()
return MemberCacheStore.findConstructors(hashCode) ?: let {
val constructors = HashSet<Constructor<*>>()
classSet?.declaredConstructors?.apply {
var paramTypeIndex = -1
var paramCountIndex = -1
var paramCountRangeIndex = -1
var modifyIndex = -1
val paramCountLastIndex =
if (paramCountR >= 0 && matchIndex != null) filter { paramCountR == it.parameterTypes.size }.lastIndex else -1
if (paramCount >= 0 && matchIndex != null) filter { paramCount == it.parameterTypes.size }.lastIndex else -1
val paramCountRangeLastIndex = if (paramCountRange.isEmpty().not() && matchIndex != null)
filter { it.parameterTypes.size in paramCountRange }.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
@@ -375,7 +395,7 @@ internal object ReflectionTool {
var isMatched = false
var conditions = true
if (paramCount >= 0)
conditions = (it.parameterTypes.size == paramCountR).let {
conditions = (it.parameterTypes.size == paramCount).let {
if (it) paramCountIndex++
isMatched = true
it && (matchIndex == null ||
@@ -384,6 +404,16 @@ internal object ReflectionTool {
abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) ||
(paramCountLastIndex == paramCountIndex && matchIndex.second.not()))
}
if (paramCountRange.isEmpty().not())
conditions = (conditions && it.parameterTypes.size in paramCountRange).let {
if (it) paramCountRangeIndex++
isMatched = true
it && (matchIndex == null ||
(matchIndex.first >= 0 && matchIndex.first == paramCountRangeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) ||
(paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not()))
}
if (paramTypes != null)
conditions = (conditions && arrayContentsEq(paramTypes, it.parameterTypes)).let {
if (it) paramTypeIndex++
@@ -408,18 +438,15 @@ internal object ReflectionTool {
(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
}
if (conditions && isMatched) constructors.add(it.apply { isAccessible = true })
}
} ?: error("Can't find this Constructor because classSet is null")
return constructor?.also { MemberCacheStore.putConstructor(hashCode, constructor) }
return constructors.takeIf { it.isNotEmpty() }?.also { MemberCacheStore.putConstructors(hashCode, constructors) }
?: if (isFindInSuperClass && classSet.hasExtends)
findConstructor(
findConstructors(
classSet.superclass,
orderIndex, matchIndex,
modifiers, paramCount,
modifiers, paramCount, paramCountRange,
paramTypes, isFindInSuperClass = true
)
else throw NoSuchMethodError(
@@ -434,13 +461,11 @@ internal object ReflectionTool {
matchIndex.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex.first}] "
} +
"paramCount:[${
paramCountR.takeIf { it >= 0 || it == -2 }
?.toString()?.replace(oldValue = "-2", newValue = "last") ?: "unspecified"
}] " +
"paramCount:[${paramCount.takeIf { it >= 0 } ?: "unspecified"}] " +
"paramCountRange:[${paramCountRange.takeIf { it.isEmpty().not() } ?: "unspecified"}] " +
"paramTypes:[${paramTypes.typeOfString()}] " +
"modifiers:${modifiers ?: "[]"} " +
"in Class [$classSet] " +
"in [$classSet] " +
"by $TAG"
)
}

View File

@@ -45,14 +45,14 @@ internal object MemberCacheStore {
/** 缓存的 [Class] */
private val classCacheDatas = HashMap<Int, Class<*>?>()
/** 缓存的 [Method] */
private val methodCacheDatas = HashMap<Int, Method?>()
/** 缓存的 [Method] 数组 */
private val methodsCacheDatas = HashMap<Int, HashSet<Method>>()
/** 缓存的 [Constructor] */
private val constructorCacheDatas = HashMap<Int, Constructor<*>?>()
/** 缓存的 [Constructor] 数组 */
private val constructorsCacheDatas = HashMap<Int, HashSet<Constructor<*>>>()
/** 缓存的 [Field] */
private val fieldCacheDatas = HashMap<Int, Field?>()
/** 缓存的 [Field] 数组 */
private val fieldsCacheDatas = HashMap<Int, HashSet<Field>>()
/**
* 查找缓存中的 [Class]
@@ -62,25 +62,25 @@ internal object MemberCacheStore {
internal fun findClass(hashCode: Int) = classCacheDatas[hashCode]
/**
* 查找缓存中的 [Method]
* 查找缓存中的 [Method] 数组
* @param hashCode 标识符
* @return [Method] or null
* @return [HashSet]<[Method]>
*/
internal fun findMethod(hashCode: Int) = methodCacheDatas[hashCode]
internal fun findMethods(hashCode: Int) = methodsCacheDatas[hashCode]
/**
* 查找缓存中的 [Constructor]
* 查找缓存中的 [Constructor] 数组
* @param hashCode 标识符
* @return [Constructor] or null
* @return [HashSet]<[Constructor]>
*/
internal fun findConstructor(hashCode: Int) = constructorCacheDatas[hashCode]
internal fun findConstructors(hashCode: Int) = constructorsCacheDatas[hashCode]
/**
* 查找缓存中的 [Field]
* 查找缓存中的 [Field] 数组
* @param hashCode 标识符
* @return [Field] or null
* @return [HashSet]<[Field]>
*/
internal fun findField(hashCode: Int) = fieldCacheDatas[hashCode]
internal fun findFields(hashCode: Int) = fieldsCacheDatas[hashCode]
/**
* 写入 [Class] 到缓存
@@ -93,32 +93,32 @@ internal object MemberCacheStore {
}
/**
* 写入 [Method] 到缓存
* 写入 [Method] 数组到缓存
* @param hashCode 标识符
* @param instance 实例
* @param instances 实例数组
*/
internal fun putMethod(hashCode: Int, instance: Method?) {
internal fun putMethods(hashCode: Int, instances: HashSet<Method>) {
if (YukiHookAPI.Configs.isEnableMemberCache.not()) return
methodCacheDatas[hashCode] = instance
methodsCacheDatas[hashCode] = instances
}
/**
* 写入 [Constructor] 到缓存
* 写入 [Constructor] 数组到缓存
* @param hashCode 标识符
* @param instance 实例
* @param instances 实例数组
*/
internal fun putConstructor(hashCode: Int, instance: Constructor<*>?) {
internal fun putConstructors(hashCode: Int, instances: HashSet<Constructor<*>>) {
if (YukiHookAPI.Configs.isEnableMemberCache.not()) return
constructorCacheDatas[hashCode] = instance
constructorsCacheDatas[hashCode] = instances
}
/**
* 写入 [Field] 到缓存
* 写入 [Field] 数组到缓存
* @param hashCode 标识符
* @param instance 实例
* @param instances 实例数组
*/
internal fun putField(hashCode: Int, instance: Field?) {
internal fun putFields(hashCode: Int, instances: HashSet<Field>) {
if (YukiHookAPI.Configs.isEnableMemberCache.not()) return
fieldCacheDatas[hashCode] = instance
fieldsCacheDatas[hashCode] = instances
}
}