Compare commits

...

13 Commits

Author SHA1 Message Date
semantic-release-bot
0fc5a4708c chore(release): 20.0.0-dev.4 [skip ci]
# [20.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.3...v20.0.0-dev.4) (2024-08-06)

### Bug Fixes

* Improve exception message wording ([bd434ce](bd434ceb33))
2024-08-06 00:04:05 +00:00
oSumAtrIX
bd434ceb33 fix: Improve exception message wording 2024-08-03 16:07:20 +02:00
semantic-release-bot
766a73345e chore(release): 20.0.0-dev.3 [skip ci]
# [20.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.2...v20.0.0-dev.3) (2024-08-01)

### Bug Fixes

* Make constructor internal as supposed ([e95fcd1](e95fcd1c0b))

### Features

* Add ability to create options outside of a patch ([b8d763a](b8d763a66e))
2024-08-01 15:55:51 +00:00
oSumAtrIX
408e8ed81c refactor: Sort dependencies 2024-08-01 17:53:58 +02:00
oSumAtrIX
e95fcd1c0b fix: Make constructor internal as supposed 2024-08-01 17:53:48 +02:00
oSumAtrIX
b8d763a66e feat: Add ability to create options outside of a patch 2024-08-01 17:39:35 +02:00
semantic-release-bot
76c262ff12 chore(release): 20.0.0-dev.2 [skip ci]
# [20.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.1...v20.0.0-dev.2) (2024-07-31)

### Bug Fixes

* Downgrade smali to fix dex compilation issue ([714447d](714447de70))
* Merge all extensions before initializing lookup maps ([328aa87](328aa876d8))
* Use null for compatible package version when adding packages only ([a8e8fa4](a8e8fa4093))
2024-07-31 00:27:24 +00:00
oSumAtrIX
714447de70 fix: Downgrade smali to fix dex compilation issue 2024-07-31 02:25:32 +02:00
oSumAtrIX
328aa876d8 fix: Merge all extensions before initializing lookup maps 2024-07-26 04:45:31 +02:00
oSumAtrIX
a8e8fa4093 fix: Use null for compatible package version when adding packages only 2024-07-26 03:41:32 +02:00
oSumAtrIX
c482dff17c refactor: Convert method bodies to single expression functions 2024-07-26 03:10:08 +02:00
oSumAtrIX
e6de1f6b4c build(Needs bump): Bump dependencies 2024-07-26 03:09:32 +02:00
oSumAtrIX
82a2b3c371 docs: Fix syntax issues and improve wording 2024-07-23 19:55:30 +02:00
38 changed files with 687 additions and 353 deletions

View File

