@@ -47,9 +47,8 @@ class ObjectValueProvider(
47
47
description : FuzzedDescription ,
48
48
type : FuzzedType
49
49
) = sequence {
50
- val classId = type.classId
51
- findAccessibleCreators(description, classId).forEach { creatorExecutableId ->
52
- yield (createValue(classId, creatorExecutableId, description))
50
+ findAccessibleCreators(description, type).forEach { creatorExecutableId ->
51
+ yield (createValue(type.classId, creatorExecutableId, description))
53
52
}
54
53
}
55
54
@@ -164,7 +163,8 @@ class AbstractsObjectValueProvider(
164
163
}
165
164
val jClass = sc.id.jClass
166
165
return isAccessible(jClass, description.description.packageName) &&
167
- findAccessibleCreators(description, jClass.id).any()
166
+ findAccessibleCreators(description, toFuzzerType(jClass, description.typeCache)).any() &&
167
+ jClass.let { toFuzzerType(it, description.typeCache).isDefinitelySubtypeOf(description, type) }
168
168
} catch (ignore: Throwable ) {
169
169
return false
170
170
}
@@ -186,12 +186,27 @@ class AbstractsObjectValueProvider(
186
186
}
187
187
}
188
188
189
- private fun findAccessibleCreators (description : FuzzedDescription , classId : ClassId ): Sequence <ExecutableId > =
190
- (classId.allConstructors + (classId.jClass.methods
191
- .filter { it.isStatic && it.returnType.id.isSubtypeOf(classId) }
192
- .map { it.executableId })
189
+ private fun findAccessibleCreators (
190
+ description : FuzzedDescription ,
191
+ neededType : FuzzedType
192
+ ): Sequence <ExecutableId > =
193
+ (neededType.classId.allConstructors + (neededType.classId.jClass.methods
194
+ .filter {
195
+ it.isStatic && toFuzzerType(it.genericReturnType, description.typeCache)
196
+ .isDefinitelySubtypeOf(description, neededType)
197
+ }
198
+ .map { it.executableId })
193
199
).filter { isAccessible(it.executable, description.description.packageName) }
194
200
201
+ /* *
202
+ * NOTE: this function takes conservative when generics are involved.
203
+ *
204
+ * For example, `false` may be returned when [this] is `List<T>` or `ArrayList<T>` while [other] is `List<String>`.
205
+ */
206
+ // TODO should be reworked with accurate generic matching
207
+ private fun FuzzedType.isDefinitelySubtypeOf (description : FuzzedDescription , other : FuzzedType ): Boolean =
208
+ classId.isSubtypeOf(other.classId) && traverseHierarchy(description.typeCache).contains(other)
209
+
195
210
internal class PublicSetterGetter (
196
211
val setter : Method ,
197
212
val getter : Method ,
0 commit comments