mirror of
https://github.com/HighCapable/KavaRef.git
synced 2025-12-11 15:53:33 +08:00
Initial commit
This commit is contained in:
34
kavaref-core/build.gradle.kts
Normal file
34
kavaref-core/build.gradle.kts
Normal file
@@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
autowire(libs.plugins.kotlin.jvm)
|
||||
autowire(libs.plugins.kotlin.dokka)
|
||||
autowire(libs.plugins.maven.publish)
|
||||
}
|
||||
|
||||
group = property.project.groupName
|
||||
version = property.project.kavaref.core.version
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
sourceSets.all { languageSettings { languageVersion = "2.0" } }
|
||||
compilerOptions {
|
||||
freeCompilerArgs = listOf(
|
||||
"-Xno-param-assertions",
|
||||
"-Xno-call-assertions",
|
||||
"-Xno-receiver-assertions"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Android Only
|
||||
compileOnly(projects.kavarefAndroidStub)
|
||||
implementation(projects.kavarefExtension)
|
||||
implementation(org.slf4j.slf4j.api)
|
||||
implementation(org.slf4j.slf4j.simple)
|
||||
}
|
||||
433
kavaref-core/src/main/kotlin/com/highcapable/kavaref/KavaRef.kt
Normal file
433
kavaref-core/src/main/kotlin/com/highcapable/kavaref/KavaRef.kt
Normal file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("unused", "MemberVisibilityCanBePrivate", "UNCHECKED_CAST", "UnusedReceiverParameter", "DeprecatedCallableAddReplaceWith")
|
||||
|
||||
package com.highcapable.kavaref
|
||||
|
||||
import com.highcapable.kavaref.KavaRef.Companion.resolve
|
||||
import com.highcapable.kavaref.condition.ConstructorCondition
|
||||
import com.highcapable.kavaref.condition.FieldCondition
|
||||
import com.highcapable.kavaref.condition.MethodCondition
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition.Configuration.Companion.createConfiguration
|
||||
import com.highcapable.kavaref.resolver.ConstructorResolver
|
||||
import com.highcapable.kavaref.resolver.FieldResolver
|
||||
import com.highcapable.kavaref.resolver.MethodResolver
|
||||
import com.highcapable.kavaref.resolver.base.MemberResolver
|
||||
import com.highcapable.kavaref.resolver.processor.MemberProcessor
|
||||
import com.highcapable.kavaref.runtime.KavaRefRuntime
|
||||
import com.highcapable.kavaref.runtime.KavaRefRuntime.Logger
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* This is the class created and managed by KavaRef.
|
||||
*
|
||||
* Try to use [KavaRef.resolve] to start a new reflection.
|
||||
*/
|
||||
class KavaRef private constructor() {
|
||||
|
||||
companion object {
|
||||
|
||||
/** Get or set the log level for KavaRef. */
|
||||
@JvmStatic
|
||||
var logLevel by KavaRefRuntime::logLevel
|
||||
|
||||
/**
|
||||
* Set the logger for KavaRef.
|
||||
* @param logger the logger to be set.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun setLogger(logger: Logger) = KavaRefRuntime.setLogger(logger)
|
||||
|
||||
/**
|
||||
* Create a [MemberScope] instance to start a new reflection.
|
||||
* @receiver the [KClass.java] to be reflected.
|
||||
* @return [MemberScope]
|
||||
*/
|
||||
@JvmSynthetic
|
||||
fun <T : Any> KClass<T>.resolve() = MemberScope(java.createConfiguration())
|
||||
|
||||
/**
|
||||
* Create a [MemberScope] with a block to start a new reflection.
|
||||
* @receiver the [KClass.java] to be reflected.
|
||||
* @param block the block to configure the [MemberScope].
|
||||
* @return [MemberScope]
|
||||
*/
|
||||
inline fun <T : Any> KClass<T>.resolve(block: MemberScope<T>.() -> Unit) = resolve().apply(block)
|
||||
|
||||
/**
|
||||
* Create a [MemberScope] instance to start a new reflection.
|
||||
* @receiver the [Class] to be reflected.
|
||||
* @return [MemberScope]
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmName("resolveClass")
|
||||
fun <T : Any> Class<T>.resolve() = MemberScope(createConfiguration())
|
||||
|
||||
/**
|
||||
* Create a [MemberScope] instance to start a new reflection.
|
||||
* @see KClass.resolve
|
||||
* @see Class.resolve
|
||||
* @return [MemberScope]
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmName("resolveObject")
|
||||
fun <T : Any> T.resolve() = when (this) {
|
||||
is KClass<*> -> MemberScope((this as KClass<T>).java.createConfiguration(memberInstance = this))
|
||||
is Class<*> -> MemberScope((this as Class<T>).createConfiguration(memberInstance = this))
|
||||
else -> MemberScope(javaClass.createConfiguration(memberInstance = this))
|
||||
}
|
||||
|
||||
// Below are deprecated functions to prevent recursive calls.
|
||||
|
||||
private const val RECURSIVELY_CALL_DEPRECATED_MESSAGE = "You are calling resolve() recursively, it's an error and should delete it."
|
||||
private const val RECURSIVELY_CALL_EXCEPTION_MESSAGE = "Not allowed to call resolve() recursively, please delete it."
|
||||
|
||||
/**
|
||||
* This is a fake function call chains to avoid recursive calls to themselves.
|
||||
*/
|
||||
@Deprecated(message = RECURSIVELY_CALL_DEPRECATED_MESSAGE, level = DeprecationLevel.ERROR)
|
||||
@JvmSynthetic
|
||||
fun MemberScope<*>.resolve(): MemberScope<*> = error(RECURSIVELY_CALL_EXCEPTION_MESSAGE)
|
||||
|
||||
/**
|
||||
* This is a fake function call chains to avoid recursive calls to themselves.
|
||||
*/
|
||||
@Deprecated(message = RECURSIVELY_CALL_DEPRECATED_MESSAGE, level = DeprecationLevel.ERROR)
|
||||
@JvmSynthetic
|
||||
fun MemberCondition<*, *, *>.resolve(): MemberCondition<*, *, *> = error(RECURSIVELY_CALL_EXCEPTION_MESSAGE)
|
||||
|
||||
/**
|
||||
* This is a fake function call chains to avoid recursive calls to themselves.
|
||||
*/
|
||||
@Deprecated(message = RECURSIVELY_CALL_DEPRECATED_MESSAGE, level = DeprecationLevel.ERROR)
|
||||
@JvmSynthetic
|
||||
fun MemberResolver<*, *>.resolve(): MemberResolver<*, *> = error(RECURSIVELY_CALL_EXCEPTION_MESSAGE)
|
||||
|
||||
/**
|
||||
* This is a fake function call chains to avoid recursive calls to themselves.
|
||||
*/
|
||||
@Deprecated(message = RECURSIVELY_CALL_DEPRECATED_MESSAGE, level = DeprecationLevel.ERROR)
|
||||
@JvmSynthetic
|
||||
fun List<MemberResolver<*, *>>.resolve(): List<MemberResolver<*, *>> = error(RECURSIVELY_CALL_EXCEPTION_MESSAGE)
|
||||
}
|
||||
|
||||
/**
|
||||
* The KavaRef scope for member reflection.
|
||||
*
|
||||
* [T] to specify the declaring class type of the member.
|
||||
* @param configuration the configuration to be reflected.
|
||||
*/
|
||||
class MemberScope<T : Any> internal constructor(private val configuration: MemberCondition.Configuration<T>) {
|
||||
|
||||
/**
|
||||
* Set the [MemberProcessor.Resolver] to be used for this reflection.
|
||||
* @see MemberCondition.Configuration.processorResolver
|
||||
* @see MemberProcessor.Resolver
|
||||
* @param resolver the resolver to be used.
|
||||
*/
|
||||
fun processor(resolver: MemberProcessor.Resolver) = apply {
|
||||
configuration.processorResolver = resolver
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable optional mode.
|
||||
* @see MemberCondition.Configuration.optional
|
||||
* @param silent see [MemberCondition.Configuration.Optional.SILENT]
|
||||
*/
|
||||
fun optional(silent: Boolean = false) = apply {
|
||||
configuration.optional = if (silent)
|
||||
MemberCondition.Configuration.Optional.SILENT
|
||||
else MemberCondition.Configuration.Optional.NOTICE
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new method reflection.
|
||||
* @return [MethodCondition]
|
||||
*/
|
||||
fun method() = MethodCondition<T>().also {
|
||||
it.configuration = configuration
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new method reflection.
|
||||
* @see firstMethod
|
||||
* @see firstMethodOrNull
|
||||
* @param condition the condition.
|
||||
* @return [MethodResolver]
|
||||
*/
|
||||
fun method(condition: MethodCondition<T>) = condition.build(configuration)
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the first matching method.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver]
|
||||
*/
|
||||
fun firstMethod(condition: MethodCondition<T>) = method(condition).first()
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the first matching method or null.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver] or null.
|
||||
*/
|
||||
fun firstMethodOrNull(condition: MethodCondition<T>) = method(condition).firstOrNull()
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the last matching method.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver]
|
||||
*/
|
||||
fun lastMethod(condition: MethodCondition<T>) = method(condition).last()
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the last matching method or null.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver] or null.
|
||||
*/
|
||||
fun lastMethodOrNull(condition: MethodCondition<T>) = method(condition).lastOrNull()
|
||||
|
||||
/**
|
||||
* Start a new method reflection.
|
||||
* @see firstMethod
|
||||
* @see firstMethodOrNull
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver]
|
||||
*/
|
||||
inline fun method(condition: MethodCondition<T>.() -> Unit) = method().apply(condition).build()
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the first matching method.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver]
|
||||
*/
|
||||
inline fun firstMethod(condition: MethodCondition<T>.() -> Unit = {}) = method(condition).first()
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the first matching method or null.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver] or null.
|
||||
*/
|
||||
inline fun firstMethodOrNull(condition: MethodCondition<T>.() -> Unit = {}) = method(condition).firstOrNull()
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the last matching method.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver]
|
||||
*/
|
||||
inline fun lastMethod(condition: MethodCondition<T>.() -> Unit = {}) = method(condition).last()
|
||||
|
||||
/**
|
||||
* Start a new method reflection and return the last matching method or null.
|
||||
* @see method
|
||||
* @param condition the condition body.
|
||||
* @return [MethodResolver] or null.
|
||||
*/
|
||||
inline fun lastMethodOrNull(condition: MethodCondition<T>.() -> Unit = {}) = method(condition).lastOrNull()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection.
|
||||
* @return [ConstructorCondition]
|
||||
*/
|
||||
fun constructor() = ConstructorCondition<T>().also {
|
||||
it.configuration = configuration
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection.
|
||||
* @see firstConstructor
|
||||
* @see firstConstructorOrNull
|
||||
* @param condition the condition.
|
||||
* @return [ConstructorResolver]
|
||||
*/
|
||||
fun constructor(condition: ConstructorCondition<T>) = condition.build(configuration)
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the first matching constructor.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver]
|
||||
*/
|
||||
fun firstConstructor(condition: ConstructorCondition<T>) = constructor(condition).first()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the first matching constructor or null.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver] or null.
|
||||
*/
|
||||
fun firstConstructorOrNull(condition: ConstructorCondition<T>) = constructor(condition).firstOrNull()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the last matching constructor.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver]
|
||||
*/
|
||||
fun lastConstructor(condition: ConstructorCondition<T>) = constructor(condition).last()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the last matching constructor or null.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver] or null.
|
||||
*/
|
||||
fun lastConstructorOrNull(condition: ConstructorCondition<T>) = constructor(condition).lastOrNull()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection.
|
||||
* @see firstConstructor
|
||||
* @see firstConstructorOrNull
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver]
|
||||
*/
|
||||
inline fun constructor(condition: ConstructorCondition<T>.() -> Unit) = constructor().apply(condition).build()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the first matching constructor.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver]
|
||||
*/
|
||||
inline fun firstConstructor(condition: ConstructorCondition<T>.() -> Unit = {}) = constructor(condition).first()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the first matching constructor or null.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver] or null.
|
||||
*/
|
||||
inline fun firstConstructorOrNull(condition: ConstructorCondition<T>.() -> Unit = {}) = constructor(condition).firstOrNull()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the last matching constructor.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver]
|
||||
*/
|
||||
inline fun lastConstructor(condition: ConstructorCondition<T>.() -> Unit = {}) = constructor(condition).last()
|
||||
|
||||
/**
|
||||
* Start a new constructor reflection and return the last matching constructor or null.
|
||||
* @see constructor
|
||||
* @param condition the condition body.
|
||||
* @return [ConstructorResolver] or null.
|
||||
*/
|
||||
inline fun lastConstructorOrNull(condition: ConstructorCondition<T>.() -> Unit = {}) = constructor(condition).lastOrNull()
|
||||
|
||||
/**
|
||||
* Start a new field reflection.
|
||||
* @return [FieldCondition]
|
||||
*/
|
||||
fun field() = FieldCondition<T>().also {
|
||||
it.configuration = configuration
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new field reflection.
|
||||
* @see firstField
|
||||
* @see firstFieldOrNull
|
||||
* @param condition the condition.
|
||||
* @return [FieldResolver]
|
||||
*/
|
||||
fun field(condition: FieldCondition<T>) = condition.build(configuration)
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the first matching field.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver]
|
||||
*/
|
||||
fun firstField(condition: FieldCondition<T>) = field(condition).first()
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the first matching field or null.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver] or null.
|
||||
*/
|
||||
fun firstFieldOrNull(condition: FieldCondition<T>) = field(condition).firstOrNull()
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the last matching field.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver]
|
||||
*/
|
||||
fun lastField(condition: FieldCondition<T>) = field(condition).last()
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the last matching field or null.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver] or null.
|
||||
*/
|
||||
fun lastFieldOrNull(condition: FieldCondition<T>) = field(condition).lastOrNull()
|
||||
|
||||
/**
|
||||
* Start a new field reflection.
|
||||
* @see firstField
|
||||
* @see firstFieldOrNull
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver]
|
||||
*/
|
||||
inline fun field(condition: FieldCondition<T>.() -> Unit) = field().apply(condition).build()
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the first matching field.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver]
|
||||
*/
|
||||
inline fun firstField(condition: FieldCondition<T>.() -> Unit = {}) = field(condition).first()
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the first matching field or null.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver] or null.
|
||||
*/
|
||||
inline fun firstFieldOrNull(condition: FieldCondition<T>.() -> Unit = {}) = field(condition).firstOrNull()
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the last matching field.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver]
|
||||
*/
|
||||
inline fun lastField(condition: FieldCondition<T>.() -> Unit = {}) = field(condition).last()
|
||||
|
||||
/**
|
||||
* Start a new field reflection and return the last matching field or null.
|
||||
* @see field
|
||||
* @param condition the condition body.
|
||||
* @return [FieldResolver] or null.
|
||||
*/
|
||||
inline fun lastFieldOrNull(condition: FieldCondition<T>.() -> Unit = {}) = field(condition).lastOrNull()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
package com.highcapable.kavaref.condition
|
||||
|
||||
import com.highcapable.kavaref.condition.base.ExecutableCondition
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import com.highcapable.kavaref.condition.type.Modifiers
|
||||
import com.highcapable.kavaref.resolver.ConstructorResolver
|
||||
import com.highcapable.kavaref.resolver.processor.MemberProcessor
|
||||
import java.lang.reflect.Constructor
|
||||
|
||||
/**
|
||||
* Condition for [Constructor] of [ConstructorResolver].
|
||||
*/
|
||||
class ConstructorCondition<T : Any> : ExecutableCondition<Constructor<T>, ConstructorResolver<T>, T>() {
|
||||
|
||||
override fun name(name: String) = apply { super.name(name) }
|
||||
override fun name(condition: (String) -> Boolean) = apply { super.name(condition) }
|
||||
override fun modifiers(vararg modifiers: Modifiers) = apply { super.modifiers(*modifiers) }
|
||||
override fun modifiersNot(vararg modifiers: Modifiers) = apply { super.modifiersNot(*modifiers) }
|
||||
override fun modifiers(condition: (Set<Modifiers>) -> Boolean) = apply { super.modifiers(condition) }
|
||||
override fun isSynthetic(isSynthetic: Boolean) = apply { super.isSynthetic(isSynthetic) }
|
||||
override fun isSyntheticNot(isSynthetic: Boolean) = apply { super.isSyntheticNot(isSynthetic) }
|
||||
override fun annotations(vararg annotations: Any) = apply { super.annotations(*annotations) }
|
||||
override fun annotationsNot(vararg annotations: Any) = apply { super.annotationsNot(*annotations) }
|
||||
override fun genericString(genericString: String) = apply { super.genericString(genericString) }
|
||||
|
||||
override fun parameters(vararg types: Any) = apply { super.parameters(*types) }
|
||||
override fun parametersNot(vararg types: Any) = apply { super.parametersNot(*types) }
|
||||
override fun parameters(condition: (List<Class<*>>) -> Boolean) = apply { super.parameters(condition) }
|
||||
override fun emptyParameters() = apply { super.emptyParameters() }
|
||||
override fun emptyParametersNot() = apply { super.emptyParametersNot() }
|
||||
override fun typeParameters(vararg types: TypeMatcher) = apply { super.typeParameters(*types) }
|
||||
override fun typeParametersNot(vararg types: TypeMatcher) = apply { super.typeParametersNot(*types) }
|
||||
override fun parameterCount(count: Int) = apply { super.parameterCount(count) }
|
||||
override fun parameterCount(condition: (Int) -> Boolean) = apply { super.parameterCount(condition) }
|
||||
override fun exceptionTypes(vararg types: Any) = apply { super.exceptionTypes(*types) }
|
||||
override fun exceptionTypesNot(vararg types: Any) = apply { super.exceptionTypesNot(*types) }
|
||||
override fun genericExceptionTypes(vararg types: TypeMatcher) = apply { super.genericExceptionTypes(*types) }
|
||||
override fun genericExceptionTypesNot(vararg types: TypeMatcher) = apply { super.genericExceptionTypesNot(*types) }
|
||||
override fun genericParameters(vararg types: TypeMatcher) = apply { super.genericParameters(*types) }
|
||||
override fun genericParametersNot(vararg types: TypeMatcher) = apply { super.genericParametersNot(*types) }
|
||||
override fun isVarArgs(isVarArgs: Boolean) = apply { super.isVarArgs(isVarArgs) }
|
||||
override fun isVarArgsNot(isVarArgs: Boolean) = apply { super.isVarArgsNot(isVarArgs) }
|
||||
override fun parameterAnnotations(vararg annotations: Set<Any>) = apply { super.parameterAnnotations(*annotations) }
|
||||
override fun parameterAnnotationsNot(vararg annotations: Set<Any>) = apply { super.parameterAnnotationsNot(*annotations) }
|
||||
override fun annotatedReturnType(vararg types: Any) = apply { super.annotatedReturnType(*types) }
|
||||
override fun annotatedReturnTypeNot(vararg types: Any) = apply { super.annotatedReturnTypeNot(*types) }
|
||||
override fun annotatedReceiverType(vararg types: Any) = apply { super.annotatedReceiverType(*types) }
|
||||
override fun annotatedReceiverTypeNot(vararg types: Any) = apply { super.annotatedReceiverTypeNot(*types) }
|
||||
override fun annotatedParameterTypes(vararg types: Any) = apply { super.annotatedParameterTypes(*types) }
|
||||
override fun annotatedParameterTypesNot(vararg types: Any) = apply { super.annotatedParameterTypesNot(*types) }
|
||||
override fun annotatedExceptionTypes(vararg types: Any) = apply { super.annotatedExceptionTypes(*types) }
|
||||
override fun annotatedExceptionTypesNot(vararg types: Any) = apply { super.annotatedExceptionTypesNot(*types) }
|
||||
|
||||
override fun superclass() = apply { super.superclass() }
|
||||
|
||||
override fun copy() = ConstructorCondition<T>().also {
|
||||
initializeCopiedData(it)
|
||||
}
|
||||
|
||||
override fun build(configuration: Configuration<T>?): List<ConstructorResolver<T>> {
|
||||
configuration?.let { checkAndSetConfiguration(it) }
|
||||
return MemberProcessor.resolve(condition = this, this.configuration)
|
||||
}
|
||||
|
||||
override val conditionStringMap get() = super.conditionStringMap
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("unused", "DuplicatedCode")
|
||||
|
||||
package com.highcapable.kavaref.condition
|
||||
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import com.highcapable.kavaref.condition.type.Modifiers
|
||||
import com.highcapable.kavaref.resolver.FieldResolver
|
||||
import com.highcapable.kavaref.resolver.processor.MemberProcessor
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* Condition for [Field] of [FieldResolver].
|
||||
*/
|
||||
class FieldCondition<T : Any> : MemberCondition<Field, FieldResolver<T>, T>() {
|
||||
|
||||
/** @see Field.isEnumConstant */
|
||||
var isEnumConstant: Boolean? = null
|
||||
|
||||
/** @see Field.isEnumConstant */
|
||||
var isEnumConstantNot: Boolean? = null
|
||||
|
||||
/** @see Field.getType */
|
||||
var type: Any? = null
|
||||
|
||||
/** @see Field.getType */
|
||||
var typeCondition: ((Class<*>) -> Boolean)? = null
|
||||
|
||||
/** @see Field.getGenericType */
|
||||
var genericType: TypeMatcher? = null
|
||||
|
||||
/** @see Field.getGenericType */
|
||||
var genericTypeCondition: ((Type) -> Boolean)? = null
|
||||
|
||||
override fun name(name: String) = apply { super.name(name) }
|
||||
override fun name(condition: (String) -> Boolean) = apply { super.name(condition) }
|
||||
override fun modifiers(vararg modifiers: Modifiers) = apply { super.modifiers(*modifiers) }
|
||||
override fun modifiersNot(vararg modifiers: Modifiers) = apply { super.modifiersNot(*modifiers) }
|
||||
override fun modifiers(condition: (Set<Modifiers>) -> Boolean) = apply { super.modifiers(condition) }
|
||||
override fun isSynthetic(isSynthetic: Boolean) = apply { super.isSynthetic(isSynthetic) }
|
||||
override fun isSyntheticNot(isSynthetic: Boolean) = apply { super.isSyntheticNot(isSynthetic) }
|
||||
override fun annotations(vararg annotations: Any) = apply { super.annotations(*annotations) }
|
||||
override fun annotationsNot(vararg annotations: Any) = apply { super.annotationsNot(*annotations) }
|
||||
override fun genericString(genericString: String) = apply { super.genericString(genericString) }
|
||||
|
||||
override fun superclass() = apply { super.superclass() }
|
||||
|
||||
/** @see Field.isEnumConstant */
|
||||
fun isEnumConstant(isEnumConstant: Boolean) = apply {
|
||||
this.isEnumConstant = isEnumConstant
|
||||
}
|
||||
|
||||
/** @see Field.isEnumConstant */
|
||||
fun isEnumConstantNot(isEnumConstant: Boolean) = apply {
|
||||
this.isEnumConstantNot = isEnumConstant
|
||||
}
|
||||
|
||||
/** @see Field.getType */
|
||||
fun type(type: Any) = apply {
|
||||
this.type = type
|
||||
}
|
||||
|
||||
/** @see Field.getType */
|
||||
fun type(condition: (Class<*>) -> Boolean) = apply {
|
||||
this.typeCondition = condition
|
||||
}
|
||||
|
||||
/** @see Field.getGenericType */
|
||||
fun genericType(type: TypeMatcher) = apply {
|
||||
this.genericType = type
|
||||
}
|
||||
|
||||
/** @see Field.getGenericType */
|
||||
fun genericType(condition: (Type) -> Boolean) = apply {
|
||||
this.genericTypeCondition = condition
|
||||
}
|
||||
|
||||
override fun initializeCopiedData(newSelf: MemberCondition<Field, FieldResolver<T>, T>) {
|
||||
super.initializeCopiedData(newSelf)
|
||||
|
||||
(newSelf as? FieldCondition)?.also {
|
||||
it.isEnumConstant = isEnumConstant
|
||||
it.isEnumConstantNot = isEnumConstantNot
|
||||
it.type = type
|
||||
it.typeCondition = typeCondition
|
||||
it.genericType = genericType
|
||||
it.genericTypeCondition = genericTypeCondition
|
||||
}
|
||||
}
|
||||
|
||||
override fun initializeMergedData(other: MemberCondition<Field, FieldResolver<T>, T>) {
|
||||
super.initializeMergedData(other)
|
||||
|
||||
(other as? FieldCondition)?.also { condition ->
|
||||
condition.isEnumConstant?.let { isEnumConstant = it }
|
||||
condition.isEnumConstantNot?.let { isEnumConstantNot = it }
|
||||
condition.type?.let { type = it }
|
||||
condition.typeCondition?.let { typeCondition = it }
|
||||
condition.genericType?.let { genericType = it }
|
||||
condition.genericTypeCondition?.let { genericTypeCondition = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun copy() = FieldCondition<T>().also {
|
||||
initializeCopiedData(it)
|
||||
}
|
||||
|
||||
override fun build(configuration: Configuration<T>?): List<FieldResolver<T>> {
|
||||
configuration?.let { checkAndSetConfiguration(it) }
|
||||
return MemberProcessor.resolve(condition = this, this.configuration)
|
||||
}
|
||||
|
||||
override val conditionStringMap
|
||||
get() = super.conditionStringMap + mapOf(
|
||||
IS_ENUM_CONSTANT to isEnumConstant,
|
||||
IS_ENUM_CONSTANT_NOT to isEnumConstantNot,
|
||||
TYPE to type,
|
||||
TYPE_CONDITION to typeCondition,
|
||||
GENERIC_TYPE to genericType,
|
||||
GENERIC_TYPE_CONDITION to genericTypeCondition
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val IS_ENUM_CONSTANT = "isEnumConstant"
|
||||
const val IS_ENUM_CONSTANT_NOT = "isEnumConstantNot"
|
||||
const val TYPE = "type"
|
||||
const val TYPE_CONDITION = "typeCondition"
|
||||
const val GENERIC_TYPE = "genericType"
|
||||
const val GENERIC_TYPE_CONDITION = "genericTypeCondition"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("unused", "DuplicatedCode")
|
||||
|
||||
package com.highcapable.kavaref.condition
|
||||
|
||||
import com.highcapable.kavaref.condition.base.ExecutableCondition
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import com.highcapable.kavaref.condition.type.Modifiers
|
||||
import com.highcapable.kavaref.resolver.MethodResolver
|
||||
import com.highcapable.kavaref.resolver.processor.MemberProcessor
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* Condition for [Method] of [MethodResolver].
|
||||
*/
|
||||
class MethodCondition<T : Any> : ExecutableCondition<Method, MethodResolver<T>, T>() {
|
||||
|
||||
/** @see Method.getReturnType */
|
||||
var returnType: Any? = null
|
||||
|
||||
/** @see Method.getReturnType */
|
||||
var returnTypeCondition: ((Class<*>) -> Boolean)? = null
|
||||
|
||||
/** @see Method.isBridge */
|
||||
var isBridge: Boolean? = null
|
||||
|
||||
/** @see Method.isBridge */
|
||||
var isBridgeNot: Boolean? = null
|
||||
|
||||
/** @see Method.isDefault */
|
||||
var isDefault: Boolean? = null
|
||||
|
||||
/** @see Method.isDefault */
|
||||
var isDefaultNot: Boolean? = null
|
||||
|
||||
override fun name(name: String) = apply { super.name(name) }
|
||||
override fun name(condition: (String) -> Boolean) = apply { super.name(condition) }
|
||||
override fun modifiers(vararg modifiers: Modifiers) = apply { super.modifiers(*modifiers) }
|
||||
override fun modifiersNot(vararg modifiers: Modifiers) = apply { super.modifiersNot(*modifiers) }
|
||||
override fun modifiers(condition: (Set<Modifiers>) -> Boolean) = apply { super.modifiers(condition) }
|
||||
override fun isSynthetic(isSynthetic: Boolean) = apply { super.isSynthetic(isSynthetic) }
|
||||
override fun isSyntheticNot(isSynthetic: Boolean) = apply { super.isSyntheticNot(isSynthetic) }
|
||||
override fun annotations(vararg annotations: Any) = apply { super.annotations(*annotations) }
|
||||
override fun annotationsNot(vararg annotations: Any) = apply { super.annotationsNot(*annotations) }
|
||||
override fun genericString(genericString: String) = apply { super.genericString(genericString) }
|
||||
|
||||
override fun parameters(vararg types: Any) = apply { super.parameters(*types) }
|
||||
override fun parametersNot(vararg types: Any) = apply { super.parametersNot(*types) }
|
||||
override fun parameters(condition: (List<Class<*>>) -> Boolean) = apply { super.parameters(condition) }
|
||||
override fun emptyParameters() = apply { super.emptyParameters() }
|
||||
override fun emptyParametersNot() = apply { super.emptyParametersNot() }
|
||||
override fun typeParameters(vararg types: TypeMatcher) = apply { super.typeParameters(*types) }
|
||||
override fun typeParametersNot(vararg types: TypeMatcher) = apply { super.typeParametersNot(*types) }
|
||||
override fun parameterCount(count: Int) = apply { super.parameterCount(count) }
|
||||
override fun parameterCount(condition: (Int) -> Boolean) = apply { super.parameterCount(condition) }
|
||||
override fun exceptionTypes(vararg types: Any) = apply { super.exceptionTypes(*types) }
|
||||
override fun exceptionTypesNot(vararg types: Any) = apply { super.exceptionTypesNot(*types) }
|
||||
override fun genericExceptionTypes(vararg types: TypeMatcher) = apply { super.genericExceptionTypes(*types) }
|
||||
override fun genericExceptionTypesNot(vararg types: TypeMatcher) = apply { super.genericExceptionTypesNot(*types) }
|
||||
override fun genericParameters(vararg types: TypeMatcher) = apply { super.genericParameters(*types) }
|
||||
override fun genericParametersNot(vararg types: TypeMatcher) = apply { super.genericParametersNot(*types) }
|
||||
override fun isVarArgs(isVarArgs: Boolean) = apply { super.isVarArgs(isVarArgs) }
|
||||
override fun isVarArgsNot(isVarArgs: Boolean) = apply { super.isVarArgsNot(isVarArgs) }
|
||||
override fun parameterAnnotations(vararg annotations: Set<Any>) = apply { super.parameterAnnotations(*annotations) }
|
||||
override fun parameterAnnotationsNot(vararg annotations: Set<Any>) = apply { super.parameterAnnotationsNot(*annotations) }
|
||||
override fun annotatedReturnType(vararg types: Any) = apply { super.annotatedReturnType(*types) }
|
||||
override fun annotatedReturnTypeNot(vararg types: Any) = apply { super.annotatedReturnTypeNot(*types) }
|
||||
override fun annotatedReceiverType(vararg types: Any) = apply { super.annotatedReceiverType(*types) }
|
||||
override fun annotatedReceiverTypeNot(vararg types: Any) = apply { super.annotatedReceiverTypeNot(*types) }
|
||||
override fun annotatedParameterTypes(vararg types: Any) = apply { super.annotatedParameterTypes(*types) }
|
||||
override fun annotatedParameterTypesNot(vararg types: Any) = apply { super.annotatedParameterTypesNot(*types) }
|
||||
override fun annotatedExceptionTypes(vararg types: Any) = apply { super.annotatedExceptionTypes(*types) }
|
||||
override fun annotatedExceptionTypesNot(vararg types: Any) = apply { super.annotatedExceptionTypesNot(*types) }
|
||||
|
||||
override fun superclass() = apply { super.superclass() }
|
||||
|
||||
/** @see Method.getReturnType */
|
||||
fun returnType(type: Any) = apply {
|
||||
this.returnType = type
|
||||
}
|
||||
|
||||
/** @see Method.getReturnType */
|
||||
fun returnType(condition: (Class<*>) -> Boolean) = apply {
|
||||
this.returnTypeCondition = condition
|
||||
}
|
||||
|
||||
/** @see Method.isBridge */
|
||||
fun isBridge(isBridge: Boolean) = apply {
|
||||
this.isBridge = isBridge
|
||||
}
|
||||
|
||||
/** @see Method.isBridge */
|
||||
fun isBridgeNot(isBridge: Boolean) = apply {
|
||||
this.isBridgeNot = isBridge
|
||||
}
|
||||
|
||||
/** @see Method.isDefault */
|
||||
fun isDefault(isDefault: Boolean) = apply {
|
||||
this.isDefault = isDefault
|
||||
}
|
||||
|
||||
/** @see Method.isDefault */
|
||||
fun isDefaultNot(isDefault: Boolean) = apply {
|
||||
this.isDefaultNot = isDefault
|
||||
}
|
||||
|
||||
override fun initializeCopiedData(newSelf: MemberCondition<Method, MethodResolver<T>, T>) {
|
||||
super.initializeCopiedData(newSelf)
|
||||
|
||||
(newSelf as? MethodCondition)?.also {
|
||||
it.returnType = returnType
|
||||
it.returnTypeCondition = returnTypeCondition
|
||||
it.isBridge = isBridge
|
||||
it.isBridgeNot = isBridgeNot
|
||||
it.isDefault = isDefault
|
||||
it.isDefaultNot = isDefaultNot
|
||||
}
|
||||
}
|
||||
|
||||
override fun initializeMergedData(other: MemberCondition<Method, MethodResolver<T>, T>) {
|
||||
super.initializeMergedData(other)
|
||||
|
||||
(other as? MethodCondition)?.also { condition ->
|
||||
condition.returnType?.let { returnType = it }
|
||||
condition.returnTypeCondition?.let { returnTypeCondition = it }
|
||||
condition.isBridge?.let { isBridge = it }
|
||||
condition.isBridgeNot?.let { isBridgeNot = it }
|
||||
condition.isDefault?.let { isDefault = it }
|
||||
condition.isDefaultNot?.let { isDefaultNot = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun copy() = MethodCondition<T>().also {
|
||||
initializeCopiedData(it)
|
||||
}
|
||||
|
||||
override fun build(configuration: Configuration<T>?): List<MethodResolver<T>> {
|
||||
configuration?.let { checkAndSetConfiguration(it) }
|
||||
return MemberProcessor.resolve(condition = this, this.configuration)
|
||||
}
|
||||
|
||||
override val conditionStringMap
|
||||
get() = super.conditionStringMap + mapOf(
|
||||
RETURN_TYPE to returnType,
|
||||
RETURN_TYPE_CONDITION to returnTypeCondition,
|
||||
IS_BRIDGE to isBridge,
|
||||
IS_BRIDGE_NOT to isBridgeNot,
|
||||
IS_DEFAULT to isDefault,
|
||||
IS_DEFAULT_NOT to isDefaultNot
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val RETURN_TYPE = "returnType"
|
||||
const val RETURN_TYPE_CONDITION = "returnTypeCondition"
|
||||
const val IS_BRIDGE = "isBridge"
|
||||
const val IS_BRIDGE_NOT = "isBridgeNot"
|
||||
const val IS_DEFAULT = "isDefault"
|
||||
const val IS_DEFAULT_NOT = "isDefaultNot"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("DuplicatedCode")
|
||||
|
||||
package com.highcapable.kavaref.condition.base
|
||||
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import com.highcapable.kavaref.resolver.base.MemberResolver
|
||||
import java.lang.reflect.Executable
|
||||
|
||||
/**
|
||||
* Base class for conditions that are applicable to executable members (methods and constructors) [E], [R].
|
||||
*
|
||||
* [T] to specify the declaring class type of the executable.
|
||||
*/
|
||||
abstract class ExecutableCondition<E : Executable, R : MemberResolver<E, T>, T : Any> : MemberCondition<E, R, T>() {
|
||||
|
||||
/** @see Executable.getParameterTypes */
|
||||
val parameters = mutableListOf<Any>()
|
||||
|
||||
/** @see Executable.getParameterTypes */
|
||||
val parametersNot = mutableListOf<Any>()
|
||||
|
||||
/** @see Executable.getParameterTypes */
|
||||
var parametersCondition: ((List<Class<*>>) -> Boolean)? = null
|
||||
|
||||
/** @see Executable.getTypeParameters */
|
||||
val typeParameters = mutableSetOf<TypeMatcher>()
|
||||
|
||||
/** @see Executable.getTypeParameters */
|
||||
val typeParametersNot = mutableSetOf<TypeMatcher>()
|
||||
|
||||
/** @see Executable.getParameterCount */
|
||||
var parameterCount: Int? = null
|
||||
|
||||
/** @see Executable.getParameterCount */
|
||||
var parameterCountCondition: ((Int) -> Boolean)? = null
|
||||
|
||||
/** @see Executable.getExceptionTypes */
|
||||
val exceptionTypes = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getExceptionTypes */
|
||||
val exceptionTypesNot = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getGenericExceptionTypes */
|
||||
val genericExceptionTypes = mutableSetOf<TypeMatcher>()
|
||||
|
||||
/** @see Executable.getGenericExceptionTypes */
|
||||
val genericExceptionTypesNot = mutableSetOf<TypeMatcher>()
|
||||
|
||||
/** @see Executable.getGenericParameterTypes */
|
||||
val genericParameters = mutableSetOf<TypeMatcher>()
|
||||
|
||||
/** @see Executable.getGenericParameterTypes */
|
||||
val genericParametersNot = mutableSetOf<TypeMatcher>()
|
||||
|
||||
/** @see Executable.isVarArgs */
|
||||
var isVarArgs: Boolean? = null
|
||||
|
||||
/** @see Executable.isVarArgs */
|
||||
var isVarArgsNot: Boolean? = null
|
||||
|
||||
/** @see Executable.getParameterAnnotations */
|
||||
val parameterAnnotations = mutableListOf<Set<Any>>()
|
||||
|
||||
/** @see Executable.getParameterAnnotations */
|
||||
val parameterAnnotationsNot = mutableListOf<Set<Any>>()
|
||||
|
||||
/** @see Executable.getAnnotatedReturnType */
|
||||
val annotatedReturnType = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getAnnotatedReturnType */
|
||||
val annotatedReturnTypeNot = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getAnnotatedReceiverType */
|
||||
val annotatedReceiverType = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getAnnotatedReceiverType */
|
||||
val annotatedReceiverTypeNot = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getAnnotatedParameterTypes */
|
||||
val annotatedParameterTypes = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getAnnotatedParameterTypes */
|
||||
val annotatedParameterTypesNot = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getAnnotatedExceptionTypes */
|
||||
val annotatedExceptionTypes = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getAnnotatedExceptionTypes */
|
||||
val annotatedExceptionTypesNot = mutableSetOf<Any>()
|
||||
|
||||
/** @see Executable.getParameterTypes */
|
||||
open fun parameters(vararg types: Any) = apply {
|
||||
this.parameters.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getParameterTypes */
|
||||
open fun parametersNot(vararg types: Any) = apply {
|
||||
this.parametersNot.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getParameterTypes */
|
||||
open fun parameters(condition: (List<Class<*>>) -> Boolean) = apply {
|
||||
this.parametersCondition = condition
|
||||
}
|
||||
|
||||
/**
|
||||
* Set [parameterCount] to `0` to match methods with no parameters.
|
||||
* @see Executable.getParameterCount
|
||||
*/
|
||||
open fun emptyParameters() = apply {
|
||||
this.parameterCount = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Set [parameterCountCondition] to check if the method has parameters.
|
||||
* @see Executable.getParameterCount
|
||||
*/
|
||||
open fun emptyParametersNot() = apply {
|
||||
this.parameterCountCondition = { it > 0 }
|
||||
}
|
||||
|
||||
/** @see Executable.getTypeParameters */
|
||||
open fun typeParameters(vararg types: TypeMatcher) = apply {
|
||||
this.typeParameters.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getTypeParameters */
|
||||
open fun typeParametersNot(vararg types: TypeMatcher) = apply {
|
||||
this.typeParametersNot.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getParameterCount */
|
||||
open fun parameterCount(count: Int) = apply {
|
||||
this.parameterCount = count
|
||||
}
|
||||
|
||||
/** @see Executable.getParameterCount */
|
||||
open fun parameterCount(condition: (Int) -> Boolean) = apply {
|
||||
this.parameterCountCondition = condition
|
||||
}
|
||||
|
||||
/** @see Executable.getExceptionTypes */
|
||||
open fun exceptionTypes(vararg types: Any) = apply {
|
||||
this.exceptionTypes.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getExceptionTypes */
|
||||
open fun exceptionTypesNot(vararg types: Any) = apply {
|
||||
this.exceptionTypesNot.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getGenericExceptionTypes */
|
||||
open fun genericExceptionTypes(vararg types: TypeMatcher) = apply {
|
||||
this.genericExceptionTypes.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getGenericExceptionTypes */
|
||||
open fun genericExceptionTypesNot(vararg types: TypeMatcher) = apply {
|
||||
this.genericExceptionTypesNot.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getGenericParameterTypes */
|
||||
open fun genericParameters(vararg types: TypeMatcher) = apply {
|
||||
this.genericParameters.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.getGenericParameterTypes */
|
||||
open fun genericParametersNot(vararg types: TypeMatcher) = apply {
|
||||
this.genericParametersNot.addAll(types)
|
||||
}
|
||||
|
||||
/** @see Executable.isVarArgs */
|
||||
open fun isVarArgs(isVarArgs: Boolean) = apply {
|
||||
this.isVarArgs = isVarArgs
|
||||
}
|
||||
|
||||
/** @see Executable.isVarArgs */
|
||||
open fun isVarArgsNot(isVarArgs: Boolean) = apply {
|
||||
this.isVarArgsNot = isVarArgs
|
||||
}
|
||||
|
||||
/** @see Executable.getParameterAnnotations */
|
||||
open fun parameterAnnotations(vararg annotations: Set<Any>) = apply {
|
||||
this.parameterAnnotations.addAll(annotations)
|
||||
}
|
||||
|
||||
/** @see Executable.getParameterAnnotations */
|
||||
open fun parameterAnnotationsNot(vararg annotations: Set<Any>) = apply {
|
||||
this.parameterAnnotationsNot.addAll(annotations)
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedReturnType */
|
||||
open fun annotatedReturnType(vararg types: Any) = apply {
|
||||
this.annotatedReturnType.addAll(types.toList())
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedReturnType */
|
||||
open fun annotatedReturnTypeNot(vararg types: Any) = apply {
|
||||
this.annotatedReturnTypeNot.addAll(types.toList())
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedReceiverType */
|
||||
open fun annotatedReceiverType(vararg types: Any) = apply {
|
||||
this.annotatedReceiverType.addAll(types.toList())
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedReceiverType */
|
||||
open fun annotatedReceiverTypeNot(vararg types: Any) = apply {
|
||||
this.annotatedReceiverTypeNot.addAll(types.toList())
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedParameterTypes */
|
||||
open fun annotatedParameterTypes(vararg types: Any) = apply {
|
||||
this.annotatedParameterTypes.addAll(types.toList())
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedParameterTypes */
|
||||
open fun annotatedParameterTypesNot(vararg types: Any) = apply {
|
||||
this.annotatedParameterTypesNot.addAll(types.toList())
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedExceptionTypes */
|
||||
open fun annotatedExceptionTypes(vararg types: Any) = apply {
|
||||
this.annotatedExceptionTypes.addAll(types.toList())
|
||||
}
|
||||
|
||||
/** @see Executable.getAnnotatedExceptionTypes */
|
||||
open fun annotatedExceptionTypesNot(vararg types: Any) = apply {
|
||||
this.annotatedExceptionTypesNot.addAll(types.toList())
|
||||
}
|
||||
|
||||
override fun initializeCopiedData(newSelf: MemberCondition<E, R, T>) {
|
||||
super.initializeCopiedData(newSelf)
|
||||
|
||||
(newSelf as? ExecutableCondition<E, R, T>)?.also {
|
||||
it.parameters.addAll(parameters)
|
||||
it.parametersNot.addAll(parametersNot)
|
||||
it.parametersCondition = parametersCondition
|
||||
it.parameterCount = parameterCount
|
||||
it.parameterCountCondition = parameterCountCondition
|
||||
it.typeParameters.addAll(typeParameters)
|
||||
it.typeParametersNot.addAll(typeParametersNot)
|
||||
it.exceptionTypes.addAll(exceptionTypes)
|
||||
it.exceptionTypesNot.addAll(exceptionTypesNot)
|
||||
it.genericExceptionTypes.addAll(genericExceptionTypes)
|
||||
it.genericExceptionTypesNot.addAll(genericExceptionTypesNot)
|
||||
it.genericParameters.addAll(genericParameters)
|
||||
it.genericParametersNot.addAll(genericParametersNot)
|
||||
it.isVarArgs = isVarArgs
|
||||
it.isVarArgsNot = isVarArgsNot
|
||||
it.parameterAnnotations.addAll(parameterAnnotations)
|
||||
it.parameterAnnotationsNot.addAll(parameterAnnotationsNot)
|
||||
it.annotatedReturnType.addAll(annotatedReturnType)
|
||||
it.annotatedReturnTypeNot.addAll(annotatedReturnTypeNot)
|
||||
it.annotatedReceiverType.addAll(annotatedReceiverType)
|
||||
it.annotatedReceiverTypeNot.addAll(annotatedReceiverTypeNot)
|
||||
it.annotatedParameterTypes.addAll(annotatedParameterTypes)
|
||||
it.annotatedParameterTypesNot.addAll(annotatedParameterTypesNot)
|
||||
it.annotatedExceptionTypes.addAll(annotatedExceptionTypes)
|
||||
it.annotatedExceptionTypesNot.addAll(annotatedExceptionTypesNot)
|
||||
}
|
||||
}
|
||||
|
||||
override fun initializeMergedData(other: MemberCondition<E, R, T>) {
|
||||
super.initializeMergedData(other)
|
||||
|
||||
(other as? ExecutableCondition<E, R, T>)?.also { condition ->
|
||||
condition.parameters.takeIf { it.isNotEmpty() }?.let {
|
||||
parameters.clear()
|
||||
parameters.addAll(it)
|
||||
}
|
||||
condition.parametersNot.takeIf { it.isNotEmpty() }?.let {
|
||||
parametersNot.clear()
|
||||
parametersNot.addAll(it)
|
||||
}
|
||||
condition.parametersCondition?.let { parametersCondition = it }
|
||||
condition.parameterCount?.let { parameterCount = it }
|
||||
condition.parameterCountCondition?.let { parameterCountCondition = it }
|
||||
condition.typeParameters.takeIf { it.isNotEmpty() }?.let {
|
||||
typeParameters.clear()
|
||||
typeParameters.addAll(it)
|
||||
}
|
||||
condition.typeParametersNot.takeIf { it.isNotEmpty() }?.let {
|
||||
typeParametersNot.clear()
|
||||
typeParametersNot.addAll(it)
|
||||
}
|
||||
condition.exceptionTypes.takeIf { it.isNotEmpty() }?.let {
|
||||
exceptionTypes.clear()
|
||||
exceptionTypes.addAll(it)
|
||||
}
|
||||
condition.exceptionTypesNot.takeIf { it.isNotEmpty() }?.let {
|
||||
exceptionTypesNot.clear()
|
||||
exceptionTypesNot.addAll(it)
|
||||
}
|
||||
condition.genericExceptionTypes.takeIf { it.isNotEmpty() }?.let {
|
||||
genericExceptionTypes.clear()
|
||||
genericExceptionTypes.addAll(it)
|
||||
}
|
||||
condition.genericExceptionTypesNot.takeIf { it.isNotEmpty() }?.let {
|
||||
genericExceptionTypesNot.clear()
|
||||
genericExceptionTypesNot.addAll(it)
|
||||
}
|
||||
condition.genericParameters.takeIf { it.isNotEmpty() }?.let {
|
||||
genericParameters.clear()
|
||||
genericParameters.addAll(it)
|
||||
}
|
||||
condition.genericParametersNot.takeIf { it.isNotEmpty() }?.let {
|
||||
genericParametersNot.clear()
|
||||
genericParametersNot.addAll(it)
|
||||
}
|
||||
condition.isVarArgs?.let { isVarArgs = it }
|
||||
condition.isVarArgsNot?.let { isVarArgsNot = it }
|
||||
condition.parameterAnnotations.takeIf { it.isNotEmpty() }?.let {
|
||||
parameterAnnotations.clear()
|
||||
parameterAnnotations.addAll(it)
|
||||
}
|
||||
condition.parameterAnnotationsNot.takeIf { it.isNotEmpty() }?.let {
|
||||
parameterAnnotationsNot.clear()
|
||||
parameterAnnotationsNot.addAll(it)
|
||||
}
|
||||
condition.annotatedReturnType.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedReturnType.clear()
|
||||
annotatedReturnType.addAll(it)
|
||||
}
|
||||
condition.annotatedReturnTypeNot.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedReturnTypeNot.clear()
|
||||
annotatedReturnTypeNot.addAll(it)
|
||||
}
|
||||
condition.annotatedReceiverType.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedReceiverType.clear()
|
||||
annotatedReceiverType.addAll(it)
|
||||
}
|
||||
condition.annotatedReceiverTypeNot.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedReceiverTypeNot.clear()
|
||||
annotatedReceiverTypeNot.addAll(it)
|
||||
}
|
||||
condition.annotatedParameterTypes.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedParameterTypes.clear()
|
||||
annotatedParameterTypes.addAll(it)
|
||||
}
|
||||
condition.annotatedParameterTypesNot.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedParameterTypesNot.clear()
|
||||
annotatedParameterTypesNot.addAll(it)
|
||||
}
|
||||
condition.annotatedExceptionTypes.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedExceptionTypes.clear()
|
||||
annotatedExceptionTypes.addAll(it)
|
||||
}
|
||||
condition.annotatedExceptionTypesNot.takeIf { it.isNotEmpty() }?.let {
|
||||
annotatedExceptionTypesNot.clear()
|
||||
annotatedExceptionTypesNot.addAll(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val conditionStringMap
|
||||
get() = super.conditionStringMap + mapOf(
|
||||
PARAMETERS to parameters,
|
||||
PARAMETERS_NOT to parametersNot,
|
||||
PARAMETERS_CONDITION to parametersCondition,
|
||||
PARAMETER_COUNT to parameterCount,
|
||||
PARAMETER_COUNT_CONDITION to parameterCountCondition,
|
||||
TYPE_PARAMETERS to typeParameters,
|
||||
TYPE_PARAMETERS_NOT to typeParametersNot,
|
||||
EXCEPTION_TYPES to exceptionTypes,
|
||||
EXCEPTION_TYPES_NOT to exceptionTypesNot,
|
||||
GENERIC_EXCEPTION_TYPES to genericExceptionTypes,
|
||||
GENERIC_EXCEPTION_TYPES_NOT to genericExceptionTypesNot,
|
||||
GENERIC_PARAMETERS to genericParameters,
|
||||
GENERIC_PARAMETERS_NOT to genericParametersNot,
|
||||
IS_VAR_ARGS to isVarArgs,
|
||||
IS_VAR_ARGS_NOT to isVarArgsNot,
|
||||
PARAMETER_ANNOTATIONS to parameterAnnotations,
|
||||
PARAMETER_ANNOTATIONS_NOT to parameterAnnotationsNot,
|
||||
ANNOTATED_RETURN_TYPE to annotatedReturnType,
|
||||
ANNOTATED_RETURN_TYPE_NOT to annotatedReturnTypeNot,
|
||||
ANNOTATED_RECEIVER_TYPE to annotatedReceiverType,
|
||||
ANNOTATED_RECEIVER_TYPE_NOT to annotatedReceiverTypeNot,
|
||||
ANNOTATED_PARAMETER_TYPES to annotatedParameterTypes,
|
||||
ANNOTATED_PARAMETER_TYPES_NOT to annotatedParameterTypesNot,
|
||||
ANNOTATED_EXCEPTION_TYPES to annotatedExceptionTypes,
|
||||
ANNOTATED_EXCEPTION_TYPES_NOT to annotatedExceptionTypesNot
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val PARAMETERS = "parameters"
|
||||
const val PARAMETERS_NOT = "parametersNot"
|
||||
const val PARAMETERS_CONDITION = "parametersCondition"
|
||||
const val PARAMETER_COUNT = "parameterCount"
|
||||
const val PARAMETER_COUNT_CONDITION = "parameterCountCondition"
|
||||
const val TYPE_PARAMETERS = "typeParameters"
|
||||
const val TYPE_PARAMETERS_NOT = "typeParametersNot"
|
||||
const val EXCEPTION_TYPES = "exceptionTypes"
|
||||
const val EXCEPTION_TYPES_NOT = "exceptionTypesNot"
|
||||
const val GENERIC_EXCEPTION_TYPES = "genericExceptionTypes"
|
||||
const val GENERIC_EXCEPTION_TYPES_NOT = "genericExceptionTypesNot"
|
||||
const val GENERIC_PARAMETERS = "genericParameters"
|
||||
const val GENERIC_PARAMETERS_NOT = "genericParametersNot"
|
||||
const val IS_VAR_ARGS = "isVarArgs"
|
||||
const val IS_VAR_ARGS_NOT = "isVarArgsNot"
|
||||
const val PARAMETER_ANNOTATIONS = "parameterAnnotations"
|
||||
const val PARAMETER_ANNOTATIONS_NOT = "parameterAnnotationsNot"
|
||||
const val ANNOTATED_RETURN_TYPE = "annotatedReturnType"
|
||||
const val ANNOTATED_RETURN_TYPE_NOT = "annotatedReturnTypeNot"
|
||||
const val ANNOTATED_RECEIVER_TYPE = "annotatedReceiverType"
|
||||
const val ANNOTATED_RECEIVER_TYPE_NOT = "annotatedReceiverTypeNot"
|
||||
const val ANNOTATED_PARAMETER_TYPES = "annotatedParameterTypes"
|
||||
const val ANNOTATED_PARAMETER_TYPES_NOT = "annotatedParameterTypesNot"
|
||||
const val ANNOTATED_EXCEPTION_TYPES = "annotatedExceptionTypes"
|
||||
const val ANNOTATED_EXCEPTION_TYPES_NOT = "annotatedExceptionTypesNot"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("DuplicatedCode")
|
||||
|
||||
package com.highcapable.kavaref.condition.base
|
||||
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition.Configuration.Optional
|
||||
import com.highcapable.kavaref.condition.type.Modifiers
|
||||
import com.highcapable.kavaref.resolver.base.MemberResolver
|
||||
import com.highcapable.kavaref.resolver.processor.MemberProcessor
|
||||
import java.lang.reflect.AnnotatedElement
|
||||
import java.lang.reflect.Executable
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Member
|
||||
|
||||
/**
|
||||
* Base class for defining conditions on members [M], [R].
|
||||
*
|
||||
* [T] to specify the declaring class type of the member.
|
||||
*/
|
||||
abstract class MemberCondition<M : Member, R : MemberResolver<M, T>, T : Any> {
|
||||
|
||||
/**
|
||||
* Configure initial conditions.
|
||||
* @param declaringClass the class that declares the member.
|
||||
* @param memberInstance the instance of the resolved member, default is null.
|
||||
* @param processorResolver the resolver for processing members, if set,
|
||||
* it will be used to resolve members instead of the default resolver.
|
||||
* If you want to change the global processor resolver, you can set it using [MemberProcessor.globalResolver].
|
||||
* @param superclass the superclass mode, which means that when the condition cannot find the corresponding member,
|
||||
* it will search the [declaringClass]'s superclass, default is false.
|
||||
* @param optional the optional mode, which means that when the condition cannot find the corresponding member,
|
||||
* do not throw an exception or do not print any logs, but return an empty list, default is [Optional.NO].
|
||||
*/
|
||||
data class Configuration<T : Any>(
|
||||
val declaringClass: Class<T>,
|
||||
val memberInstance: T? = null,
|
||||
var processorResolver: MemberProcessor.Resolver? = null,
|
||||
var superclass: Boolean = false,
|
||||
var optional: Optional = Optional.NO
|
||||
) {
|
||||
|
||||
/**
|
||||
* Optional mode for handling member resolution.
|
||||
*/
|
||||
enum class Optional {
|
||||
/** Do not use optional mode. */
|
||||
NO,
|
||||
|
||||
/**
|
||||
* Enable optional mode to minimize exception prompts (do not throw
|
||||
* exceptions), but the warning log will still be printed.
|
||||
*/
|
||||
NOTICE,
|
||||
|
||||
/**
|
||||
* Enable optional mode to minimize exception prompts (do not throw
|
||||
* exceptions) and do not print any logs.
|
||||
*/
|
||||
SILENT
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Create a new instance of [Configuration].
|
||||
* @return [Configuration]
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun <T : Any> Class<T>.createConfiguration(
|
||||
memberInstance: T? = null,
|
||||
processorResolver: MemberProcessor.Resolver? = null,
|
||||
superclass: Boolean = false,
|
||||
optional: Optional = Optional.NO
|
||||
) = Configuration(declaringClass = this, memberInstance, processorResolver, superclass, optional)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The configuration of this condition,
|
||||
* user can only set by [build] function.
|
||||
*/
|
||||
@get:JvmSynthetic
|
||||
@set:JvmSynthetic
|
||||
internal var configuration: Configuration<T>? = null
|
||||
|
||||
/** @see Member.getName */
|
||||
var name: String? = null
|
||||
|
||||
/** @see Member.getName */
|
||||
var nameCondition: ((String) -> Boolean)? = null
|
||||
|
||||
/** @see Member.getModifiers */
|
||||
val modifiers = mutableSetOf<Modifiers>()
|
||||
|
||||
/** @see Member.getModifiers */
|
||||
val modifiersNot = mutableSetOf<Modifiers>()
|
||||
|
||||
/** @see Member.getModifiers */
|
||||
var modifiersCondition: ((Set<Modifiers>) -> Boolean)? = null
|
||||
|
||||
/** @see Member.isSynthetic */
|
||||
var isSynthetic: Boolean? = null
|
||||
|
||||
/** @see Member.isSynthetic */
|
||||
var isSyntheticNot: Boolean? = null
|
||||
|
||||
/** @see AnnotatedElement.getDeclaredAnnotations */
|
||||
val annotations = mutableSetOf<Any>()
|
||||
|
||||
/** @see AnnotatedElement.getDeclaredAnnotations */
|
||||
val annotationsNot = mutableSetOf<Any>()
|
||||
|
||||
/**
|
||||
* @see Executable.toGenericString
|
||||
* @see Field.toGenericString
|
||||
*/
|
||||
var genericString: String? = null
|
||||
|
||||
/** @see Member.getName */
|
||||
open fun name(name: String) = apply {
|
||||
this.name = name
|
||||
}
|
||||
|
||||
/** @see Member.getName */
|
||||
open fun name(condition: (String) -> Boolean) = apply {
|
||||
this.nameCondition = condition
|
||||
}
|
||||
|
||||
/** @see Member.getModifiers */
|
||||
open fun modifiers(vararg modifiers: Modifiers) = apply {
|
||||
this.modifiers.addAll(modifiers)
|
||||
}
|
||||
|
||||
/** @see Member.getModifiers */
|
||||
open fun modifiersNot(vararg modifiers: Modifiers) = apply {
|
||||
this.modifiersNot.addAll(modifiers)
|
||||
}
|
||||
|
||||
/** @see Member.getModifiers */
|
||||
open fun modifiers(condition: (Set<Modifiers>) -> Boolean) = apply {
|
||||
this.modifiersCondition = condition
|
||||
}
|
||||
|
||||
/** @see Member.isSynthetic */
|
||||
open fun isSynthetic(isSynthetic: Boolean) = apply {
|
||||
this.isSynthetic = isSynthetic
|
||||
}
|
||||
|
||||
/** @see Member.isSynthetic */
|
||||
open fun isSyntheticNot(isSynthetic: Boolean) = apply {
|
||||
this.isSyntheticNot = isSynthetic
|
||||
}
|
||||
|
||||
/** @see AnnotatedElement.getDeclaredAnnotations */
|
||||
open fun annotations(vararg annotations: Any) = apply {
|
||||
this.annotations.addAll(annotations.toList())
|
||||
}
|
||||
|
||||
/** @see AnnotatedElement.getDeclaredAnnotations */
|
||||
open fun annotationsNot(vararg annotations: Any) = apply {
|
||||
this.annotationsNot.addAll(annotations.toList())
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Executable.toGenericString
|
||||
* @see Field.toGenericString
|
||||
*/
|
||||
open fun genericString(genericString: String) = apply {
|
||||
this.genericString = genericString
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable superclass mode.
|
||||
* @see Configuration.superclass
|
||||
*/
|
||||
open fun superclass() = apply {
|
||||
configuration?.superclass = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the copied data from this condition to the new condition.
|
||||
* @param newSelf the new condition instance.
|
||||
*/
|
||||
protected open fun initializeCopiedData(newSelf: MemberCondition<M, R, T>) {
|
||||
newSelf.name = name
|
||||
newSelf.nameCondition = nameCondition
|
||||
newSelf.modifiers.addAll(modifiers)
|
||||
newSelf.modifiersNot.addAll(modifiersNot)
|
||||
newSelf.isSynthetic = isSynthetic
|
||||
newSelf.isSyntheticNot = isSyntheticNot
|
||||
newSelf.annotations.addAll(annotations)
|
||||
newSelf.annotationsNot.addAll(annotationsNot)
|
||||
newSelf.genericString = genericString
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the merged data from this condition to the new condition.
|
||||
* @param other the other condition instance to merge with.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal open fun initializeMergedData(other: MemberCondition<M, R, T>) {
|
||||
other.name?.let { name = it }
|
||||
other.nameCondition?.let { nameCondition = it }
|
||||
other.modifiers.takeIf { it.isNotEmpty() }?.let {
|
||||
modifiers.clear()
|
||||
modifiers.addAll(it)
|
||||
}
|
||||
other.modifiersNot.takeIf { it.isNotEmpty() }?.let {
|
||||
modifiersNot.clear()
|
||||
modifiersNot.addAll(it)
|
||||
}
|
||||
other.isSynthetic?.let { isSynthetic = it }
|
||||
other.isSyntheticNot?.let { isSyntheticNot = it }
|
||||
other.annotations.takeIf { it.isNotEmpty() }?.let {
|
||||
annotations.clear()
|
||||
annotations.addAll(it)
|
||||
}
|
||||
other.annotationsNot.takeIf { it.isNotEmpty() }?.let {
|
||||
annotationsNot.clear()
|
||||
annotationsNot.addAll(it)
|
||||
}
|
||||
other.genericString?.let { genericString = it }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of this condition.
|
||||
* @return [MemberCondition]<[M], [R], [T]>
|
||||
*/
|
||||
abstract fun copy(): MemberCondition<M, R, T>
|
||||
|
||||
/**
|
||||
* Build the condition with the given [configuration].
|
||||
*
|
||||
* - Note: If you are not a manually created condition instance, then you cannot set [configuration] again.
|
||||
* @param configuration the class that declares the member.
|
||||
* @return [List]<[R]>
|
||||
*/
|
||||
@JvmOverloads
|
||||
open fun build(configuration: Configuration<T>? = null): List<R> =
|
||||
TODO("Implemented build function in subclass.")
|
||||
|
||||
/**
|
||||
* Get the condition string map.
|
||||
* @return [Map]<[String], [Any] or null>
|
||||
*/
|
||||
@get:JvmSynthetic
|
||||
internal open val conditionStringMap get() = mapOf(
|
||||
NAME to name,
|
||||
NAME_CONDITION to nameCondition,
|
||||
MODIFIERS to modifiers,
|
||||
MODIFIERS_NOT to modifiersNot,
|
||||
MODIFIERS_CONDITION to modifiersCondition,
|
||||
IS_SYNTHETIC to isSynthetic,
|
||||
IS_SYNTHETIC_NOT to isSyntheticNot,
|
||||
ANNOTATIONS to annotations,
|
||||
ANNOTATIONS_NOT to annotationsNot,
|
||||
GENERIC_STRING to genericString
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val NAME = "name"
|
||||
const val NAME_CONDITION = "nameCondition"
|
||||
const val MODIFIERS = "modifiers"
|
||||
const val MODIFIERS_NOT = "modifiersNot"
|
||||
const val MODIFIERS_CONDITION = "modifiersCondition"
|
||||
const val IS_SYNTHETIC = "isSynthetic"
|
||||
const val IS_SYNTHETIC_NOT = "isSyntheticNot"
|
||||
const val ANNOTATIONS = "annotations"
|
||||
const val ANNOTATIONS_NOT = "annotationsNot"
|
||||
const val GENERIC_STRING = "genericString"
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the [configuration] is null and set it.
|
||||
* If the [configuration] is not null, throw an exception.
|
||||
* @param configuration the configuration to set.
|
||||
* @throws IllegalStateException if the [configuration] is not null.
|
||||
*/
|
||||
protected fun checkAndSetConfiguration(configuration: Configuration<T>) {
|
||||
check(this.configuration == null) {
|
||||
"Configuration already set for this condition \"$javaClass\" of \"${this.configuration}\". " +
|
||||
"To prevent problems, the configuration can only be set once in a condition, " +
|
||||
"otherwise use copy() to reuse the condition."
|
||||
}; this.configuration = configuration
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/6/20.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.highcapable.kavaref.condition.extension
|
||||
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition
|
||||
import com.highcapable.kavaref.resolver.base.MemberResolver
|
||||
import java.lang.reflect.Member
|
||||
|
||||
/**
|
||||
* Merge this condition with another [other] condition.
|
||||
* @receiver the condition to merge from.
|
||||
* @param other the other condition to merge with.
|
||||
*/
|
||||
infix fun <M : Member, R : MemberResolver<M, T>, T : Any, U : MemberCondition<M, R, T>> U.mergeWith(other: U) = initializeMergedData(other)
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/20.
|
||||
*/
|
||||
package com.highcapable.kavaref.condition.matcher
|
||||
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* A [TypeMatcher] that matches a specific class type.
|
||||
* @param clazz the class type to match.
|
||||
*/
|
||||
data class ClassTypeMatcher(
|
||||
val clazz: Class<*>
|
||||
) : TypeMatcher {
|
||||
|
||||
override fun matches(type: Type) = type == clazz
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/20.
|
||||
*/
|
||||
package com.highcapable.kavaref.condition.matcher
|
||||
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import java.lang.reflect.GenericArrayType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* A [TypeMatcher] that matches a generic array type.
|
||||
* @see GenericArrayType.getGenericComponentType
|
||||
* @see Class.getComponentType
|
||||
* @param componentMatcher the [TypeMatcher] for the component type of the array.
|
||||
*/
|
||||
data class GenericArrayTypeMatcher(
|
||||
val componentMatcher: TypeMatcher
|
||||
) : TypeMatcher {
|
||||
|
||||
override fun matches(type: Type) = when (type) {
|
||||
is GenericArrayType -> componentMatcher.matches(type.genericComponentType)
|
||||
is Class<*> -> type.isArray && componentMatcher.matches(type.componentType)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/20.
|
||||
*/
|
||||
package com.highcapable.kavaref.condition.matcher
|
||||
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import com.highcapable.kavaref.condition.matcher.extension.matchesAll
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* A [TypeMatcher] that matches a parameterized type.
|
||||
* @see ParameterizedType.getRawType
|
||||
* @see ParameterizedType.getActualTypeArguments
|
||||
* @param rawType the raw type of the parameterized type.
|
||||
* @param arguments the [TypeMatcher]s for the type arguments of the parameterized type.
|
||||
*/
|
||||
data class ParameterizedTypeMatcher(
|
||||
val rawType: Class<*>,
|
||||
val arguments: List<TypeMatcher>
|
||||
) : TypeMatcher {
|
||||
|
||||
override fun matches(type: Type): Boolean {
|
||||
if (type !is ParameterizedType) return false
|
||||
if (type.rawType != rawType) return false
|
||||
val args = type.actualTypeArguments
|
||||
|
||||
return args.toList().matchesAll(arguments)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/20.
|
||||
*/
|
||||
package com.highcapable.kavaref.condition.matcher
|
||||
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import java.lang.reflect.Type
|
||||
import java.lang.reflect.TypeVariable
|
||||
|
||||
/**
|
||||
* A [TypeMatcher] that matches a type variable.
|
||||
* @see TypeVariable.getName
|
||||
* @param name the name of the type variable.
|
||||
*/
|
||||
data class TypeVariableMatcher(
|
||||
val name: String
|
||||
) : TypeMatcher {
|
||||
|
||||
override fun matches(type: Type) = type is TypeVariable<*> && type.name == name
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/20.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.highcapable.kavaref.condition.matcher
|
||||
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import com.highcapable.kavaref.condition.matcher.extension.matchesAll
|
||||
import java.lang.reflect.Type
|
||||
import java.lang.reflect.WildcardType
|
||||
|
||||
/**
|
||||
* A [TypeMatcher] that matches a wildcard type.
|
||||
* @see WildcardType.getUpperBounds
|
||||
* @see WildcardType.getLowerBounds
|
||||
* @param upperBounds the upper bounds of the wildcard type.
|
||||
* @param lowerBounds the lower bounds of the wildcard type.
|
||||
*/
|
||||
data class WildcardTypeMatcher(
|
||||
val upperBounds: List<TypeMatcher> = emptyList(),
|
||||
val lowerBounds: List<TypeMatcher> = emptyList()
|
||||
) : TypeMatcher {
|
||||
|
||||
override fun matches(type: Type): Boolean {
|
||||
if (type !is WildcardType) return false
|
||||
return type.upperBounds.toList().matchesAll(upperBounds) &&
|
||||
type.lowerBounds.toList().matchesAll(lowerBounds)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/20.
|
||||
*/
|
||||
package com.highcapable.kavaref.condition.matcher.base
|
||||
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* Base interface for type matchers.
|
||||
*/
|
||||
interface TypeMatcher {
|
||||
|
||||
/**
|
||||
* Check if the type matches the given [type].
|
||||
* @param type the type to check.
|
||||
* @return [Boolean]
|
||||
*/
|
||||
fun matches(type: Type): Boolean
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/20.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.highcapable.kavaref.condition.matcher.extension
|
||||
|
||||
import com.highcapable.kavaref.condition.matcher.ClassTypeMatcher
|
||||
import com.highcapable.kavaref.condition.matcher.GenericArrayTypeMatcher
|
||||
import com.highcapable.kavaref.condition.matcher.ParameterizedTypeMatcher
|
||||
import com.highcapable.kavaref.condition.matcher.TypeVariableMatcher
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Creates a [TypeMatcher] for a specific class type.
|
||||
* @param name the name of the type variable.
|
||||
* @return [TypeVariableMatcher]
|
||||
*/
|
||||
fun typeVar(name: String) = TypeVariableMatcher(name)
|
||||
|
||||
/**
|
||||
* Converts a [Class] to a [ClassTypeMatcher].
|
||||
* @receiver [Class]
|
||||
* @return [ClassTypeMatcher]
|
||||
*/
|
||||
fun Class<*>.toTypeMatcher() = ClassTypeMatcher(clazz = this)
|
||||
|
||||
/**
|
||||
* Converts a [KClass.java] to a [ClassTypeMatcher].
|
||||
* @receiver [KClass]
|
||||
* @return [ClassTypeMatcher]
|
||||
*/
|
||||
fun KClass<*>.toTypeMatcher() = java.toTypeMatcher()
|
||||
|
||||
/**
|
||||
* Creates a [ParameterizedTypeMatcher] for a specific [Class] type with the given type arguments.
|
||||
* @receiver [Class]
|
||||
* @param arguments the type arguments for the parameterized type.
|
||||
* @return [ParameterizedTypeMatcher]
|
||||
*/
|
||||
fun Class<*>.parameterizedBy(vararg arguments: TypeMatcher) =
|
||||
ParameterizedTypeMatcher(rawType = this, arguments.toList())
|
||||
|
||||
/**
|
||||
* Creates a [ParameterizedTypeMatcher] for a specific [KClass.java] type with the given type arguments.
|
||||
* @receiver [KClass]
|
||||
* @param arguments the type arguments for the parameterized type.
|
||||
* @return [ParameterizedTypeMatcher]
|
||||
*/
|
||||
fun KClass<*>.parameterizedBy(vararg arguments: TypeMatcher) = java.parameterizedBy(*arguments)
|
||||
|
||||
/**
|
||||
* Creates a [GenericArrayTypeMatcher] from [TypeMatcher].
|
||||
* @receiver [TypeMatcher]
|
||||
* @return [GenericArrayTypeMatcher]
|
||||
*/
|
||||
fun TypeMatcher.asGenericArray() = GenericArrayTypeMatcher(componentMatcher = this)
|
||||
|
||||
/**
|
||||
* Check if the list of [Type] matches all the given [TypeMatcher].
|
||||
* @receiver the list of [Type] to be checked.
|
||||
* @param matchers the list of [TypeMatcher] to be checked.
|
||||
* @return [Boolean]
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun List<Type>.matchesAll(matchers: List<TypeMatcher>): Boolean {
|
||||
if (this.size != matchers.size) return false
|
||||
return this.zip(matchers).all { (t, m) -> m.matches(t) }
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.highcapable.kavaref.condition.type
|
||||
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
/**
|
||||
* Modifiers for Java reflection.
|
||||
* @param mod the modifier bitmask.
|
||||
*/
|
||||
enum class Modifiers(private val mod: Int) {
|
||||
PUBLIC(Modifier.PUBLIC),
|
||||
PRIVATE(Modifier.PRIVATE),
|
||||
PROTECTED(Modifier.PROTECTED),
|
||||
STATIC(Modifier.STATIC),
|
||||
FINAL(Modifier.FINAL),
|
||||
SYNCHRONIZED(Modifier.SYNCHRONIZED),
|
||||
VOLATILE(Modifier.VOLATILE),
|
||||
TRANSIENT(Modifier.TRANSIENT),
|
||||
NATIVE(Modifier.NATIVE),
|
||||
INTERFACE(Modifier.INTERFACE),
|
||||
ABSTRACT(Modifier.ABSTRACT),
|
||||
STRICT(Modifier.STRICT);
|
||||
|
||||
/**
|
||||
* Check if the modifier matches the given modifier.
|
||||
* @param modifier the modifier bitmask to check against.
|
||||
* @return [Boolean]
|
||||
*/
|
||||
fun matches(modifier: Int) = (mod and modifier) != 0
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Get the set of modifiers that match the given modifier bitmask.
|
||||
* @param modifier the modifier bitmask to check against.
|
||||
* @return [Set]<[Modifiers]>
|
||||
*/
|
||||
fun matching(modifier: Int) = entries.filter { it.matches(modifier) }.toSet()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
package com.highcapable.kavaref.condition.type
|
||||
|
||||
import com.highcapable.kavaref.extension.classOf
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* You can fill this type in the reflection lookup condition as a placeholder.
|
||||
*
|
||||
* It is a vague type that you can use when the signature of the JVM type is too long and does not want to declare a type.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```
|
||||
* public void a(java.lang.String, some.name.like.too.long.Type, int);
|
||||
* ```
|
||||
*
|
||||
* ```kotlin
|
||||
* method {
|
||||
* name = "a"
|
||||
* parameters(String::class, VagueType, Int::class)
|
||||
* }
|
||||
*/
|
||||
object VagueType {
|
||||
|
||||
private const val TAG = "VagueType"
|
||||
|
||||
/**
|
||||
* Format the placeholder to a string.
|
||||
* @param placeholder the placeholder to be formatted.
|
||||
* @return [String]
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun format(placeholder: Any?): String? = when (placeholder) {
|
||||
null -> null
|
||||
is VagueType -> TAG
|
||||
is Class<*> -> if (placeholder != classOf<VagueType>())
|
||||
placeholder.toString()
|
||||
else TAG
|
||||
is KClass<*> -> if (placeholder != VagueType::class)
|
||||
placeholder.toString()
|
||||
else TAG
|
||||
is Collection<*> ->
|
||||
placeholder.map {
|
||||
if (it != null) format(it) else null
|
||||
}.toString()
|
||||
else -> placeholder.toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package com.highcapable.kavaref.resolver
|
||||
|
||||
import com.highcapable.kavaref.extension.classOf
|
||||
import com.highcapable.kavaref.extension.makeAccessible
|
||||
import com.highcapable.kavaref.resolver.base.MemberResolver
|
||||
import java.lang.reflect.Constructor
|
||||
|
||||
/**
|
||||
* Resolving [Constructor].
|
||||
* @param self the member to be resolved.
|
||||
*/
|
||||
class ConstructorResolver<T : Any> internal constructor(override val self: Constructor<T>) : MemberResolver<Constructor<T>, T>(self) {
|
||||
|
||||
override fun copy() = ConstructorResolver(self)
|
||||
|
||||
/**
|
||||
* Create a new instance of the class represented by this constructor.
|
||||
* @see Constructor.newInstance
|
||||
* @see createQuietly
|
||||
* @see createAsType
|
||||
* @see createAsTypeQuietly
|
||||
* @return [T]
|
||||
*/
|
||||
fun create(vararg args: Any?): T {
|
||||
self.makeAccessible()
|
||||
return self.newInstance(*args)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the class represented by this constructor and cast it to the specified type [T].
|
||||
* @see Constructor.newInstance
|
||||
* @see createAsTypeQuietly
|
||||
* @see createQuietly
|
||||
* @return [T]
|
||||
*/
|
||||
inline fun <reified T : Any> createAsType(vararg args: Any?): T {
|
||||
self.makeAccessible()
|
||||
return self.newInstance(*args) as? T ?: error("$this's instance cannot be cast to type ${classOf<T>()}.")
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the class represented by this constructor and ignore any exceptions.
|
||||
* @see Constructor.newInstance
|
||||
* @see create
|
||||
* @see createAsType
|
||||
* @see createAsTypeQuietly
|
||||
* @return [T] or null.
|
||||
*/
|
||||
fun createQuietly(vararg args: Any?) = runCatching { create(*args) }.getOrNull()
|
||||
|
||||
/**
|
||||
* Create a new instance of the class represented by this constructor and cast it to the
|
||||
* specified type [T] and ignore any exceptions.
|
||||
* @see Constructor.newInstance
|
||||
* @see create
|
||||
* @see createAsType
|
||||
* @see createQuietly
|
||||
* @return [T] or null.
|
||||
*/
|
||||
inline fun <reified T : Any> createAsTypeQuietly(vararg args: Any?) = runCatching { createAsType<T>(*args) }.getOrNull()
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate")
|
||||
|
||||
package com.highcapable.kavaref.resolver
|
||||
|
||||
import com.highcapable.kavaref.extension.makeAccessible
|
||||
import com.highcapable.kavaref.resolver.base.InstanceAwareResolver
|
||||
import java.lang.reflect.Field
|
||||
|
||||
/**
|
||||
* Resolving [Field].
|
||||
* @param self the member to be resolved.
|
||||
*/
|
||||
class FieldResolver<T : Any> internal constructor(override val self: Field) : InstanceAwareResolver<Field, T>(self) {
|
||||
|
||||
override fun of(instance: T?) = apply {
|
||||
checkAndSetInstance(instance)
|
||||
}
|
||||
|
||||
override fun copy() = FieldResolver<T>(self)
|
||||
|
||||
/**
|
||||
* Get the value of the field.
|
||||
* @see Field.get
|
||||
* @see getQuietly
|
||||
* @return [T] or null.
|
||||
*/
|
||||
@JvmName("getTyped")
|
||||
fun <T : Any?> get(): T? {
|
||||
self.makeAccessible()
|
||||
return self.get(instance) as? T?
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the field and ignore any exceptions.
|
||||
* @see Field.get
|
||||
* @see get
|
||||
* @return [T] or null.
|
||||
*/
|
||||
@JvmName("getQuietlyTyped")
|
||||
fun <T : Any?> getQuietly() = runCatching { get<T>() }.getOrNull()
|
||||
|
||||
/**
|
||||
* Get the value of the field.
|
||||
* @see Field.get
|
||||
* @see getQuietly
|
||||
* @return [Any] or null.
|
||||
*/
|
||||
fun get(): Any? {
|
||||
self.makeAccessible()
|
||||
return self.get(instance)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the field and ignore any exceptions.
|
||||
* @see Field.get
|
||||
* @see get
|
||||
* @return [Any] or null.
|
||||
*/
|
||||
fun getQuietly() = runCatching { get() }.getOrNull()
|
||||
|
||||
/**
|
||||
* Set the value of the field.
|
||||
* @see Field.set
|
||||
* @see setQuietly
|
||||
* @param value the value to set.
|
||||
*/
|
||||
fun set(value: Any?) {
|
||||
self.makeAccessible()
|
||||
self.set(instance, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the field and ignore any exceptions.
|
||||
* @see Field.set
|
||||
* @see set
|
||||
* @param value the value to set.
|
||||
*/
|
||||
fun setQuietly(value: Any?) = runCatching { set(value) }.getOrNull() ?: Unit
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate")
|
||||
|
||||
package com.highcapable.kavaref.resolver
|
||||
|
||||
import com.highcapable.kavaref.extension.makeAccessible
|
||||
import com.highcapable.kavaref.resolver.base.InstanceAwareResolver
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* Resolving [Method].
|
||||
* @param self the member to be resolved.
|
||||
*/
|
||||
class MethodResolver<T : Any> internal constructor(override val self: Method) : InstanceAwareResolver<Method, T>(self) {
|
||||
|
||||
override fun of(instance: T?) = apply {
|
||||
checkAndSetInstance(instance)
|
||||
}
|
||||
|
||||
override fun copy() = MethodResolver<T>(self)
|
||||
|
||||
/**
|
||||
* Invoke the method with the given arguments.
|
||||
* @see Method.invoke
|
||||
* @see invokeQuietly
|
||||
* @return [T] or null.
|
||||
*/
|
||||
@JvmName("invokeTyped")
|
||||
fun <T : Any?> invoke(vararg args: Any?): T? {
|
||||
self.makeAccessible()
|
||||
return self.invoke(instance, *args) as? T?
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the method with the given arguments and ignore any exceptions.
|
||||
* @see Method.invoke
|
||||
* @see invokeQuietly
|
||||
* @return [T] or null.
|
||||
*/
|
||||
@JvmName("invokeQuietlyTyped")
|
||||
fun <T : Any?> invokeQuietly(vararg args: Any?) = runCatching { invoke<T>(*args) }.getOrNull()
|
||||
|
||||
/**
|
||||
* Invoke the method with the given arguments.
|
||||
* @see Method.invoke
|
||||
* @see invoke
|
||||
* @return [Any] or null.
|
||||
*/
|
||||
fun invoke(vararg args: Any?): Any? {
|
||||
self.makeAccessible()
|
||||
return self.invoke(instance, *args)
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the method with the given arguments and ignore any exceptions.
|
||||
* @see Method.invoke
|
||||
* @see invoke
|
||||
* @return [Any] or null.
|
||||
*/
|
||||
fun invokeQuietly(vararg args: Any?) = runCatching { invoke(*args) }.getOrNull()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
package com.highcapable.kavaref.resolver.base
|
||||
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition
|
||||
import java.lang.reflect.Member
|
||||
|
||||
/**
|
||||
* Base [instance] aware class for resolving member [M].
|
||||
*
|
||||
* [T] to specify the declaring class type of the member.
|
||||
* @param self the member to be resolved.
|
||||
*/
|
||||
abstract class InstanceAwareResolver<M : Member, T : Any>(override val self: M) : MemberResolver<M, T>(self) {
|
||||
|
||||
/** The instance of [self]. */
|
||||
@get:JvmSynthetic
|
||||
@set:JvmSynthetic
|
||||
internal var instance: T? = null
|
||||
|
||||
/**
|
||||
* Set the instance of [self].
|
||||
*
|
||||
* If you have already set it in [MemberCondition.Configuration.memberInstance],
|
||||
* then there is no need to set it here.
|
||||
* If you want to reuse the resolver, please use [copy] to create a new resolver.
|
||||
* @param instance the instance to set.
|
||||
*/
|
||||
abstract fun of(instance: T?): InstanceAwareResolver<M, T>
|
||||
|
||||
/**
|
||||
* Check if the [instance] is null and set it.
|
||||
* If the [instance] is not null, throw an exception.
|
||||
* @param instance the instance to set.
|
||||
* @throws IllegalStateException if the [instance] is not null.
|
||||
*/
|
||||
protected fun checkAndSetInstance(instance: T?) {
|
||||
check(this.instance == null) {
|
||||
"Instance already set for this resolver \"$javaClass\" of \"$self(${this.instance})\". " +
|
||||
"To prevent problems, the instance object can only be set once in a resolver, " +
|
||||
"otherwise use copy() to reuse the resolver."
|
||||
}
|
||||
|
||||
this.instance = instance
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
package com.highcapable.kavaref.resolver.base
|
||||
|
||||
import java.lang.reflect.Member
|
||||
|
||||
/**
|
||||
* Base class for resolving member [M].
|
||||
*
|
||||
* [T] to specify the declaring class type of the member.
|
||||
* @param self the member to be resolved.
|
||||
*/
|
||||
abstract class MemberResolver<M : Member, T : Any>(open val self: M) {
|
||||
|
||||
/**
|
||||
* Create a copy of this resolver.
|
||||
* @return [MemberResolver]<[M]>
|
||||
*/
|
||||
abstract fun copy(): MemberResolver<M, T>
|
||||
}
|
||||
@@ -0,0 +1,518 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/16.
|
||||
*/
|
||||
@file:Suppress("UNCHECKED_CAST", "UnnecessaryVariable")
|
||||
|
||||
package com.highcapable.kavaref.resolver.processor
|
||||
|
||||
import com.highcapable.kavaref.condition.ConstructorCondition
|
||||
import com.highcapable.kavaref.condition.FieldCondition
|
||||
import com.highcapable.kavaref.condition.MethodCondition
|
||||
import com.highcapable.kavaref.condition.base.ExecutableCondition
|
||||
import com.highcapable.kavaref.condition.base.MemberCondition
|
||||
import com.highcapable.kavaref.condition.matcher.base.TypeMatcher
|
||||
import com.highcapable.kavaref.condition.type.Modifiers
|
||||
import com.highcapable.kavaref.condition.type.VagueType
|
||||
import com.highcapable.kavaref.extension.classOf
|
||||
import com.highcapable.kavaref.extension.toClass
|
||||
import com.highcapable.kavaref.extension.toClassOrNull
|
||||
import com.highcapable.kavaref.generated.KavarefCoreProperties
|
||||
import com.highcapable.kavaref.resolver.ConstructorResolver
|
||||
import com.highcapable.kavaref.resolver.FieldResolver
|
||||
import com.highcapable.kavaref.resolver.MethodResolver
|
||||
import com.highcapable.kavaref.resolver.base.InstanceAwareResolver
|
||||
import com.highcapable.kavaref.resolver.base.MemberResolver
|
||||
import com.highcapable.kavaref.runtime.KavaRefRuntime
|
||||
import java.lang.reflect.AnnotatedElement
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Executable
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Processing member resolver core implementation.
|
||||
*/
|
||||
object MemberProcessor {
|
||||
|
||||
private const val PRODUCT_DESCRIPTION = "\n====== Generated by KavaRef ${KavarefCoreProperties.PROJECT_KAVAREF_CORE_VERSION} ======\n"
|
||||
|
||||
/**
|
||||
* Global [Resolver] used by KavaRef to resolve members.
|
||||
*
|
||||
* You can change this resolver to use a custom member resolver, which will affect global behavior.
|
||||
*/
|
||||
@JvmStatic
|
||||
var globalResolver: Resolver = Resolver()
|
||||
|
||||
/**
|
||||
* Resolver class for resolving members.
|
||||
*
|
||||
* Provides methods to resolve fields, methods, and constructors of a class.
|
||||
*
|
||||
* You can inherit this class to implement a custom member parser,
|
||||
* and override the [getDeclaredFields], [getDeclaredMethods] and
|
||||
* [getDeclaredConstructors] methods to implement custom member resolution logic.
|
||||
*/
|
||||
open class Resolver {
|
||||
|
||||
/**
|
||||
* Resolve fields of the specified class [T].
|
||||
* @param declaringClass the class to resolve fields from.
|
||||
* @return [List]<[Field]>
|
||||
*/
|
||||
open fun <T : Any> getDeclaredFields(declaringClass: Class<T>): List<Field> =
|
||||
runCatching { declaringClass.declaredFields.toList() }.onFailure {
|
||||
KavaRefRuntime.warn("Failed to get declared fields in $this because got an exception.", it)
|
||||
}.getOrNull() ?: emptyList()
|
||||
|
||||
/**
|
||||
* Resolve methods of the specified class [T].
|
||||
* @param declaringClass the class to resolve methods from.
|
||||
* @return [List]<[Method]>
|
||||
*/
|
||||
open fun <T : Any> getDeclaredMethods(declaringClass: Class<T>): List<Method> =
|
||||
runCatching { declaringClass.declaredMethods.toList() }.onFailure {
|
||||
KavaRefRuntime.warn("Failed to get declared methods in $this because got an exception.", it)
|
||||
}.getOrNull() ?: emptyList()
|
||||
|
||||
/**
|
||||
* Resolve constructors of the specified class [T].
|
||||
* @param declaringClass the class to resolve constructors from.
|
||||
* @return [List]<[Constructor]<[T]>>
|
||||
*/
|
||||
open fun <T : Any> getDeclaredConstructors(declaringClass: Class<T>): List<Constructor<T>> =
|
||||
runCatching { declaringClass.declaredConstructors.filterIsInstance<Constructor<T>>() }.onFailure {
|
||||
KavaRefRuntime.warn("Failed to get declared constructors in $this because got an exception.", it)
|
||||
}.getOrNull() ?: emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve members with current [condition] and [configuration].
|
||||
* @param condition the condition to resolve members.
|
||||
* @param configuration the configuration to resolve members, must not be null.
|
||||
* @return [List]<[R]>
|
||||
*/
|
||||
internal inline fun <reified M : Member, reified R : MemberResolver<M, T>, T : Any> resolve(
|
||||
condition: MemberCondition<M, R, T>,
|
||||
configuration: MemberCondition.Configuration<T>?
|
||||
): List<R> {
|
||||
require(configuration != null) {
|
||||
"You must provide a configuration to resolve the member use build(configuration)."
|
||||
}
|
||||
|
||||
return when (condition) {
|
||||
is MethodCondition -> resolveInClass(
|
||||
condition, configuration, configuration.declaringClass
|
||||
) { declaringClass ->
|
||||
methodFilters(condition, configuration, declaringClass)
|
||||
}
|
||||
is ConstructorCondition -> resolveInClass(
|
||||
condition, configuration, configuration.declaringClass
|
||||
) { declaringClass ->
|
||||
constructorFilters(condition, configuration, declaringClass)
|
||||
}
|
||||
is FieldCondition -> resolveInClass(
|
||||
condition, configuration, configuration.declaringClass
|
||||
) { declaringClass ->
|
||||
fieldFilters(condition, configuration, declaringClass)
|
||||
}
|
||||
else -> error("Unsupported condition type: $condition")
|
||||
} as List<R>
|
||||
}
|
||||
|
||||
private fun <M : Member, R : MemberResolver<M, T>, T : Any> resolveInClass(
|
||||
condition: MemberCondition<M, R, T>,
|
||||
configuration: MemberCondition.Configuration<T>,
|
||||
declaringClass: Class<*>?,
|
||||
result: (declaringClass: Class<*>) -> List<R>
|
||||
): List<R> {
|
||||
if (declaringClass == null || declaringClass == classOf<Any>())
|
||||
return throwIfNotOptional(condition, configuration)
|
||||
|
||||
return result(declaringClass).ifEmpty {
|
||||
if (configuration.superclass)
|
||||
resolveInClass(condition, configuration, declaringClass.superclass, result)
|
||||
else throwIfNotOptional(condition, configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Any> methodFilters(
|
||||
condition: MethodCondition<T>,
|
||||
configuration: MemberCondition.Configuration<T>,
|
||||
declaringClass: Class<*>
|
||||
): List<MethodResolver<T>> = configuration.currentProcessorResolver.getDeclaredMethods(declaringClass)
|
||||
.asSequence()
|
||||
.baseFilters(condition, configuration)
|
||||
.executableFilters(condition, configuration)
|
||||
.filter(configuration, MethodCondition.RETURN_TYPE, condition.returnType) { key, value ->
|
||||
value.returnType == key.toTypeClass(configuration, noVague = "Method: returnType")
|
||||
}
|
||||
.filter(configuration, MethodCondition.RETURN_TYPE_CONDITION, condition.returnTypeCondition) { key, value ->
|
||||
runOrElse { key(value.returnType) }
|
||||
}
|
||||
.filter(configuration, MethodCondition.IS_BRIDGE, condition.isBridge) { key, value -> value.isBridge == key }
|
||||
.filter(configuration, MethodCondition.IS_BRIDGE_NOT, condition.isBridgeNot) { key, value -> value.isBridge != key }
|
||||
.filter(configuration, MethodCondition.IS_DEFAULT, condition.isDefault) { key, value -> value.isDefault == key }
|
||||
.filter(configuration, MethodCondition.IS_DEFAULT_NOT, condition.isDefaultNot) { key, value -> value.isDefault != key }
|
||||
.resolve(configuration)
|
||||
|
||||
private fun <T : Any> constructorFilters(
|
||||
condition: ConstructorCondition<T>,
|
||||
configuration: MemberCondition.Configuration<T>,
|
||||
declaringClass: Class<*>
|
||||
): List<ConstructorResolver<T>> = configuration.currentProcessorResolver.getDeclaredConstructors(declaringClass)
|
||||
.asSequence()
|
||||
.baseFilters(condition, configuration)
|
||||
.executableFilters(condition, configuration)
|
||||
.resolve(configuration)
|
||||
|
||||
private fun <T : Any> fieldFilters(
|
||||
condition: FieldCondition<T>,
|
||||
configuration: MemberCondition.Configuration<T>,
|
||||
declaringClass: Class<*>
|
||||
): List<FieldResolver<T>> = configuration.currentProcessorResolver.getDeclaredFields(declaringClass)
|
||||
.asSequence()
|
||||
.baseFilters(condition, configuration)
|
||||
.filter(configuration, FieldCondition.IS_ENUM_CONSTANT, condition.isEnumConstant) { key, value -> value.isEnumConstant == key }
|
||||
.filter(configuration, FieldCondition.IS_ENUM_CONSTANT_NOT, condition.isEnumConstantNot) { key, value -> value.isEnumConstant != key }
|
||||
.filter(configuration, FieldCondition.TYPE, condition.type) { key, value ->
|
||||
value.type == key.toTypeClass(configuration, noVague = "Field: type")
|
||||
}
|
||||
.filter(configuration, FieldCondition.TYPE_CONDITION, condition.typeCondition) { key, value -> key(value.type) }
|
||||
.filter(configuration, FieldCondition.GENERIC_TYPE, condition.genericType) { key, value -> key.matches(value.genericType) }
|
||||
.filter(configuration, FieldCondition.GENERIC_TYPE_CONDITION, condition.genericTypeCondition) { key, value -> key(value.genericType) }
|
||||
.resolve(configuration)
|
||||
|
||||
private fun <M : Member, T : Any> Sequence<M>.baseFilters(
|
||||
condition: MemberCondition<*, *, *>,
|
||||
configuration: MemberCondition.Configuration<T>
|
||||
) = this.filter(configuration, MemberCondition.NAME, condition.name) { key, value -> value.name == key }
|
||||
.filter(configuration, MemberCondition.NAME_CONDITION, condition.nameCondition) { key, value -> runOrElse { key(value.name) } }
|
||||
.filter(configuration, MemberCondition.MODIFIERS, condition.modifiers) { key, value ->
|
||||
key.all { it.matches(value.modifiers) }
|
||||
}
|
||||
.filter(configuration, MemberCondition.MODIFIERS_NOT, condition.modifiersNot) { key, value ->
|
||||
key.none { it.matches(value.modifiers) }
|
||||
}
|
||||
.filter(configuration, MemberCondition.MODIFIERS_CONDITION, condition.modifiersCondition) { key, value ->
|
||||
runOrElse { key(Modifiers.matching(value.modifiers)) }
|
||||
}
|
||||
.filter(configuration, MemberCondition.IS_SYNTHETIC, condition.isSynthetic) { key, value -> value.isSynthetic == key }
|
||||
.filter(configuration, MemberCondition.IS_SYNTHETIC_NOT, condition.isSyntheticNot) { key, value -> value.isSynthetic != key }
|
||||
.filter(configuration, MemberCondition.ANNOTATIONS, condition.annotations) { key, value ->
|
||||
val annotations = value.annotations.map { it.annotationClass.java }
|
||||
compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, MemberCondition.ANNOTATIONS_NOT, condition.annotationsNot) { key, value ->
|
||||
val annotations = value.annotations.map { it.annotationClass.java }
|
||||
!compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, MemberCondition.GENERIC_STRING, condition.genericString) { key, value -> value.toGenericString() == key }
|
||||
|
||||
private fun <M : Executable, T : Any> Sequence<M>.executableFilters(
|
||||
condition: ExecutableCondition<*, *, *>,
|
||||
configuration: MemberCondition.Configuration<T>
|
||||
) = this
|
||||
.filter(configuration, ExecutableCondition.PARAMETERS, condition.parameters) { key, value ->
|
||||
compareElementTypes(key, value.parameterTypes.toList(), configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.PARAMETERS_NOT, condition.parametersNot) { key, value ->
|
||||
!compareElementTypes(key, value.parameterTypes.toList(), configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.PARAMETERS_CONDITION, condition.parametersCondition) { key, value ->
|
||||
runOrElse { key(value.parameterTypes.toList()) }
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.PARAMETER_COUNT, condition.parameterCount) { key, value -> value.parameterCount == key }
|
||||
.filter(configuration, ExecutableCondition.PARAMETER_COUNT_CONDITION, condition.parameterCountCondition) { key, value ->
|
||||
runOrElse { key(value.parameterCount) }
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.TYPE_PARAMETERS, condition.typeParameters) { key, value ->
|
||||
compareMatcherTypes(key, value.typeParameters.toList())
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.TYPE_PARAMETERS_NOT, condition.typeParametersNot) { key, value ->
|
||||
!compareMatcherTypes(key, value.typeParameters.toList())
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.EXCEPTION_TYPES, condition.exceptionTypes) { key, value ->
|
||||
compareElementTypes(key, value.exceptionTypes.toList(), configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.EXCEPTION_TYPES_NOT, condition.exceptionTypesNot) { key, value ->
|
||||
!compareElementTypes(key, value.exceptionTypes.toList(), configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.GENERIC_EXCEPTION_TYPES, condition.genericExceptionTypes) { key, value ->
|
||||
compareMatcherTypes(key, value.genericExceptionTypes.toList())
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.GENERIC_EXCEPTION_TYPES_NOT, condition.genericExceptionTypesNot) { key, value ->
|
||||
!compareMatcherTypes(key, value.genericExceptionTypes.toList())
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.GENERIC_PARAMETERS, condition.genericParameters) { key, value ->
|
||||
compareMatcherTypes(key, value.genericParameterTypes.toList())
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.GENERIC_PARAMETERS_NOT, condition.genericParametersNot) { key, value ->
|
||||
!compareMatcherTypes(key, value.genericParameterTypes.toList())
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.IS_VAR_ARGS, condition.isVarArgs) { key, value -> value.isVarArgs == key }
|
||||
.filter(configuration, ExecutableCondition.IS_VAR_ARGS_NOT, condition.isVarArgsNot) { key, value -> value.isVarArgs != key }
|
||||
.filter(configuration, ExecutableCondition.PARAMETER_ANNOTATIONS, condition.parameterAnnotations) { key, value ->
|
||||
val annotations = value.parameterAnnotations.map { it.map { e -> e.annotationClass.java } }
|
||||
compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.PARAMETER_ANNOTATIONS_NOT, condition.parameterAnnotationsNot) { key, value ->
|
||||
val annotations = value.parameterAnnotations.map { it.map { e -> e.annotationClass.java } }
|
||||
!compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_RETURN_TYPE, condition.annotatedReturnType) { key, value ->
|
||||
val annotations = value.annotatedReturnType.annotations.map { it.annotationClass.java }
|
||||
compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_RETURN_TYPE_NOT, condition.annotatedReturnTypeNot) { key, value ->
|
||||
val annotations = value.annotatedReturnType.annotations.map { it.annotationClass.java }
|
||||
!compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_RECEIVER_TYPE, condition.annotatedReceiverType) { key, value ->
|
||||
val annotations = value.annotatedReceiverType.annotations.map { it.annotationClass.java }
|
||||
compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_RECEIVER_TYPE_NOT, condition.annotatedReceiverTypeNot) { key, value ->
|
||||
val annotations = value.annotatedReceiverType.annotations.map { it.annotationClass.java }
|
||||
!compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_PARAMETER_TYPES, condition.annotatedParameterTypes) { key, value ->
|
||||
val annotations = value.annotatedParameterTypes.map { it.annotations.map { e -> e.annotationClass.java } }.flatten()
|
||||
compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_PARAMETER_TYPES_NOT, condition.annotatedParameterTypesNot) { key, value ->
|
||||
val annotations = value.annotatedParameterTypes.map { it.annotations.map { e -> e.annotationClass.java } }.flatten()
|
||||
!compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_EXCEPTION_TYPES, condition.annotatedExceptionTypes) { key, value ->
|
||||
val annotations = value.annotatedExceptionTypes.map { it.annotations.map { e -> e.annotationClass.java } }.flatten()
|
||||
compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
.filter(configuration, ExecutableCondition.ANNOTATED_EXCEPTION_TYPES_NOT, condition.annotatedExceptionTypesNot) { key, value ->
|
||||
val annotations = value.annotatedExceptionTypes.map { it.annotations.map { e -> e.annotationClass.java } }.flatten()
|
||||
!compareElementTypes(key, annotations, configuration)
|
||||
}
|
||||
|
||||
private inline fun <reified M : Member, reified R : MemberResolver<M, T>, T : Any> Sequence<M>.resolve(
|
||||
configuration: MemberCondition.Configuration<T>
|
||||
) = when (M::class) {
|
||||
Method::class -> map { MethodResolver<T>(it as Method).apply(configuration) }
|
||||
Constructor::class -> map { ConstructorResolver(it as Constructor<T>).apply(configuration) }
|
||||
Field::class -> map { FieldResolver<T>(it as Field).apply(configuration) }
|
||||
else -> error("Unsupported member type: $this")
|
||||
}.toList() as List<R>
|
||||
|
||||
private fun <M : Member, R : MemberResolver<M, T>, T : Any> throwIfNotOptional(
|
||||
condition: MemberCondition<M, R, T>,
|
||||
configuration: MemberCondition.Configuration<T>
|
||||
): List<R> {
|
||||
fun splicingString(name: String) = "No $name found matching the condition for " +
|
||||
"current class${if (configuration.superclass) " (Also tried for superclass)" else ""}.\n" +
|
||||
buildConditionTable(condition, configuration) + "\n" +
|
||||
"Suggestion: ${if (!configuration.superclass) "Members in superclass are not reflected in the current class, " +
|
||||
"you can try adding superclass() in your condition and try again. "
|
||||
else "Check if the conditions are correct and valid, and try again. "}"
|
||||
|
||||
val exceptionNote = "If you want to ignore this exception, adding optional() in your condition."
|
||||
val message = when (condition) {
|
||||
is MethodCondition -> splicingString(name = "method")
|
||||
is ConstructorCondition -> splicingString(name = "constructor")
|
||||
is FieldCondition -> splicingString(name = "field")
|
||||
else -> error("Unsupported condition type: $condition")
|
||||
}
|
||||
|
||||
return if (configuration.optional == MemberCondition.Configuration.Optional.NO) throw when (condition) {
|
||||
is MethodCondition -> NoSuchMethodException("$message\n$exceptionNote\n$PRODUCT_DESCRIPTION")
|
||||
is ConstructorCondition -> NoSuchMethodException("$message\n$exceptionNote\n$PRODUCT_DESCRIPTION")
|
||||
is FieldCondition -> NoSuchFieldException("$message\n$exceptionNote\n$PRODUCT_DESCRIPTION")
|
||||
else -> error("Unsupported condition type: $condition")
|
||||
} else {
|
||||
if (configuration.optional == MemberCondition.Configuration.Optional.NOTICE)
|
||||
KavaRefRuntime.warn(message.trim())
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified M : Member, T : Any> MemberResolver<M, T>.apply(configuration: MemberCondition.Configuration<T>) =
|
||||
apply { configuration.memberInstance?.let { if (this is InstanceAwareResolver) of(it) } }
|
||||
|
||||
private fun <T, R> Sequence<T>.filter(
|
||||
configuration: MemberCondition.Configuration<*>,
|
||||
name: String,
|
||||
key: R?,
|
||||
predicate: (key: R, value: T) -> Boolean
|
||||
) = filter { condition ->
|
||||
val predicateKey = if (key is Collection<*>)
|
||||
key.takeIf { it.isNotEmpty() }
|
||||
else key
|
||||
|
||||
predicateKey?.let {
|
||||
val result = predicate(it, condition)
|
||||
val sKey = VagueType.format(it)?.toStringIgnore()
|
||||
val sValue = condition?.toStringIgnore()
|
||||
|
||||
if (configuration.optional != MemberCondition.Configuration.Optional.SILENT)
|
||||
KavaRefRuntime.debug("[FILTER] [${if (result) "HIT" else "MISS"}] $name: $sKey [RESOLVED] $sValue")
|
||||
|
||||
result
|
||||
} ?: true
|
||||
}
|
||||
|
||||
private fun <T : Any> compareElementTypes(
|
||||
conditionKey: Collection<Any>,
|
||||
typesValue: List<Class<*>>,
|
||||
configuration: MemberCondition.Configuration<T>
|
||||
): Boolean {
|
||||
// If size is different at first, return false.
|
||||
if (conditionKey.size != typesValue.size) return false
|
||||
|
||||
val isMatched = conditionKey
|
||||
.map { it.toTypeClass(configuration) }
|
||||
.filterIndexed { index, type ->
|
||||
val target = typesValue[index]
|
||||
type == classOf<VagueType>() || target == type
|
||||
}.size == typesValue.size
|
||||
|
||||
return isMatched
|
||||
}
|
||||
|
||||
@JvmName("compareElementTypesMultiple")
|
||||
private fun <T : Any> compareElementTypes(
|
||||
conditionKey: Collection<Collection<Any>>,
|
||||
typesValue: List<List<Class<*>>>,
|
||||
configuration: MemberCondition.Configuration<T>
|
||||
): Boolean {
|
||||
// If size is different at first, return false.
|
||||
if (conditionKey.size != typesValue.size) return false
|
||||
|
||||
val isMatched = conditionKey.filterIndexed { index, type ->
|
||||
val target = typesValue[index]
|
||||
compareElementTypes(type, target, configuration)
|
||||
}.size == typesValue.size
|
||||
|
||||
return isMatched
|
||||
}
|
||||
|
||||
private fun compareMatcherTypes(
|
||||
conditionKey: Collection<TypeMatcher>,
|
||||
typesValue: List<Type>
|
||||
): Boolean {
|
||||
// If size is different at first, return false.
|
||||
if (conditionKey.size != typesValue.size) return false
|
||||
|
||||
val isMatched = conditionKey.filterIndexed { index, type ->
|
||||
val target = typesValue[index]
|
||||
type.matches(target)
|
||||
}.size == typesValue.size
|
||||
|
||||
return isMatched
|
||||
}
|
||||
|
||||
private fun <T : Any> buildConditionTable(
|
||||
condition: MemberCondition<*, *, *>,
|
||||
configuration: MemberCondition.Configuration<T>
|
||||
) = runCatching {
|
||||
fun displayWidth(str: String) = str.sumOf { if (it.code > 127L) 2L else 1L }.toInt()
|
||||
|
||||
fun padDisplay(str: String, targetWidth: Int): String {
|
||||
val currentWidth = displayWidth(str)
|
||||
val padding = targetWidth - currentWidth
|
||||
return if (padding > 0) str + " ".repeat(padding) else str
|
||||
}
|
||||
|
||||
val rows = condition.conditionStringMap.mapNotNull { (label, value) ->
|
||||
val displayValue = when (value) {
|
||||
null -> null
|
||||
is Function<*> -> "(Runtime Condition)"
|
||||
is Collection<*> -> if (value.isEmpty()) null else VagueType.format(value)
|
||||
else -> VagueType.format(value)
|
||||
// Remove the Kotlin reflection warning message.
|
||||
}?.toStringIgnore()
|
||||
displayValue?.let { label to it }
|
||||
}
|
||||
|
||||
if (rows.isEmpty()) return configuration.declaringClass.toString()
|
||||
|
||||
val originalLabelWidth = rows.maxOf { displayWidth(it.first) }
|
||||
val originalValueWidth = rows.maxOf { displayWidth(it.second) }
|
||||
|
||||
val headerText = configuration.declaringClass.toStringIgnore()
|
||||
val headerWidth = displayWidth(headerText)
|
||||
|
||||
val contentWidth = originalLabelWidth + originalValueWidth + 3 // 3: " | "
|
||||
|
||||
// If header is wider, increase value column width.
|
||||
val extraPadding = (headerWidth - contentWidth).coerceAtLeast(0)
|
||||
|
||||
val labelWidth = originalLabelWidth
|
||||
val valueWidth = originalValueWidth + extraPadding
|
||||
|
||||
val border = "+-${"-".repeat(labelWidth)}-+-${"-".repeat(valueWidth)}-+"
|
||||
val headerBorder = "+-${"-".repeat(labelWidth + valueWidth + 3)}-+"
|
||||
val header = "| ${padDisplay(headerText, labelWidth + valueWidth + 3)} |"
|
||||
|
||||
val content = rows.joinToString("\n") { (label, value) ->
|
||||
"| ${padDisplay(label, labelWidth)} | ${padDisplay(value, valueWidth)} |"
|
||||
}
|
||||
|
||||
return listOf(headerBorder, header, border, content, border).joinToString("\n")
|
||||
}.getOrDefault("${configuration.declaringClass.toStringIgnore()}\nFailed to build condition table.")
|
||||
|
||||
private val <T : Any> MemberCondition.Configuration<T>.currentProcessorResolver
|
||||
get() = processorResolver ?: globalResolver
|
||||
|
||||
private val Member.annotations get() = when (this) {
|
||||
is AnnotatedElement -> declaredAnnotations
|
||||
else -> error("Unsupported member type: $this")
|
||||
}
|
||||
|
||||
private fun Member.toGenericString() = when (this) {
|
||||
is Method -> toGenericString()
|
||||
is Constructor<*> -> toGenericString()
|
||||
is Field -> toGenericString()
|
||||
else -> error("Unsupported member type: $this")
|
||||
}
|
||||
|
||||
private fun <T : Any> Any.toTypeClass(configuration: MemberCondition.Configuration<T>, noVague: String? = null): Class<*> {
|
||||
fun Class<*>.parseVagueType() =
|
||||
if (this == classOf<VagueType>())
|
||||
noVague?.let { error("VagueType is not supported for \"$it\".") } ?: this
|
||||
else this
|
||||
|
||||
return when (this) {
|
||||
is Class<*> -> this
|
||||
is KClass<*> -> this.java
|
||||
is String -> if (configuration.optional == MemberCondition.Configuration.Optional.NO)
|
||||
toClass(configuration.declaringClass.classLoader)
|
||||
// If enabled optional mode, use the "Object.class" as the default return type when not found.
|
||||
else toClassOrNull(configuration.declaringClass.classLoader) ?: classOf<Any>()
|
||||
is VagueType -> javaClass
|
||||
else -> error("Unsupported type: $this, supported types are Class, KClass, String and VagueType.")
|
||||
}.parseVagueType()
|
||||
}
|
||||
|
||||
private fun Any.toStringIgnore() = toString().replace(" (Kotlin reflection is not available)", "")
|
||||
|
||||
private inline fun runOrElse(block: () -> Boolean) = runCatching(block).getOrDefault(false)
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* KavaRef - A modernizing Java Reflection with Kotlin.
|
||||
* Copyright (C) 2019 HighCapable
|
||||
* https://github.com/HighCapable/KavaRef
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2025/5/19.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.highcapable.kavaref.runtime
|
||||
|
||||
import android.util.Log
|
||||
import com.highcapable.kavaref.KavaRef
|
||||
import com.highcapable.kavaref.extension.hasClass
|
||||
import com.highcapable.kavaref.generated.KavarefCoreProperties
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* Runtime class for KavaRef logging.
|
||||
*/
|
||||
object KavaRefRuntime {
|
||||
|
||||
private const val TAG = KavarefCoreProperties.PROJECT_NAME
|
||||
|
||||
private val slf4jLogger by lazy { LoggerFactory.getLogger(TAG) }
|
||||
|
||||
private val isAndroidEnv by lazy {
|
||||
javaClass.classLoader.hasClass("android.os.Build")
|
||||
}
|
||||
|
||||
private var logger: Logger = DefaultLogger()
|
||||
|
||||
/**
|
||||
* Log levels for KavaRef.
|
||||
* @param levelName the name of the log level.
|
||||
*/
|
||||
enum class LogLevel(val levelName: String) {
|
||||
/** DEBUG */
|
||||
DEBUG("debug"),
|
||||
|
||||
/** INFO */
|
||||
INFO("info"),
|
||||
|
||||
/** WARN */
|
||||
WARN("warn"),
|
||||
|
||||
/** ERROR */
|
||||
ERROR("error"),
|
||||
|
||||
/** OFF (Turn off logging) */
|
||||
OFF("off")
|
||||
}
|
||||
|
||||
/**
|
||||
* Logger interface for KavaRef.
|
||||
*
|
||||
* You can implement this interface to create your own logger and set it to [KavaRef.setLogger].
|
||||
*/
|
||||
interface Logger {
|
||||
|
||||
/** Logger tag. */
|
||||
val tag: String
|
||||
|
||||
/**
|
||||
* Log a debug message.
|
||||
* @param msg the message to log.
|
||||
* @param throwable an optional throwable to log.
|
||||
*/
|
||||
fun debug(msg: Any?, throwable: Throwable? = null)
|
||||
|
||||
/**
|
||||
* Log an info message.
|
||||
* @param msg the message to log.
|
||||
* @param throwable an optional throwable to log.
|
||||
*/
|
||||
fun info(msg: Any?, throwable: Throwable? = null)
|
||||
|
||||
/**
|
||||
* Log a warning message.
|
||||
* @param msg the message to log.
|
||||
* @param throwable an optional throwable to log.
|
||||
*/
|
||||
fun warn(msg: Any?, throwable: Throwable? = null)
|
||||
|
||||
/**
|
||||
* Log an error message.
|
||||
* @param msg the message to log.
|
||||
* @param throwable an optional throwable to log.
|
||||
*/
|
||||
fun error(msg: Any?, throwable: Throwable? = null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Default logger implementation for KavaRef.
|
||||
*
|
||||
* This logger uses SLF4J for non-Android environments and Android Log for Android environments.
|
||||
*/
|
||||
private class DefaultLogger : Logger {
|
||||
|
||||
override val tag = TAG
|
||||
|
||||
override fun debug(msg: Any?, throwable: Throwable?) {
|
||||
if (!isAndroidEnv)
|
||||
slf4jLogger.debug(msg.toString(), throwable)
|
||||
else Log.d(TAG, msg.toString(), throwable)
|
||||
}
|
||||
|
||||
override fun info(msg: Any?, throwable: Throwable?) {
|
||||
if (!isAndroidEnv)
|
||||
slf4jLogger.info(msg.toString(), throwable)
|
||||
else Log.i(TAG, msg.toString(), throwable)
|
||||
}
|
||||
|
||||
override fun warn(msg: Any?, throwable: Throwable?) {
|
||||
if (!isAndroidEnv)
|
||||
slf4jLogger.warn(msg.toString(), throwable)
|
||||
else Log.w(TAG, msg.toString(), throwable)
|
||||
}
|
||||
|
||||
override fun error(msg: Any?, throwable: Throwable?) {
|
||||
if (!isAndroidEnv)
|
||||
slf4jLogger.error(msg.toString(), throwable)
|
||||
else Log.e(TAG, msg.toString(), throwable)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set the log level for KavaRef.
|
||||
*
|
||||
* Use [KavaRef.logLevel] to control it.
|
||||
* @see KavaRef.logLevel
|
||||
* @return [LogLevel]
|
||||
*/
|
||||
@get:JvmSynthetic
|
||||
@set:JvmSynthetic
|
||||
internal var logLevel = LogLevel.WARN
|
||||
set(value) {
|
||||
if (!isAndroidEnv)
|
||||
// Enable level for SLF4J.
|
||||
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", value.levelName)
|
||||
|
||||
field = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the logger for KavaRef.
|
||||
*
|
||||
* Use [KavaRef.setLogger] to control it.
|
||||
* @see KavaRef.setLogger
|
||||
* @param logger the logger to be set.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun setLogger(logger: Logger) {
|
||||
this.logger = logger
|
||||
}
|
||||
|
||||
init {
|
||||
// Initialize the log level to WARN if not set.
|
||||
logLevel = logLevel
|
||||
}
|
||||
|
||||
/**
|
||||
* DEBUG
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun debug(msg: Any?, throwable: Throwable? = null) {
|
||||
if (shouldLog(LogLevel.DEBUG)) logger.debug(msg, throwable)
|
||||
}
|
||||
|
||||
/**
|
||||
* INFO
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun info(msg: Any?, throwable: Throwable? = null) {
|
||||
if (shouldLog(LogLevel.INFO)) logger.info(msg, throwable)
|
||||
}
|
||||
|
||||
/**
|
||||
* WARN
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun warn(msg: Any?, throwable: Throwable? = null) {
|
||||
if (shouldLog(LogLevel.WARN)) logger.warn(msg, throwable)
|
||||
}
|
||||
|
||||
/**
|
||||
* ERROR
|
||||
*/
|
||||
@JvmSynthetic
|
||||
internal fun error(msg: Any?, throwable: Throwable? = null) {
|
||||
if (shouldLog(LogLevel.ERROR)) logger.error(msg, throwable)
|
||||
}
|
||||
|
||||
private fun shouldLog(level: LogLevel) = logLevel.ordinal <= level.ordinal
|
||||
}
|
||||
Reference in New Issue
Block a user