11package org.utbot.fuzzing.providers
22
3+ import com.google.common.reflect.TypeToken
34import org.utbot.framework.plugin.api.*
45import org.utbot.framework.plugin.api.util.*
56import org.utbot.fuzzer.FuzzedType
67import org.utbot.fuzzer.FuzzedValue
78import org.utbot.fuzzer.IdGenerator
89import org.utbot.fuzzer.fuzzed
910import org.utbot.fuzzing.*
11+ import org.utbot.fuzzing.spring.utils.jType
1012import org.utbot.fuzzing.utils.hex
13+ import java.lang.reflect.Method
1114import kotlin.reflect.KClass
1215
1316class EmptyCollectionValueProvider (
@@ -80,9 +83,25 @@ class EmptyCollectionValueProvider(
8083class MapValueProvider (
8184 idGenerator : IdGenerator <Int >
8285) : CollectionValueProvider(idGenerator, java.util.Map : :class.id) {
86+
87+ private enum class MethodCall { KEYS , VALUES }
88+
89+ private fun findTypeByMethod (description : FuzzedDescription , type : FuzzedType , method : MethodCall ): FuzzedType {
90+ val methodName = when (method) {
91+ MethodCall .KEYS -> " keySet"
92+ MethodCall .VALUES -> " values"
93+ }
94+ val m = Map ::class .java.getMethod(methodName)
95+ return resolveTypeByMethod(description, type, m)?.let {
96+ assert (it.classId.isSubtypeOf(collectionClassId))
97+ assert (it.generics.size == 1 )
98+ it.generics[0 ]
99+ } ? : FuzzedType (objectClassId)
100+ }
101+
83102 override fun resolveType (description : FuzzedDescription , type : FuzzedType ) = sequence {
84- val keyGeneric = type.generics.getOrNull( 0 ) ? : FuzzedType (objectClassId )
85- val valueGeneric = type.generics.getOrNull( 1 ) ? : FuzzedType (objectClassId )
103+ val keyGeneric = findTypeByMethod(description, type, MethodCall . KEYS )
104+ val valueGeneric = findTypeByMethod(description, type, MethodCall . VALUES )
86105 when (type.classId) {
87106 java.util.Map ::class .id -> {
88107 if (keyGeneric.classId isSubtypeOf Comparable ::class ) {
@@ -108,8 +127,20 @@ class MapValueProvider(
108127class ListSetValueProvider (
109128 idGenerator : IdGenerator <Int >
110129) : CollectionValueProvider(idGenerator, java.util.Collection : :class.id) {
130+
131+ private val iteratorClassId = java.util.Iterator ::class .java.id
132+
133+ private fun findTypeByMethod (description : FuzzedDescription , type : FuzzedType ): FuzzedType {
134+ val method = java.util.Collection ::class .java.getMethod(" iterator" )
135+ return resolveTypeByMethod(description, type, method)?.let {
136+ assert (it.classId.isSubtypeOf(iteratorClassId))
137+ assert (it.generics.size == 1 )
138+ it.generics[0 ]
139+ } ? : FuzzedType (objectClassId)
140+ }
141+
111142 override fun resolveType (description : FuzzedDescription , type : FuzzedType ) = sequence {
112- val generic = type.generics.firstOrNull() ? : FuzzedType (objectClassId )
143+ val generic = findTypeByMethod(description, type )
113144 when (type.classId) {
114145 java.util.Queue ::class .id,
115146 java.util.Deque ::class .id-> {
@@ -171,6 +202,20 @@ abstract class CollectionValueProvider(
171202 }
172203 }
173204
205+ /* *
206+ * Can be used to resolve some types using [type] and some method of this type
207+ */
208+ protected fun resolveTypeByMethod (description : FuzzedDescription , type : FuzzedType , method : Method ): FuzzedType ? {
209+ return try {
210+ toFuzzerType(
211+ TypeToken .of(type.jType).resolveType(method.genericReturnType).type,
212+ description.typeCache
213+ )
214+ } catch (t: Throwable ) {
215+ null
216+ }
217+ }
218+
174219 /* *
175220 * Types should be resolved with type parameters
176221 */
0 commit comments