@@ -1,3 +1,31 @@
# [20.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.3...v20.0.0-dev.4) (2024-08-06)
### Bug Fixes
* Improve exception message wording ([bd434ce](https://github.com/ReVanced/revanced-patcher/commit/bd434ceb3394d1d5292e8b94e5bfd6da0e4e9c72))
# [20.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.2...v20.0.0-dev.3) (2024-08-01)
### Bug Fixes
* Make constructor internal as supposed ([e95fcd1](https://github.com/ReVanced/revanced-patcher/commit/e95fcd1c0b641164bbf0840ec7e562aeb3bacc3e))
### Features
* Add ability to create options outside of a patch ([b8d763a](https://github.com/ReVanced/revanced-patcher/commit/b8d763a66e0601627dd71c8c24247726aa300146))
# [20.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.1...v20.0.0-dev.2) (2024-07-31)
### Bug Fixes
* Downgrade smali to fix dex compilation issue ([714447d](https://github.com/ReVanced/revanced-patcher/commit/714447de70096bf736e8e1d31c14bb5f24195070))
* Merge all extensions before initializing lookup maps ([328aa87](https://github.com/ReVanced/revanced-patcher/commit/328aa876d8ed7826be3713754b6404195e9fe84b))
* Use null for compatible package version when adding packages only ([a8e8fa4](https://github.com/ReVanced/revanced-patcher/commit/a8e8fa4093deb8cffbd7a582409f41867f6b568b))
# [20.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v19.3.1...v20.0.0-dev.1) (2024-07-22) # [20.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v19.3.1...v20.0.0-dev.1) (2024-07-22)

View File

@@ -67,7 +67,8 @@ public final class app/revanced/patcher/PatcherConfig {
public synthetic fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
} }
public final class app/revanced/patcher/PatcherContext { public final class app/revanced/patcher/PatcherContext : java/io/Closeable {
public fun close ()V
public final fun getPackageMetadata ()Lapp/revanced/patcher/PackageMetadata; public final fun getPackageMetadata ()Lapp/revanced/patcher/PackageMetadata;
} }
@@ -148,13 +149,13 @@ public final class app/revanced/patcher/patch/BytecodePatchBuilder : app/revance
} }
public final class app/revanced/patcher/patch/BytecodePatchBuilder$InvokedFingerprint { public final class app/revanced/patcher/patch/BytecodePatchBuilder$InvokedFingerprint {
public fun <init> (Lapp/revanced/patcher/Fingerprint;)V
public final fun getValue (Ljava/lang/Void;Lkotlin/reflect/KProperty;)Lapp/revanced/patcher/Match; public final fun getValue (Ljava/lang/Void;Lkotlin/reflect/KProperty;)Lapp/revanced/patcher/Match;
} }
public final class app/revanced/patcher/patch/BytecodePatchContext : app/revanced/patcher/patch/PatchContext { public final class app/revanced/patcher/patch/BytecodePatchContext : app/revanced/patcher/patch/PatchContext, java/io/Closeable {
public final fun classBy (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/proxy/ClassProxy; public final fun classBy (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/proxy/ClassProxy;
public final fun classByType (Ljava/lang/String;)Lapp/revanced/patcher/util/proxy/ClassProxy; public final fun classByType (Ljava/lang/String;)Lapp/revanced/patcher/util/proxy/ClassProxy;
public fun close ()V
public synthetic fun get ()Ljava/lang/Object; public synthetic fun get ()Ljava/lang/Object;
public fun get ()Ljava/util/Set; public fun get ()Ljava/util/Set;
public final fun getClasses ()Lapp/revanced/patcher/util/ProxyClassList; public final fun getClasses ()Lapp/revanced/patcher/util/ProxyClassList;
@@ -203,25 +204,43 @@ public final class app/revanced/patcher/patch/OptionException$ValueValidationExc
public final class app/revanced/patcher/patch/OptionKt { public final class app/revanced/patcher/patch/OptionKt {
public static final fun booleanOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun booleanOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun booleanOption (Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleanOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun booleanOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleanOption$default (Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun booleansOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun booleansOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun booleansOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleansOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun booleansOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleansOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun floatOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun floatOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun floatOption (Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun floatOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun floatOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun floatOption$default (Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun floatsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun floatsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun floatsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun floatsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun intOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun intOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun intOption (Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun intOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intOption$default (Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun intsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun intsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun intsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun intsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun longOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun longOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun longOption (Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun longOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longOption$default (Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun longsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun longsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun longsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun longsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun stringOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun stringOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun stringOption (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun stringOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringOption$default (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun stringsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; public static final fun stringsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun stringsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; public static synthetic fun stringsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
} }
public final class app/revanced/patcher/patch/Options : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker { public final class app/revanced/patcher/patch/Options : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker {

View File

@@ -36,20 +36,21 @@ repositories {
} }
dependencies { dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.xpp3)
implementation(libs.smali)
implementation(libs.multidexlib2)
implementation(libs.apktool.lib)
implementation(libs.kotlin.reflect)
// TODO: Convert project to KMP. // TODO: Convert project to KMP.
compileOnly(libs.android) { compileOnly(libs.android) {
// Exclude, otherwise the org.w3c.dom API breaks. // Exclude, otherwise the org.w3c.dom API breaks.
exclude(group = "xerces", module = "xmlParserAPIs") exclude(group = "xerces", module = "xmlParserAPIs")
} }
testImplementation(libs.kotlin.test)
implementation(libs.apktool.lib)
implementation(libs.kotlin.reflect)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.multidexlib2)
implementation(libs.smali)
implementation(libs.xpp3)
testImplementation(libs.mockk) testImplementation(libs.mockk)
testImplementation(libs.kotlin.test)
} }
kotlin { kotlin {

View File

@@ -115,9 +115,9 @@ val disableAdsPatch = bytecodePatch(
Patches can have options to get and set before a patch is executed. Patches can have options to get and set before a patch is executed.
Options are useful for making patches configurable. Options are useful for making patches configurable.
After loading the patches using `PatchLoader`, options can be set for a patch. After loading the patches using `PatchLoader`, options can be set for a patch.
Multiple types are already inbuilt in ReVanced Patcher and are supported by any application that uses ReVanced Patcher. Multiple types are already built into ReVanced Patcher and are supported by any application that uses ReVanced Patcher.
To define an option, use available `option` functions: To define an option, use the available `option` functions:
```kt ```kt
val patch = bytecodePatch(name = "Patch") { val patch = bytecodePatch(name = "Patch") {
@@ -149,9 +149,21 @@ The type of an option can be obtained from the `type` property of the option:
option.type // The KType of the option. option.type // The KType of the option.
``` ```
Options can be declared outside of a patch and added to a patch manually:
```kt
val option = stringOption(key = "option")
bytecodePatch(name = "Patch") {
val value by option()
}
```
This is useful when the same option is referenced in multiple patches.
### 🧩 Extensions ### 🧩 Extensions
An extension is a precompiled DEX file that is merged into the patched app before a patch is executed. An extension is a precompiled DEX file merged into the patched app before a patch is executed.
While patches are compile-time constructs, extensions are runtime constructs While patches are compile-time constructs, extensions are runtime constructs
that extend the patched app with additional classes. that extend the patched app with additional classes.
@@ -232,13 +244,13 @@ The same order is followed for multiple patches depending on the patch.
## 💡 Additional tips ## 💡 Additional tips
- When using ´PatchLoader` to load patches, only patches with a name are loaded. - When using `PatchLoader` to load patches, only patches with a name are loaded.
Refer to the inline documentation of `PatchLoader` for detailed information. Refer to the inline documentation of `PatchLoader` for detailed information.
- Patches can depend on others. Dependencies are executed first. - Patches can depend on others. Dependencies are executed first.
The dependent patch will not be executed if a dependency raises an exception while executing. The dependent patch will not be executed if a dependency raises an exception while executing.
- A patch can declare compatibility with specific packages and versions, - A patch can declare compatibility with specific packages and versions,
but patches can still be executed on any package or version. but patches can still be executed on any package or version.
It is recommended to declare compatibility to present known compatible packages and versions. It is recommended that compatibility is specified to present known compatible packages and versions.
- If `compatibleWith` is not used, the patch is treated as compatible with any package - If `compatibleWith` is not used, the patch is treated as compatible with any package
- If a package is specified with no versions, the patch is compatible with any version of the package - If a package is specified with no versions, the patch is compatible with any version of the package
- If an empty array of versions is specified, the patch is not compatible with any version of the package. - If an empty array of versions is specified, the patch is not compatible with any version of the package.

View File

@@ -1,3 +1,3 @@
org.gradle.parallel = true org.gradle.parallel = true
org.gradle.caching = true org.gradle.caching = true
version = 20.0.0-dev.1 version = 20.0.0-dev.4

View File

@@ -1,20 +1,22 @@
[versions] [versions]
android = "4.1.1.4" android = "4.1.1.4"
apktool-lib = "2.9.3" apktool-lib = "2.9.3"
kotlin = "1.9.22" binary-compatibility-validator = "0.15.1"
kotlinx-coroutines-core = "1.7.3" kotlin = "2.0.0"
kotlinx-coroutines-core = "1.8.1"
mockk = "1.13.10" mockk = "1.13.10"
multidexlib2 = "3.0.3.r3" multidexlib2 = "3.0.3.r3"
# Tracking https://github.com/google/smali/issues/64.
#noinspection GradleDependency
smali = "3.0.5" smali = "3.0.5"
binary-compatibility-validator = "0.14.0"
xpp3 = "1.1.4c" xpp3 = "1.1.4c"
[libraries] [libraries]
android = { module = "com.google.android:android", version.ref = "android" } android = { module = "com.google.android:android", version.ref = "android" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
apktool-lib = { module = "app.revanced:apktool-lib", version.ref = "apktool-lib" } apktool-lib = { module = "app.revanced:apktool-lib", version.ref = "apktool-lib" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
multidexlib2 = { module = "app.revanced:multidexlib2", version.ref = "multidexlib2" } multidexlib2 = { module = "app.revanced:multidexlib2", version.ref = "multidexlib2" }
smali = { module = "com.android.tools.smali:smali", version.ref = "smali" } smali = { module = "com.android.tools.smali:smali", version.ref = "smali" }

View File

@@ -3,8 +3,7 @@
package app.revanced.patcher package app.revanced.patcher
import app.revanced.patcher.extensions.InstructionExtensions.instructionsOrNull import app.revanced.patcher.extensions.InstructionExtensions.instructionsOrNull
import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.BytecodePatchContext.LookupMaps.Companion.appendParameters import app.revanced.patcher.patch.BytecodePatchContext.LookupMaps.Companion.appendParameters
import app.revanced.patcher.patch.MethodClassPairs import app.revanced.patcher.patch.MethodClassPairs
import app.revanced.patcher.util.proxy.ClassProxy import app.revanced.patcher.util.proxy.ClassProxy

View File

@@ -39,9 +39,6 @@ class Patcher(private val config: PatcherConfig) : Closeable {
patch.addRecursively() patch.addRecursively()
} }
fun Patch<*>.anyRecursively(predicate: (Patch<*>) -> Boolean): Boolean =
predicate(this) || dependencies.any { dependency -> dependency.anyRecursively(predicate) }
context.allPatches.let { allPatches -> context.allPatches.let { allPatches ->
// Check, if what kind of resource mode is required. // Check, if what kind of resource mode is required.
config.resourceMode = if (allPatches.any { patch -> patch.anyRecursively { it is ResourcePatch } }) { config.resourceMode = if (allPatches.any { patch -> patch.anyRecursively { it is ResourcePatch } }) {
@@ -99,6 +96,17 @@ class Patcher(private val config: PatcherConfig) : Closeable {
context.resourceContext.decodeResources(config.resourceMode) context.resourceContext.decodeResources(config.resourceMode)
} }
logger.info("Merging extensions")
context.executablePatches.forEachRecursively { patch ->
if (patch is BytecodePatch && patch.extension != null) {
context.bytecodeContext.merge(patch.extension)
}
}
// Initialize lookup maps.
context.bytecodeContext.lookupMaps
logger.info("Executing patches") logger.info("Executing patches")
val executedPatches = LinkedHashMap<Patch<*>, PatchResult>() val executedPatches = LinkedHashMap<Patch<*>, PatchResult>()
@@ -146,7 +154,7 @@ class Patcher(private val config: PatcherConfig) : Closeable {
} }
} }
override fun close() = context.bytecodeContext.lookupMaps.close() override fun close() = context.close()
/** /**
* Compile and save patched APK files. * Compile and save patched APK files.

View File

@@ -5,6 +5,7 @@ import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.ResourcePatchContext import app.revanced.patcher.patch.ResourcePatchContext
import brut.androlib.apk.ApkInfo import brut.androlib.apk.ApkInfo
import brut.directory.ExtFile import brut.directory.ExtFile
import java.io.Closeable
/** /**
* A context for the patcher containing the current state of the patcher. * A context for the patcher containing the current state of the patcher.
@@ -12,7 +13,7 @@ import brut.directory.ExtFile
* @param config The configuration for the patcher. * @param config The configuration for the patcher.
*/ */
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
class PatcherContext internal constructor(config: PatcherConfig) { class PatcherContext internal constructor(config: PatcherConfig): Closeable {
/** /**
* [PackageMetadata] of the supplied [PatcherConfig.apkFile]. * [PackageMetadata] of the supplied [PatcherConfig.apkFile].
*/ */
@@ -37,4 +38,6 @@ class PatcherContext internal constructor(config: PatcherConfig) {
* The context for patches containing the current state of the bytecode. * The context for patches containing the current state of the bytecode.
*/ */
internal val bytecodeContext = BytecodePatchContext(config) internal val bytecodeContext = BytecodePatchContext(config)
override fun close() = bytecodeContext.close()
} }

View File

@@ -31,7 +31,9 @@ import java.util.logging.Logger
* @param config The [PatcherConfig] used to create this context. * @param config The [PatcherConfig] used to create this context.
*/ */
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
class BytecodePatchContext internal constructor(private val config: PatcherConfig) : PatchContext<Set<PatcherResult.PatchedDexFile>> { class BytecodePatchContext internal constructor(private val config: PatcherConfig) :
PatchContext<Set<PatcherResult.PatchedDexFile>>,
Closeable {
private val logger = Logger.getLogger(BytecodePatchContext::class.java.name) private val logger = Logger.getLogger(BytecodePatchContext::class.java.name)
/** /**
@@ -57,6 +59,13 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
*/ */
internal val lookupMaps by lazy { LookupMaps(classes) } internal val lookupMaps by lazy { LookupMaps(classes) }
/**
* A map for lookup by [merge].
*/
internal val classesByType = mutableMapOf<String, ClassDef>().apply {
classes.forEach { classDef -> put(classDef.type, classDef) }
}
/** /**
* Merge an extension to [classes]. * Merge an extension to [classes].
* *
@@ -66,11 +75,11 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
val extension = extensionInputStream.readAllBytes() val extension = extensionInputStream.readAllBytes()
RawDexIO.readRawDexFile(extension, 0, null).classes.forEach { classDef -> RawDexIO.readRawDexFile(extension, 0, null).classes.forEach { classDef ->
val existingClass = lookupMaps.classesByType[classDef.type] ?: run { val existingClass = classesByType[classDef.type] ?: run {
logger.fine("Adding class \"$classDef\"") logger.fine("Adding class \"$classDef\"")
lookupMaps.classesByType[classDef.type] = classDef
classes += classDef classes += classDef
classesByType[classDef.type] = classDef
return@forEach return@forEach
} }
@@ -254,6 +263,12 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
methodsByStrings.clear() methodsByStrings.clear()
} }
} }
override fun close() {
lookupMaps.close()
classesByType.clear()
classes.clear()
}
} }
/** /**

View File

@@ -100,7 +100,7 @@ class Option<T> @PublishedApi internal constructor(
} }
/** /**
* A collection of [Option]s where options can be set and retrieved by key. * A collection of [Option]s where options can be set and retrieved by their key.
* *
* @param options The options. * @param options The options.
* *
@@ -143,6 +143,39 @@ class Options internal constructor(
override fun get(key: String) = options[key] ?: throw OptionException.OptionNotFoundException(key) override fun get(key: String) = options[key] ?: throw OptionException.OptionNotFoundException(key)
} }
/**
* Create a new [Option] with a string value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun stringOption(
key: String,
default: String? = null,
values: Map<String, String?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<String>.(String?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with a string value and add it to the current [PatchBuilder]. * Create a new [Option] with a string value and add it to the current [PatchBuilder].
* *
@@ -176,6 +209,39 @@ fun PatchBuilder<*>.stringOption(
validator, validator,
) )
/**
* Create a new [Option] with an integer value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun intOption(
key: String,
default: Int? = null,
values: Map<String, Int?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<Int?>.(Int?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with an integer value and add it to the current [PatchBuilder]. * Create a new [Option] with an integer value and add it to the current [PatchBuilder].
* *
@@ -209,6 +275,39 @@ fun PatchBuilder<*>.intOption(
validator, validator,
) )
/**
* Create a new [Option] with a boolean value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun booleanOption(
key: String,
default: Boolean? = null,
values: Map<String, Boolean?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<Boolean?>.(Boolean?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with a boolean value and add it to the current [PatchBuilder]. * Create a new [Option] with a boolean value and add it to the current [PatchBuilder].
* *
@@ -242,6 +341,39 @@ fun PatchBuilder<*>.booleanOption(
validator, validator,
) )
/**
* Create a new [Option] with a float value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun floatOption(
key: String,
default: Float? = null,
values: Map<String, Float?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<Float?>.(Float?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with a float value and add it to the current [PatchBuilder]. * Create a new [Option] with a float value and add it to the current [PatchBuilder].
* *
@@ -275,6 +407,39 @@ fun PatchBuilder<*>.floatOption(
validator, validator,
) )
/**
* Create a new [Option] with a long value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun longOption(
key: String,
default: Long? = null,
values: Map<String, Long?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<Long?>.(Long?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with a long value and add it to the current [PatchBuilder]. * Create a new [Option] with a long value and add it to the current [PatchBuilder].
* *
@@ -308,6 +473,39 @@ fun PatchBuilder<*>.longOption(
validator, validator,
) )
/**
* Create a new [Option] with a string list value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun stringsOption(
key: String,
default: List<String>? = null,
values: Map<String, List<String>?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<List<String>>.(List<String>?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with a string list value and add it to the current [PatchBuilder]. * Create a new [Option] with a string list value and add it to the current [PatchBuilder].
* *
@@ -341,6 +539,39 @@ fun PatchBuilder<*>.stringsOption(
validator, validator,
) )
/**
* Create a new [Option] with an integer list value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun intsOption(
key: String,
default: List<Int>? = null,
values: Map<String, List<Int>?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<List<Int>>.(List<Int>?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with an integer list value and add it to the current [PatchBuilder]. * Create a new [Option] with an integer list value and add it to the current [PatchBuilder].
* *
@@ -374,6 +605,39 @@ fun PatchBuilder<*>.intsOption(
validator, validator,
) )
/**
* Create a new [Option] with a boolean list value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun booleansOption(
key: String,
default: List<Boolean>? = null,
values: Map<String, List<Boolean>?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<List<Boolean>>.(List<Boolean>?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with a boolean list value and add it to the current [PatchBuilder]. * Create a new [Option] with a boolean list value and add it to the current [PatchBuilder].
* *
@@ -440,6 +704,39 @@ fun PatchBuilder<*>.floatsOption(
validator, validator,
) )
/**
* Create a new [Option] with a long list value.
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
fun longsOption(
key: String,
default: List<Long>? = null,
values: Map<String, List<Long>?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: Option<List<Long>>.(List<Long>?) -> Boolean = { true },
) = option(
key,
default,
values,
title,
description,
required,
validator,
)
/** /**
* Create a new [Option] with a long list value and add it to the current [PatchBuilder]. * Create a new [Option] with a long list value and add it to the current [PatchBuilder].
* *
@@ -473,6 +770,40 @@ fun PatchBuilder<*>.longsOption(
validator, validator,
) )
/**
* Create a new [Option].
*
* @param key The key.
* @param default The default value.
* @param values Eligible option values mapped to a human-readable name.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validator The function to validate the option value.
*
* @return The created [Option].
*
* @see Option
*/
inline fun <reified T> option(
key: String,
default: T? = null,
values: Map<String, T?>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
noinline validator: Option<T>.(T?) -> Boolean = { true },
) = Option(
key,
default,
values,
title,
description,
required,
typeOf<T>(),
validator,
)
/** /**
* Create a new [Option] and add it to the current [PatchBuilder]. * Create a new [Option] and add it to the current [PatchBuilder].
* *
@@ -496,14 +827,13 @@ inline fun <reified T> PatchBuilder<*>.option(
description: String? = null, description: String? = null,
required: Boolean = false, required: Boolean = false,
noinline validator: Option<T>.(T?) -> Boolean = { true }, noinline validator: Option<T>.(T?) -> Boolean = { true },
) = Option( ) = app.revanced.patcher.patch.option(
key, key,
default, default,
values, values,
title, title,
description, description,
required, required,
typeOf<T>(),
validator, validator,
).also { it() } ).also { it() }
@@ -519,30 +849,26 @@ sealed class OptionException(errorMessage: String) : Exception(errorMessage, nul
* @param invalidType The type of the value that was passed. * @param invalidType The type of the value that was passed.
* @param expectedType The type of the value that was expected. * @param expectedType The type of the value that was expected.
*/ */
class InvalidValueTypeException(invalidType: String, expectedType: String) : class InvalidValueTypeException(invalidType: String, expectedType: String) : OptionException("Type $expectedType was expected but received type $invalidType")
OptionException("Type $expectedType was expected but received type $invalidType")
/** /**
* An exception thrown when a value did not satisfy the value conditions specified by the [Option]. * An exception thrown when a value did not satisfy the value conditions specified by the [Option].
* *
* @param value The value that failed validation. * @param value The value that failed validation.
*/ */
class ValueValidationException(value: Any?, option: Option<*>) : class ValueValidationException(value: Any?, option: Option<*>) : OptionException("The option value \"$value\" failed validation for ${option.key}")
OptionException("The option value \"$value\" failed validation for ${option.key}")
/** /**
* An exception thrown when a value is required but null was passed. * An exception thrown when a value is required but null was passed.
* *
* @param option The [Option] that requires a value. * @param option The [Option] that requires a value.
*/ */
class ValueRequiredException(option: Option<*>) : class ValueRequiredException(option: Option<*>) : OptionException("The option ${option.key} requires a value, but the value was null")
OptionException("The option ${option.key} requires a value, but null was passed")
/** /**
* An exception thrown when a [Option] is not found. * An exception thrown when a [Option] is not found.
* *
* @param key The key of the [Option]. * @param key The key of the [Option].
*/ */
class OptionNotFoundException(key: String) : class OptionNotFoundException(key: String) : OptionException("No option with key $key")
OptionException("No option with key $key")
} }

View File

@@ -48,6 +48,9 @@ sealed class Patch<C : PatchContext<*>>(
// if a patch has a finalizing block in order to not emit it twice. // if a patch has a finalizing block in order to not emit it twice.
internal var finalizeBlock: (Patch<C>.(C) -> Unit)?, internal var finalizeBlock: (Patch<C>.(C) -> Unit)?,
) { ) {
/**
* The options of the patch.
*/
val options = Options(options) val options = Options(options)
/** /**
@@ -85,6 +88,31 @@ sealed class Patch<C : PatchContext<*>>(
override fun toString() = name ?: "Patch" override fun toString() = name ?: "Patch"
} }
internal fun Patch<*>.anyRecursively(
visited: MutableSet<Patch<*>> = mutableSetOf(),
predicate: (Patch<*>) -> Boolean,
): Boolean {
if (this in visited) return false
if (predicate(this)) return true
visited += this
return dependencies.any { it.anyRecursively(visited, predicate) }
}
internal fun Iterable<Patch<*>>.forEachRecursively(
visited: MutableSet<Patch<*>> = mutableSetOf(),
action: (Patch<*>) -> Unit,
): Unit = forEach {
if (it in visited) return@forEach
visited += it
action(it)
it.dependencies.forEachRecursively(visited, action)
}
/** /**
* A bytecode patch. * A bytecode patch.
* *
@@ -127,7 +155,6 @@ class BytecodePatch internal constructor(
finalizeBlock, finalizeBlock,
) { ) {
override fun execute(context: PatcherContext) = with(context.bytecodeContext) { override fun execute(context: PatcherContext) = with(context.bytecodeContext) {
extension?.let(::merge)
fingerprints.forEach { it.match(this) } fingerprints.forEach { it.match(this) }
execute(this) execute(this)
@@ -268,7 +295,14 @@ sealed class PatchBuilder<C : PatchContext<*>>(
* *
* @param versions The versions of the package. * @param versions The versions of the package.
*/ */
operator fun String.invoke(vararg versions: String) = this to versions.toSet() operator fun String.invoke(vararg versions: String) = invoke(versions.toSet())
/**
* Create a package a patch is compatible with.
*
* @param versions The versions of the package.
*/
private operator fun String.invoke(versions: Set<String>? = null) = this to versions
/** /**
* Add packages the patch is compatible with. * Add packages the patch is compatible with.
@@ -325,6 +359,16 @@ sealed class PatchBuilder<C : PatchContext<*>>(
internal abstract fun build(): Patch<C> internal abstract fun build(): Patch<C>
} }
/**
* Builds a [Patch].
*
* @param B The [PatchBuilder] to build the patch with.
* @param block The block to build the patch.
*
* @return The built [Patch].
*/
private fun <B : PatchBuilder<*>> B.buildPatch(block: B.() -> Unit = {}) = apply(block).build()
/** /**
* A [BytecodePatchBuilder] builder. * A [BytecodePatchBuilder] builder.
* *
@@ -352,13 +396,13 @@ class BytecodePatchBuilder internal constructor(
*/ */
operator fun Fingerprint.invoke() = InvokedFingerprint(also { fingerprints.add(it) }) operator fun Fingerprint.invoke() = InvokedFingerprint(also { fingerprints.add(it) })
class InvokedFingerprint(private val fingerprint: Fingerprint) { class InvokedFingerprint internal constructor(private val fingerprint: Fingerprint) {
// The reason getValue isn't extending the Fingerprint class is // The reason getValue isn't extending the Fingerprint class is
// because delegating makes only sense if the fingerprint was previously added to the patch by invoking it. // because delegating makes only sense if the fingerprint was previously added to the patch by invoking it.
// It may be likely to forget invoking it. By wrapping the fingerprint into this class, // It may be likely to forget invoking it. By wrapping the fingerprint into this class,
// the compiler will throw an error if the fingerprint was not invoked if attempting to delegate the match. // the compiler will throw an error if the fingerprint was not invoked if attempting to delegate the match.
operator fun getValue(nothing: Nothing?, property: KProperty<*>) = fingerprint.match operator fun getValue(nothing: Nothing?, property: KProperty<*>) = fingerprint.match
?: throw PatchException("No fingerprint match to delegate to ${property.name}.") ?: throw PatchException("No fingerprint match to delegate to \"${property.name}\".")
} }
// Must be internal for the inlined function "extendWith". // Must be internal for the inlined function "extendWith".
@@ -372,9 +416,10 @@ class BytecodePatchBuilder internal constructor(
* *
* @param extension The name of the extension resource. * @param extension The name of the extension resource.
*/ */
@Suppress("NOTHING_TO_INLINE")
inline fun extendWith(extension: String) = apply { inline fun extendWith(extension: String) = apply {
this.extension = object {}.javaClass.classLoader.getResourceAsStream(extension) this.extension = object {}.javaClass.classLoader.getResourceAsStream(extension)
?: throw PatchException("Extension resource \"$extension\" not found") ?: throw PatchException("Extension \"$extension\" not found")
} }
override fun build() = BytecodePatch( override fun build() = BytecodePatch(
@@ -391,6 +436,24 @@ class BytecodePatchBuilder internal constructor(
) )
} }
/**
* Create a new [BytecodePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
*
* @return The created [BytecodePatch].
*/
fun bytecodePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: BytecodePatchBuilder.() -> Unit = {},
) = BytecodePatchBuilder(name, description, use).buildPatch(block) as BytecodePatch
/** /**
* A [RawResourcePatch] builder. * A [RawResourcePatch] builder.
* *
@@ -418,6 +481,23 @@ class RawResourcePatchBuilder internal constructor(
) )
} }
/**
* Create a new [RawResourcePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
* @return The created [RawResourcePatch].
*/
fun rawResourcePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: RawResourcePatchBuilder.() -> Unit = {},
) = RawResourcePatchBuilder(name, description, use).buildPatch(block) as RawResourcePatch
/** /**
* A [ResourcePatch] builder. * A [ResourcePatch] builder.
* *
@@ -445,51 +525,6 @@ class ResourcePatchBuilder internal constructor(
) )
} }
/**
* Builds a [Patch].
*
* @param B The [PatchBuilder] to build the patch with.
* @param block The block to build the patch.
*
* @return The built [Patch].
*/
private fun <B : PatchBuilder<*>> B.buildPatch(block: B.() -> Unit = {}) = apply(block).build()
/**
* Create a new [BytecodePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
*
* @return The created [BytecodePatch].
*/
fun bytecodePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: BytecodePatchBuilder.() -> Unit = {},
) = BytecodePatchBuilder(name, description, use).buildPatch(block) as BytecodePatch
/**
* Create a new [RawResourcePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
* @return The created [RawResourcePatch].
*/
fun rawResourcePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: RawResourcePatchBuilder.() -> Unit = {},
) = RawResourcePatchBuilder(name, description, use).buildPatch(block) as RawResourcePatch
/** /**
* Create a new [ResourcePatch]. * Create a new [ResourcePatch].
* *

View File

@@ -9,21 +9,13 @@ class MutableAnnotation(annotation: Annotation) : BaseAnnotation() {
private val type = annotation.type private val type = annotation.type
private val _elements by lazy { annotation.elements.map { element -> element.toMutable() }.toMutableSet() } private val _elements by lazy { annotation.elements.map { element -> element.toMutable() }.toMutableSet() }
override fun getType(): String { override fun getType(): String = type
return type
}
override fun getElements(): MutableSet<MutableAnnotationElement> { override fun getElements(): MutableSet<MutableAnnotationElement> = _elements
return _elements
}
override fun getVisibility(): Int { override fun getVisibility(): Int = visibility
return visibility
}
companion object { companion object {
fun Annotation.toMutable(): MutableAnnotation { fun Annotation.toMutable(): MutableAnnotation = MutableAnnotation(this)
return MutableAnnotation(this)
}
} }
} }

View File

@@ -18,17 +18,11 @@ class MutableAnnotationElement(annotationElement: AnnotationElement) : BaseAnnot
this.value = value this.value = value
} }
override fun getName(): String { override fun getName(): String = name
return name
}
override fun getValue(): EncodedValue { override fun getValue(): EncodedValue = value
return value
}
companion object { companion object {
fun AnnotationElement.toMutable(): MutableAnnotationElement { fun AnnotationElement.toMutable(): MutableAnnotationElement = MutableAnnotationElement(this)
return MutableAnnotationElement(this)
}
} }
} }

View File

@@ -7,9 +7,10 @@ import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference
import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.util.FieldUtil import com.android.tools.smali.dexlib2.util.FieldUtil
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
import com.google.common.collect.Iterables
class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() { class MutableClass(classDef: ClassDef) :
BaseTypeReference(),
ClassDef {
// Class // Class
private var type = classDef.type private var type = classDef.type
private var sourceFile = classDef.sourceFile private var sourceFile = classDef.sourceFile
@@ -23,13 +24,13 @@ class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
// Methods // Methods
private val _methods by lazy { classDef.methods.map { method -> method.toMutable() }.toMutableSet() } private val _methods by lazy { classDef.methods.map { method -> method.toMutable() }.toMutableSet() }
private val _directMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_DIRECT).toMutableSet() } private val _directMethods by lazy { _methods.filter { method -> MethodUtil.isDirect(method) }.toMutableSet() }
private val _virtualMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_VIRTUAL).toMutableSet() } private val _virtualMethods by lazy { _methods.filter { method -> !MethodUtil.isDirect(method) }.toMutableSet() }
// Fields // Fields
private val _fields by lazy { classDef.fields.map { field -> field.toMutable() }.toMutableSet() } private val _fields by lazy { classDef.fields.map { field -> field.toMutable() }.toMutableSet() }
private val _staticFields by lazy { Iterables.filter(_fields, FieldUtil.FIELD_IS_STATIC).toMutableSet() } private val _staticFields by lazy { _fields.filter { field -> FieldUtil.isStatic(field) }.toMutableSet() }
private val _instanceFields by lazy { Iterables.filter(_fields, FieldUtil.FIELD_IS_INSTANCE).toMutableSet() } private val _instanceFields by lazy { _fields.filter { field -> !FieldUtil.isStatic(field) }.toMutableSet() }
fun setType(type: String) { fun setType(type: String) {
this.type = type this.type = type
@@ -47,57 +48,31 @@ class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
this.superclass = superclass this.superclass = superclass
} }
override fun getType(): String { override fun getType(): String = type
return type
}
override fun getAccessFlags(): Int { override fun getAccessFlags(): Int = accessFlags
return accessFlags
}
override fun getSourceFile(): String? { override fun getSourceFile(): String? = sourceFile
return sourceFile
}
override fun getSuperclass(): String? { override fun getSuperclass(): String? = superclass
return superclass
}
override fun getInterfaces(): MutableList<String> { override fun getInterfaces(): MutableList<String> = _interfaces
return _interfaces
}
override fun getAnnotations(): MutableSet<MutableAnnotation> { override fun getAnnotations(): MutableSet<MutableAnnotation> = _annotations
return _annotations
}
override fun getStaticFields(): MutableSet<MutableField> { override fun getStaticFields(): MutableSet<MutableField> = _staticFields
return _staticFields
}
override fun getInstanceFields(): MutableSet<MutableField> { override fun getInstanceFields(): MutableSet<MutableField> = _instanceFields
return _instanceFields
}
override fun getFields(): MutableSet<MutableField> { override fun getFields(): MutableSet<MutableField> = _fields
return _fields
}
override fun getDirectMethods(): MutableSet<MutableMethod> { override fun getDirectMethods(): MutableSet<MutableMethod> = _directMethods
return _directMethods
}
override fun getVirtualMethods(): MutableSet<MutableMethod> { override fun getVirtualMethods(): MutableSet<MutableMethod> = _virtualMethods
return _virtualMethods
}
override fun getMethods(): MutableSet<MutableMethod> { override fun getMethods(): MutableSet<MutableMethod> = _methods
return _methods
}
companion object { companion object {
fun ClassDef.toMutable(): MutableClass { fun ClassDef.toMutable(): MutableClass = MutableClass(this)
return MutableClass(this)
}
} }
} }

View File

@@ -7,7 +7,9 @@ import com.android.tools.smali.dexlib2.HiddenApiRestriction
import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference
import com.android.tools.smali.dexlib2.iface.Field import com.android.tools.smali.dexlib2.iface.Field
class MutableField(field: Field) : Field, BaseFieldReference() { class MutableField(field: Field) :
BaseFieldReference(),
Field {
private var definingClass = field.definingClass private var definingClass = field.definingClass
private var name = field.name private var name = field.name
private var type = field.type private var type = field.type
@@ -37,37 +39,21 @@ class MutableField(field: Field) : Field, BaseFieldReference() {
this.initialValue = initialValue this.initialValue = initialValue
} }
override fun getDefiningClass(): String { override fun getDefiningClass(): String = this.definingClass
return this.definingClass
}
override fun getName(): String { override fun getName(): String = this.name
return this.name
}
override fun getType(): String { override fun getType(): String = this.type
return this.type
}
override fun getAnnotations(): MutableSet<MutableAnnotation> { override fun getAnnotations(): MutableSet<MutableAnnotation> = this._annotations
return this._annotations
}
override fun getAccessFlags(): Int { override fun getAccessFlags(): Int = this.accessFlags
return this.accessFlags
}
override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> { override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> = this._hiddenApiRestrictions
return this._hiddenApiRestrictions
}
override fun getInitialValue(): MutableEncodedValue? { override fun getInitialValue(): MutableEncodedValue? = this.initialValue
return this.initialValue
}
companion object { companion object {
fun Field.toMutable(): MutableField { fun Field.toMutable(): MutableField = MutableField(this)
return MutableField(this)
}
} }
} }

View File

@@ -7,7 +7,9 @@ import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
class MutableMethod(method: Method) : Method, BaseMethodReference() { class MutableMethod(method: Method) :
BaseMethodReference(),
Method {
private var definingClass = method.definingClass private var definingClass = method.definingClass
private var name = method.name private var name = method.name
private var accessFlags = method.accessFlags private var accessFlags = method.accessFlags
@@ -36,45 +38,25 @@ class MutableMethod(method: Method) : Method, BaseMethodReference() {
this.returnType = returnType this.returnType = returnType
} }
override fun getDefiningClass(): String { override fun getDefiningClass(): String = definingClass
return definingClass
}
override fun getName(): String { override fun getName(): String = name
return name
}
override fun getParameterTypes(): MutableList<CharSequence> { override fun getParameterTypes(): MutableList<CharSequence> = _parameterTypes
return _parameterTypes
}
override fun getReturnType(): String { override fun getReturnType(): String = returnType
return returnType
}
override fun getAnnotations(): MutableSet<MutableAnnotation> { override fun getAnnotations(): MutableSet<MutableAnnotation> = _annotations
return _annotations
}
override fun getAccessFlags(): Int { override fun getAccessFlags(): Int = accessFlags
return accessFlags
}
override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> { override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> = _hiddenApiRestrictions
return _hiddenApiRestrictions
}
override fun getParameters(): MutableList<MutableMethodParameter> { override fun getParameters(): MutableList<MutableMethodParameter> = _parameters
return _parameters
}
override fun getImplementation(): MutableMethodImplementation? { override fun getImplementation(): MutableMethodImplementation? = _implementation
return _implementation
}
companion object { companion object {
fun Method.toMutable(): MutableMethod { fun Method.toMutable(): MutableMethod = MutableMethod(this)
return MutableMethod(this)
}
} }
} }

View File

@@ -5,7 +5,9 @@ import com.android.tools.smali.dexlib2.base.BaseMethodParameter
import com.android.tools.smali.dexlib2.iface.MethodParameter import com.android.tools.smali.dexlib2.iface.MethodParameter
// TODO: finish overriding all members if necessary // TODO: finish overriding all members if necessary
class MutableMethodParameter(parameter: MethodParameter) : MethodParameter, BaseMethodParameter() { class MutableMethodParameter(parameter: MethodParameter) :
BaseMethodParameter(),
MethodParameter {
private var type = parameter.type private var type = parameter.type
private var name = parameter.name private var name = parameter.name
private var signature = parameter.signature private var signature = parameter.signature
@@ -13,25 +15,15 @@ class MutableMethodParameter(parameter: MethodParameter) : MethodParameter, Base
parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet()
} }
override fun getType(): String { override fun getType(): String = type
return type
}
override fun getName(): String? { override fun getName(): String? = name
return name
}
override fun getSignature(): String? { override fun getSignature(): String? = signature
return signature
}
override fun getAnnotations(): MutableSet<MutableAnnotation> { override fun getAnnotations(): MutableSet<MutableAnnotation> = _annotations
return _annotations
}
companion object { companion object {
fun MethodParameter.toMutable(): MutableMethodParameter { fun MethodParameter.toMutable(): MutableMethodParameter = MutableMethodParameter(this)
return MutableMethodParameter(this)
}
} }
} }

View File

@@ -14,21 +14,15 @@ class MutableAnnotationEncodedValue(annotationEncodedValue: AnnotationEncodedVal
annotationEncodedValue.elements.map { annotationElement -> annotationElement.toMutable() }.toMutableSet() annotationEncodedValue.elements.map { annotationElement -> annotationElement.toMutable() }.toMutableSet()
} }
override fun getType(): String { override fun getType(): String = this.type
return this.type
}
fun setType(type: String) { fun setType(type: String) {
this.type = type this.type = type
} }
override fun getElements(): MutableSet<out AnnotationElement> { override fun getElements(): MutableSet<out AnnotationElement> = _elements
return _elements
}
companion object { companion object {
fun AnnotationEncodedValue.toMutable(): MutableAnnotationEncodedValue { fun AnnotationEncodedValue.toMutable(): MutableAnnotationEncodedValue = MutableAnnotationEncodedValue(this)
return MutableAnnotationEncodedValue(this)
}
} }
} }

View File

@@ -5,18 +5,16 @@ import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue
import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue
import com.android.tools.smali.dexlib2.iface.value.EncodedValue import com.android.tools.smali.dexlib2.iface.value.EncodedValue
class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) : BaseArrayEncodedValue(), MutableEncodedValue { class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) :
BaseArrayEncodedValue(),
MutableEncodedValue {
private val _value by lazy { private val _value by lazy {
arrayEncodedValue.value.map { encodedValue -> encodedValue.toMutable() }.toMutableList() arrayEncodedValue.value.map { encodedValue -> encodedValue.toMutable() }.toMutableList()
} }
override fun getValue(): MutableList<out EncodedValue> { override fun getValue(): MutableList<out EncodedValue> = _value
return _value
}
companion object { companion object {
fun ArrayEncodedValue.toMutable(): MutableArrayEncodedValue { fun ArrayEncodedValue.toMutable(): MutableArrayEncodedValue = MutableArrayEncodedValue(this)
return MutableArrayEncodedValue(this)
}
} }
} }

View File

@@ -8,17 +8,13 @@ class MutableBooleanEncodedValue(booleanEncodedValue: BooleanEncodedValue) :
MutableEncodedValue { MutableEncodedValue {
private var value = booleanEncodedValue.value private var value = booleanEncodedValue.value
override fun getValue(): Boolean { override fun getValue(): Boolean = this.value
return this.value
}
fun setValue(value: Boolean) { fun setValue(value: Boolean) {
this.value = value this.value = value
} }
companion object { companion object {
fun BooleanEncodedValue.toMutable(): MutableBooleanEncodedValue { fun BooleanEncodedValue.toMutable(): MutableBooleanEncodedValue = MutableBooleanEncodedValue(this)
return MutableBooleanEncodedValue(this)
}
} }
} }

View File

@@ -3,20 +3,18 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseByteEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseByteEncodedValue
import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue
class MutableByteEncodedValue(byteEncodedValue: ByteEncodedValue) : BaseByteEncodedValue(), MutableEncodedValue { class MutableByteEncodedValue(byteEncodedValue: ByteEncodedValue) :
BaseByteEncodedValue(),
MutableEncodedValue {
private var value = byteEncodedValue.value private var value = byteEncodedValue.value
override fun getValue(): Byte { override fun getValue(): Byte = this.value
return this.value
}
fun setValue(value: Byte) { fun setValue(value: Byte) {
this.value = value this.value = value
} }
companion object { companion object {
fun ByteEncodedValue.toMutable(): MutableByteEncodedValue { fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this)
return MutableByteEncodedValue(this)
}
} }
} }

View File

@@ -3,20 +3,18 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseCharEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseCharEncodedValue
import com.android.tools.smali.dexlib2.iface.value.CharEncodedValue import com.android.tools.smali.dexlib2.iface.value.CharEncodedValue
class MutableCharEncodedValue(charEncodedValue: CharEncodedValue) : BaseCharEncodedValue(), MutableEncodedValue { class MutableCharEncodedValue(charEncodedValue: CharEncodedValue) :
BaseCharEncodedValue(),
MutableEncodedValue {
private var value = charEncodedValue.value private var value = charEncodedValue.value
override fun getValue(): Char { override fun getValue(): Char = this.value
return this.value
}
fun setValue(value: Char) { fun setValue(value: Char) {
this.value = value this.value = value
} }
companion object { companion object {
fun CharEncodedValue.toMutable(): MutableCharEncodedValue { fun CharEncodedValue.toMutable(): MutableCharEncodedValue = MutableCharEncodedValue(this)
return MutableCharEncodedValue(this)
}
} }
} }

View File

@@ -8,17 +8,13 @@ class MutableDoubleEncodedValue(doubleEncodedValue: DoubleEncodedValue) :
MutableEncodedValue { MutableEncodedValue {
private var value = doubleEncodedValue.value private var value = doubleEncodedValue.value
override fun getValue(): Double { override fun getValue(): Double = this.value
return this.value
}
fun setValue(value: Double) { fun setValue(value: Double) {
this.value = value this.value = value
} }
companion object { companion object {
fun DoubleEncodedValue.toMutable(): MutableDoubleEncodedValue { fun DoubleEncodedValue.toMutable(): MutableDoubleEncodedValue = MutableDoubleEncodedValue(this)
return MutableDoubleEncodedValue(this)
}
} }
} }

View File

@@ -4,20 +4,18 @@ import com.android.tools.smali.dexlib2.base.value.BaseEnumEncodedValue
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.value.EnumEncodedValue import com.android.tools.smali.dexlib2.iface.value.EnumEncodedValue
class MutableEnumEncodedValue(enumEncodedValue: EnumEncodedValue) : BaseEnumEncodedValue(), MutableEncodedValue { class MutableEnumEncodedValue(enumEncodedValue: EnumEncodedValue) :
BaseEnumEncodedValue(),
MutableEncodedValue {
private var value = enumEncodedValue.value private var value = enumEncodedValue.value
override fun getValue(): FieldReference { override fun getValue(): FieldReference = this.value
return this.value
}
fun setValue(value: FieldReference) { fun setValue(value: FieldReference) {
this.value = value this.value = value
} }
companion object { companion object {
fun EnumEncodedValue.toMutable(): MutableEnumEncodedValue { fun EnumEncodedValue.toMutable(): MutableEnumEncodedValue = MutableEnumEncodedValue(this)
return MutableEnumEncodedValue(this)
}
} }
} }

View File

@@ -5,24 +5,20 @@ import com.android.tools.smali.dexlib2.base.value.BaseFieldEncodedValue
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.value.FieldEncodedValue import com.android.tools.smali.dexlib2.iface.value.FieldEncodedValue
class MutableFieldEncodedValue(fieldEncodedValue: FieldEncodedValue) : BaseFieldEncodedValue(), MutableEncodedValue { class MutableFieldEncodedValue(fieldEncodedValue: FieldEncodedValue) :
BaseFieldEncodedValue(),
MutableEncodedValue {
private var value = fieldEncodedValue.value private var value = fieldEncodedValue.value
override fun getValueType(): Int { override fun getValueType(): Int = ValueType.FIELD
return ValueType.FIELD
}
override fun getValue(): FieldReference { override fun getValue(): FieldReference = this.value
return this.value
}
fun setValue(value: FieldReference) { fun setValue(value: FieldReference) {
this.value = value this.value = value
} }
companion object { companion object {
fun FieldEncodedValue.toMutable(): MutableFieldEncodedValue { fun FieldEncodedValue.toMutable(): MutableFieldEncodedValue = MutableFieldEncodedValue(this)
return MutableFieldEncodedValue(this)
}
} }
} }

View File

@@ -3,20 +3,18 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseFloatEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseFloatEncodedValue
import com.android.tools.smali.dexlib2.iface.value.FloatEncodedValue import com.android.tools.smali.dexlib2.iface.value.FloatEncodedValue
class MutableFloatEncodedValue(floatEncodedValue: FloatEncodedValue) : BaseFloatEncodedValue(), MutableEncodedValue { class MutableFloatEncodedValue(floatEncodedValue: FloatEncodedValue) :
BaseFloatEncodedValue(),
MutableEncodedValue {
private var value = floatEncodedValue.value private var value = floatEncodedValue.value
override fun getValue(): Float { override fun getValue(): Float = this.value
return this.value
}
fun setValue(value: Float) { fun setValue(value: Float) {
this.value = value this.value = value
} }
companion object { companion object {
fun FloatEncodedValue.toMutable(): MutableFloatEncodedValue { fun FloatEncodedValue.toMutable(): MutableFloatEncodedValue = MutableFloatEncodedValue(this)
return MutableFloatEncodedValue(this)
}
} }
} }

View File

@@ -3,20 +3,18 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseIntEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseIntEncodedValue
import com.android.tools.smali.dexlib2.iface.value.IntEncodedValue import com.android.tools.smali.dexlib2.iface.value.IntEncodedValue
class MutableIntEncodedValue(intEncodedValue: IntEncodedValue) : BaseIntEncodedValue(), MutableEncodedValue { class MutableIntEncodedValue(intEncodedValue: IntEncodedValue) :
BaseIntEncodedValue(),
MutableEncodedValue {
private var value = intEncodedValue.value private var value = intEncodedValue.value
override fun getValue(): Int { override fun getValue(): Int = this.value
return this.value
}
fun setValue(value: Int) { fun setValue(value: Int) {
this.value = value this.value = value
} }
companion object { companion object {
fun IntEncodedValue.toMutable(): MutableIntEncodedValue { fun IntEncodedValue.toMutable(): MutableIntEncodedValue = MutableIntEncodedValue(this)
return MutableIntEncodedValue(this)
}
} }
} }

View File

@@ -3,20 +3,18 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseLongEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseLongEncodedValue
import com.android.tools.smali.dexlib2.iface.value.LongEncodedValue import com.android.tools.smali.dexlib2.iface.value.LongEncodedValue
class MutableLongEncodedValue(longEncodedValue: LongEncodedValue) : BaseLongEncodedValue(), MutableEncodedValue { class MutableLongEncodedValue(longEncodedValue: LongEncodedValue) :
BaseLongEncodedValue(),
MutableEncodedValue {
private var value = longEncodedValue.value private var value = longEncodedValue.value
override fun getValue(): Long { override fun getValue(): Long = this.value
return this.value
}
fun setValue(value: Long) { fun setValue(value: Long) {
this.value = value this.value = value
} }
companion object { companion object {
fun LongEncodedValue.toMutable(): MutableLongEncodedValue { fun LongEncodedValue.toMutable(): MutableLongEncodedValue = MutableLongEncodedValue(this)
return MutableLongEncodedValue(this)
}
} }
} }

View File

@@ -9,17 +9,13 @@ class MutableMethodEncodedValue(methodEncodedValue: MethodEncodedValue) :
MutableEncodedValue { MutableEncodedValue {
private var value = methodEncodedValue.value private var value = methodEncodedValue.value
override fun getValue(): MethodReference { override fun getValue(): MethodReference = this.value
return this.value
}
fun setValue(value: MethodReference) { fun setValue(value: MethodReference) {
this.value = value this.value = value
} }
companion object { companion object {
fun MethodEncodedValue.toMutable(): MutableMethodEncodedValue { fun MethodEncodedValue.toMutable(): MutableMethodEncodedValue = MutableMethodEncodedValue(this)
return MutableMethodEncodedValue(this)
}
} }
} }

View File

@@ -9,17 +9,13 @@ class MutableMethodHandleEncodedValue(methodHandleEncodedValue: MethodHandleEnco
MutableEncodedValue { MutableEncodedValue {
private var value = methodHandleEncodedValue.value private var value = methodHandleEncodedValue.value
override fun getValue(): MethodHandleReference { override fun getValue(): MethodHandleReference = this.value
return this.value
}
fun setValue(value: MethodHandleReference) { fun setValue(value: MethodHandleReference) {
this.value = value this.value = value
} }
companion object { companion object {
fun MethodHandleEncodedValue.toMutable(): MutableMethodHandleEncodedValue { fun MethodHandleEncodedValue.toMutable(): MutableMethodHandleEncodedValue = MutableMethodHandleEncodedValue(this)
return MutableMethodHandleEncodedValue(this)
}
} }
} }

View File

@@ -9,17 +9,13 @@ class MutableMethodTypeEncodedValue(methodTypeEncodedValue: MethodTypeEncodedVal
MutableEncodedValue { MutableEncodedValue {
private var value = methodTypeEncodedValue.value private var value = methodTypeEncodedValue.value
override fun getValue(): MethodProtoReference { override fun getValue(): MethodProtoReference = this.value
return this.value
}
fun setValue(value: MethodProtoReference) { fun setValue(value: MethodProtoReference) {
this.value = value this.value = value
} }
companion object { companion object {
fun MethodTypeEncodedValue.toMutable(): MutableMethodTypeEncodedValue { fun MethodTypeEncodedValue.toMutable(): MutableMethodTypeEncodedValue = MutableMethodTypeEncodedValue(this)
return MutableMethodTypeEncodedValue(this)
}
} }
} }

View File

@@ -3,10 +3,10 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseNullEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseNullEncodedValue
import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue
class MutableNullEncodedValue : BaseNullEncodedValue(), MutableEncodedValue { class MutableNullEncodedValue :
BaseNullEncodedValue(),
MutableEncodedValue {
companion object { companion object {
fun ByteEncodedValue.toMutable(): MutableByteEncodedValue { fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this)
return MutableByteEncodedValue(this)
}
} }
} }

View File

@@ -3,20 +3,18 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseShortEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseShortEncodedValue
import com.android.tools.smali.dexlib2.iface.value.ShortEncodedValue import com.android.tools.smali.dexlib2.iface.value.ShortEncodedValue
class MutableShortEncodedValue(shortEncodedValue: ShortEncodedValue) : BaseShortEncodedValue(), MutableEncodedValue { class MutableShortEncodedValue(shortEncodedValue: ShortEncodedValue) :
BaseShortEncodedValue(),
MutableEncodedValue {
private var value = shortEncodedValue.value private var value = shortEncodedValue.value
override fun getValue(): Short { override fun getValue(): Short = this.value
return this.value
}
fun setValue(value: Short) { fun setValue(value: Short) {
this.value = value this.value = value
} }
companion object { companion object {
fun ShortEncodedValue.toMutable(): MutableShortEncodedValue { fun ShortEncodedValue.toMutable(): MutableShortEncodedValue = MutableShortEncodedValue(this)
return MutableShortEncodedValue(this)
}
} }
} }

View File

@@ -9,17 +9,13 @@ class MutableStringEncodedValue(stringEncodedValue: StringEncodedValue) :
MutableEncodedValue { MutableEncodedValue {
private var value = stringEncodedValue.value private var value = stringEncodedValue.value
override fun getValue(): String { override fun getValue(): String = this.value
return this.value
}
fun setValue(value: String) { fun setValue(value: String) {
this.value = value this.value = value
} }
companion object { companion object {
fun ByteEncodedValue.toMutable(): MutableByteEncodedValue { fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this)
return MutableByteEncodedValue(this)
}
} }
} }

View File

@@ -3,20 +3,18 @@ package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import com.android.tools.smali.dexlib2.base.value.BaseTypeEncodedValue import com.android.tools.smali.dexlib2.base.value.BaseTypeEncodedValue
import com.android.tools.smali.dexlib2.iface.value.TypeEncodedValue import com.android.tools.smali.dexlib2.iface.value.TypeEncodedValue
class MutableTypeEncodedValue(typeEncodedValue: TypeEncodedValue) : BaseTypeEncodedValue(), MutableEncodedValue { class MutableTypeEncodedValue(typeEncodedValue: TypeEncodedValue) :
BaseTypeEncodedValue(),
MutableEncodedValue {
private var value = typeEncodedValue.value private var value = typeEncodedValue.value
override fun getValue(): String { override fun getValue(): String = this.value
return this.value
}
fun setValue(value: String) { fun setValue(value: String) {
this.value = value this.value = value
} }
companion object { companion object {
fun TypeEncodedValue.toMutable(): MutableTypeEncodedValue { fun TypeEncodedValue.toMutable(): MutableTypeEncodedValue = MutableTypeEncodedValue(this)
return MutableTypeEncodedValue(this)
}
} }
} }

View File

@@ -192,6 +192,7 @@ internal object PatcherTest {
private operator fun Set<Patch<*>>.invoke(): List<PatchResult> { private operator fun Set<Patch<*>>.invoke(): List<PatchResult> {
every { patcher.context.executablePatches } returns toMutableSet() every { patcher.context.executablePatches } returns toMutableSet()
every { patcher.context.bytecodeContext.lookupMaps } returns LookupMaps(patcher.context.bytecodeContext.classes)
return runBlocking { patcher().toList() } return runBlocking { patcher().toList() }
} }

View File

@@ -7,7 +7,11 @@ import kotlin.reflect.typeOf
import kotlin.test.* import kotlin.test.*
internal object OptionsTest { internal object OptionsTest {
private val externalOption = stringOption("external", "default")
private val optionsTestPatch = bytecodePatch { private val optionsTestPatch = bytecodePatch {
externalOption()
booleanOption("bool", true) booleanOption("bool", true)
stringOption("required", "default", required = true) stringOption("required", "default", required = true)
@@ -124,5 +128,17 @@ internal object OptionsTest {
} }
} }
@Test
fun `external option should be accessible`() {
assertDoesNotThrow {
externalOption.value = "test"
}
}
@Test
fun `should allow getting the external option from the patch`() {
assertEquals(optionsTestPatch.options["external"].value, externalOption.value)
}
private fun options(block: Options.() -> Unit) = optionsTestPatch.options.let(block) private fun options(block: Options.() -> Unit) = optionsTestPatch.options.let(block)
} }