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/MemberBaseFinder-IndexTypeCondition.md ':include')
[filename](public/BaseFinder-IndexTypeCondition.md ':include')
[filename](public/ModifierRules.md ':include')

View File

@@ -1,4 +1,4 @@
## MemberBaseFinder.IndexTypeCondition *- class*
## BaseFinder.IndexTypeCondition *- class*
```kotlin
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.93` `修改`
重命名 `BaseFinder``MemberBaseFinder`
**功能描述**
> 字节码下标筛选实现类。

View File

@@ -1,7 +1,7 @@
## ConstructorFinder *- class*
```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` `修改`
修正拼写错误的 **Creater** 命名到 **Creator**
合并到 `MemberBaseFinder`
**功能描述**
@@ -90,7 +90,7 @@ fun param(vararg paramType: Any): IndexTypeCondition
> 设置 `Constructor` 参数。
如果同时使用了 `paramCount``paramTypes` 的数量必须与 `paramCount` 完全匹配。
如果同时使用了 `paramCount``paramType` 的数量必须与 `paramCount` 完全匹配。
!> 无参 `Constructor` 请使用 `emptyParam` 设置查询条件。

View File

@@ -1,7 +1,7 @@
## FieldFinder *- class*
```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`
`v1.0.93` `修改`
合并到 `MemberBaseFinder`
**功能描述**
> `Field` 查找类。

View File

