Skip to content

Commit 8198463

Browse files
authored
Fix for filtering anonymous function types (#984)
1 parent f53b7f6 commit 8198463

File tree

4 files changed

+63
-36
lines changed

4 files changed

+63
-36
lines changed

utbot-core/src/main/kotlin/org/utbot/common/FileUtil.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,16 @@ object FileUtil {
224224
}
225225

226226
// https://stackoverflow.com/a/68822715
227-
fun byteCountToDisplaySize(bytes: Long): String =
228-
when {
229-
bytes >= 1 shl 30 -> "%.1f GB".format(bytes / (1 shl 30))
230-
bytes >= 1 shl 20 -> "%.1f MB".format(bytes / (1 shl 20))
231-
bytes >= 1 shl 10 -> "%.0f kB".format(bytes / (1 shl 10))
232-
else -> "$bytes bytes"
227+
fun byteCountToDisplaySize(bytes: Long): String {
228+
val bytesInDouble = bytes.toDouble()
229+
230+
return when {
231+
bytesInDouble >= 1 shl 30 -> "%.1f GB".format(bytesInDouble / (1 shl 30))
232+
bytesInDouble >= 1 shl 20 -> "%.1f MB".format(bytesInDouble / (1 shl 20))
233+
bytesInDouble >= 1 shl 10 -> "%.0f kB".format(bytesInDouble / (1 shl 10))
234+
else -> "$bytesInDouble bytes"
233235
}
236+
}
234237
}
235238

236239
/**
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.utbot.examples.lambda
2+
3+
import org.junit.jupiter.api.Test
4+
import org.utbot.testcheckers.eq
5+
import org.utbot.tests.infrastructure.UtValueTestCaseChecker
6+
7+
class PredicateNotExampleTest : UtValueTestCaseChecker(testClass = PredicateNotExample::class) {
8+
@Test
9+
fun testPredicateNotExample() {
10+
check(
11+
PredicateNotExample::predicateNotExample,
12+
eq(2),
13+
{ a, r -> a == 5 && r == false },
14+
{ a, r -> a != 5 && r == true },
15+
)
16+
}
17+
}

utbot-framework/src/main/kotlin/org/utbot/engine/TypeResolver.kt

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
112112
if (numDimensions == 0) baseType else baseType.makeArrayType(numDimensions)
113113
}
114114

115-
return TypeStorage(type, concretePossibleTypes).filterInappropriateClassesForCodeGeneration()
115+
return TypeStorage(type, concretePossibleTypes).removeInappropriateTypes()
116116
}
117117

118118
private fun isInappropriateOrArrayOfMocksOrLocals(numDimensions: Int, baseType: Type?): Boolean {
@@ -182,46 +182,40 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
182182
else -> error("Unexpected type $type")
183183
}
184184

185-
return TypeStorage(type, possibleTypes).filterInappropriateClassesForCodeGeneration()
185+
return TypeStorage(type, possibleTypes).removeInappropriateTypes()
186186
}
187187

188188
/**
189-
* Where possible, remove types that are not currently supported by code generation.
190-
* For example, we filter out artificial entities (lambdas are an example of them)
191-
* if the least common type is **not** artificial itself.
189+
* Remove wrapper types and, if any other type is available, artificial entities.
192190
*/
193-
private fun TypeStorage.filterInappropriateClassesForCodeGeneration(): TypeStorage {
194-
val unwantedTypes = mutableSetOf<Type>()
195-
val concreteTypes = mutableSetOf<Type>()
196-
191+
private fun TypeStorage.removeInappropriateTypes(): TypeStorage {
197192
val leastCommonSootClass = (leastCommonType as? RefType)?.sootClass
198193
val keepArtificialEntities = leastCommonSootClass?.isArtificialEntity == true
199194

200-
possibleConcreteTypes.forEach {
201-
val sootClass = (it.baseType as? RefType)?.sootClass ?: run {
202-
// All not RefType should be included in the concreteTypes, e.g., arrays
203-
concreteTypes += it
204-
return@forEach
195+
val appropriateTypes = possibleConcreteTypes.filter {
196+
// All not RefType should be included in the concreteTypes, e.g., arrays
197+
val sootClass = (it.baseType as? RefType)?.sootClass ?: return@filter true
198+
199+
// All artificial entities except anonymous functions should be filtered out if we have another types
200+
if (sootClass.isArtificialEntity) {
201+
if (sootClass.isLambda) {
202+
return@filter true
203+
}
204+
205+
return@filter keepArtificialEntities
205206
}
206-
when {
207-
sootClass.isUtMock -> unwantedTypes += it
208-
sootClass.isArtificialEntity -> {
209-
if (sootClass.isLambda) {
210-
unwantedTypes += it
211-
} else if (keepArtificialEntities) {
212-
concreteTypes += it
213-
}
207+
208+
// All wrappers should filtered out because they could not be instantiated
209+
workaround(WorkaroundReason.HACK) {
210+
if (leastCommonSootClass == OBJECT_TYPE && sootClass.isOverridden) {
211+
return@filter false
214212
}
215-
workaround(WorkaroundReason.HACK) { leastCommonSootClass == OBJECT_TYPE && sootClass.isOverridden } -> Unit
216-
else -> concreteTypes += it
217213
}
218-
}
219214

220-
return if (concreteTypes.isEmpty()) {
221-
copy(possibleConcreteTypes = unwantedTypes)
222-
} else {
223-
copy(possibleConcreteTypes = concreteTypes)
224-
}
215+
return@filter true
216+
}.toSet()
217+
218+
return copy(possibleConcreteTypes = appropriateTypes)
225219
}
226220

227221
/**
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.utbot.examples.lambda;
2+
3+
import java.util.function.*;
4+
5+
public class PredicateNotExample {
6+
public boolean predicateNotExample(int a) {
7+
if (Predicate.not(i -> i.equals(5)).test(a)) {
8+
return true;
9+
} else {
10+
return false;
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)