Skip to content

Commit

Permalink
[1.0.17] Fix Annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
Bkm016 committed Aug 6, 2022
1 parent 899cf68 commit 4523bfe
Show file tree
Hide file tree
Showing 16 changed files with 211 additions and 31 deletions.
26 changes: 17 additions & 9 deletions analyser/src/main/kotlin/org/tabooproject/reflex/ClassAnalyser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,24 @@ object ClassAnalyser {

fun analyse(clazz: Class<*>): ClassStructure {
return try {
val annotations = clazz.declaredAnnotations.map { InstantAnnotation(it) }
val fields = clazz.declaredFields.map { InstantClassField(clazz, it) }
val methods = clazz.declaredMethods.map { InstantClassMethod(clazz, it) }
val constructors = clazz.declaredConstructors.map { InstantClassConstructor(clazz, it) }
JavaClassStructure(clazz, annotations, fields, methods, constructors)
analyseByReflection(clazz)
} catch (ex: NoClassDefFoundError) {
val classReader = ClassReader(Objects.requireNonNull(clazz.getResourceAsStream("/${clazz.name.replace('.', '/')}.class")))
val analyser = AsmClassVisitor(clazz, ClassWriter(ClassWriter.COMPUTE_MAXS))
classReader.accept(analyser, ClassReader.SKIP_DEBUG)
JavaClassStructure(clazz, analyser.annotations, analyser.fields, analyser.methods, analyser.constructors)
analyseByASM(clazz)
}
}

fun analyseByReflection(clazz: Class<*>): JavaClassStructure {
val annotations = clazz.declaredAnnotations.map { InstantAnnotation(it) }
val fields = clazz.declaredFields.map { InstantClassField(clazz, it) }
val methods = clazz.declaredMethods.map { InstantClassMethod(clazz, it) }
val constructors = clazz.declaredConstructors.map { InstantClassConstructor(clazz, it) }
return JavaClassStructure(clazz, annotations, fields, methods, constructors)
}

fun analyseByASM(clazz: Class<*>): JavaClassStructure {
val classReader = ClassReader(Objects.requireNonNull(clazz.getResourceAsStream("/${clazz.name.replace('.', '/')}.class")))
val analyser = AsmClassVisitor(clazz, ClassWriter(ClassWriter.COMPUTE_MAXS))
classReader.accept(analyser, ClassReader.SKIP_DEBUG)
return JavaClassStructure(clazz, analyser.annotations, analyser.fields, analyser.methods, analyser.constructors)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ abstract class ClassAnnotation(val source: LazyClass) {

abstract fun <T> property(name: String): T?

abstract fun <T> property(name: String, def: T): T

abstract fun properties(): Map<String, Any>

abstract fun propertyKeys(): Set<String>
Expand All @@ -18,6 +20,12 @@ abstract class ClassAnnotation(val source: LazyClass) {
return if (value is LazyEnum) value.instance as T else value as T
}

@Suppress("UNCHECKED_CAST")
fun <T> enum(name: String, def: Any): T {
val value = property(name, def)
return if (value is LazyEnum) value.instance as T else value as T
}

override fun toString(): String {
return "ClassAnnotation(source=$source, properties=${propertyKeys()})"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ abstract class ClassMember(val name: String, val owner: Class<*>) {

abstract val isStatic: Boolean

fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation? {
return annotations.firstOrNull { it.source.name == annotation.name }
fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation {
return annotations.first { it.source.name == annotation.name }
}

fun isAnnotationPresent(annotation: Class<out Annotation>): Boolean {
return getAnnotation(annotation) != null
return annotations.any { it.source.name == annotation.name }
}

override fun toString(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,9 @@ abstract class ClassStructure(

abstract fun getConstructorByTypeSilently(vararg parameter: Class<*>): ClassConstructor?

abstract fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation?
abstract fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation

fun isAnnotationPresent(annotation: Class<out Annotation>): Boolean {
return getAnnotation(annotation) != null
}
abstract fun isAnnotationPresent(annotation: Class<out Annotation>): Boolean

override fun toString(): String {
return "ClassStructure(owner=$owner, fields=$fields, methods=$methods, constructors=$constructors)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ class JavaClassStructure(
return kotlin.runCatching { getConstructorByType(*parameter) }.getOrNull()
}

override fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation? {
return annotations.firstOrNull { it.source.name == annotation.name }
override fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation {
return annotations.first { it.source.name == annotation.name }
}

override fun isAnnotationPresent(annotation: Class<out Annotation>): Boolean {
return annotations.any { it.source.name == annotation.name }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ package org.tabooproject.reflex
@Internal
open class LazyAnnotatedClass(name: String, val annotations: List<ClassAnnotation>): LazyClass(name) {

fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation? {
return annotations.firstOrNull { it.source.name == annotation.name }
fun getAnnotation(annotation: Class<out Annotation>): ClassAnnotation {
return annotations.first { it.source.name == annotation.name }
}

fun isAnnotationPresent(annotation: Class<out Annotation>): Boolean {
return annotations.any { it.source.name == annotation.name }
}

override fun toString(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class AsmAnnotation(val annotationVisitor: AsmClassAnnotationVisitor) : ClassAnn
return annotationVisitor.map[name] as? T?
}

override fun <T> property(name: String, def: T): T {
return property(name) ?: def
}

override fun properties(): Map<String, Any> {
return annotationVisitor.map
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,20 @@ class AsmClassAnnotationVisitor(val descriptor: String, annotationVisitor: Annot
}

override fun visitAnnotation(name: String?, descriptor: String): AnnotationVisitor {
name ?: return super.visitAnnotation(null, descriptor)
return AsmClassAnnotationVisitor(descriptor, super.visitAnnotation(name, descriptor)).apply { this@AsmClassAnnotationVisitor.map[name] = this }
return AsmClassAnnotationVisitor(descriptor, super.visitAnnotation(name, descriptor)).apply {
if (name != null) {
this@AsmClassAnnotationVisitor.map[name] = this
}
}

}

override fun visitArray(name: String?): AnnotationVisitor {
name ?: return super.visitArray(null)
return AsmClassAnnotationVisitor(descriptor, super.visitArray(name), true).apply { this@AsmClassAnnotationVisitor.map[name] = array }
return AsmClassAnnotationVisitor(descriptor, super.visitArray(name), true).apply {
if (name != null) {
this@AsmClassAnnotationVisitor.map[name] = array
}
}
}

fun toAnnotation(): AsmAnnotation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class InstantAnnotation(val annotation: Annotation) : ClassAnnotation(InstantCla
return methods[name]?.invoke(annotation) as? T
}

override fun <T> property(name: String, def: T): T {
return property(name) ?: def
}

override fun properties(): Map<String, Any> {
return methods.mapValues { it.value.invoke(annotation) }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.tabooproject.reflex

import org.junit.jupiter.api.Test
import org.tabooproject.reflex.res.EventPriority
import org.tabooproject.reflex.res.SubscribeEvent

/**
* Reflex
* org.tabooproject.reflex.AnalyserTestAnnotation
*
* @author 坏黑
* @since 2022/8/6 14:47
*/
class AnalyserTestAnnotation {

@SubscribeEvent(priority = EventPriority.HIGH)
fun event() {
}

@Test
fun testKotlinReflect() {
val analyser = ClassAnalyser.analyseByASM(AnalyserTestAnnotation::class.java)
val method = analyser.getMethod("event")
assert(method.getAnnotation(SubscribeEvent::class.java).properties().size == 1)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,42 +152,42 @@ class AnalyserTestAsm {

@Test
fun testClassAnnotationGet1() {
val annotation = analyse.getAnnotation(AnalyserAnnotation::class.java)!!
val annotation = analyse.getAnnotation(AnalyserAnnotation::class.java)
assert(annotation is AsmAnnotation)
assert(annotation.property<String>("value") == "test1")
}

@Test
fun testClassAnnotationGet2() {
val annotation = analyse.getField("range").getAnnotation(AnalyserAnnotation::class.java)!!
val annotation = analyse.getField("range").getAnnotation(AnalyserAnnotation::class.java)
assert(annotation is AsmAnnotation)
assert(annotation.property<String>("value") == "test2")
}

@Test
fun testClassAnnotationGet3() {
val annotation = analyse.getConstructor().getAnnotation(AnalyserAnnotation::class.java)!!
val annotation = analyse.getConstructor().getAnnotation(AnalyserAnnotation::class.java)
assert(annotation is AsmAnnotation)
assert(annotation.property<String>("value") == "test3")
}

@Test
fun testClassAnnotationGet4() {
val annotation = analyse.getMethod("method", 0).getAnnotation(AnalyserAnnotation::class.java)!!
val annotation = analyse.getMethod("method", 0).getAnnotation(AnalyserAnnotation::class.java)
assert(annotation is AsmAnnotation)
assert(annotation.property<String>("value") == "test4")
}

@Test
fun testClassAnnotationGet5() {
val annotation = analyse.getMethod("method", 0).parameter[0].getAnnotation(AnalyserAnnotation::class.java)!!
val annotation = analyse.getMethod("method", 0).parameter[0].getAnnotation(AnalyserAnnotation::class.java)
assert(annotation is AsmAnnotation)
assert(annotation.property<String>("value") == "test5")
}

@Test
fun testClassAnnotationGetEnum() {
val annotation = analyse.getAnnotation(AnalyserAnnotation::class.java)!!
val annotation = analyse.getAnnotation(AnalyserAnnotation::class.java)
assert(annotation is AsmAnnotation)
assert(annotation.enum<AnalyserAnnotation.Test>("type") == AnalyserAnnotation.Test.C)
}
Expand Down
71 changes: 71 additions & 0 deletions analyser/src/test/kotlin/org/tabooproject/reflex/res/EventOrder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.tabooproject.reflex.res

/**
* Sponge Only
*
* TabooLib
* org.tabooproject.reflex.res.EventOrder
*
* @author sky
* @since 2021/6/21 6:24 下午
*/
enum class EventOrder {

/**
* The order point of PRE handles setting up things that need to be done
* before other things are handled PRE is read only and cannot cancel the
* events.
*/
PRE,

/**
* The order point of AFTER_PRE handles things that need to be done after
* PRE AFTER_PRE is read only and cannot cancel the events.
*/
AFTER_PRE,

/**
* The order point of FIRST handles cancellation by protection plugins for
* informational responses FIRST is read only but can cancel events.
*/
FIRST,

/**
* The order point of EARLY handles standard actions that need to be done
* before other plugins EARLY is not read only and can cancel events.
*/
EARLY,

/**
* The order point of DEFAULT handles just standard event handlings, you
* should use this unless you know you need otherwise DEFAULT is not read
* only and can cancel events.
*/
DEFAULT,

/**
* The order point of LATE handles standard actions that need to be done
* after other plugins LATE is not read only and can cancel the event.
*/
LATE,

/**
* The order point of LAST handles last minute cancellations by protection
* plugins LAST is read only but can cancel events.
*/
LAST,

/**
* The order point of BEFORE_POST handles preparation for things needing
* to be done in post BEFORE_POST is read only and cannot cancel events.
*/
BEFORE_POST,

/**
* The order point of POST handles last minute things and monitoring
* of events for rollback or logging POST is read only and
* cannot cancel events.</p>
*/
POST

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.tabooproject.reflex.res

/**
* TabooLib
* org.tabooproject.reflex.res.EventPriority
*
* @author sky
* @since 2021/6/16 1:07 上午
*/
enum class EventPriority(val level: Int) {

LOWEST(-64), LOW(-32), NORMAL(0), HIGH(32), HIGHEST(64), MONITOR(128)
}
13 changes: 13 additions & 0 deletions analyser/src/test/kotlin/org/tabooproject/reflex/res/PostOrder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.tabooproject.reflex.res

/**
* TabooLib
* org.tabooproject.reflex.res.PostOrder
*
* @author sky
* @since 2021/7/2 11:26 下午
*/
enum class PostOrder {

FIRST, EARLY, NORMAL, LATE, LAST
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.tabooproject.reflex.res

import org.tabooproject.reflex.res.EventOrder
import org.tabooproject.reflex.res.EventPriority
import org.tabooproject.reflex.res.PostOrder

@Target(AnnotationTarget.FUNCTION)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class SubscribeEvent(
val priority: EventPriority = EventPriority.NORMAL,
val ignoreCancelled: Boolean = false,
// only bungeecord platform
val level: Int = -1,
// only velocity
val postOrder: PostOrder = PostOrder.NORMAL,
// only sponge platform
val order: EventOrder = EventOrder.DEFAULT,
val beforeModifications: Boolean = false,
// optional event
val bind: String = ""
)
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group=org.tabooproject.reflex
version=1.0.15
version=1.0.17
kotlin.incremental=true
kotlin.incremental.java=true
kotlin.caching.enabled=true
Expand Down

0 comments on commit 4523bfe

Please sign in to comment.