@@ -1,7 +1,7 @@
## MethodFinder *- class*
```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`
`v1.0.93` `修改`
合并到 `MemberBaseFinder`
**功能描述**
> `Method` 查找类。
@@ -120,7 +124,7 @@ fun param(vararg paramType: Any): IndexTypeCondition
> 设置 `Method` 参数。
如果同时使用了 `paramCount``paramTypes` 的数量必须与 `paramCount` 完全匹配。
如果同时使用了 `paramCount``paramType` 的数量必须与 `paramCount` 完全匹配。
!> 无参 `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.annotation.YukiPrivateApi
import com.highcapable.yukihookapi.hook.bean.VariousClass
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.yLoggerI
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
import com.highcapable.yukihookapi.hook.utils.await
import com.highcapable.yukihookapi.hook.utils.unit
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.Member
import java.lang.reflect.Method
import kotlin.math.abs
/**
* 这是 [Member] 查找类功能的基本类实现
@@ -56,72 +52,7 @@ abstract class MemberBaseFinder internal constructor(
internal open val hookInstance: YukiMemberHookCreator.MemberHookCreator? = null,
@PublishedApi
internal open val classSet: Class<*>? = null
) {
/**
* 字节码下标筛选数据类型
*/
@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)
}
}
}
) : BaseFinder() {
/** 是否使用了重查找功能 */
@PublishedApi
@@ -176,13 +107,7 @@ abstract class MemberBaseFinder internal constructor(
* 将目标类型转换为可识别的兼容类型
* @return [Class] or null
*/
internal fun Any?.compat() = when (this) {
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<*>?
internal fun Any?.compat() = compat(tag, classSet?.classLoader)
/**
* 发生错误时输出日志
@@ -221,49 +146,22 @@ abstract class MemberBaseFinder internal constructor(
if (YukiHookAPI.Configs.isDebug && YukiHookBridge.hasXposedBridge && hookInstance != null) yLoggerI(msg = msg)
}
/**
* 返回结果实现类
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun build(): BaseResult
/**
* 返回结果处理类并设置到目标 [YukiMemberHookCreator.MemberHookCreator]
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [BaseResult]
* @return [BaseFinder.BaseResult]
*/
@YukiPrivateApi
abstract fun process(): BaseResult
/**
* 返回只有异常的结果实现类
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param throwable 异常
* @return [BaseResult]
*/
@YukiPrivateApi
abstract fun failure(throwable: Throwable?): BaseResult
/**
* 返回只有异常的结果处理类并作用于目标 [YukiMemberHookCreator.MemberHookCreator]
*
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
* @param throwable 异常
* @return [BaseResult]
* @return [BaseFinder.BaseResult]
*/
@YukiPrivateApi
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.hook.bean.VariousClass
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.members.data.ConstructorRulesData
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.core.reflex.tools.ReflectionTool
import com.highcapable.yukihookapi.hook.factory.ConstructorCondition
@@ -62,21 +64,12 @@ class ConstructorFinder @PublishedApi internal constructor(
/** 当前使用的 [classSet] */
private var usedClassSet = classSet
/** 是否在未找到后继续在当前 [classSet] 的父类中查找 */
private var isFindInSuperClass = false
/** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null
/** [Constructor] 参数数组 */
private var paramTypes: Array<out Class<*>>? = null
/** [Constructor] 参数个数范围 */
private var paramCountRange = IntRange.EMPTY
/** [ModifierRules] 实例 */
/** 当前查询条件规则数据 */
@PublishedApi
internal var modifiers: ModifierRules? = null
internal var rulesData = ConstructorRulesData()
/**
* 设置 [Constructor] 参数个数
@@ -84,50 +77,55 @@ class ConstructorFinder @PublishedApi internal constructor(
* 你可以不使用 [param] 指定参数类型而是仅使用此变量指定参数个数
*
* 若参数个数小于零则忽略并使用 [param]
* @return [Int]
*/
var paramCount = -1
var paramCount
get() = rulesData.paramCount
set(value) {
rulesData.paramCount = value
}
/**
* 设置 [Constructor] 标识符筛选条件
*
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param initiate 方法体
* @return [MemberBaseFinder.IndexTypeCondition]
* @return [BaseFinder.IndexTypeCondition]
*/
inline fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition {
modifiers = ModifierRules().apply(initiate)
rulesData.modifiers = ModifierRules().apply(initiate)
return IndexTypeCondition(IndexConfigType.MATCH)
}
/**
* 设置 [Constructor] 空参数、无参数
*
* @return [MemberBaseFinder.IndexTypeCondition]
* @return [BaseFinder.IndexTypeCondition]
*/
fun emptyParam() = paramCount(num = 0)
/**
* 设置 [Constructor] 参数
*
* 如果同时使用了 [paramCount] 则 [paramTypes] 的数量必须与 [paramCount] 完全匹配
* 如果同时使用了 [paramCount] 则 [paramType] 的数量必须与 [paramCount] 完全匹配
*
* - ❗无参 [Constructor] 请使用 [emptyParam] 设置查询条件
*
* - ❗有参 [Constructor] 必须使用此方法设定参数或使用 [paramCount] 指定个数
*
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass]
* @return [MemberBaseFinder.IndexTypeCondition]
* @return [BaseFinder.IndexTypeCondition]
*/
fun param(vararg paramType: Any): IndexTypeCondition {
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 [MemberBaseFinder.IndexTypeCondition]
* @return [BaseFinder.IndexTypeCondition]
*/
fun order() = IndexTypeCondition(IndexConfigType.ORDER)
@@ -138,12 +136,12 @@ class ConstructorFinder @PublishedApi internal constructor(
*
* 若参数个数小于零则忽略并使用 [param]
*
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param num 个数
* @return [MemberBaseFinder.IndexTypeCondition]
* @return [BaseFinder.IndexTypeCondition]
*/
fun paramCount(num: Int): IndexTypeCondition {
paramCount = num
rulesData.paramCount = num
return IndexTypeCondition(IndexConfigType.MATCH)
}
@@ -152,12 +150,12 @@ class ConstructorFinder @PublishedApi internal constructor(
*
* 你可以不使用 [param] 指定参数类型而是仅使用此方法指定参数个数范围
*
* - ❗存在多个 [MemberBaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
* @param numRange 个数范围
* @return [MemberBaseFinder.IndexTypeCondition]
* @return [BaseFinder.IndexTypeCondition]
*/
fun paramCount(numRange: IntRange): IndexTypeCondition {
paramCountRange = numRange
rulesData.paramCountRange = numRange
return IndexTypeCondition(IndexConfigType.MATCH)
}
@@ -168,7 +166,7 @@ class ConstructorFinder @PublishedApi internal constructor(
* @param isOnlySuperClass 是否仅在当前 [classSet] 的父类中查找 - 若父类是 [Any] 则不会生效
*/
fun superClass(isOnlySuperClass: Boolean = false) {
isFindInSuperClass = true
rulesData.isFindInSuper = true
if (isOnlySuperClass && classSet?.hasExtends == true) usedClassSet = classSet.superclass
}
@@ -177,11 +175,7 @@ class ConstructorFinder @PublishedApi internal constructor(
* @return [HashSet]<[Constructor]>
* @throws NoSuchMethodError 如果找不到构造方法
*/
private val result
get() = ReflectionTool.findConstructors(
usedClassSet, orderIndex, matchIndex, modifiers,
paramCount, paramCountRange, paramTypes, isFindInSuperClass
)
private val result get() = ReflectionTool.findConstructors(usedClassSet, orderIndex, matchIndex, rulesData)
/**
* 设置实例

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

View File

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

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

View File

@@ -29,9 +29,9 @@
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.MethodFinder
import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder
import com.highcapable.yukihookapi.hook.log.yLoggerE
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
import de.robv.android.xposed.XC_MethodHook
@@ -81,12 +81,12 @@ internal object YukiHookHelper {
if (YukiHookBridge.hasXposedBridge) XposedHelpers.findClass(name, loader) else null
/**
* Hook [MemberBaseFinder.BaseResult]
* @param traction 直接调用 [MemberBaseFinder.BaseResult]
* Hook [BaseFinder.BaseResult]
* @param traction 直接调用 [BaseFinder.BaseResult]
* @param callback 回调
* @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(
when (traction) {
is MethodFinder.Result -> traction.ignored().give()