Modify move orderIndex, matchIndex in BaseRulesData and move modifiers to BaseRulesData and add objectName in BaseRulesData and make ReflectionTool simplify

This commit is contained in:
2022-09-09 03:39:57 +08:00
parent 1490a03b7e
commit 57aba63e90
10 changed files with 397 additions and 361 deletions

View File

@@ -29,6 +29,7 @@ package com.highcapable.yukihookapi.hook.core.finder.base
import com.highcapable.yukihookapi.annotation.YukiPrivateApi import com.highcapable.yukihookapi.annotation.YukiPrivateApi
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.core.finder.base.data.BaseRulesData
import com.highcapable.yukihookapi.hook.factory.toClass import com.highcapable.yukihookapi.hook.factory.toClass
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
import java.lang.reflect.Member import java.lang.reflect.Member
@@ -39,18 +40,16 @@ import kotlin.math.abs
*/ */
abstract class BaseFinder { abstract class BaseFinder {
/** 当前查询条件规则数据 */
@PublishedApi
internal abstract val rulesData: BaseRulesData
/** /**
* 字节码、数组下标筛选数据类型 * 字节码、数组下标筛选数据类型
*/ */
@PublishedApi @PublishedApi
internal enum class IndexConfigType { ORDER, MATCH } internal enum class IndexConfigType { ORDER, MATCH }
/** 字节码、数组顺序下标 */
internal var orderIndex: Pair<Int, Boolean>? = null
/** 字节码、数组筛选下标 */
internal var matchIndex: Pair<Int, Boolean>? = null
/** /**
* 字节码、数组下标筛选实现类 * 字节码、数组下标筛选实现类
* @param type 类型 * @param type 类型
@@ -66,8 +65,8 @@ abstract class BaseFinder {
* @param num 下标 * @param num 下标
*/ */
fun index(num: Int) = when (type) { fun index(num: Int) = when (type) {
IndexConfigType.ORDER -> orderIndex = Pair(num, true) IndexConfigType.ORDER -> rulesData.orderIndex = Pair(num, true)
IndexConfigType.MATCH -> matchIndex = Pair(num, true) IndexConfigType.MATCH -> rulesData.matchIndex = Pair(num, true)
} }
/** /**
@@ -88,8 +87,8 @@ abstract class BaseFinder {
/** 设置满足条件的最后一个*/ /** 设置满足条件的最后一个*/
fun last() = when (type) { fun last() = when (type) {
IndexConfigType.ORDER -> orderIndex = Pair(0, false) IndexConfigType.ORDER -> rulesData.orderIndex = Pair(0, false)
IndexConfigType.MATCH -> matchIndex = Pair(0, false) IndexConfigType.MATCH -> rulesData.matchIndex = Pair(0, false)
} }
/** /**

View File

@@ -0,0 +1,64 @@
/*
* 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/8.
*/
package com.highcapable.yukihookapi.hook.core.finder.base.data
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import java.lang.reflect.Member
/**
* 这是 [Class] 与 [Member] 规则查询数据基本类实现
* @param modifiers 描述符
* @param orderIndex 字节码、数组顺序下标
* @param matchIndex 字节码、数组筛选下标
*/
@PublishedApi
internal abstract class BaseRulesData internal constructor(
var modifiers: ModifierRules? = null,
var orderIndex: Pair<Int, Boolean>? = null,
var matchIndex: Pair<Int, Boolean>? = null
) {
/**
* 获取规则对象名称
* @return [String]
*/
internal abstract val objectName: String
/**
* 判断规则是否已经初始化 (设置了任意一个参数)
* @return [Boolean]
*/
internal open val isInitialize get() = modifiers != null || orderIndex != null || matchIndex != null
/**
* 通过规则数据 [toString] 来得到一个 [Any.hashCode]
* @param other 额外的数据 - 可选
* @return [Int]
*/
internal open fun hashCode(other: Any? = null) = "[$other][$modifiers][$orderIndex][$matchIndex]".hashCode()
}

View File

@@ -61,16 +61,15 @@ class ConstructorFinder @PublishedApi internal constructor(
override val classSet: Class<*>? = null override val classSet: Class<*>? = null
) : MemberBaseFinder(tag = "Constructor", hookInstance, classSet) { ) : MemberBaseFinder(tag = "Constructor", hookInstance, classSet) {
@PublishedApi
override var rulesData = ConstructorRulesData()
/** 当前使用的 [classSet] */ /** 当前使用的 [classSet] */
private var usedClassSet = classSet private var usedClassSet = classSet
/** 当前重查找结果回调 */ /** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null private var remedyPlansCallback: (() -> Unit)? = null
/** 当前查询条件规则数据 */
@PublishedApi
internal var rulesData = ConstructorRulesData()
/** /**
* 设置 [Constructor] 参数个数 * 设置 [Constructor] 参数个数
* *
@@ -175,7 +174,7 @@ class ConstructorFinder @PublishedApi internal constructor(
* @return [HashSet]<[Constructor]> * @return [HashSet]<[Constructor]>
* @throws NoSuchMethodError 如果找不到 [Constructor] * @throws NoSuchMethodError 如果找不到 [Constructor]
*/ */
private val result get() = ReflectionTool.findConstructors(usedClassSet, orderIndex, matchIndex, rulesData) private val result by lazy { ReflectionTool.findConstructors(usedClassSet, rulesData) }
/** /**
* 设置实例 * 设置实例

View File

@@ -62,16 +62,15 @@ class FieldFinder @PublishedApi internal constructor(
override val classSet: Class<*>? = null override val classSet: Class<*>? = null
) : MemberBaseFinder(tag = "Field", hookInstance, classSet) { ) : MemberBaseFinder(tag = "Field", hookInstance, classSet) {
@PublishedApi
override var rulesData = FieldRulesData()
/** 当前使用的 [classSet] */ /** 当前使用的 [classSet] */
private var usedClassSet = classSet private var usedClassSet = classSet
/** 当前重查找结果回调 */ /** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null private var remedyPlansCallback: (() -> Unit)? = null
/** 当前查询条件规则数据 */
@PublishedApi
internal var rulesData = FieldRulesData()
/** /**
* 设置 [Field] 名称 * 设置 [Field] 名称
* *
@@ -176,7 +175,7 @@ class FieldFinder @PublishedApi internal constructor(
* @return [HashSet]<[Field]> * @return [HashSet]<[Field]>
* @throws NoSuchFieldError 如果找不到 [Field] * @throws NoSuchFieldError 如果找不到 [Field]
*/ */
private val result get() = ReflectionTool.findFields(usedClassSet, orderIndex, matchIndex, rulesData) private val result get() = ReflectionTool.findFields(usedClassSet, rulesData)
/** /**
* 设置实例 * 设置实例

View File

@@ -63,16 +63,15 @@ class MethodFinder @PublishedApi internal constructor(
override val classSet: Class<*>? = null override val classSet: Class<*>? = null
) : MemberBaseFinder(tag = "Method", hookInstance, classSet) { ) : MemberBaseFinder(tag = "Method", hookInstance, classSet) {
@PublishedApi
override var rulesData = MethodRulesData()
/** 当前使用的 [classSet] */ /** 当前使用的 [classSet] */
private var usedClassSet = classSet private var usedClassSet = classSet
/** 当前重查找结果回调 */ /** 当前重查找结果回调 */
private var remedyPlansCallback: (() -> Unit)? = null private var remedyPlansCallback: (() -> Unit)? = null
/** 当前查询条件规则数据 */
@PublishedApi
internal var rulesData = MethodRulesData()
/** /**
* 设置 [Method] 名称 * 设置 [Method] 名称
* *
@@ -247,7 +246,7 @@ class MethodFinder @PublishedApi internal constructor(
* @return [HashSet]<[Method]> * @return [HashSet]<[Method]>
* @throws NoSuchMethodError 如果找不到 [Method] * @throws NoSuchMethodError 如果找不到 [Method]
*/ */
private val result get() = ReflectionTool.findMethods(usedClassSet, orderIndex, matchIndex, rulesData) private val result get() = ReflectionTool.findMethods(usedClassSet, rulesData)
/** /**
* 设置实例 * 设置实例

View File

@@ -40,4 +40,11 @@ internal class ConstructorRulesData internal constructor(
var paramTypes: Array<out Class<*>>? = null, var paramTypes: Array<out Class<*>>? = null,
var paramCount: Int = -1, var paramCount: Int = -1,
var paramCountRange: IntRange = IntRange.EMPTY var paramCountRange: IntRange = IntRange.EMPTY
) : MemberRulesData() ) : MemberRulesData() {
override val objectName get() = "Constructor"
override val isInitialize get() = super.isInitializeOfSuper || paramTypes != null || paramCount >= 0 || paramCountRange != IntRange.EMPTY
override fun hashCode(other: Any?) = super.hashCode(other) + "[$paramTypes][$paramCount][$paramCountRange]".hashCode()
}

View File

@@ -41,4 +41,11 @@ internal class FieldRulesData internal constructor(
var name: String = "", var name: String = "",
var nameConditions: NameConditions? = null, var nameConditions: NameConditions? = null,
var type: Any? = null var type: Any? = null
) : MemberRulesData() ) : MemberRulesData() {
override val objectName get() = "Field"
override val isInitialize get() = super.isInitializeOfSuper || name.isNotBlank() || nameConditions != null || type != null
override fun hashCode(other: Any?) = super.hashCode(other) + "[$name][$nameConditions][$type]".hashCode()
}

View File

@@ -27,20 +27,31 @@
*/ */
package com.highcapable.yukihookapi.hook.core.finder.members.data package com.highcapable.yukihookapi.hook.core.finder.members.data
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules import com.highcapable.yukihookapi.hook.core.finder.base.data.BaseRulesData
import java.lang.reflect.Member import java.lang.reflect.Member
/** /**
* [Member] 规则查询数据类 * [Member] 规则查询数据类
* @param modifiers 描述符
* @param isFindInSuper 是否在未找到后继续在父类中查找 * @param isFindInSuper 是否在未找到后继续在父类中查找
* @param matchCount 匹配的字节码个数 * @param matchCount 匹配的字节码个数
* @param matchCountRange 匹配的字节码个数范围 * @param matchCountRange 匹配的字节码个数范围
*/ */
@PublishedApi @PublishedApi
internal open class MemberRulesData internal constructor( internal open class MemberRulesData internal constructor(
var modifiers: ModifierRules? = null,
var isFindInSuper: Boolean = false, var isFindInSuper: Boolean = false,
var matchCount: Int = -1, var matchCount: Int = -1,
var matchCountRange: IntRange = IntRange.EMPTY var matchCountRange: IntRange = IntRange.EMPTY
) ) : BaseRulesData() {
override val objectName get() = "Member"
/**
* 判断 [BaseRulesData] 规则是否已经初始化 (设置了任意一个参数)
* @return [Boolean]
*/
internal val isInitializeOfSuper get() = super.isInitialize
override val isInitialize get() = isInitializeOfSuper || matchCount >= 0 || matchCountRange != IntRange.EMPTY
override fun hashCode(other: Any?) = super.hashCode(other) + "[$isFindInSuper][$matchIndex][$matchCountRange]".hashCode()
}

View File

@@ -47,4 +47,14 @@ internal class MethodRulesData internal constructor(
var paramCount: Int = -1, var paramCount: Int = -1,
var paramCountRange: IntRange = IntRange.EMPTY, var paramCountRange: IntRange = IntRange.EMPTY,
var returnType: Any? = null var returnType: Any? = null
) : MemberRulesData() ) : MemberRulesData() {
override val objectName get() = "Method"
override val isInitialize
get() = super.isInitializeOfSuper || name.isNotBlank() || nameConditions != null || paramTypes != null ||
paramCount >= 0 || paramCountRange != IntRange.EMPTY || returnType != null
override fun hashCode(other: Any?) =
super.hashCode(other) + "[$name][$nameConditions][$paramTypes][$paramCount][$paramCountRange][$returnType]".hashCode()
}

View File

@@ -27,13 +27,17 @@
*/ */
package com.highcapable.yukihookapi.hook.core.reflex.tools package com.highcapable.yukihookapi.hook.core.reflex.tools
import com.highcapable.yukihookapi.hook.core.finder.base.data.BaseRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.ConstructorRulesData 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.FieldRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.MemberRulesData
import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
import com.highcapable.yukihookapi.hook.factory.hasExtends import com.highcapable.yukihookapi.hook.factory.hasExtends
import com.highcapable.yukihookapi.hook.store.ReflectsCacheStore import com.highcapable.yukihookapi.hook.store.ReflectsCacheStore
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
import com.highcapable.yukihookapi.hook.utils.conditions import com.highcapable.yukihookapi.hook.utils.conditions
import com.highcapable.yukihookapi.hook.utils.let
import com.highcapable.yukihookapi.hook.utils.takeIf
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiHookHelper import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiHookHelper
import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics
@@ -84,413 +88,350 @@ internal object ReflectionTool {
/** /**
* 查找任意 [Field] 或一组 [Field] * 查找任意 [Field] 或一组 [Field]
* @param classSet [Field] 所在类 * @param classSet [Field] 所在类
* @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标
* @param rulesData 规则查询数据 * @param rulesData 规则查询数据
* @return [HashSet]<[Field]> * @return [HashSet]<[Field]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [FieldRulesData.type] 目标类不存在 * @throws IllegalStateException 如果未设置任何条件或 [FieldRulesData.type] 目标类不存在
* @throws NoSuchFieldError 如果找不到 [Field] * @throws NoSuchFieldError 如果找不到 [Field]
*/ */
internal fun findFields( internal fun findFields(classSet: Class<*>?, rulesData: FieldRulesData) = rulesData.createResult {
classSet: Class<*>?, if (type == UndefinedType) error("Field match type class is not found")
orderIndex: Pair<Int, Boolean>?, if (classSet == null) return@createResult hashSetOf()
matchIndex: Pair<Int, Boolean>?, ReflectsCacheStore.findFields(hashCode(classSet)) ?: hashSetOf<Field>().also { fields ->
rulesData: FieldRulesData classSet.declaredFields.also { declares ->
): HashSet<Field> { var iType = -1
if (rulesData.type == UndefinedType) error("Field match type class is not found") var iName = -1
if (orderIndex == null && matchIndex == null && var iModify = -1
rulesData.name.isBlank() && rulesData.nameConditions == null && var iNameCds = -1
rulesData.modifiers == null && rulesData.type == null val iLType = type?.let(matchIndex) { e -> declares.filter { e == it.type }.lastIndex } ?: -1
) error("You must set a condition when finding a Field") val iLName = name.takeIf(matchIndex) { it.isNotBlank() }?.let { e -> declares.filter { e == it.name }.lastIndex } ?: -1
val hashCode = ("[$orderIndex][$matchIndex][${rulesData.name}][${rulesData.nameConditions}]" + val iLModify = modifiers?.let(matchIndex) { e -> declares.filter { e.contains(it) }.lastIndex } ?: -1
"[${rulesData.type}][${rulesData.modifiers}][$classSet]").hashCode() val iLNameCds = nameConditions?.let(matchIndex) { e -> declares.filter { e.contains(it) }.lastIndex } ?: -1
return ReflectsCacheStore.findFields(hashCode) ?: let { declares.forEachIndexed { index, instance ->
val fields = HashSet<Field>()
classSet?.declaredFields?.apply {
var typeIndex = -1
var nameIndex = -1
var modifyIndex = -1
var nameCdsIndex = -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, instance ->
var isMatched = false var isMatched = false
rulesData.conditions { conditions {
value.type?.also { e -> type?.also {
and((e == instance.type).let { and((it == instance.type).let { hold ->
if (it) typeIndex++ if (hold) iType++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iType, iLType)
(matchIndex.first >= 0 && matchIndex.first == typeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (typeLastIndex - typeIndex) && matchIndex.second) ||
(typeLastIndex == typeIndex && matchIndex.second.not()))
}) })
} }
value.name.takeIf { it.isNotBlank() }?.also { e -> name.takeIf { it.isNotBlank() }?.also {
and((e == instance.name).let { and((it == instance.name).let { hold ->
if (it) nameIndex++ if (hold) iName++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iName, iLName)
(matchIndex.first >= 0 && matchIndex.first == nameIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) ||
(nameLastIndex == nameIndex && matchIndex.second.not()))
}) })
} }
value.modifiers?.also { e -> modifiers?.also {
and(e.contains(instance).let { and(it.contains(instance).let { hold ->
if (it) modifyIndex++ if (hold) iModify++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iModify, iLModify)
(matchIndex.first >= 0 && matchIndex.first == modifyIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) ||
(modifyLastIndex == modifyIndex && matchIndex.second.not()))
}) })
} }
value.nameConditions?.also { e -> nameConditions?.also {
and(e.contains(instance).let { and(it.contains(instance).let { hold ->
if (it) nameCdsIndex++ if (hold) iNameCds++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iNameCds, iLNameCds)
(matchIndex.first >= 0 && matchIndex.first == nameCdsIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (nameCdsLastIndex - nameCdsIndex) && matchIndex.second) ||
(nameCdsLastIndex == nameCdsIndex && matchIndex.second.not()))
}) })
} }
orderIndex?.also { orderIndex.compare(index, declares.lastIndex) { and(it); isMatched = it }
and(((it.first >= 0 && it.first == p && it.second) ||
(it.first < 0 && abs(it.first) == (lastIndex - p) && it.second) ||
(lastIndex == p && it.second.not())).also { isMatched = true })
}
}.finally { if (isMatched) fields.add(instance.apply { isAccessible = true }) } }.finally { if (isMatched) fields.add(instance.apply { isAccessible = true }) }
} }
} ?: error("Can't find this Field [${rulesData.name}] because classSet is null")
fields.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putFields(hashCode, fields) }
?: if (rulesData.isFindInSuper && classSet.hasExtends)
findFields(classSet.superclass, orderIndex, matchIndex, rulesData)
else throw NoSuchFieldError(
"Can't find this Field --> " +
when {
orderIndex == null -> ""
orderIndex.second.not() -> "orderIndex:[last] "
else -> "orderIndex:[${orderIndex.first}] "
} +
when {
matchIndex == null -> ""
matchIndex.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex.first}] "
} +
when (rulesData.nameConditions) {
null -> ""
else -> "nameConditions:${rulesData.nameConditions} "
} +
"name:[${rulesData.name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"type:[${rulesData.type ?: "unspecified"}] " +
"modifiers:${rulesData.modifiers ?: "[]"} " +
"in [$classSet] " +
"by $TAG"
)
} }
}.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putFields(hashCode(classSet), it) } ?: findSuperOrThrow(classSet)
} }
/** /**
* 查找任意 [Method] 或一组 [Method] * 查找任意 [Method] 或一组 [Method]
* @param classSet [Method] 所在类 * @param classSet [Method] 所在类
* @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标
* @param rulesData 规则查询数据 * @param rulesData 规则查询数据
* @return [HashSet]<[Method]> * @return [HashSet]<[Method]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [MethodRulesData.paramTypes] 以及 [MethodRulesData.returnType] 目标类不存在 * @throws IllegalStateException 如果未设置任何条件或 [MethodRulesData.paramTypes] 以及 [MethodRulesData.returnType] 目标类不存在
* @throws NoSuchMethodError 如果找不到 [Method] * @throws NoSuchMethodError 如果找不到 [Method]
*/ */
internal fun findMethods( internal fun findMethods(classSet: Class<*>?, rulesData: MethodRulesData) = rulesData.createResult {
classSet: Class<*>?, if (returnType == UndefinedType) error("Method match returnType class is not found")
orderIndex: Pair<Int, Boolean>?, if (classSet == null) return@createResult hashSetOf()
matchIndex: Pair<Int, Boolean>?, paramTypes?.takeIf { it.isNotEmpty() }
rulesData: MethodRulesData
): HashSet<Method> {
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") } ?.forEachIndexed { p, it -> if (it == UndefinedType) error("Method match paramType[$p] class is not found") }
if (orderIndex == null && matchIndex == null && ReflectsCacheStore.findMethods(hashCode(classSet)) ?: hashSetOf<Method>().also { methods ->
rulesData.name.isBlank() && rulesData.nameConditions == null && classSet.declaredMethods.also { declares ->
rulesData.modifiers == null && rulesData.paramCount < 0 && var iReturnType = -1
rulesData.paramCountRange.isEmpty() && rulesData.paramTypes == null && var iParamTypes = -1
rulesData.returnType == null var iParamCount = -1
) error("You must set a condition when finding a Method") var iParamCountRange = -1
val hashCode = ("[$orderIndex][$matchIndex][${rulesData.name}][${rulesData.nameConditions}][${rulesData.paramCount}]" + var iName = -1
"[${rulesData.paramTypes.typeOfString()}][${rulesData.returnType}][${rulesData.modifiers}][$classSet]").hashCode() var iModify = -1
return ReflectsCacheStore.findMethods(hashCode) ?: let { var iNameCds = -1
val methods = HashSet<Method>() val iLReturnType = returnType?.let(matchIndex) { e -> declares.filter { e == it.returnType }.lastIndex } ?: -1
classSet?.declaredMethods?.apply { val iLParamCount = paramCount.takeIf(matchIndex) { it >= 0 }
var returnTypeIndex = -1 ?.let { e -> declares.filter { e == it.parameterTypes.size }.lastIndex } ?: -1
var paramTypeIndex = -1 val iLParamCountRange = paramCountRange.takeIf(matchIndex) { it.isEmpty().not() }
var paramCountIndex = -1 ?.let { e -> declares.filter { it.parameterTypes.size in e }.lastIndex } ?: -1
var paramCountRangeIndex = -1 val iLParamTypes = paramTypes?.let(matchIndex) { e -> declares.filter { arrayContentsEq(e, it.parameterTypes) }.lastIndex } ?: -1
var nameIndex = -1 val iLName = name.takeIf(matchIndex) { it.isNotBlank() }?.let { e -> declares.filter { e == it.name }.lastIndex } ?: -1
var modifyIndex = -1 val iLModify = modifiers?.let(matchIndex) { e -> declares.filter { e.contains(it) }.lastIndex } ?: -1
var nameCdsIndex = -1 val iLNameCds = nameConditions?.let(matchIndex) { e -> declares.filter { e.contains(it) }.lastIndex } ?: -1
val returnTypeLastIndex = declares.forEachIndexed { index, instance ->
if (rulesData.returnType != null && matchIndex != null) filter { rulesData.returnType == it.returnType }.lastIndex else -1
val paramCountLastIndex =
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 (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, instance ->
var isMatched = false var isMatched = false
rulesData.conditions { conditions {
value.name.takeIf { it.isNotBlank() }?.also { e -> name.takeIf { it.isNotBlank() }?.also {
and((e == instance.name).let { and((it == instance.name).let { hold ->
if (it) nameIndex++ if (hold) iName++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iName, iLName)
(matchIndex.first >= 0 && matchIndex.first == nameIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (nameLastIndex - nameIndex) && matchIndex.second) ||
(nameLastIndex == nameIndex && matchIndex.second.not()))
}) })
} }
value.returnType?.also { e -> returnType?.also {
and((e == instance.returnType).let { and((it == instance.returnType).let { hold ->
if (it) returnTypeIndex++ if (hold) iReturnType++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iReturnType, iLReturnType)
(matchIndex.first >= 0 && matchIndex.first == returnTypeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (returnTypeLastIndex - returnTypeIndex) && matchIndex.second) ||
(returnTypeLastIndex == returnTypeIndex && matchIndex.second.not()))
}) })
} }
value.paramCount.takeIf { it >= 0 }?.also { e -> paramCount.takeIf { it >= 0 }?.also {
and((instance.parameterTypes.size == e).let { and((instance.parameterTypes.size == it).let { hold ->
if (it) paramCountIndex++ if (hold) iParamCount++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iParamCount, iLParamCount)
(matchIndex.first >= 0 && matchIndex.first == paramCountIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) ||
(paramCountLastIndex == paramCountIndex && matchIndex.second.not()))
}) })
} }
value.paramCountRange.takeIf { it.isEmpty().not() }?.also { e -> paramCountRange.takeIf { it.isEmpty().not() }?.also {
and((instance.parameterTypes.size in e).let { and((instance.parameterTypes.size in it).let { hold ->
if (it) paramCountRangeIndex++ if (hold) iParamCountRange++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iParamCountRange, iLParamCountRange)
(matchIndex.first >= 0 && matchIndex.first == paramCountRangeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) ||
(paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not()))
}) })
} }
value.paramTypes?.also { e -> paramTypes?.also {
and(arrayContentsEq(e, instance.parameterTypes).let { and(arrayContentsEq(it, instance.parameterTypes).let { hold ->
if (it) paramTypeIndex++ if (hold) iParamTypes++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iParamTypes, iLParamTypes)
(matchIndex.first >= 0 && matchIndex.first == paramTypeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) ||
(paramTypeLastIndex == paramTypeIndex && matchIndex.second.not()))
}) })
} }
value.modifiers?.also { e -> modifiers?.also {
and(e.contains(instance).let { and(it.contains(instance).let { hold ->
if (it) modifyIndex++ if (hold) iModify++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iModify, iLModify)
(matchIndex.first >= 0 && matchIndex.first == modifyIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) ||
(modifyLastIndex == modifyIndex && matchIndex.second.not()))
}) })
} }
value.nameConditions?.also { e -> nameConditions?.also {
and(e.contains(instance).let { and(it.contains(instance).let { hold ->
if (it) nameCdsIndex++ if (hold) iNameCds++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iNameCds, iLNameCds)
(matchIndex.first >= 0 && matchIndex.first == nameCdsIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (nameCdsLastIndex - nameCdsIndex) && matchIndex.second) ||
(nameCdsLastIndex == nameCdsIndex && matchIndex.second.not()))
}) })
} }
orderIndex?.also { orderIndex.compare(index, declares.lastIndex) { and(it); isMatched = it }
and(((it.first >= 0 && it.first == p && it.second) ||
(it.first < 0 && abs(it.first) == (lastIndex - p) && it.second) ||
(lastIndex == p && it.second.not())).also { isMatched = true })
}
}.finally { if (isMatched) methods.add(instance.apply { isAccessible = true }) } }.finally { if (isMatched) methods.add(instance.apply { isAccessible = true }) }
} }
} ?: error("Can't find this Method [${rulesData.name}] because classSet is null")
methods.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putMethods(hashCode, methods) }
?: if (rulesData.isFindInSuper && classSet.hasExtends)
findMethods(classSet.superclass, orderIndex, matchIndex, rulesData)
else throw NoSuchMethodError(
"Can't find this Method --> " +
when {
orderIndex == null -> ""
orderIndex.second.not() -> "orderIndex:[last] "
else -> "orderIndex:[${orderIndex.first}] "
} +
when {
matchIndex == null -> ""
matchIndex.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex.first}] "
} +
when (rulesData.nameConditions) {
null -> ""
else -> "nameConditions:${rulesData.nameConditions} "
} +
"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"
)
} }
}.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putMethods(hashCode(classSet), it) } ?: findSuperOrThrow(classSet)
} }
/** /**
* 查找任意 [Constructor] 或一组 [Constructor] * 查找任意 [Constructor] 或一组 [Constructor]
* @param classSet [Constructor] 所在类 * @param classSet [Constructor] 所在类
* @param orderIndex 字节码顺序下标
* @param matchIndex 字节码筛选下标
* @param rulesData 规则查询数据 * @param rulesData 规则查询数据
* @return [HashSet]<[Constructor]> * @return [HashSet]<[Constructor]>
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [ConstructorRulesData.paramTypes] 目标类不存在 * @throws IllegalStateException 如果未设置任何条件或 [ConstructorRulesData.paramTypes] 目标类不存在
* @throws NoSuchMethodError 如果找不到 [Constructor] * @throws NoSuchMethodError 如果找不到 [Constructor]
*/ */
internal fun findConstructors( internal fun findConstructors(classSet: Class<*>?, rulesData: ConstructorRulesData) = rulesData.createResult {
classSet: Class<*>?, if (classSet == null) return@createResult hashSetOf()
orderIndex: Pair<Int, Boolean>?, paramTypes?.takeIf { it.isNotEmpty() }
matchIndex: Pair<Int, Boolean>?,
rulesData: ConstructorRulesData
): HashSet<Constructor<*>> {
rulesData.paramTypes?.takeIf { it.isNotEmpty() }
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Constructor match paramType[$p] class is not found") } ?.forEachIndexed { p, it -> if (it == UndefinedType) error("Constructor match paramType[$p] class is not found") }
if (orderIndex == null && matchIndex == null && ReflectsCacheStore.findConstructors(hashCode(classSet)) ?: hashSetOf<Constructor<*>>().also { constructors ->
rulesData.modifiers == null && rulesData.paramCount < 0 && classSet.declaredConstructors.also { declares ->
rulesData.paramCountRange.isEmpty() && rulesData.paramTypes == null var iParamTypes = -1
) error("You must set a condition when finding a Constructor") var iParamCount = -1
val hashCode = ("[$orderIndex][$matchIndex][${rulesData.paramCount}][${rulesData.paramTypes.typeOfString()}]" + var iParamCountRange = -1
"[${rulesData.modifiers}][$classSet]").hashCode() var iModify = -1
return ReflectsCacheStore.findConstructors(hashCode) ?: let { val iLParamCount = paramCount.takeIf(matchIndex) { it >= 0 }
val constructors = HashSet<Constructor<*>>() ?.let { e -> declares.filter { e == it.parameterTypes.size }.lastIndex } ?: -1
classSet?.declaredConstructors?.apply { val iLParamCountRange = paramCountRange.takeIf(matchIndex) { it.isEmpty().not() }
var paramTypeIndex = -1 ?.let { e -> declares.filter { it.parameterTypes.size in e }.lastIndex } ?: -1
var paramCountIndex = -1 val iLParamTypes = paramTypes?.let(matchIndex) { e -> declares.filter { arrayContentsEq(e, it.parameterTypes) }.lastIndex } ?: -1
var paramCountRangeIndex = -1 val iLModify = modifiers?.let(matchIndex) { e -> declares.filter { e.contains(it) }.lastIndex } ?: -1
var modifyIndex = -1 declares.forEachIndexed { index, instance ->
val paramCountLastIndex =
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 (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, instance ->
var isMatched = false var isMatched = false
rulesData.conditions { conditions {
value.paramCount.takeIf { it >= 0 }?.also { e -> paramCount.takeIf { it >= 0 }?.also {
and((instance.parameterTypes.size == e).let { and((instance.parameterTypes.size == it).let { hold ->
if (it) paramCountIndex++ if (hold) iParamCount++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iParamCount, iLParamCount)
(matchIndex.first >= 0 && matchIndex.first == paramCountIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramCountLastIndex - paramCountIndex) && matchIndex.second) ||
(paramCountLastIndex == paramCountIndex && matchIndex.second.not()))
}) })
} }
value.paramCountRange.takeIf { it.isEmpty().not() }?.also { e -> paramCountRange.takeIf { it.isEmpty().not() }?.also {
and((instance.parameterTypes.size in e).let { and((instance.parameterTypes.size in it).let { hold ->
if (it) paramCountRangeIndex++ if (hold) iParamCountRange++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iParamCountRange, iLParamCountRange)
(matchIndex.first >= 0 && matchIndex.first == paramCountRangeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramCountRangeLastIndex - paramCountRangeIndex) && matchIndex.second) ||
(paramCountRangeLastIndex == paramCountRangeIndex && matchIndex.second.not()))
}) })
} }
value.paramTypes?.also { e -> paramTypes?.also {
and(arrayContentsEq(e, instance.parameterTypes).let { and(arrayContentsEq(it, instance.parameterTypes).let { hold ->
if (it) paramTypeIndex++ if (hold) iParamTypes++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iParamTypes, iLParamTypes)
(matchIndex.first >= 0 && matchIndex.first == paramTypeIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (paramTypeLastIndex - paramTypeIndex) && matchIndex.second) ||
(paramTypeLastIndex == paramTypeIndex && matchIndex.second.not()))
}) })
} }
value.modifiers?.also { e -> modifiers?.also {
and(e.contains(instance).let { and(it.contains(instance).let { hold ->
if (it) modifyIndex++ if (hold) iModify++
isMatched = true isMatched = true
it && (matchIndex == null || hold && matchIndex.compare(iModify, iLModify)
(matchIndex.first >= 0 && matchIndex.first == modifyIndex && matchIndex.second) ||
(matchIndex.first < 0 &&
abs(matchIndex.first) == (modifyLastIndex - modifyIndex) && matchIndex.second) ||
(modifyLastIndex == modifyIndex && matchIndex.second.not()))
}) })
} }
orderIndex?.also { orderIndex.compare(index, declares.lastIndex) { and(it); isMatched = it }
and(((it.first >= 0 && it.first == p && it.second) ||
(it.first < 0 && abs(it.first) == (lastIndex - p) && it.second) ||
(lastIndex == p && it.second.not())).also { isMatched = true })
}
}.finally { if (isMatched) constructors.add(instance.apply { isAccessible = true }) } }.finally { if (isMatched) constructors.add(instance.apply { isAccessible = true }) }
} }
} ?: error("Can't find this Constructor because classSet is null") }
return constructors.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putConstructors(hashCode, constructors) } }.takeIf { it.isNotEmpty() }?.also { ReflectsCacheStore.putConstructors(hashCode(classSet), it) } ?: findSuperOrThrow(classSet)
?: if (rulesData.isFindInSuper && classSet.hasExtends) }
findConstructors(classSet.superclass, orderIndex, matchIndex, rulesData)
else throw NoSuchMethodError( /**
"Can't find this Constructor --> " + * 比较位置下标的前后顺序
* @param need 当前位置
* @param last 最后位置
* @return [Boolean] 返回是否成立
*/
private fun Pair<Int, Boolean>?.compare(need: Int, last: Int) = this == null || ((first >= 0 && first == need && second) ||
(first < 0 && abs(first) == (last - need) && second) || (last == need && second.not()))
/**
* 比较位置下标的前后顺序
* @param need 当前位置
* @param last 最后位置
* @param result 回调是否成立
*/
private fun Pair<Int, Boolean>?.compare(need: Int, last: Int, result: (Boolean) -> Unit) {
if (this == null) return
((first >= 0 && first == need && second) ||
(first < 0 && abs(first) == (last - need) && second) ||
(last == need && second.not())).also(result)
}
/**
* 创建查找结果方法体
* @param result 回调方法体
* @return [T]
* @throws IllegalStateException 如果没有 [BaseRulesData.isInitialize]
*/
private inline fun <reified T, R : BaseRulesData> R.createResult(result: R.() -> T): T {
when (this) {
is FieldRulesData -> isInitialize.not()
is MethodRulesData -> isInitialize.not()
is ConstructorRulesData -> isInitialize.not()
is MemberRulesData -> isInitialize.not()
else -> true
}.takeIf { it }?.also { error("You must set a condition when finding a $objectName") }
return result(this)
}
/**
* 在 [Class.getSuperclass] 中查找或抛出异常
* @param classSet 所在类
* @return [T]
* @throws NoSuchFieldError 继承于方法 [throwNotFoundError] 的异常
* @throws NoSuchMethodError 继承于方法 [throwNotFoundError] 的异常
* @throws IllegalStateException 如果 [R] 的类型错误
*/
private inline fun <reified T, R : MemberRulesData> R.findSuperOrThrow(classSet: Class<*>): T = when (this) {
is FieldRulesData ->
if (isFindInSuper && classSet.hasExtends)
findFields(classSet.superclass, rulesData = this) as T
else throwNotFoundError(classSet)
is MethodRulesData ->
if (isFindInSuper && classSet.hasExtends)
findMethods(classSet.superclass, rulesData = this) as T
else throwNotFoundError(classSet)
is ConstructorRulesData ->
if (isFindInSuper && classSet.hasExtends)
findConstructors(classSet.superclass, rulesData = this) as T
else throwNotFoundError(classSet)
else -> error("Type [$this] not allowed")
}
/**
* 抛出找不到 [Class]、[Member] 的异常
* @param instanceSet 所在 [ClassLoader] or [Class]
* @throws NoClassDefFoundError 如果找不到 [Class]
* @throws NoSuchFieldError 如果找不到 [Field]
* @throws NoSuchMethodError 如果找不到 [Method] or [Constructor]
* @throws IllegalStateException 如果 [BaseRulesData] 的类型错误
*/
private fun BaseRulesData.throwNotFoundError(instanceSet: Any?): Nothing = when (this) {
is FieldRulesData -> throw NoSuchFieldError(
"Can't find this Field --> " +
when { when {
orderIndex == null -> "" orderIndex == null -> ""
orderIndex.second.not() -> "orderIndex:[last] " orderIndex!!.second.not() -> "orderIndex:[last] "
else -> "orderIndex:[${orderIndex.first}] " else -> "orderIndex:[${orderIndex!!.first}] "
} + } +
when { when {
matchIndex == null -> "" matchIndex == null -> ""
matchIndex.second.not() -> "matchIndex:[last] " matchIndex!!.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex.first}] " else -> "matchIndex:[${matchIndex!!.first}] "
} + } +
"paramCount:[${rulesData.paramCount.takeIf { it >= 0 } ?: "unspecified"}] " + when (nameConditions) {
"paramCountRange:[${rulesData.paramCountRange.takeIf { it.isEmpty().not() } ?: "unspecified"}] " + null -> ""
"paramTypes:[${rulesData.paramTypes.typeOfString()}] " + else -> "nameConditions:${nameConditions} "
"modifiers:${rulesData.modifiers ?: "[]"} " + } +
"in [$classSet] " + "name:[${name.takeIf { it.isNotBlank() } ?: "unspecified"}] " +
"by $TAG" "type:[${type ?: "unspecified"}] " +
"modifiers:${modifiers ?: "[]"} " +
"in [$instanceSet] by $TAG"
) )
} is MethodRulesData -> throw NoSuchMethodError(
"Can't find this Method --> " +
when {
orderIndex == null -> ""
orderIndex!!.second.not() -> "orderIndex:[last] "
else -> "orderIndex:[${orderIndex!!.first}] "
} +
when {
matchIndex == null -> ""
matchIndex!!.second.not() -> "matchIndex:[last] "
else -> "matchIndex:[${matchIndex!!.first}] "
} +
when (nameConditions) {
null -> ""
else -> "nameConditions:${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 ?: "[]"} " +
"in [$instanceSet] by $TAG"
)
is ConstructorRulesData -> throw NoSuchMethodError(
"Can't find this Constructor --> " +
when {
orderIndex == null -> ""
orderIndex!!.second.not() -> "orderIndex:[last] "
else -> "orderIndex:[${orderIndex!!.first}] "
} +
when {
matchIndex == null -> ""
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 ?: "[]"} " +
"in [$instanceSet] by $TAG"
)
else -> error("Type [$this] not allowed")
} }
/** /**