Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

De-duplicate ValueClassSupport #913

Merged
merged 13 commits into from Sep 6, 2022
5 changes: 0 additions & 5 deletions modules/mockk-agent-android/api/mockk-agent-android.api
@@ -1,8 +1,3 @@
public final class io/mockk/ValueClassSupportAndroidKt {
public static final fun getBoxedClass (Lkotlin/reflect/KClass;)Lkotlin/reflect/KClass;
public static final fun getBoxedValue (Ljava/lang/Object;)Ljava/lang/Object;
}

public final class io/mockk/proxy/android/AndroidMockKAgentFactory : io/mockk/proxy/MockKAgentFactory {
public static final field Companion Lio/mockk/proxy/android/AndroidMockKAgentFactory$Companion;
public field constructorProxyMaker Lio/mockk/proxy/MockKConstructorProxyMaker;
Expand Down
2 changes: 2 additions & 0 deletions modules/mockk-agent-android/build.gradle.kts
Expand Up @@ -45,6 +45,8 @@ dependencies {
api(projects.modules.mockkAgentApi)
api(projects.modules.mockkAgent)

implementation(projects.modules.mockkCore)

implementation(kotlin("reflect"))
implementation("com.linkedin.dexmaker:dexmaker:${buildsrc.config.Deps.Versions.dexmaker}")
implementation("org.objenesis:objenesis:${buildsrc.config.Deps.Versions.objenesis}")
Expand Down

This file was deleted.

Expand Up @@ -5,7 +5,7 @@

package io.mockk.proxy.android.advice

import io.mockk.boxedValue
import io.mockk.core.ValueClassSupport.boxedValue
import io.mockk.proxy.MockKAgentException
import io.mockk.proxy.android.AndroidMockKMap
import io.mockk.proxy.android.MethodDescriptor
Expand Down
5 changes: 0 additions & 5 deletions modules/mockk-agent/api/mockk-agent.api
@@ -1,8 +1,3 @@
public final class io/mockk/ValueClassSupportKt {
public static final fun getBoxedClass (Lkotlin/reflect/KClass;)Lkotlin/reflect/KClass;
public static final fun getBoxedValue (Ljava/lang/Object;)Ljava/lang/Object;
}

public class io/mockk/proxy/jvm/ClassLoadingStrategyChooser {
public fun <init> ()V
public static fun chooseClassLoadingStrategy (Ljava/lang/Class;)Lnet/bytebuddy/dynamic/loading/ClassLoadingStrategy;
Expand Down
1 change: 1 addition & 0 deletions modules/mockk-agent/build.gradle.kts
Expand Up @@ -24,6 +24,7 @@ kotlin {
dependencies {
api(projects.modules.mockkAgentApi)
implementation(kotlin("reflect"))
implementation(projects.modules.mockkCore)
}
}
val commonTest by getting {
Expand Down

This file was deleted.

@@ -1,6 +1,6 @@
package io.mockk.proxy.jvm.advice

import io.mockk.boxedValue
import io.mockk.core.ValueClassSupport.boxedValue
import io.mockk.proxy.MockKInvocationHandler
import java.lang.reflect.Method
import java.util.concurrent.Callable
Expand Down
6 changes: 6 additions & 0 deletions modules/mockk-core/api/mockk-core.api
@@ -0,0 +1,6 @@
public final class io/mockk/core/ValueClassSupport {
public static final field INSTANCE Lio/mockk/core/ValueClassSupport;
public final fun getBoxedClass (Lkotlin/reflect/KClass;)Lkotlin/reflect/KClass;
public final fun getBoxedValue (Ljava/lang/Object;)Ljava/lang/Object;
}

39 changes: 39 additions & 0 deletions modules/mockk-core/build.gradle.kts
@@ -0,0 +1,39 @@
import buildsrc.config.Deps

plugins {
buildsrc.convention.`kotlin-multiplatform`

buildsrc.convention.`mockk-publishing`
}

description = "MockK functionality that is used by other MockK modules"

val mavenName: String by extra("MockK Core")
val mavenDescription: String by extra("${project.description}")

kotlin {
jvm()

sourceSets {
val commonMain by getting {
dependencies {
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val jvmMain by getting {
dependencies {
implementation(kotlin("reflect"))
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test-junit5"))
implementation(Deps.Libs.junitJupiter)
}
}
}
}
@@ -0,0 +1,22 @@
package io.mockk.core

import kotlin.reflect.KClass


expect object ValueClassSupport {

/**
* Underlying property value of a **`value class`** or self.
*
* The type of the return might also be a `value class`!
*/
val <T : Any> T.boxedValue: Any?

/**
* Underlying property class of a **`value class`**, or self.
*
* The result might also be a value class! So check recursively, if necessary.
*/
val KClass<*>.boxedClass: KClass<*>

}
@@ -1,26 +1,21 @@
package io.mockk
package io.mockk.core

import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField

/**
* Provides value class support in the `mockk-dsl-jvm` subproject.
*
* This is marked as internal so that it won't clash with the other class in `mockk-agent-jvm`.
*
* TODO this class is copy-pasted and should be de-duplicated, see https://github.com/mockk/mockk/issues/857
*/
internal object ValueClassSupportDsl {

actual object ValueClassSupport {

/**
* Underlying property value of a **`value class`** or self.
*
* The type of the return might also be a `value class`!
*/
val <T : Any> T.boxedValue: Any?
actual val <T : Any> T.boxedValue: Any?
@Suppress("UNCHECKED_CAST")
get() = if (!this::class.isValue_safe) {
this
Expand All @@ -33,7 +28,7 @@ internal object ValueClassSupportDsl {
*
* The returned class might also be a `value class`!
*/
val KClass<*>.boxedClass: KClass<*>
actual val KClass<*>.boxedClass: KClass<*>
get() = if (!this.isValue_safe) {
this
} else {
Expand Down Expand Up @@ -69,4 +64,5 @@ internal object ValueClassSupportDsl {
} catch (_: UnsupportedOperationException) {
false
}

}
1 change: 0 additions & 1 deletion modules/mockk-dsl/api/mockk-dsl.api
Expand Up @@ -326,7 +326,6 @@ public final class io/mockk/InternalPlatformDsl {
public final fun toArray (Ljava/lang/Object;)[Ljava/lang/Object;
public final fun toStr (Ljava/lang/Object;)Ljava/lang/String;
public final fun unboxChar (Ljava/lang/Object;)Ljava/lang/Object;
public final fun unboxClass (Lkotlin/reflect/KClass;)Lkotlin/reflect/KClass;
}

public abstract interface class io/mockk/InternalRef {
Expand Down
1 change: 1 addition & 0 deletions modules/mockk-dsl/build.gradle.kts
Expand Up @@ -20,6 +20,7 @@ kotlin {
implementation(dependencies.platform(Deps.Libs.kotlinCoroutinesBom))
implementation(Deps.Libs.kotlinCoroutinesCore)
implementation(kotlin("reflect"))
implementation(projects.modules.mockkCore)
}
}
val commonTest by getting {
Expand Down
20 changes: 10 additions & 10 deletions modules/mockk-dsl/src/commonMain/kotlin/io/mockk/API.kt
Expand Up @@ -4,9 +4,9 @@ package io.mockk

import io.mockk.InternalPlatformDsl.toStr
import io.mockk.MockKGateway.*
import io.mockk.core.ValueClassSupport.boxedClass
import kotlin.coroutines.Continuation
import kotlin.reflect.KClass
import io.mockk.*

/**
* Exception thrown by library
Expand Down Expand Up @@ -536,14 +536,14 @@ object MockKDsl {
inline fun internalUnmockkConstructor(vararg classes: KClass<*>) {
classes.forEach {
MockKGateway.implementation().constructorMockFactory.clear(
it,
MockKGateway.ClearOptions(
answers = true,
recordedCalls = true,
childMocks = true,
verificationMarks = true,
exclusionRules = true
)
it,
MockKGateway.ClearOptions(
answers = true,
recordedCalls = true,
childMocks = true,
verificationMarks = true,
exclusionRules = true
)
)
MockKCancellationRegistry
.subRegistry(MockKCancellationRegistry.Type.CONSTRUCTOR)
Expand Down Expand Up @@ -3553,7 +3553,7 @@ interface TypedMatcher {
return when {
argumentType.simpleName === null -> true
else -> {
val unboxedClass = InternalPlatformDsl.unboxClass(argumentType)
val unboxedClass = argumentType.boxedClass
return unboxedClass.isInstance(arg)
}
}
Expand Down
Expand Up @@ -37,22 +37,13 @@ expect object InternalPlatformDsl {

fun <T> coroutineCall(lambda: suspend () -> T): CoroutineCall<T>

/**
* Get the [KClass] of the single value that a `value class` contains.
*
* The result might also be a value class! So check recursively, if necessary.
*
* @return [KClass] of boxed value, if this is `value class`, else [cls].
*/
internal fun unboxClass(cls: KClass<*>): KClass<*>

/**
* Normally this simply casts [arg] to `T`
*
* However, if `T` is a `value class` (of type [cls]) this will construct a new instance of the
* value class, and set [arg] as the value.
*/
internal fun <T : Any> boxCast(
internal fun <T : Any> boxCast(
cls: KClass<*>,
arg: Any,
): T
Expand Down