Skip to content

Commit 24f8f56

Browse files
authored
Fix lambdas in concrete (#1389)
1 parent 9d08eb8 commit 24f8f56

File tree

2 files changed

+55
-5
lines changed
  • utbot-framework/src/main/kotlin/org/utbot/framework/concrete
  • utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api

2 files changed

+55
-5
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -570,12 +570,31 @@ class UtLambdaModel(
570570
val capturedValues: MutableList<UtModel> = mutableListOf(),
571571
) : UtReferenceModel(id, samType) {
572572

573+
val isFake: Boolean = lambdaName == fakeName
574+
573575
val lambdaMethodId: MethodId
574-
get() = declaringClass.jClass
575-
.declaredMethods
576-
.singleOrNull { it.name == lambdaName }
577-
?.executableId // synthetic lambda methods should not have overloads, so we always expect there to be only one method with the given name
578-
?: error("More than one method with name $lambdaName found in class: ${declaringClass.canonicalName}")
576+
get() {
577+
if (isFake) {
578+
val targetMethod = samType.jClass.declaredMethods.single()
579+
return object : MethodId(
580+
declaringClass,
581+
fakeName,
582+
targetMethod.returnType.id,
583+
targetMethod.parameterTypes.map { it.id }
584+
) {
585+
override val modifiers: Int = ModifierFactory.invoke {
586+
public = true
587+
static = true
588+
final = true
589+
}
590+
}
591+
}
592+
return declaringClass.jClass
593+
.declaredMethods
594+
.singleOrNull { it.name == lambdaName }
595+
?.executableId // synthetic lambda methods should not have overloads, so we always expect there to be only one method with the given name
596+
?: error("More than one method with name $lambdaName found in class: ${declaringClass.canonicalName}")
597+
}
579598

580599
override fun toString(): String = "Anonymous function $lambdaName implementing functional interface $declaringClass"
581600

@@ -591,6 +610,18 @@ class UtLambdaModel(
591610
}
592611

593612
override fun hashCode(): Int = id
613+
614+
companion object {
615+
private const val fakeName = "<FAKE>"
616+
617+
/**
618+
* Create a non-existent lambda with fake method.
619+
*
620+
* That's temporary solution for building lambdas from concrete values.
621+
*/
622+
fun createFake(id: Int, samType: ClassId, declaringClass: ClassId) =
623+
UtLambdaModel(id, samType, declaringClass, fakeName)
624+
}
594625
}
595626

596627
/**

utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtModelConstructor.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import org.utbot.framework.util.valueToClassId
3535
import java.lang.reflect.Modifier
3636
import java.util.IdentityHashMap
3737
import java.util.stream.BaseStream
38+
import org.utbot.framework.plugin.api.util.utContext
3839

3940
/**
4041
* Represents common interface for model constructors.
@@ -79,6 +80,21 @@ class UtModelConstructor(
7980
return objectToModelCache[value]?.let { (it as? UtReferenceModel)?.id } ?: computeUnusedIdAndUpdate()
8081
}
8182

83+
private val proxyLambdaSubstring = "$\$Lambda$"
84+
85+
private fun isProxyLambda(value: Any?): Boolean {
86+
if (value == null) {
87+
return false
88+
}
89+
return proxyLambdaSubstring in value::class.java.name
90+
}
91+
92+
private fun constructFakeLambda(value: Any, classId: ClassId): UtLambdaModel {
93+
val baseClassName = value::class.java.name.substringBefore(proxyLambdaSubstring)
94+
val baseClass = utContext.classLoader.loadClass(baseClassName).id
95+
return UtLambdaModel.createFake(handleId(value), classId, baseClass)
96+
}
97+
8298
/**
8399
* Constructs a UtModel from a concrete [value] with a specific [classId]. The result can be a [UtAssembleModel]
84100
* as well.
@@ -91,6 +107,9 @@ class UtModelConstructor(
91107
return model
92108
}
93109
}
110+
if (isProxyLambda(value)) {
111+
return constructFakeLambda(value!!, classId)
112+
}
94113
return when (value) {
95114
null -> UtNullModel(classId)
96115
is Unit -> UtVoidModel

0 commit comments

Comments
 (0)