You've already forked revanced-patcher
mirror of
https://github.com/revanced/revanced-patcher
synced 2025-09-10 05:30:49 +02:00
Compare commits
30 Commits
v18.0.0-de
...
v18.0.0-de
Author | SHA1 | Date | |
---|---|---|---|
![]() |
167bd83f4e | ||
![]() |
aed1eac315 | ||
![]() |
54a2f8f16f | ||
![]() |
2ca543ffb9 | ||
![]() |
58e7f815a5 | ||
![]() |
15b38fc841 | ||
![]() |
e2ca50729d | ||
![]() |
6192089b71 | ||
![]() |
a4212f6bf9 | ||
![]() |
124a2e9d3e | ||
![]() |
f77624b3b9 | ||
![]() |
a76ac04214 | ||
![]() |
0447fa9c28 | ||
![]() |
54ac1394a9 | ||
![]() |
0b04c73ac5 | ||
![]() |
079de45238 | ||
![]() |
56ce9ec2f9 | ||
![]() |
1b52e4b0f9 | ||
![]() |
098c2c1efa | ||
![]() |
64343e5a7c | ||
![]() |
0caf6caeb9 | ||
![]() |
55f6c2a9fc | ||
![]() |
c6095bc38a | ||
![]() |
09cd6aa568 | ||
![]() |
ebbaafb78e | ||
![]() |
e6de90d300 | ||
![]() |
c7922e90d0 | ||
![]() |
c1f4c0445a | ||
![]() |
caa634fac6 | ||
![]() |
f28bfe0dbd |
70
CHANGELOG.md
70
CHANGELOG.md
@@ -1,3 +1,73 @@
|
|||||||
|
# [18.0.0-dev.6](https://github.com/ReVanced/revanced-patcher/compare/v18.0.0-dev.5...v18.0.0-dev.6) (2023-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Only allow setting `MethodFingerprint#result` privately ([aed1eac](https://github.com/ReVanced/revanced-patcher/commit/aed1eac3157317acf87f522750cf2f41509606c3))
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* Change data classes to actual classes ([6192089](https://github.com/ReVanced/revanced-patcher/commit/6192089b71bdca15765369f3e607ddd1f8266205))
|
||||||
|
* Convert extension functions to member functions ([e2ca507](https://github.com/ReVanced/revanced-patcher/commit/e2ca50729da7085799c0ff6fc4f7afaf82579738))
|
||||||
|
* Move files to simplify package structure ([124a2e9](https://github.com/ReVanced/revanced-patcher/commit/124a2e9d3efb88f0f038ae306d941e918ad3ad3c))
|
||||||
|
* Remove deprecated classes and members ([a4212f6](https://github.com/ReVanced/revanced-patcher/commit/a4212f6bf952971541c4550e20f6bf57a382e19a))
|
||||||
|
|
||||||
|
|
||||||
|
* refactor!: Remove `Fingerprint` interface ([54a2f8f](https://github.com/ReVanced/revanced-patcher/commit/54a2f8f16fddf2b2ed47eb23717ba3734c4a6c5d))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* The `MethodFingerprint#result` member can now only be set inside `MethodFingerprint`.
|
||||||
|
* The `Fingerprint` interface is no longer present.
|
||||||
|
* Some extension functions are now member functions.
|
||||||
|
* This gets rid of data class members.
|
||||||
|
* Some deprecated classes and members are not present anymore.
|
||||||
|
* Classes and members have changed packages.
|
||||||
|
|
||||||
|
# [18.0.0-dev.5](https://github.com/ReVanced/revanced-patcher/compare/v18.0.0-dev.4...v18.0.0-dev.5) (2023-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Do not set patch fields if they are empty ([a76ac04](https://github.com/ReVanced/revanced-patcher/commit/a76ac04214a2ab91e3b2f9dddb13ed52816fe723))
|
||||||
|
|
||||||
|
# [18.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v18.0.0-dev.3...v18.0.0-dev.4) (2023-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Use a map for `PatchOption#values` ([54ac139](https://github.com/ReVanced/revanced-patcher/commit/54ac1394a914d3eed7865ec697e8016834134911))
|
||||||
|
|
||||||
|
# [18.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v18.0.0-dev.2...v18.0.0-dev.3) (2023-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Make `PatchOption#values` nullable ([56ce9ec](https://github.com/ReVanced/revanced-patcher/commit/56ce9ec2f98ff351c3d42df71b49e5c88f07e665))
|
||||||
|
|
||||||
|
# [18.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v18.0.0-dev.1...v18.0.0-dev.2) (2023-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* Change `PatchOption` from abstract to open class ([09cd6aa](https://github.com/ReVanced/revanced-patcher/commit/09cd6aa568988dd5241bfa6a2e12b7926a7b0683))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Add function to reset options to their default value ([ebbaafb](https://github.com/ReVanced/revanced-patcher/commit/ebbaafb78e88f34faeafe9ff8532afe29231bd79))
|
||||||
|
* Add function to reset options to their default value ([e6de90d](https://github.com/ReVanced/revanced-patcher/commit/e6de90d300bc9c82ca1696cb898db04c65a1cd5b))
|
||||||
|
* Add getter for default option value ([c7922e9](https://github.com/ReVanced/revanced-patcher/commit/c7922e90d0c6ae83f513611c706ebea33c1a2b63))
|
||||||
|
* Name patch option value validator property correctly ([caa634f](https://github.com/ReVanced/revanced-patcher/commit/caa634fac6d7a717f54e3b015827c8858fd637b9))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* This gets rid of the existing basic implementations of the `PatchOptions` type and moves extension functions.
|
||||||
|
* This changes the getter name of the property.
|
||||||
|
|
||||||
# [18.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v17.0.1-dev.1...v18.0.0-dev.1) (2023-10-14)
|
# [18.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v17.0.1-dev.1...v18.0.0-dev.1) (2023-10-14)
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.9.0"
|
kotlin("jvm") version "1.9.10"
|
||||||
alias(libs.plugins.binary.compatibility.validator)
|
alias(libs.plugins.binary.compatibility.validator)
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
signing
|
signing
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 18.0.0-dev.1
|
version = 18.0.0-dev.6
|
||||||
|
@@ -2,8 +2,9 @@ package app.revanced.patcher
|
|||||||
|
|
||||||
import app.revanced.patcher.PatchBundleLoader.Utils.getInstance
|
import app.revanced.patcher.PatchBundleLoader.Utils.getInstance
|
||||||
import app.revanced.patcher.data.ResourceContext
|
import app.revanced.patcher.data.ResourceContext
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.LookupMap.Maps.clearLookupMaps
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolveUsingLookupMap
|
import app.revanced.patcher.fingerprint.LookupMap.Maps.initializeLookupMaps
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint.Companion.resolveUsingLookupMap
|
||||||
import app.revanced.patcher.patch.*
|
import app.revanced.patcher.patch.*
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
@@ -187,7 +188,7 @@ class Patcher(
|
|||||||
|
|
||||||
if (context.bytecodeContext.integrations.merge) context.bytecodeContext.integrations.flush()
|
if (context.bytecodeContext.integrations.merge) context.bytecodeContext.integrations.flush()
|
||||||
|
|
||||||
MethodFingerprint.initializeFingerprintResolutionLookupMaps(context.bytecodeContext)
|
initializeLookupMaps(context.bytecodeContext)
|
||||||
|
|
||||||
// Prevent from decoding the app manifest twice if it is not needed.
|
// Prevent from decoding the app manifest twice if it is not needed.
|
||||||
if (options.resourceDecodingMode == ResourceContext.ResourceDecodingMode.FULL)
|
if (options.resourceDecodingMode == ResourceContext.ResourceDecodingMode.FULL)
|
||||||
@@ -249,7 +250,7 @@ class Patcher(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() = MethodFingerprint.clearFingerprintResolutionLookupMaps()
|
override fun close() = clearLookupMaps()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile and save the patched APK file.
|
* Compile and save the patched APK file.
|
||||||
|
@@ -38,27 +38,6 @@ data class PatcherOptions(
|
|||||||
frameworkDirectory = frameworkFileDirectory
|
frameworkDirectory = frameworkFileDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for ReVanced [Patcher].
|
|
||||||
* @param inputFile The input file to patch.
|
|
||||||
* @param resourceCachePath The path to the directory to use for caching resources.
|
|
||||||
* @param aaptBinaryPath The path to a custom aapt binary.
|
|
||||||
* @param frameworkFileDirectory The path to the directory to cache the framework file in.
|
|
||||||
*/
|
|
||||||
@Deprecated("Use the constructor with the multithreadingDexFileWriter parameter instead")
|
|
||||||
constructor(
|
|
||||||
inputFile: File,
|
|
||||||
resourceCachePath: File = File("revanced-resource-cache"),
|
|
||||||
aaptBinaryPath: String? = null,
|
|
||||||
frameworkFileDirectory: String? = null,
|
|
||||||
) : this(
|
|
||||||
inputFile,
|
|
||||||
resourceCachePath,
|
|
||||||
aaptBinaryPath,
|
|
||||||
frameworkFileDirectory,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
|
|
||||||
fun recreateResourceCacheDirectory() = resourceCachePath.also {
|
fun recreateResourceCacheDirectory() = resourceCachePath.also {
|
||||||
if (it.exists()) {
|
if (it.exists()) {
|
||||||
logger.info("Deleting existing resource cache directory")
|
logger.info("Deleting existing resource cache directory")
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
package app.revanced.patcher.extensions
|
package app.revanced.patcher.extensions
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.AnnotationExtensions.findAnnotationRecursively
|
import app.revanced.patcher.extensions.AnnotationExtensions.findAnnotationRecursively
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
||||||
object MethodFingerprintExtensions {
|
object MethodFingerprintExtensions {
|
||||||
// TODO: Make this a property.
|
// TODO: Make this a property.
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
package app.revanced.patcher.fingerprint
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ReVanced fingerprint.
|
|
||||||
* Can be a [MethodFingerprint].
|
|
||||||
*/
|
|
||||||
interface Fingerprint
|
|
125
src/main/kotlin/app/revanced/patcher/fingerprint/LookupMap.kt
Normal file
125
src/main/kotlin/app/revanced/patcher/fingerprint/LookupMap.kt
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||||
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
internal typealias MethodClassPair = Pair<Method, ClassDef>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup map for methods.
|
||||||
|
*/
|
||||||
|
internal class LookupMap : MutableMap<String, LookupMap.MethodClassList> by mutableMapOf() {
|
||||||
|
/**
|
||||||
|
* Adds a [MethodClassPair] to the list associated with the given key.
|
||||||
|
* If the key does not exist, a new list is created and the [MethodClassPair] is added to it.
|
||||||
|
*/
|
||||||
|
fun add(
|
||||||
|
key: String,
|
||||||
|
methodClassPair: MethodClassPair
|
||||||
|
) {
|
||||||
|
getOrPut(key) { MethodClassList() }.add(methodClassPair)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of methods and the class they are a member of.
|
||||||
|
*/
|
||||||
|
internal class MethodClassList : LinkedList<MethodClassPair>()
|
||||||
|
|
||||||
|
companion object Maps {
|
||||||
|
/**
|
||||||
|
* A list of methods and the class they are a member of.
|
||||||
|
*/
|
||||||
|
internal val methods = MethodClassList()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup map for methods keyed to the methods access flags, return type and parameter.
|
||||||
|
*/
|
||||||
|
internal val methodSignatureLookupMap = LookupMap()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup map for methods associated by strings referenced in the method.
|
||||||
|
*/
|
||||||
|
internal val methodStringsLookupMap = LookupMap()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes lookup maps for [MethodFingerprint] resolution
|
||||||
|
* using attributes of methods such as the method signature or strings.
|
||||||
|
*
|
||||||
|
* @param context The [BytecodeContext] containing the classes to initialize the lookup maps with.
|
||||||
|
*/
|
||||||
|
internal fun initializeLookupMaps(context: BytecodeContext) {
|
||||||
|
if (methods.isNotEmpty()) clearLookupMaps()
|
||||||
|
|
||||||
|
context.classes.forEach { classDef ->
|
||||||
|
classDef.methods.forEach { method ->
|
||||||
|
val methodClassPair = method to classDef
|
||||||
|
|
||||||
|
// For fingerprints with no access or return type specified.
|
||||||
|
methods += methodClassPair
|
||||||
|
|
||||||
|
val accessFlagsReturnKey = method.accessFlags.toString() + method.returnType.first()
|
||||||
|
|
||||||
|
// Add <access><returnType> as the key.
|
||||||
|
methodSignatureLookupMap.add(accessFlagsReturnKey, methodClassPair)
|
||||||
|
|
||||||
|
// Add <access><returnType>[parameters] as the key.
|
||||||
|
methodSignatureLookupMap.add(
|
||||||
|
buildString {
|
||||||
|
append(accessFlagsReturnKey)
|
||||||
|
appendParameters(method.parameterTypes)
|
||||||
|
},
|
||||||
|
methodClassPair
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add strings contained in the method as the key.
|
||||||
|
method.implementation?.instructions?.forEach instructions@{ instruction ->
|
||||||
|
if (instruction.opcode != Opcode.CONST_STRING && instruction.opcode != Opcode.CONST_STRING_JUMBO)
|
||||||
|
return@instructions
|
||||||
|
|
||||||
|
val string = ((instruction as ReferenceInstruction).reference as StringReference).string
|
||||||
|
|
||||||
|
methodStringsLookupMap.add(string, methodClassPair)
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the future, the class type could be added to the lookup map.
|
||||||
|
// This would require MethodFingerprint to be changed to include the class type.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the internal lookup maps created in [initializeLookupMaps]
|
||||||
|
*/
|
||||||
|
internal fun clearLookupMaps() {
|
||||||
|
methods.clear()
|
||||||
|
methodSignatureLookupMap.clear()
|
||||||
|
methodStringsLookupMap.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a string based on the parameter reference types of this method.
|
||||||
|
*/
|
||||||
|
internal fun StringBuilder.appendParameters(parameters: Iterable<CharSequence>) {
|
||||||
|
// Maximum parameters to use in the signature key.
|
||||||
|
// Some apps have methods with an incredible number of parameters (over 100 parameters have been seen).
|
||||||
|
// To keep the signature map from becoming needlessly bloated,
|
||||||
|
// group together in the same map entry all methods with the same access/return and 5 or more parameters.
|
||||||
|
// The value of 5 was chosen based on local performance testing and is not set in stone.
|
||||||
|
val maxSignatureParameters = 5
|
||||||
|
// Must append a unique value before the parameters to distinguish this key includes the parameters.
|
||||||
|
// If this is not appended, then methods with no parameters
|
||||||
|
// will collide with different keys that specify access/return but omit the parameters.
|
||||||
|
append("p:")
|
||||||
|
parameters.forEachIndexed { index, parameter ->
|
||||||
|
if (index >= maxSignatureParameters) return
|
||||||
|
append(parameter.first())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
|||||||
|
package app.revanced.patcher.fingerprint
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.util.proxy.ClassProxy
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||||
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the result of a [MethodFingerprintResult].
|
||||||
|
*
|
||||||
|
* @param method The matching method.
|
||||||
|
* @param classDef The [ClassDef] that contains the matching [method].
|
||||||
|
* @param scanResult The result of scanning for the [MethodFingerprint].
|
||||||
|
* @param context The [BytecodeContext] this [MethodFingerprintResult] is attached to, to create proxies.
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
class MethodFingerprintResult(
|
||||||
|
val method: Method,
|
||||||
|
val classDef: ClassDef,
|
||||||
|
val scanResult: MethodFingerprintScanResult,
|
||||||
|
internal val context: BytecodeContext
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Returns a mutable clone of [classDef]
|
||||||
|
*
|
||||||
|
* Please note, this method allocates a [ClassProxy].
|
||||||
|
* Use [classDef] where possible.
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
val mutableClass by lazy { context.proxy(classDef).mutableClass }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable clone of [method]
|
||||||
|
*
|
||||||
|
* Please note, this method allocates a [ClassProxy].
|
||||||
|
* Use [method] where possible.
|
||||||
|
*/
|
||||||
|
val mutableMethod by lazy {
|
||||||
|
mutableClass.methods.first {
|
||||||
|
MethodUtil.methodSignaturesMatch(it, this.method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of scanning on the [MethodFingerprint].
|
||||||
|
* @param patternScanResult The result of the pattern scan.
|
||||||
|
* @param stringsScanResult The result of the string scan.
|
||||||
|
*/
|
||||||
|
class MethodFingerprintScanResult(
|
||||||
|
val patternScanResult: PatternScanResult?,
|
||||||
|
val stringsScanResult: StringsScanResult?
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* The result of scanning strings on the [MethodFingerprint].
|
||||||
|
* @param matches The list of strings that were matched.
|
||||||
|
*/
|
||||||
|
class StringsScanResult(val matches: List<StringMatch>) {
|
||||||
|
/**
|
||||||
|
* Represents a match for a string at an index.
|
||||||
|
* @param string The string that was matched.
|
||||||
|
* @param index The index of the string.
|
||||||
|
*/
|
||||||
|
class StringMatch(val string: String, val index: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of a pattern scan.
|
||||||
|
* @param startIndex The start index of the instructions where to which this pattern matches.
|
||||||
|
* @param endIndex The end index of the instructions where to which this pattern matches.
|
||||||
|
* @param warnings A list of warnings considering this [PatternScanResult].
|
||||||
|
*/
|
||||||
|
class PatternScanResult(
|
||||||
|
val startIndex: Int,
|
||||||
|
val endIndex: Int,
|
||||||
|
var warnings: List<Warning>? = null
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Represents warnings of the pattern scan.
|
||||||
|
* @param correctOpcode The opcode the instruction list has.
|
||||||
|
* @param wrongOpcode The opcode the pattern list of the signature currently has.
|
||||||
|
* @param instructionIndex The index of the opcode relative to the instruction list.
|
||||||
|
* @param patternIndex The index of the opcode relative to the pattern list from the signature.
|
||||||
|
*/
|
||||||
|
class Warning(
|
||||||
|
val correctOpcode: Opcode,
|
||||||
|
val wrongOpcode: Opcode,
|
||||||
|
val instructionIndex: Int,
|
||||||
|
val patternIndex: Int,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
package app.revanced.patcher.fingerprint.method.annotation
|
package app.revanced.patcher.fingerprint.annotation
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotations to scan a pattern [MethodFingerprint] with fuzzy algorithm.
|
* Annotations to scan a pattern [MethodFingerprint] with fuzzy algorithm.
|
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
|||||||
package app.revanced.patcher.logging
|
|
||||||
|
|
||||||
@Deprecated("This will be removed in a future release")
|
|
||||||
interface Logger {
|
|
||||||
fun error(msg: String) {}
|
|
||||||
fun warn(msg: String) {}
|
|
||||||
fun info(msg: String) {}
|
|
||||||
fun trace(msg: String) {}
|
|
||||||
}
|
|
@@ -1,6 +0,0 @@
|
|||||||
package app.revanced.patcher.logging.impl
|
|
||||||
|
|
||||||
import app.revanced.patcher.logging.Logger
|
|
||||||
|
|
||||||
@Deprecated("This will be removed in a future release")
|
|
||||||
object NopLogger : Logger
|
|
@@ -1,7 +1,7 @@
|
|||||||
package app.revanced.patcher.patch
|
package app.revanced.patcher.patch
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ReVanced [Patch] that works on [BytecodeContext].
|
* A ReVanced [Patch] that works on [BytecodeContext].
|
||||||
|
@@ -65,7 +65,8 @@ sealed class Patch<out T : Context<*>> {
|
|||||||
name = annotation.name.ifEmpty { null }
|
name = annotation.name.ifEmpty { null }
|
||||||
description = annotation.description.ifEmpty { null }
|
description = annotation.description.ifEmpty { null }
|
||||||
compatiblePackages = annotation.compatiblePackages
|
compatiblePackages = annotation.compatiblePackages
|
||||||
.map { CompatiblePackage(it.name, it.versions.toSet()) }.toSet()
|
.map { CompatiblePackage(it.name, it.versions.toSet().ifEmpty { null }) }
|
||||||
|
.toSet().ifEmpty { null }
|
||||||
dependencies = annotation.dependencies.toSet().ifEmpty { null }
|
dependencies = annotation.dependencies.toSet().ifEmpty { null }
|
||||||
use = annotation.use
|
use = annotation.use
|
||||||
requiresIntegrations = annotation.requiresIntegrations
|
requiresIntegrations = annotation.requiresIntegrations
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [Boolean].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class BooleanPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Boolean?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Boolean?) -> Boolean
|
|
||||||
) : PatchOption<Boolean>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [BooleanPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [BooleanPatchOption].
|
|
||||||
*
|
|
||||||
* @see BooleanPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.booleanPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Boolean? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Boolean?) -> Boolean = { true }
|
|
||||||
) = BooleanPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [Float].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class FloatPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Float?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Float?) -> Boolean
|
|
||||||
) : PatchOption<Float>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [FloatPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [FloatPatchOption].
|
|
||||||
*
|
|
||||||
* @see FloatPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.floatPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Float? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Float?) -> Boolean = { true }
|
|
||||||
) = FloatPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing an [Integer].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class IntPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Int?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Int?) -> Boolean
|
|
||||||
) : PatchOption<Int>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [IntPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [IntPatchOption].
|
|
||||||
*
|
|
||||||
* @see IntPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.intPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Int? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Int?) -> Boolean = { true }
|
|
||||||
) = IntPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [Long].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class LongPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Long?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Long?) -> Boolean
|
|
||||||
) : PatchOption<Long>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [LongPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [LongPatchOption].
|
|
||||||
*
|
|
||||||
* @see LongPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.longPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Long? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Long?) -> Boolean = { true }
|
|
||||||
) = LongPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [String].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class StringPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: String?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (String?) -> Boolean
|
|
||||||
) : PatchOption<String>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [StringPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [StringPatchOption].
|
|
||||||
*
|
|
||||||
* @see StringPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.stringPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: String? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (String?) -> Boolean = { true }
|
|
||||||
) = StringPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types.array
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [Boolean] array.
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class BooleanArrayPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Array<Boolean>?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Array<Boolean>?) -> Boolean
|
|
||||||
) : PatchOption<Array<Boolean>>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [BooleanArrayPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [BooleanArrayPatchOption].
|
|
||||||
*
|
|
||||||
* @see BooleanArrayPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.booleanArrayPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Array<Boolean>? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Array<Boolean>?) -> Boolean = { true }
|
|
||||||
) = BooleanArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types.array
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [Float] array.
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class FloatArrayPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Array<Float>?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Array<Float>?) -> Boolean
|
|
||||||
) : PatchOption<Array<Float>>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [FloatArrayPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [FloatArrayPatchOption].
|
|
||||||
*
|
|
||||||
* @see FloatArrayPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.floatArrayPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Array<Float>? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Array<Float>?) -> Boolean = { true }
|
|
||||||
) = FloatArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types.array
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing an [Integer] array.
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class IntArrayPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Array<Int>?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Array<Int>?) -> Boolean
|
|
||||||
) : PatchOption<Array<Int>>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [IntArrayPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [IntArrayPatchOption].
|
|
||||||
*
|
|
||||||
* @see IntArrayPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.intArrayPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Array<Int>? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Array<Int>?) -> Boolean = { true }
|
|
||||||
) = IntArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types.array
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [Long] array.
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class LongArrayPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Array<Long>?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Array<Long>?) -> Boolean
|
|
||||||
) : PatchOption<Array<Long>>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [LongArrayPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [LongArrayPatchOption].
|
|
||||||
*
|
|
||||||
* @see LongArrayPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.longArrayPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Array<Long>? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Array<Long>?) -> Boolean = { true }
|
|
||||||
) = LongArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package app.revanced.patcher.patch.options.types.array
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.options.PatchOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [PatchOption] representing a [String] array.
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
*
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
class StringArrayPatchOption private constructor(
|
|
||||||
key: String,
|
|
||||||
default: Array<String>?,
|
|
||||||
title: String?,
|
|
||||||
description: String?,
|
|
||||||
required: Boolean,
|
|
||||||
validator: (Array<String>?) -> Boolean
|
|
||||||
) : PatchOption<Array<String>>(key, default, title, description, required, validator) {
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a new [StringArrayPatchOption] and add it to the current [Patch].
|
|
||||||
*
|
|
||||||
* @param key The identifier.
|
|
||||||
* @param default The default value.
|
|
||||||
* @param title The title.
|
|
||||||
* @param description A description.
|
|
||||||
* @param required Whether the option is required.
|
|
||||||
* @return The created [StringArrayPatchOption].
|
|
||||||
*
|
|
||||||
* @see StringArrayPatchOption
|
|
||||||
* @see PatchOption
|
|
||||||
*/
|
|
||||||
fun <T : Patch<*>> T.stringArrayPatchOption(
|
|
||||||
key: String,
|
|
||||||
default: Array<String>? = null,
|
|
||||||
title: String? = null,
|
|
||||||
description: String? = null,
|
|
||||||
required: Boolean = false,
|
|
||||||
validator: (Array<String>?) -> Boolean = { true }
|
|
||||||
) = StringArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -2,31 +2,43 @@ package app.revanced.patcher.patch.options
|
|||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.options.types.BooleanPatchOption.Companion.booleanPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
|
||||||
import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringArrayPatchOption
|
||||||
import app.revanced.patcher.patch.options.types.array.StringArrayPatchOption.Companion.stringArrayPatchOption
|
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||||
import org.junit.jupiter.api.assertDoesNotThrow
|
import org.junit.jupiter.api.assertDoesNotThrow
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertNull
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
internal class PatchOptionsTest {
|
internal class PatchOptionsTest {
|
||||||
@Test
|
@Test
|
||||||
fun `should not fail because default value is unvalidated`() {
|
fun `should not fail because default value is unvalidated`() {
|
||||||
assertDoesNotThrow {
|
assertDoesNotThrow { OptionsTestPatch.requiredStringOption }
|
||||||
OptionsTestPatch.options["required"].value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should not allow setting custom value with validation`() {
|
||||||
|
// Getter validation on incorrect value.
|
||||||
|
assertThrows<PatchOptionException.ValueValidationException> { OptionsTestPatch.validatedOption }
|
||||||
|
|
||||||
|
// Setter validation on incorrect value.
|
||||||
|
assertThrows<PatchOptionException.ValueValidationException> { OptionsTestPatch.validatedOption = "invalid" }
|
||||||
|
|
||||||
|
// Setter validation on correct value.
|
||||||
|
assertDoesNotThrow { OptionsTestPatch.validatedOption = "valid" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should throw due to incorrect type`() {
|
fun `should throw due to incorrect type`() {
|
||||||
assertThrows<PatchOptionException.InvalidValueTypeException> {
|
assertThrows<PatchOptionException.InvalidValueTypeException> {
|
||||||
OptionsTestPatch.options["bool"] = 0
|
OptionsTestPatch.options["bool"] = "not a boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should be nullable`() {
|
fun `should be nullable`() {
|
||||||
OptionsTestPatch.options["bool"] = null
|
OptionsTestPatch.booleanOption = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -46,13 +58,65 @@ internal class PatchOptionsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object OptionsTestPatch : BytecodePatch() {
|
@Suppress("UNCHECKED_CAST")
|
||||||
private var stringOption by stringPatchOption("string", "default")
|
@Test
|
||||||
private var booleanOption by booleanPatchOption("bool", true)
|
fun `should allow setting value from values`() =
|
||||||
private var requiredStringOption by stringPatchOption("required", "default", required = true)
|
with(OptionsTestPatch.options["choices"] as PatchOption<String>) {
|
||||||
private var nullDefaultRequiredOption by stringPatchOption("null", null, required = true)
|
value = values!!.values.last()
|
||||||
|
assertTrue(value == "valid")
|
||||||
|
}
|
||||||
|
|
||||||
val stringArrayOption = stringArrayPatchOption("array", arrayOf("1", "2"))
|
@Test
|
||||||
|
fun `should allow setting custom value`() =
|
||||||
|
assertDoesNotThrow { OptionsTestPatch.stringOptionWithChoices = "unknown" }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should allow resetting value`() = assertDoesNotThrow { OptionsTestPatch.stringOptionWithChoices = null }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `reset should not fail`() {
|
||||||
|
assertDoesNotThrow {
|
||||||
|
OptionsTestPatch.resettableOption.value = "test"
|
||||||
|
OptionsTestPatch.resettableOption.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThrows<PatchOptionException.ValueRequiredException> {
|
||||||
|
OptionsTestPatch.resettableOption.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getting default value should work`() =
|
||||||
|
assertDoesNotThrow { assertNull(OptionsTestPatch.resettableOption.default) }
|
||||||
|
|
||||||
|
private object OptionsTestPatch : BytecodePatch() {
|
||||||
|
var booleanOption by booleanPatchOption(
|
||||||
|
"bool",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
var requiredStringOption by stringPatchOption(
|
||||||
|
"required",
|
||||||
|
"default",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
var stringArrayOption = stringArrayPatchOption(
|
||||||
|
"array",
|
||||||
|
arrayOf("1", "2")
|
||||||
|
)
|
||||||
|
var stringOptionWithChoices by stringPatchOption(
|
||||||
|
"choices",
|
||||||
|
"value",
|
||||||
|
values = mapOf("Valid option value" to "valid")
|
||||||
|
)
|
||||||
|
var validatedOption by stringPatchOption(
|
||||||
|
|
||||||
|
"validated",
|
||||||
|
"default"
|
||||||
|
) { it == "valid" }
|
||||||
|
var resettableOption = stringPatchOption(
|
||||||
|
"resettable", null,
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {}
|
override fun execute(context: BytecodeContext) {}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package app.revanced.patcher.patch.usage
|
package app.revanced.patcher.patch.usage
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user