You've already forked revanced-patcher
mirror of
https://github.com/revanced/revanced-patcher
synced 2025-09-06 16:38:50 +02:00
Compare commits
49 Commits
v15.0.0-de
...
v16.0.1-de
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fdaf9c21c8 | ||
![]() |
06c2b76f11 | ||
![]() |
3896b30738 | ||
![]() |
2c4b88e1a0 | ||
![]() |
dfc7e1596b | ||
![]() |
f590436399 | ||
![]() |
cbfb9ba02f | ||
![]() |
b4cfe80ad5 | ||
![]() |
b37906fa35 | ||
![]() |
356f1f1553 | ||
![]() |
e882af74ee | ||
![]() |
46875fb28e | ||
![]() |
417c3e4234 | ||
![]() |
6d2c28807b | ||
![]() |
4d6e08a650 | ||
![]() |
5cebc1fd30 | ||
![]() |
ac61731dc6 | ||
![]() |
9e4ffabd5c | ||
![]() |
3f410bd39f | ||
![]() |
d51bc32e37 | ||
![]() |
b7f6aa94cc | ||
![]() |
ff965e6953 | ||
![]() |
468d5d7421 | ||
![]() |
fc95b28c49 | ||
![]() |
69184187d9 | ||
![]() |
a802d0df46 | ||
![]() |
8de30633ae | ||
![]() |
a1fbb7990f | ||
![]() |
aa71146b1b | ||
![]() |
9fdb8f087f | ||
![]() |
670f0153de | ||
![]() |
1d7aeca696 | ||
![]() |
4e7811ea07 | ||
![]() |
e11283744a | ||
![]() |
91cdfd53ef | ||
![]() |
bc7d6b9941 | ||
![]() |
6b1e0a1656 | ||
![]() |
72c9eb2129 | ||
![]() |
4bc4b0dc01 | ||
![]() |
637d48746f | ||
![]() |
9a109c129b | ||
![]() |
d49e4ee5ea | ||
![]() |
30f0ea29a3 | ||
![]() |
49930f6565 | ||
![]() |
909d89fa8d | ||
![]() |
81d1d7f544 | ||
![]() |
67b7dff67a | ||
![]() |
4b76d19596 | ||
![]() |
080fbe9feb |
6
.github/workflows/pull_request.yml
vendored
6
.github/workflows/pull_request.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: PR to main
|
||||
name: Open a PR to main
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
MESSAGE: merge branch `${{ github.head_ref || github.ref_name }}` to `main`
|
||||
MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main`
|
||||
|
||||
jobs:
|
||||
pull-request:
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Open pull request
|
||||
uses: repo-sync/pull-request@v2
|
||||
with:
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Make sure the release step uses its own credentials:
|
||||
# https://github.com/cycjimmy/semantic-release-action#private-packages
|
||||
|
164
CHANGELOG.md
164
CHANGELOG.md
@@ -1,3 +1,167 @@
|
||||
## [16.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v16.0.0...v16.0.1-dev.1) (2023-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Merge integrations when required ([06c2b76](https://github.com/ReVanced/revanced-patcher/commit/06c2b76f11ac1bfe43d51d54d425e7577ecefdf6))
|
||||
|
||||
# [16.0.0](https://github.com/ReVanced/revanced-patcher/compare/v15.0.3...v16.0.0) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use correct super class type ([f590436](https://github.com/ReVanced/revanced-patcher/commit/f590436399f6385c51cea54618251b5d823c31f9))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This changes the super classes of some `PatchOptionException` classes
|
||||
|
||||
# [16.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.3...v16.0.0-dev.1) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use correct super class type ([f590436](https://github.com/ReVanced/revanced-patcher/commit/f590436399f6385c51cea54618251b5d823c31f9))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This changes the super classes of some `PatchOptionException` classes
|
||||
|
||||
## [15.0.3](https://github.com/ReVanced/revanced-patcher/compare/v15.0.2...v15.0.3) (2023-10-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix SMALI compilation on devices with RTL language ([#242](https://github.com/ReVanced/revanced-patcher/issues/242)) ([356f1f1](https://github.com/ReVanced/revanced-patcher/commit/356f1f155348347a8f318a2e024716ebf4fec99b))
|
||||
|
||||
## [15.0.3-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.2...v15.0.3-dev.1) (2023-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix SMALI compilation on devices with RTL language ([#242](https://github.com/ReVanced/revanced-patcher/issues/242)) ([356f1f1](https://github.com/ReVanced/revanced-patcher/commit/356f1f155348347a8f318a2e024716ebf4fec99b))
|
||||
|
||||
## [15.0.2](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2) (2023-09-27)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](https://github.com/ReVanced/revanced-patcher/commit/4d6e08a650dde6ec2e18611c5db1ab92b9a61dd1))
|
||||
|
||||
## [15.0.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2-dev.1) (2023-09-26)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](https://github.com/ReVanced/revanced-patcher/commit/4d6e08a650dde6ec2e18611c5db1ab92b9a61dd1))
|
||||
|
||||
## [15.0.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1) (2023-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Remove log management ([d51bc32](https://github.com/ReVanced/revanced-patcher/commit/d51bc32e37a865194c3825471085b3ccf8c78421))
|
||||
|
||||
## [15.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1-dev.1) (2023-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Remove log management ([d51bc32](https://github.com/ReVanced/revanced-patcher/commit/d51bc32e37a865194c3825471085b3ccf8c78421))
|
||||
|
||||
# [15.0.0](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0) (2023-09-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Account for source patch dependency for tests ([6918418](https://github.com/ReVanced/revanced-patcher/commit/69184187d90f126478d2f49415c1e3381217557f))
|
||||
* Always make the generated patch depend on the source patch ([8de3063](https://github.com/ReVanced/revanced-patcher/commit/8de30633ae6eb7acf7f0a351e26d4a6c2fdbdfec))
|
||||
* Catch correct exception ([637d487](https://github.com/ReVanced/revanced-patcher/commit/637d48746ff8694e01c5aead1c75a9a1efeb5ac8))
|
||||
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](https://github.com/ReVanced/revanced-patcher/commit/9a109c129b135a634be1aad4130a06d9e8e96ecd))
|
||||
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](https://github.com/ReVanced/revanced-patcher/commit/e11283744a21fe2d09435e99d6924462b6aac3b8))
|
||||
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](https://github.com/ReVanced/revanced-patcher/commit/6b1e0a16568124e9f82fb5740353360fa8ec614a))
|
||||
* Filter for patches correctly ([4bc4b0d](https://github.com/ReVanced/revanced-patcher/commit/4bc4b0dc0104073b62528d02a88383cecd7a50e7))
|
||||
* Find dependency in `context.allPatches` ([670f015](https://github.com/ReVanced/revanced-patcher/commit/670f0153de10c6f0db25b08df1c01a2905037f84))
|
||||
* Log the correct patch names ([9fdb8f0](https://github.com/ReVanced/revanced-patcher/commit/9fdb8f087f62babf6081879db65c80db639aa0a7))
|
||||
* Make `CompatiblePackage.versions` a property ([67b7dff](https://github.com/ReVanced/revanced-patcher/commit/67b7dff67a212b4fc30eb4f0cbe58f0ba09fb09a))
|
||||
* Print patch name instead of class name ([4e7811e](https://github.com/ReVanced/revanced-patcher/commit/4e7811ea07762667a1f22526dc176022038f60eb))
|
||||
* Print stack trace of exception ([aa71146](https://github.com/ReVanced/revanced-patcher/commit/aa71146b1bf4ffebcc81a1663e15abae89e97ff0))
|
||||
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](https://github.com/ReVanced/revanced-patcher/commit/1d7aeca696be873dfaf88eaa6d312949a3b8572b))
|
||||
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](https://github.com/ReVanced/revanced-patcher/commit/72c9eb212985f99f3390cf1faa10ab547d2dbe7e))
|
||||
* Use correct module name ([080fbe9](https://github.com/ReVanced/revanced-patcher/commit/080fbe9feb9d4ea9ec4e599ecef296eacd803b05))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* Internalize processor constructor ([a802d0d](https://github.com/ReVanced/revanced-patcher/commit/a802d0df463695976e85d8391762942eb977920b))
|
||||
|
||||
|
||||
* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](https://github.com/ReVanced/revanced-patcher/commit/4b76d1959691babf8c99d3d5235df4a4388956f0))
|
||||
* feat!: Add patch annotation processor ([3fc6a13](https://github.com/ReVanced/revanced-patcher/commit/3fc6a139eef67237c116fb4e3e29bf9542d3a981))
|
||||
* feat!: Remove patch annotations ([3b4db3d](https://github.com/ReVanced/revanced-patcher/commit/3b4db3ddb72cdcee8af2f787eadf58eeb37543de))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add patch annotation processor ([#231](https://github.com/ReVanced/revanced-patcher/issues/231)) ([a29931f](https://github.com/ReVanced/revanced-patcher/commit/a29931f2ec0a666dba209b54855425d9dc2f4462))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This gets rid of the public constructor.
|
||||
* `PatchBundleLoader` is not a map anymore
|
||||
* This renames packages and the Maven package.
|
||||
* The manifest for patches has been removed, and the properties have been added to patches. Patches are now `OptionsContainer`. The `@Patch` annotation has been removed in favour of the `@Patch` annotation from the annotation processor.
|
||||
* Patch annotations have been removed. PatcherException is now thrown in various places. PatchBundleLoader is now a map of patches associated by their name. Patches are now instances.
|
||||
|
||||
# [15.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.3...v15.0.0-dev.4) (2023-09-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Account for source patch dependency for tests ([6918418](https://github.com/ReVanced/revanced-patcher/commit/69184187d90f126478d2f49415c1e3381217557f))
|
||||
* Always make the generated patch depend on the source patch ([8de3063](https://github.com/ReVanced/revanced-patcher/commit/8de30633ae6eb7acf7f0a351e26d4a6c2fdbdfec))
|
||||
* Catch correct exception ([637d487](https://github.com/ReVanced/revanced-patcher/commit/637d48746ff8694e01c5aead1c75a9a1efeb5ac8))
|
||||
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](https://github.com/ReVanced/revanced-patcher/commit/9a109c129b135a634be1aad4130a06d9e8e96ecd))
|
||||
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](https://github.com/ReVanced/revanced-patcher/commit/e11283744a21fe2d09435e99d6924462b6aac3b8))
|
||||
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](https://github.com/ReVanced/revanced-patcher/commit/6b1e0a16568124e9f82fb5740353360fa8ec614a))
|
||||
* Filter for patches correctly ([4bc4b0d](https://github.com/ReVanced/revanced-patcher/commit/4bc4b0dc0104073b62528d02a88383cecd7a50e7))
|
||||
* Find dependency in `context.allPatches` ([670f015](https://github.com/ReVanced/revanced-patcher/commit/670f0153de10c6f0db25b08df1c01a2905037f84))
|
||||
* Log the correct patch names ([9fdb8f0](https://github.com/ReVanced/revanced-patcher/commit/9fdb8f087f62babf6081879db65c80db639aa0a7))
|
||||
* Print patch name instead of class name ([4e7811e](https://github.com/ReVanced/revanced-patcher/commit/4e7811ea07762667a1f22526dc176022038f60eb))
|
||||
* Print stack trace of exception ([aa71146](https://github.com/ReVanced/revanced-patcher/commit/aa71146b1bf4ffebcc81a1663e15abae89e97ff0))
|
||||
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](https://github.com/ReVanced/revanced-patcher/commit/1d7aeca696be873dfaf88eaa6d312949a3b8572b))
|
||||
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](https://github.com/ReVanced/revanced-patcher/commit/72c9eb212985f99f3390cf1faa10ab547d2dbe7e))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* Internalize processor constructor ([a802d0d](https://github.com/ReVanced/revanced-patcher/commit/a802d0df463695976e85d8391762942eb977920b))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This gets rid of the public constructor.
|
||||
|
||||
# [15.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.2...v15.0.0-dev.3) (2023-09-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Make `CompatiblePackage.versions` a property ([67b7dff](https://github.com/ReVanced/revanced-patcher/commit/67b7dff67a212b4fc30eb4f0cbe58f0ba09fb09a))
|
||||
* Use correct module name ([080fbe9](https://github.com/ReVanced/revanced-patcher/commit/080fbe9feb9d4ea9ec4e599ecef296eacd803b05))
|
||||
|
||||
|
||||
* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](https://github.com/ReVanced/revanced-patcher/commit/4b76d1959691babf8c99d3d5235df4a4388956f0))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* `PatchBundleLoader` is not a map anymore
|
||||
* This renames packages and the Maven package.
|
||||
|
||||
# [15.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.1...v15.0.0-dev.2) (2023-09-06)
|
||||
|
||||
# [15.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0-dev.1) (2023-09-04)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 15.0.0-dev.2
|
||||
version = 16.0.1-dev.1
|
||||
|
@@ -1,10 +1,10 @@
|
||||
public abstract interface annotation class app/revanced/patcher/patch/annotations/CompatiblePackage : java/lang/annotation/Annotation {
|
||||
public abstract interface annotation class app/revanced/patcher/patch/annotation/CompatiblePackage : java/lang/annotation/Annotation {
|
||||
public abstract fun name ()Ljava/lang/String;
|
||||
public abstract fun versions ()[Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface annotation class app/revanced/patcher/patch/annotations/Patch : java/lang/annotation/Annotation {
|
||||
public abstract fun compatiblePackages ()[Lapp/revanced/patcher/patch/annotations/CompatiblePackage;
|
||||
public abstract interface annotation class app/revanced/patcher/patch/annotation/Patch : java/lang/annotation/Annotation {
|
||||
public abstract fun compatiblePackages ()[Lapp/revanced/patcher/patch/annotation/CompatiblePackage;
|
||||
public abstract fun dependencies ()[Ljava/lang/Class;
|
||||
public abstract fun description ()Ljava/lang/String;
|
||||
public abstract fun name ()Ljava/lang/String;
|
||||
@@ -12,14 +12,13 @@ public abstract interface annotation class app/revanced/patcher/patch/annotation
|
||||
public abstract fun use ()Z
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/annotations/processor/PatchProcessor : com/google/devtools/ksp/processing/SymbolProcessor {
|
||||
public fun <init> (Lcom/google/devtools/ksp/processing/CodeGenerator;Lcom/google/devtools/ksp/processing/KSPLogger;)V
|
||||
public final class app/revanced/patcher/patch/annotation/processor/PatchProcessor : com/google/devtools/ksp/processing/SymbolProcessor {
|
||||
public fun process (Lcom/google/devtools/ksp/processing/Resolver;)Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/annotations/processor/PatchProcessorProvider : com/google/devtools/ksp/processing/SymbolProcessorProvider {
|
||||
public final class app/revanced/patcher/patch/annotation/processor/PatchProcessorProvider : com/google/devtools/ksp/processing/SymbolProcessorProvider {
|
||||
public fun <init> ()V
|
||||
public fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lapp/revanced/patcher/patch/annotations/processor/PatchProcessor;
|
||||
public fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lapp/revanced/patcher/patch/annotation/processor/PatchProcessor;
|
||||
public synthetic fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lcom/google/devtools/ksp/processing/SymbolProcessor;
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ publishing {
|
||||
version = project.version.toString()
|
||||
|
||||
pom {
|
||||
name = "ReVanced Patch annotations processor"
|
||||
name = "ReVanced patch annotation processor"
|
||||
description = "Annotation processor for patches."
|
||||
url = "https://revanced.app"
|
||||
|
2
revanced-patch-annotation-processor/settings.gradle.kts
Normal file
2
revanced-patch-annotation-processor/settings.gradle.kts
Normal file
@@ -0,0 +1,2 @@
|
||||
rootProject.name = "revanced-patch-annotation-processor"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patcher.patch.annotations
|
||||
package app.revanced.patcher.patch.annotation
|
||||
|
||||
import java.lang.annotation.Inherited
|
||||
import kotlin.reflect.KClass
|
@@ -1,11 +1,14 @@
|
||||
package app.revanced.patcher.patch.annotations.processor
|
||||
package app.revanced.patcher.patch.annotation.processor
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import com.google.devtools.ksp.processing.*
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import com.google.devtools.ksp.processing.CodeGenerator
|
||||
import com.google.devtools.ksp.processing.Dependencies
|
||||
import com.google.devtools.ksp.processing.Resolver
|
||||
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||
import com.google.devtools.ksp.symbol.KSAnnotation
|
||||
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||
@@ -16,9 +19,8 @@ import com.squareup.kotlinpoet.ksp.toClassName
|
||||
import com.squareup.kotlinpoet.ksp.writeTo
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class PatchProcessor(
|
||||
class PatchProcessor internal constructor(
|
||||
private val codeGenerator: CodeGenerator,
|
||||
private val logger: KSPLogger
|
||||
) : SymbolProcessor {
|
||||
|
||||
private fun KSAnnotated.isSubclassOf(cls: KClass<*>): Boolean {
|
||||
@@ -31,7 +33,7 @@ class PatchProcessor(
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||
val executablePatches = buildMap {
|
||||
val patches = buildMap {
|
||||
resolver.getSymbolsWithAnnotation(Patch::class.qualifiedName!!).filter {
|
||||
// Do not check here if Patch is super of the class, because it is expensive.
|
||||
// Check it later when processing.
|
||||
@@ -79,14 +81,14 @@ class PatchProcessor(
|
||||
dependencies?.map { dependency -> dependency.toClassName() },
|
||||
compatiblePackages?.map {
|
||||
val packageName = it.property("name")
|
||||
val packageVersions = (it.property("versions") as List<String>)
|
||||
.joinToString(", ") { version -> "\"$version\"" }
|
||||
val packageVersions = (it.property("versions") as List<String>).ifEmpty { null }
|
||||
?.joinToString(", ") { version -> "\"$version\"" }
|
||||
|
||||
CodeBlock.of(
|
||||
"%T(%S, setOf(%L))",
|
||||
"%T(%S, %L)",
|
||||
app.revanced.patcher.patch.Patch.CompatiblePackage::class,
|
||||
packageName,
|
||||
packageVersions
|
||||
packageVersions?.let { "setOf($packageVersions)" },
|
||||
)
|
||||
},
|
||||
use,
|
||||
@@ -97,13 +99,13 @@ class PatchProcessor(
|
||||
}
|
||||
|
||||
// If a patch depends on another, that is annotated, the dependency should be replaced with the generated patch,
|
||||
// because the generated patch has all the necessary properties to invoke the super constructor,
|
||||
// because the generated patch has all the necessary properties to invoke the super constructor with,
|
||||
// unlike the annotated patch.
|
||||
val dependencyResolutionMap = buildMap {
|
||||
executablePatches.values.filter { it.dependencies != null }.flatMap {
|
||||
patches.values.filter { it.dependencies != null }.flatMap {
|
||||
it.dependencies!!
|
||||
}.distinct().forEach { dependency ->
|
||||
executablePatches.keys.find { it.qualifiedName?.asString() == dependency.toString() }
|
||||
patches.keys.find { it.qualifiedName?.asString() == dependency.toString() }
|
||||
?.let { patch ->
|
||||
this[dependency] = ClassName(
|
||||
patch.packageName.asString(),
|
||||
@@ -113,7 +115,7 @@ class PatchProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
executablePatches.forEach { (patchDeclaration, patchAnnotation) ->
|
||||
patches.forEach { (patchDeclaration, patchAnnotation) ->
|
||||
val isBytecodePatch = patchDeclaration.isSubclassOf(BytecodePatch::class)
|
||||
|
||||
val superClass = if (isBytecodePatch) {
|
||||
@@ -152,18 +154,18 @@ class PatchProcessor(
|
||||
)
|
||||
}
|
||||
|
||||
patchAnnotation.dependencies?.let { dependencies ->
|
||||
addSuperclassConstructorParameter(
|
||||
"dependencies = setOf(%L)",
|
||||
buildList {
|
||||
addAll(dependencies)
|
||||
// Also add the source class of the generated class so that it is also executed.
|
||||
add(patchDeclaration.toClassName())
|
||||
}.joinToString(", ") { dependency ->
|
||||
"${(dependencyResolutionMap[dependency] ?: dependency)}::class"
|
||||
// The generated patch always depends on the source patch.
|
||||
addSuperclassConstructorParameter(
|
||||
"dependencies = setOf(%L)",
|
||||
buildList {
|
||||
patchAnnotation.dependencies?.forEach { dependency ->
|
||||
add("${(dependencyResolutionMap[dependency] ?: dependency)}::class")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
add("${patchDeclaration.toClassName()}::class")
|
||||
}.joinToString(", "),
|
||||
)
|
||||
|
||||
addSuperclassConstructorParameter(
|
||||
"use = %L", patchAnnotation.use
|
||||
)
|
||||
@@ -182,7 +184,7 @@ class PatchProcessor(
|
||||
.addInitializerBlock(
|
||||
CodeBlock.builder()
|
||||
.add(
|
||||
"%T.options.forEach { (key, option) ->",
|
||||
"%T.options.forEach { (_, option) ->",
|
||||
patchDeclaration.toClassName()
|
||||
)
|
||||
.addStatement(
|
@@ -1,9 +1,9 @@
|
||||
package app.revanced.patcher.patch.annotations.processor
|
||||
package app.revanced.patcher.patch.annotation.processor
|
||||
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||
|
||||
class PatchProcessorProvider : SymbolProcessorProvider {
|
||||
override fun create(environment: SymbolProcessorEnvironment) =
|
||||
PatchProcessor(environment.codeGenerator, environment.logger)
|
||||
PatchProcessor(environment.codeGenerator)
|
||||
}
|
@@ -0,0 +1 @@
|
||||
app.revanced.patcher.patch.annotation.processor.PatchProcessorProvider
|
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patcher.patch.annotations.processor
|
||||
package app.revanced.patcher.patch.annotation.processor
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import com.tschuchort.compiletesting.KotlinCompilation
|
||||
@@ -21,6 +21,16 @@ class TestPatchAnnotationProcessor {
|
||||
).loadPatch("$SAMPLE_PACKAGE.processing.ProcessablePatchGenerated").name
|
||||
)
|
||||
|
||||
@Test
|
||||
fun generateNullProperties() = compile(
|
||||
getSourceFile(
|
||||
"null", "NullPropertiesPatch"
|
||||
)
|
||||
).loadPatch("$SAMPLE_PACKAGE.null.NullPropertiesPatchGenerated").let {
|
||||
assertNull(it.description) // Because no description was provided.
|
||||
assertNull(it.compatiblePackages!!.first().versions) // Because no versions were provided.
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Dependencies
|
||||
@@ -70,21 +80,23 @@ class TestPatchAnnotationProcessor {
|
||||
// endregion
|
||||
|
||||
// region Limitations
|
||||
|
||||
@Test
|
||||
fun failingManualDependency() = assertNull(
|
||||
fun failingManualDependency() = assertEquals(
|
||||
1, // Generated patch is always dependent on source class.
|
||||
compile(
|
||||
getSourceFile(
|
||||
"limitations/manualdependency", "DependentPatch"
|
||||
), getSourceFile(
|
||||
"limitations/manualdependency", "DependencyPatch"
|
||||
)
|
||||
).loadPatch("$SAMPLE_PACKAGE.limitations.manualdependency.DependentPatchGenerated").dependencies
|
||||
).loadPatch("$SAMPLE_PACKAGE.limitations.manualdependency.DependentPatchGenerated").dependencies!!.size
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
private companion object Utils {
|
||||
const val SAMPLE_PACKAGE = "app.revanced.patcher.patch.annotations.processor.samples"
|
||||
const val SAMPLE_PACKAGE = "app.revanced.patcher.patch.annotation.processor.samples"
|
||||
|
||||
/**
|
||||
* Get a source file from the given sample and class name.
|
||||
@@ -93,11 +105,16 @@ class TestPatchAnnotationProcessor {
|
||||
* @param className The name of the class to get the source file from.
|
||||
* @return The source file.
|
||||
*/
|
||||
fun getSourceFile(sample: String, className: String) = SourceFile.kotlin(
|
||||
"$className.kt", TestPatchAnnotationProcessor::class.java.classLoader.getResourceAsStream(
|
||||
"app/revanced/patcher/patch/annotations/processor/samples/$sample/$className.kt"
|
||||
)?.readAllBytes()?.toString(Charsets.UTF_8) ?: error("Could not find resource $className")
|
||||
)
|
||||
fun getSourceFile(sample: String, className: String): SourceFile {
|
||||
val resourceName = "app/revanced/patcher/patch/annotation/processor/samples/$sample/$className.kt"
|
||||
return SourceFile.kotlin(
|
||||
"$className.kt",
|
||||
TestPatchAnnotationProcessor::class.java.classLoader.getResourceAsStream(resourceName)
|
||||
?.readAllBytes()
|
||||
?.toString(Charsets.UTF_8)
|
||||
?: error("Could not find resource $resourceName")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the given source files and return the result.
|
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patcher.patch.annotations.processor.samples.dependencies
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.dependencies
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(name = "Dependency patch")
|
||||
object DependencyPatch : ResourcePatch() {
|
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patcher.patch.annotations.processor.samples.dependencies
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.dependencies
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(
|
||||
name = "Dependent patch",
|
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patcher.patch.annotations.processor.samples.limitations.manualdependency
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.limitations.manualdependency
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(name = "Dependency patch")
|
||||
object DependencyPatch : ResourcePatch() {
|
@@ -1,7 +1,7 @@
|
||||
package app.revanced.patcher.patch.annotations.processor.samples.limitations.manualdependency
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.limitations.manualdependency
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(name = "Dependent patch")
|
||||
object DependentPatch : BytecodePatch(
|
@@ -0,0 +1,14 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.`null`
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(
|
||||
"Patch with null properties",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.youtube")],
|
||||
)
|
||||
object NullPropertiesPatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patcher.patch.annotations.processor.samples.options
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.options
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
|
||||
|
||||
@Patch(name = "Options patch")
|
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patcher.patch.annotations.processor.samples.processing
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.processing
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch("Processable patch")
|
||||
object ProcessablePatch : BytecodePatch() {
|
@@ -1,2 +0,0 @@
|
||||
rootProject.name = "revanced-patch-annotations-processor"
|
||||
|
@@ -1 +0,0 @@
|
||||
app.revanced.patcher.patch.annotations.processor.PatchProcessorProvider
|
@@ -7,46 +7,24 @@ public final class app/revanced/patcher/PackageMetadata {
|
||||
public final fun getPackageVersion ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/PatchBundleLoader : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public synthetic fun <init> (Ljava/lang/ClassLoader;[Ljava/io/File;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public abstract class app/revanced/patcher/PatchBundleLoader : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public synthetic fun <init> (Ljava/lang/ClassLoader;[Ljava/io/File;Lkotlin/jvm/functions/Function1;Ljava/util/Set;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun add (Lapp/revanced/patcher/patch/Patch;)Z
|
||||
public synthetic fun add (Ljava/lang/Object;)Z
|
||||
public fun addAll (Ljava/util/Collection;)Z
|
||||
public fun clear ()V
|
||||
public synthetic fun compute (Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;
|
||||
public fun compute (Ljava/lang/String;Ljava/util/function/BiFunction;)Lapp/revanced/patcher/patch/Patch;
|
||||
public synthetic fun computeIfAbsent (Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;
|
||||
public fun computeIfAbsent (Ljava/lang/String;Ljava/util/function/Function;)Lapp/revanced/patcher/patch/Patch;
|
||||
public synthetic fun computeIfPresent (Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;
|
||||
public fun computeIfPresent (Ljava/lang/String;Ljava/util/function/BiFunction;)Lapp/revanced/patcher/patch/Patch;
|
||||
public final fun containsKey (Ljava/lang/Object;)Z
|
||||
public fun containsKey (Ljava/lang/String;)Z
|
||||
public fun containsValue (Lapp/revanced/patcher/patch/Patch;)Z
|
||||
public final fun containsValue (Ljava/lang/Object;)Z
|
||||
public final fun entrySet ()Ljava/util/Set;
|
||||
public final fun get (Ljava/lang/Object;)Lapp/revanced/patcher/patch/Patch;
|
||||
public final synthetic fun get (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun get (Ljava/lang/String;)Lapp/revanced/patcher/patch/Patch;
|
||||
public fun getEntries ()Ljava/util/Set;
|
||||
public fun getKeys ()Ljava/util/Set;
|
||||
public fun contains (Lapp/revanced/patcher/patch/Patch;)Z
|
||||
public final fun contains (Ljava/lang/Object;)Z
|
||||
public fun containsAll (Ljava/util/Collection;)Z
|
||||
public fun getSize ()I
|
||||
public fun getValues ()Ljava/util/Collection;
|
||||
public fun isEmpty ()Z
|
||||
public final fun keySet ()Ljava/util/Set;
|
||||
public synthetic fun merge (Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;
|
||||
public fun merge (Ljava/lang/String;Lapp/revanced/patcher/patch/Patch;Ljava/util/function/BiFunction;)Lapp/revanced/patcher/patch/Patch;
|
||||
public synthetic fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun put (Ljava/lang/String;Lapp/revanced/patcher/patch/Patch;)Lapp/revanced/patcher/patch/Patch;
|
||||
public fun putAll (Ljava/util/Map;)V
|
||||
public synthetic fun putIfAbsent (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun putIfAbsent (Ljava/lang/String;Lapp/revanced/patcher/patch/Patch;)Lapp/revanced/patcher/patch/Patch;
|
||||
public fun remove (Ljava/lang/Object;)Lapp/revanced/patcher/patch/Patch;
|
||||
public synthetic fun remove (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun remove (Ljava/lang/Object;Ljava/lang/Object;)Z
|
||||
public synthetic fun replace (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public synthetic fun replace (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z
|
||||
public fun replace (Ljava/lang/String;Lapp/revanced/patcher/patch/Patch;)Lapp/revanced/patcher/patch/Patch;
|
||||
public fun replace (Ljava/lang/String;Lapp/revanced/patcher/patch/Patch;Lapp/revanced/patcher/patch/Patch;)Z
|
||||
public fun replaceAll (Ljava/util/function/BiFunction;)V
|
||||
public fun iterator ()Ljava/util/Iterator;
|
||||
public fun remove (Ljava/lang/Object;)Z
|
||||
public fun removeAll (Ljava/util/Collection;)Z
|
||||
public fun retainAll (Ljava/util/Collection;)Z
|
||||
public final fun size ()I
|
||||
public final fun values ()Ljava/util/Collection;
|
||||
public fun toArray ()[Ljava/lang/Object;
|
||||
public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PatchBundleLoader$Dex : app/revanced/patcher/PatchBundleLoader {
|
||||
@@ -352,6 +330,7 @@ public final class app/revanced/patcher/patch/Patch$CompatiblePackage {
|
||||
public fun <init> (Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getVersions ()Ljava/util/Set;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/PatchException : java/lang/Exception {
|
||||
@@ -392,15 +371,15 @@ public final class app/revanced/patcher/patch/options/PatchOptionException$Inval
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$PatchOptionNotFoundException : java/lang/Exception {
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$PatchOptionNotFoundException : app/revanced/patcher/patch/options/PatchOptionException {
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueRequiredException : java/lang/Exception {
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueRequiredException : app/revanced/patcher/patch/options/PatchOptionException {
|
||||
public fun <init> (Lapp/revanced/patcher/patch/options/PatchOption;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueValidationException : java/lang/Exception {
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueValidationException : app/revanced/patcher/patch/options/PatchOptionException {
|
||||
public fun <init> (Ljava/lang/Object;Lapp/revanced/patcher/patch/options/PatchOption;)V
|
||||
}
|
||||
|
||||
@@ -428,6 +407,7 @@ public final class app/revanced/patcher/patch/options/PatchOptions : java/util/M
|
||||
public final fun remove (Ljava/lang/Object;)Lapp/revanced/patcher/patch/options/PatchOption;
|
||||
public final synthetic fun remove (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun remove (Ljava/lang/String;)Lapp/revanced/patcher/patch/options/PatchOption;
|
||||
public final fun set (Ljava/lang/String;Ljava/lang/Object;)V
|
||||
public final fun size ()I
|
||||
public final fun values ()Ljava/util/Collection;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ dependencies {
|
||||
|
||||
compileOnly(libs.android)
|
||||
|
||||
testImplementation(project(":revanced-patch-annotations-processor"))
|
||||
testImplementation(project(":revanced-patch-annotation-processor"))
|
||||
testImplementation(libs.kotlin.test)
|
||||
}
|
||||
|
||||
|
@@ -13,9 +13,9 @@ import java.util.logging.Logger
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* [Patch]es mapped by their name.
|
||||
* A set of [Patch]es.
|
||||
*/
|
||||
typealias PatchMap = Map<String, Patch<*>>
|
||||
typealias PatchSet = Set<Patch<*>>
|
||||
|
||||
/**
|
||||
* A [Patch] class.
|
||||
@@ -28,28 +28,30 @@ typealias PatchClass = KClass<out Patch<*>>
|
||||
*
|
||||
* @param getBinaryClassNames A function that returns the binary names of all classes in a patch bundle.
|
||||
* @param classLoader The [ClassLoader] to use for loading the classes.
|
||||
* @param patchBundles A set of patches to initialize this instance with.
|
||||
*/
|
||||
sealed class PatchBundleLoader private constructor(
|
||||
classLoader: ClassLoader,
|
||||
patchBundles: Array<out File>,
|
||||
getBinaryClassNames: (patchBundle: File) -> List<String>,
|
||||
) : PatchMap by mutableMapOf() {
|
||||
// This constructor parameter is unfortunately necessary,
|
||||
// so that a reference to the mutable set is present in the constructor to be able to add patches to it.
|
||||
// because the instance itself is a PatchSet, which is immutable, that is delegated by the parameter.
|
||||
private val patchSet: MutableSet<Patch<*>> = mutableSetOf()
|
||||
) : PatchSet by patchSet {
|
||||
private val logger = Logger.getLogger(PatchBundleLoader::class.java.name)
|
||||
|
||||
init {
|
||||
patchBundles.flatMap(getBinaryClassNames).asSequence().map {
|
||||
classLoader.loadClass(it)
|
||||
}.filter {
|
||||
it.isInstance(Patch::class.java)
|
||||
Patch::class.java.isAssignableFrom(it)
|
||||
}.mapNotNull { patchClass ->
|
||||
patchClass.getInstance(logger)
|
||||
patchClass.getInstance(logger, silent = true)
|
||||
}.filter {
|
||||
it.name != null
|
||||
}.associateBy {
|
||||
it.name!!
|
||||
}.let { patches ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(this as MutableMap<String, Patch<*>>).putAll(patches)
|
||||
patchSet.addAll(patches)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +60,14 @@ sealed class PatchBundleLoader private constructor(
|
||||
* Instantiates a [Patch]. If the class is a singleton, the INSTANCE field will be used.
|
||||
*
|
||||
* @param logger The [Logger] to use for logging.
|
||||
* @param silent Whether to suppress logging.
|
||||
* @return The instantiated [Patch] or `null` if the [Patch] could not be instantiated.
|
||||
*/
|
||||
internal fun Class<*>.getInstance(logger: Logger): Patch<*>? {
|
||||
internal fun Class<*>.getInstance(logger: Logger, silent: Boolean = false): Patch<*>? {
|
||||
return try {
|
||||
getField("INSTANCE").get(null)
|
||||
} catch (exception: NoSuchFileException) {
|
||||
logger.fine(
|
||||
} catch (exception: NoSuchFieldException) {
|
||||
if (!silent) logger.fine(
|
||||
"Patch class '${name}' has no INSTANCE field, therefor not a singleton. " +
|
||||
"Will try to instantiate it."
|
||||
)
|
||||
@@ -72,7 +75,7 @@ sealed class PatchBundleLoader private constructor(
|
||||
try {
|
||||
getDeclaredConstructor().newInstance()
|
||||
} catch (exception: Exception) {
|
||||
logger.severe(
|
||||
if (!silent) logger.severe(
|
||||
"Patch class '${name}' is not singleton and has no suitable constructor, " +
|
||||
"therefor cannot be instantiated and will be ignored."
|
||||
)
|
||||
|
@@ -9,8 +9,6 @@ import kotlinx.coroutines.flow.flow
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import java.util.function.Supplier
|
||||
import java.util.logging.Level
|
||||
import java.util.logging.LogManager
|
||||
import java.util.logging.Logger
|
||||
|
||||
/**
|
||||
@@ -30,18 +28,6 @@ class Patcher(
|
||||
val context = PatcherContext(options)
|
||||
|
||||
init {
|
||||
LogManager.getLogManager().let { manager ->
|
||||
// Disable root logger.
|
||||
manager.getLogger("").level = Level.OFF
|
||||
|
||||
// Enable ReVanced logging only.
|
||||
manager.loggerNames
|
||||
.toList()
|
||||
.filter { it.startsWith("app.revanced") }
|
||||
.map { manager.getLogger(it) }
|
||||
.forEach { it.level = Level.INFO }
|
||||
}
|
||||
|
||||
context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.MANIFEST_ONLY)
|
||||
}
|
||||
|
||||
@@ -74,7 +60,7 @@ class Patcher(
|
||||
}
|
||||
|
||||
// Add all patches and their dependencies to the context.
|
||||
for (patch in patches) context.executablePatches.putIfAbsent(patch::class, patch) ?: {
|
||||
for (patch in patches) context.executablePatches.putIfAbsent(patch::class, patch) ?: run {
|
||||
context.allPatches[patch::class] = patch
|
||||
|
||||
patch.dependencies?.forEach { it.putDependenciesRecursively() }
|
||||
@@ -118,7 +104,7 @@ class Patcher(
|
||||
|
||||
// Determine, if merging integrations is required.
|
||||
for (patch in patches)
|
||||
if (!patch.anyRecursively { it.requiresIntegrations }) {
|
||||
if (patch.anyRecursively { it.requiresIntegrations }) {
|
||||
context.bytecodeContext.integrations.merge = true
|
||||
break
|
||||
}
|
||||
@@ -153,7 +139,7 @@ class Patcher(
|
||||
patch: Patch<*>,
|
||||
executedPatches: LinkedHashMap<Patch<*>, PatchResult>
|
||||
): PatchResult {
|
||||
val patchName = patch.name
|
||||
val patchName = patch.name ?: patch.toString()
|
||||
|
||||
executedPatches[patch]?.let { patchResult ->
|
||||
patchResult.exception ?: return patchResult
|
||||
@@ -164,14 +150,17 @@ class Patcher(
|
||||
}
|
||||
|
||||
// Recursively execute all dependency patches.
|
||||
patch.dependencies?.forEach { dependencyName ->
|
||||
val dependency = context.executablePatches[dependencyName]!!
|
||||
patch.dependencies?.forEach { dependencyClass ->
|
||||
val dependency = context.allPatches[dependencyClass]!!
|
||||
val result = executePatch(dependency, executedPatches)
|
||||
|
||||
result.exception?.let {
|
||||
return PatchResult(
|
||||
patch,
|
||||
PatchException("'$patchName' depends on '${dependency}' that raised an exception: $it")
|
||||
PatchException(
|
||||
"'$patchName' depends on '${dependency.name ?: dependency}' " +
|
||||
"that raised an exception:\n${it.stackTraceToString()}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -180,7 +169,7 @@ class Patcher(
|
||||
// TODO: Implement this in a more polymorphic way.
|
||||
when (patch) {
|
||||
is BytecodePatch -> {
|
||||
patch.fingerprints.toList().resolveUsingLookupMap(context.bytecodeContext)
|
||||
patch.fingerprints.resolveUsingLookupMap(context.bytecodeContext)
|
||||
patch.execute(context.bytecodeContext)
|
||||
}
|
||||
is ResourcePatch -> {
|
||||
@@ -208,7 +197,7 @@ class Patcher(
|
||||
|
||||
val executedPatches = LinkedHashMap<Patch<*>, PatchResult>() // Key is name.
|
||||
|
||||
context.executablePatches.map { it.value }.sortedBy { it.name }.forEach { patch ->
|
||||
context.executablePatches.values.sortedBy { it.name }.forEach { patch ->
|
||||
val patchResult = executePatch(patch, executedPatches)
|
||||
|
||||
// If the patch failed, emit the result, even if it is closeable.
|
||||
@@ -245,7 +234,7 @@ class Patcher(
|
||||
PatchResult(
|
||||
patch,
|
||||
PatchException(
|
||||
"'${patch.name}' raised an exception while being closed: $it",
|
||||
"'${patch.name}' raised an exception while being closed: ${it.stackTraceToString()}",
|
||||
result.exception
|
||||
)
|
||||
)
|
||||
|
@@ -96,7 +96,7 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
|
||||
internal inner class Integrations : MutableList<File> by mutableListOf(), Flushable {
|
||||
/**
|
||||
* Whether to merge integrations.
|
||||
* True when any supplied [Patch] is annotated with [RequiresIntegrations].
|
||||
* Set to true, if the field requiresIntegrations of any supplied [Patch] is true.
|
||||
*/
|
||||
var merge = false
|
||||
|
||||
|
@@ -159,10 +159,10 @@ abstract class MethodFingerprint(
|
||||
* - Faster: Specify [accessFlags], [returnType] and [parameters].
|
||||
* - Fastest: Specify [strings], with at least one string being an exact (non-partial) match.
|
||||
*/
|
||||
internal fun List<MethodFingerprint>.resolveUsingLookupMap(context: BytecodeContext) {
|
||||
internal fun Set<MethodFingerprint>.resolveUsingLookupMap(context: BytecodeContext) {
|
||||
if (methods.isEmpty()) throw PatchException("lookup map not initialized")
|
||||
|
||||
for (fingerprint in this) {
|
||||
forEach { fingerprint ->
|
||||
fingerprint.resolveUsingLookupMap(context)
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
@file:Suppress("MemberVisibilityCanBePrivate", "UNUSED_PARAMETER")
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package app.revanced.patcher.patch
|
||||
|
||||
@@ -65,7 +65,7 @@ sealed class Patch<out T : Context<*>>(
|
||||
*/
|
||||
class CompatiblePackage(
|
||||
val name: String,
|
||||
versions: Set<String>? = null,
|
||||
val versions: Set<String>? = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -6,5 +6,4 @@ package app.revanced.patcher.patch
|
||||
* @param patch The [Patch] that was executed.
|
||||
* @param exception The [PatchException] thrown, if any.
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
class PatchResult internal constructor(val patch: Patch<*>, val exception: PatchException? = null)
|
@@ -21,7 +21,7 @@ sealed class PatchOptionException(errorMessage: String) : Exception(errorMessage
|
||||
* @param value The value that failed validation.
|
||||
*/
|
||||
class ValueValidationException(value: Any?, option: PatchOption<*>) :
|
||||
Exception("The option value \"$value\" failed validation for ${option.key}")
|
||||
PatchOptionException("The option value \"$value\" failed validation for ${option.key}")
|
||||
|
||||
/**
|
||||
* An exception thrown when a value is required but null was passed.
|
||||
@@ -29,7 +29,7 @@ sealed class PatchOptionException(errorMessage: String) : Exception(errorMessage
|
||||
* @param option The [PatchOption] that requires a value.
|
||||
*/
|
||||
class ValueRequiredException(option: PatchOption<*>) :
|
||||
Exception("The option ${option.key} requires a value, but null was passed")
|
||||
PatchOptionException("The option ${option.key} requires a value, but null was passed")
|
||||
|
||||
/**
|
||||
* An exception thrown when a [PatchOption] is not found.
|
||||
@@ -37,5 +37,5 @@ sealed class PatchOptionException(errorMessage: String) : Exception(errorMessage
|
||||
* @param key The key of the [PatchOption].
|
||||
*/
|
||||
class PatchOptionNotFoundException(key: String)
|
||||
: Exception("No option with key $key")
|
||||
: PatchOptionException("No option with key $key")
|
||||
}
|
@@ -23,16 +23,18 @@ class PatchOptions internal constructor(
|
||||
* @param value The value.
|
||||
* @throws PatchOptionException.PatchOptionNotFoundException If the option does not exist.
|
||||
*/
|
||||
inline operator fun <reified T: Any> set(key: String, value: T?) {
|
||||
operator fun <T : Any> set(key: String, value: T?) {
|
||||
val option = this[key]
|
||||
|
||||
if (option.value !is T) throw PatchOptionException.InvalidValueTypeException(
|
||||
T::class.java.name,
|
||||
option.value?.let { it::class.java.name } ?: "null",
|
||||
)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(option as PatchOption<T>).value = value
|
||||
try {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(option as PatchOption<T>).value = value
|
||||
} catch (e: ClassCastException) {
|
||||
throw PatchOptionException.InvalidValueTypeException(
|
||||
value?.let { it::class.java.name } ?: "null",
|
||||
option.value?.let { it::class.java.name } ?: "null",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -13,6 +13,7 @@ import com.android.tools.smali.smali.smaliFlexLexer
|
||||
import com.android.tools.smali.smali.smaliParser
|
||||
import com.android.tools.smali.smali.smaliTreeWalker
|
||||
import java.io.InputStreamReader
|
||||
import java.util.Locale
|
||||
|
||||
private const val METHOD_TEMPLATE = """
|
||||
.class LInlineCompiler;
|
||||
@@ -33,7 +34,7 @@ class InlineSmaliCompiler {
|
||||
fun compile(
|
||||
instructions: String, parameters: String, registers: Int, forStaticMethod: Boolean
|
||||
): List<BuilderInstruction> {
|
||||
val input = METHOD_TEMPLATE.format(
|
||||
val input = METHOD_TEMPLATE.format(Locale.ENGLISH,
|
||||
if (forStaticMethod) {
|
||||
"static"
|
||||
} else {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user