mirror of
https://github.com/revanced/revanced-patcher.git
synced 2025-05-09 16:44:25 +02:00
feat: Retrieve annotations in super and interface classes
This commit is contained in:
parent
f1de9b39ef
commit
7aeae93f3d
@ -1,35 +1,61 @@
|
|||||||
|
@file:Suppress("UNCHECKED_CAST")
|
||||||
|
|
||||||
package app.revanced.patcher.extensions
|
package app.revanced.patcher.extensions
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
internal object AnnotationExtensions {
|
internal object AnnotationExtensions {
|
||||||
/**
|
/**
|
||||||
* Search for an annotation recursively.
|
* Search for an annotation recursively.
|
||||||
*
|
*
|
||||||
|
* @param targetAnnotationClass The annotation class to search for.
|
||||||
|
* @param searchedClasses A set of annotations that have already been searched.
|
||||||
|
* @return The annotation if found, otherwise null.
|
||||||
|
*/
|
||||||
|
fun <T : Annotation> Class<*>.findAnnotationRecursively(
|
||||||
|
targetAnnotationClass: Class<T>,
|
||||||
|
searchedClasses: HashSet<Annotation> = hashSetOf(),
|
||||||
|
): T? {
|
||||||
|
annotations.forEach { annotation ->
|
||||||
|
// Terminate if the annotation is already searched.
|
||||||
|
if (annotation in searchedClasses) return@forEach
|
||||||
|
searchedClasses.add(annotation)
|
||||||
|
|
||||||
|
// Terminate if the annotation is found.
|
||||||
|
if (targetAnnotationClass == annotation.annotationClass.java) return annotation as T
|
||||||
|
|
||||||
|
return annotation.annotationClass.java.findAnnotationRecursively(
|
||||||
|
targetAnnotationClass,
|
||||||
|
searchedClasses,
|
||||||
|
) ?: return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the super class.
|
||||||
|
superclass?.findAnnotationRecursively(
|
||||||
|
targetAnnotationClass,
|
||||||
|
searchedClasses,
|
||||||
|
)?.let { return it }
|
||||||
|
|
||||||
|
// Search the interfaces.
|
||||||
|
interfaces.forEach { superClass ->
|
||||||
|
return superClass.findAnnotationRecursively(
|
||||||
|
targetAnnotationClass,
|
||||||
|
searchedClasses,
|
||||||
|
) ?: return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for an annotation recursively.
|
||||||
|
*
|
||||||
|
* First the annotations, then the annotated classes super class and then it's interfaces
|
||||||
|
* are searched for the annotation recursively.
|
||||||
|
*
|
||||||
* @param targetAnnotation The annotation to search for.
|
* @param targetAnnotation The annotation to search for.
|
||||||
* @return The annotation if found, otherwise null.
|
* @return The annotation if found, otherwise null.
|
||||||
*/
|
*/
|
||||||
fun <T : Annotation> Class<*>.findAnnotationRecursively(targetAnnotation: Class<T>): T? {
|
fun <T : Annotation> KClass<*>.findAnnotationRecursively(targetAnnotation: KClass<T>) =
|
||||||
fun <T : Annotation> Class<*>.findAnnotationRecursively(
|
java.findAnnotationRecursively(targetAnnotation.java)
|
||||||
targetAnnotation: Class<T>,
|
|
||||||
searchedAnnotations: HashSet<Annotation>,
|
|
||||||
): T? {
|
|
||||||
val found = this.annotations.firstOrNull { it.annotationClass.java.name == targetAnnotation.name }
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
if (found != null) return found as T
|
|
||||||
|
|
||||||
for (annotation in this.annotations) {
|
|
||||||
if (searchedAnnotations.contains(annotation)) continue
|
|
||||||
searchedAnnotations.add(annotation)
|
|
||||||
|
|
||||||
return annotation.annotationClass.java.findAnnotationRecursively(
|
|
||||||
targetAnnotation,
|
|
||||||
searchedAnnotations
|
|
||||||
) ?: continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.findAnnotationRecursively(targetAnnotation, hashSetOf())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ object MethodFingerprintExtensions {
|
|||||||
*/
|
*/
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
message = "Use the property instead.",
|
message = "Use the property instead.",
|
||||||
replaceWith = ReplaceWith("this.fuzzyPatternScanMethod")
|
replaceWith = ReplaceWith("this.fuzzyPatternScanMethod"),
|
||||||
)
|
)
|
||||||
val MethodFingerprint.fuzzyPatternScanMethod
|
val MethodFingerprint.fuzzyPatternScanMethod
|
||||||
get() = this.fuzzyPatternScanMethod
|
get() = this.fuzzyPatternScanMethod
|
||||||
|
@ -48,7 +48,7 @@ abstract class MethodFingerprint(
|
|||||||
*
|
*
|
||||||
* If the annotation is not present, this property is null.
|
* If the annotation is not present, this property is null.
|
||||||
*/
|
*/
|
||||||
val fuzzyPatternScanMethod = javaClass.findAnnotationRecursively(FuzzyPatternScanMethod::class.java)
|
val fuzzyPatternScanMethod = this::class.findAnnotationRecursively(FuzzyPatternScanMethod::class)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a [MethodFingerprint] using the lookup map built by [initializeLookupMaps].
|
* Resolve a [MethodFingerprint] using the lookup map built by [initializeLookupMaps].
|
||||||
|
@ -5,9 +5,10 @@ package app.revanced.patcher.patch
|
|||||||
import app.revanced.patcher.PatchClass
|
import app.revanced.patcher.PatchClass
|
||||||
import app.revanced.patcher.Patcher
|
import app.revanced.patcher.Patcher
|
||||||
import app.revanced.patcher.data.Context
|
import app.revanced.patcher.data.Context
|
||||||
|
import app.revanced.patcher.extensions.AnnotationExtensions.findAnnotationRecursively
|
||||||
import app.revanced.patcher.patch.options.PatchOptions
|
import app.revanced.patcher.patch.options.PatchOptions
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import kotlin.reflect.full.findAnnotation
|
import app.revanced.patcher.patch.annotation.Patch as PatchAnnotation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ReVanced patch.
|
* A ReVanced patch.
|
||||||
@ -60,7 +61,7 @@ sealed class Patch<out T : Context<*>> {
|
|||||||
val options = PatchOptions()
|
val options = PatchOptions()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this::class.findAnnotation<app.revanced.patcher.patch.annotation.Patch>()?.let { annotation ->
|
this::class.findAnnotationRecursively(PatchAnnotation::class)?.let { annotation ->
|
||||||
name = annotation.name.ifEmpty { null }
|
name = annotation.name.ifEmpty { null }
|
||||||
description = annotation.description.ifEmpty { null }
|
description = annotation.description.ifEmpty { null }
|
||||||
compatiblePackages =
|
compatiblePackages =
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package app.revanced.patcher.extensions
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.AnnotationExtensions.findAnnotationRecursively
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertNotNull
|
||||||
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
|
private object AnnotationExtensionsTest {
|
||||||
|
@Test
|
||||||
|
fun `find annotation in annotated class`() {
|
||||||
|
assertNotNull(TestClasses.Annotation2::class.findAnnotationRecursively(TestClasses.Annotation::class))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `find annotation`() {
|
||||||
|
assertNotNull(TestClasses.AnnotatedClass::class.findAnnotationRecursively(TestClasses.Annotation::class))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `find annotation recursively in super class`() {
|
||||||
|
assertNotNull(TestClasses.AnnotatedClass2::class.findAnnotationRecursively(TestClasses.Annotation::class))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `find annotation recursively in super class with annotation`() {
|
||||||
|
assertNotNull(TestClasses.AnnotatedTestClass3::class.findAnnotationRecursively(TestClasses.Annotation::class))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `don't find unknown annotation in annotated class`() {
|
||||||
|
assertNull(TestClasses.AnnotatedClass::class.findAnnotationRecursively(TestClasses.UnknownAnnotation::class))
|
||||||
|
}
|
||||||
|
|
||||||
|
object TestClasses {
|
||||||
|
annotation class Annotation
|
||||||
|
|
||||||
|
@Annotation
|
||||||
|
annotation class Annotation2
|
||||||
|
|
||||||
|
annotation class UnknownAnnotation
|
||||||
|
|
||||||
|
@Annotation
|
||||||
|
abstract class AnnotatedClass
|
||||||
|
|
||||||
|
@Annotation2
|
||||||
|
class AnnotatedTestClass3
|
||||||
|
|
||||||
|
abstract class AnnotatedClass2 : AnnotatedClass()
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user