Skip to content

Commit 462fbe2

Browse files
committed
feat: Add constructor to initialize patches without annotations
1 parent 7aeae93 commit 462fbe2

File tree

7 files changed

+152
-22
lines changed

7 files changed

+152
-22
lines changed

api/revanced-patcher.api

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,14 @@ public abstract interface annotation class app/revanced/patcher/fingerprint/anno
234234

235235
public abstract class app/revanced/patcher/patch/BytecodePatch : app/revanced/patcher/patch/Patch {
236236
public fun <init> ()V
237+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZLjava/util/Set;)V
238+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZLjava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
237239
public fun <init> (Ljava/util/Set;)V
238240
public synthetic fun <init> (Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
239241
}
240242

241243
public abstract class app/revanced/patcher/patch/Patch {
244+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
242245
public fun equals (Ljava/lang/Object;)Z
243246
public abstract fun execute (Lapp/revanced/patcher/data/Context;)V
244247
public final fun getCompatiblePackages ()Ljava/util/Set;
@@ -272,6 +275,8 @@ public final class app/revanced/patcher/patch/PatchResult {
272275

273276
public abstract class app/revanced/patcher/patch/ResourcePatch : app/revanced/patcher/patch/Patch {
274277
public fun <init> ()V
278+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZ)V
279+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
275280
}
276281

277282
public abstract interface annotation class app/revanced/patcher/patch/annotation/CompatiblePackage : java/lang/annotation/Annotation {

src/main/kotlin/app/revanced/patcher/PatchBundleLoader.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import java.util.jar.JarFile
1212
import java.util.logging.Logger
1313
import kotlin.reflect.KClass
1414

15+
1516
/**
1617
* A set of [Patch]es.
1718
*/
@@ -73,7 +74,7 @@ sealed class PatchBundleLoader private constructor(
7374
if (!silent) {
7475
logger.fine(
7576
"Patch class '$name' has no INSTANCE field, therefor not a singleton. " +
76-
"Will try to instantiate it.",
77+
"Attempting to instantiate it.",
7778
)
7879
}
7980

@@ -83,7 +84,7 @@ sealed class PatchBundleLoader private constructor(
8384
if (!silent) {
8485
logger.severe(
8586
"Patch class '$name' is not singleton and has no suitable constructor, " +
86-
"therefor cannot be instantiated and will be ignored.",
87+
"therefor cannot be instantiated and is ignored.",
8788
)
8889
}
8990

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,61 @@
11
package app.revanced.patcher.patch
22

3+
import app.revanced.patcher.PatchClass
4+
import app.revanced.patcher.Patcher
35
import app.revanced.patcher.data.BytecodeContext
46
import app.revanced.patcher.fingerprint.MethodFingerprint
7+
import java.io.Closeable
58

69
/**
7-
* A ReVanced [Patch] that works on [BytecodeContext].
10+
* A ReVanced [Patch] that accesses a [BytecodeContext].
811
*
9-
* @param fingerprints A list of [MethodFingerprint]s which will be resolved before the patch is executed.
12+
* If an implementation of [Patch] also implements [Closeable]
13+
* it will be closed in reverse execution order of patches executed by ReVanced [Patcher].
1014
*/
11-
abstract class BytecodePatch(
12-
internal val fingerprints: Set<MethodFingerprint> = emptySet(),
13-
) : Patch<BytecodeContext>()
15+
@Suppress("unused")
16+
abstract class BytecodePatch : Patch<BytecodeContext> {
17+
/**
18+
* The fingerprints to resolve before executing the patch.
19+
*/
20+
internal val fingerprints: Set<MethodFingerprint>
21+
22+
/**
23+
* Create a new [BytecodePatch].
24+
*
25+
* @param fingerprints The fingerprints to resolve before executing the patch.
26+
*/
27+
constructor(fingerprints: Set<MethodFingerprint> = emptySet()) {
28+
this.fingerprints = fingerprints
29+
}
30+
31+
/**
32+
* Create a new [BytecodePatch].
33+
*
34+
* @param name The name of the patch.
35+
* @param description The description of the patch.
36+
* @param compatiblePackages The packages the patch is compatible with.
37+
* @param dependencies Other patches this patch depends on.
38+
* @param use Weather or not the patch should be used.
39+
* @param requiresIntegrations Weather or not the patch requires integrations.
40+
*/
41+
constructor(
42+
name: String? = null,
43+
description: String? = null,
44+
compatiblePackages: Set<CompatiblePackage>? = null,
45+
dependencies: Set<PatchClass>? = null,
46+
use: Boolean = true,
47+
requiresIntegrations: Boolean = false,
48+
fingerprints: Set<MethodFingerprint> = emptySet(),
49+
) : super(name, description, compatiblePackages, dependencies, use, requiresIntegrations) {
50+
this.fingerprints = fingerprints
51+
}
52+
53+
/**
54+
* Create a new [BytecodePatch].
55+
*/
56+
@Deprecated(
57+
"Use the constructor with fingerprints instead.",
58+
ReplaceWith("BytecodePatch(emptySet())"),
59+
)
60+
constructor() : this(emptySet())
61+
}

src/main/kotlin/app/revanced/patcher/patch/Patch.kt

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import app.revanced.patcher.data.Context
88
import app.revanced.patcher.extensions.AnnotationExtensions.findAnnotationRecursively
99
import app.revanced.patcher.patch.options.PatchOptions
1010
import java.io.Closeable
11-
import app.revanced.patcher.patch.annotation.Patch as PatchAnnotation
1211

1312
/**
1413
* A ReVanced patch.
14+
*
1515
* If an implementation of [Patch] also implements [Closeable]
1616
* it will be closed in reverse execution order of patches executed by ReVanced [Patcher].
1717
*
@@ -55,25 +55,41 @@ sealed class Patch<out T : Context<*>> {
5555
var requiresIntegrations = false
5656
private set
5757

58-
/**
59-
* The options of the patch associated by the options key.
60-
*/
61-
val options = PatchOptions()
58+
constructor(
59+
name: String?,
60+
description: String?,
61+
compatiblePackages: Set<CompatiblePackage>?,
62+
dependencies: Set<PatchClass>?,
63+
use: Boolean,
64+
requiresIntegrations: Boolean,
65+
) {
66+
this.name = name
67+
this.description = description
68+
this.compatiblePackages = compatiblePackages
69+
this.dependencies = dependencies
70+
this.use = use
71+
this.requiresIntegrations = requiresIntegrations
72+
}
6273

63-
init {
64-
this::class.findAnnotationRecursively(PatchAnnotation::class)?.let { annotation ->
65-
name = annotation.name.ifEmpty { null }
66-
description = annotation.description.ifEmpty { null }
67-
compatiblePackages =
74+
constructor() {
75+
this::class.findAnnotationRecursively(app.revanced.patcher.patch.annotation.Patch::class)?.let { annotation ->
76+
this.name = annotation.name.ifEmpty { null }
77+
this.description = annotation.description.ifEmpty { null }
78+
this.compatiblePackages =
6879
annotation.compatiblePackages
6980
.map { CompatiblePackage(it.name, it.versions.toSet().ifEmpty { null }) }
7081
.toSet().ifEmpty { null }
71-
dependencies = annotation.dependencies.toSet().ifEmpty { null }
72-
use = annotation.use
73-
requiresIntegrations = annotation.requiresIntegrations
82+
this.dependencies = annotation.dependencies.toSet().ifEmpty { null }
83+
this.use = annotation.use
84+
this.requiresIntegrations = annotation.requiresIntegrations
7485
}
7586
}
7687

88+
/**
89+
* The options of the patch associated by the options key.
90+
*/
91+
val options = PatchOptions()
92+
7793
/**
7894
* The execution function of the patch.
7995
*
Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,38 @@
11
package app.revanced.patcher.patch
22

3+
import app.revanced.patcher.PatchClass
4+
import app.revanced.patcher.Patcher
35
import app.revanced.patcher.data.ResourceContext
6+
import java.io.Closeable
47

58
/**
6-
* A ReVanced [Patch] that works on [ResourceContext].
9+
* A ReVanced [Patch] that accesses a [ResourceContext].
10+
*
11+
* If an implementation of [Patch] also implements [Closeable]
12+
* it will be closed in reverse execution order of patches executed by ReVanced [Patcher].
713
*/
8-
abstract class ResourcePatch : Patch<ResourceContext>()
14+
abstract class ResourcePatch : Patch<ResourceContext> {
15+
/**
16+
* Create a new [ResourcePatch].
17+
*/
18+
constructor()
19+
20+
/**
21+
* Create a new [ResourcePatch].
22+
*
23+
* @param name The name of the patch.
24+
* @param description The description of the patch.
25+
* @param compatiblePackages The packages the patch is compatible with.
26+
* @param dependencies Other patches this patch depends on.
27+
* @param use Weather or not the patch should be used.
28+
* @param requiresIntegrations Weather or not the patch requires integrations.
29+
*/
30+
constructor(
31+
name: String? = null,
32+
description: String? = null,
33+
compatiblePackages: Set<CompatiblePackage>? = null,
34+
dependencies: Set<PatchClass>? = null,
35+
use: Boolean = true,
36+
requiresIntegrations: Boolean = false,
37+
) : super(name, description, compatiblePackages, dependencies, use, requiresIntegrations)
38+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package app.revanced.patcher.patch
2+
3+
import app.revanced.patcher.data.ResourceContext
4+
import org.junit.jupiter.api.assertThrows
5+
import kotlin.test.Test
6+
import app.revanced.patcher.patch.annotation.Patch as PatchAnnotation
7+
8+
object PatchInitializationTest {
9+
@Test
10+
fun `initialize using constructor`() {
11+
val patch =
12+
object : ResourcePatch(name = "Resource patch test") {
13+
override fun execute(context: ResourceContext) {}
14+
}
15+
16+
assert(patch.name == "Resource patch test")
17+
}
18+
19+
@Test
20+
fun `initialize using annotation`() {
21+
val patch =
22+
@PatchAnnotation("Resource patch test")
23+
object : ResourcePatch() {
24+
override fun execute(context: ResourceContext) {}
25+
}
26+
27+
assert(patch.name == "Resource patch test")
28+
}
29+
}

src/test/kotlin/app/revanced/patcher/patch/options/PatchOptionsTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ internal class PatchOptionsTest {
9090
@Test
9191
fun `getting default value should work`() = assertDoesNotThrow { assertNull(OptionsTestPatch.resettableOption.default) }
9292

93+
@Suppress("DEPRECATION")
9394
private object OptionsTestPatch : BytecodePatch() {
9495
var booleanOption by booleanPatchOption(
9596
"bool",

0 commit comments

Comments
 (0)