11package org.utbot.framework.codegen.tree
22
3+ import kotlinx.collections.immutable.PersistentList
4+ import kotlinx.collections.immutable.PersistentSet
35import org.utbot.framework.codegen.domain.RegularImport
46import org.utbot.framework.codegen.domain.StaticImport
7+ import org.utbot.framework.codegen.domain.builtin.setArrayElement
58import org.utbot.framework.codegen.domain.context.CgContextOwner
9+ import org.utbot.framework.codegen.domain.models.CgAllocateInitializedArray
10+ import org.utbot.framework.codegen.domain.models.CgArrayInitializer
611import org.utbot.framework.codegen.domain.models.CgClassId
712import org.utbot.framework.codegen.domain.models.CgExpression
813import org.utbot.framework.codegen.domain.models.CgTypeCast
914import org.utbot.framework.codegen.domain.models.CgValue
1015import org.utbot.framework.codegen.domain.models.CgVariable
16+ import org.utbot.framework.codegen.services.access.CgCallableAccessManager
17+ import org.utbot.framework.codegen.util.at
1118import org.utbot.framework.codegen.util.isAccessibleFrom
1219import org.utbot.framework.fields.ArrayElementAccess
1320import org.utbot.framework.fields.FieldAccess
1421import org.utbot.framework.fields.FieldPath
15- import org.utbot.framework.plugin.api.util.booleanClassId
16- import org.utbot.framework.plugin.api.util.byteClassId
17- import org.utbot.framework.plugin.api.util.charClassId
18- import org.utbot.framework.plugin.api.util.doubleClassId
19- import org.utbot.framework.plugin.api.util.enclosingClass
20- import org.utbot.framework.plugin.api.util.executable
21- import org.utbot.framework.plugin.api.util.floatClassId
22- import org.utbot.framework.plugin.api.util.id
23- import org.utbot.framework.plugin.api.util.intClassId
24- import org.utbot.framework.plugin.api.util.isRefType
25- import org.utbot.framework.plugin.api.util.isSubtypeOf
26- import org.utbot.framework.plugin.api.util.longClassId
27- import org.utbot.framework.plugin.api.util.shortClassId
28- import org.utbot.framework.plugin.api.util.underlyingType
29- import kotlinx.collections.immutable.PersistentList
30- import kotlinx.collections.immutable.PersistentSet
31- import org.utbot.framework.codegen.domain.builtin.setArrayElement
32- import org.utbot.framework.codegen.domain.models.CgAllocateInitializedArray
33- import org.utbot.framework.codegen.domain.models.CgArrayInitializer
34- import org.utbot.framework.codegen.services.access.CgCallableAccessManager
35- import org.utbot.framework.codegen.util.at
3622import org.utbot.framework.plugin.api.BuiltinClassId
3723import org.utbot.framework.plugin.api.BuiltinMethodId
3824import org.utbot.framework.plugin.api.ClassId
@@ -45,13 +31,32 @@ import org.utbot.framework.plugin.api.UtModel
4531import org.utbot.framework.plugin.api.UtNullModel
4632import org.utbot.framework.plugin.api.UtPrimitiveModel
4733import org.utbot.framework.plugin.api.WildcardTypeParameter
48- import org.utbot.framework.plugin.api.util.isStatic
4934import org.utbot.framework.plugin.api.util.arrayLikeName
35+ import org.utbot.framework.plugin.api.util.booleanClassId
5036import org.utbot.framework.plugin.api.util.builtinStaticMethodId
37+ import org.utbot.framework.plugin.api.util.byteClassId
38+ import org.utbot.framework.plugin.api.util.charClassId
5139import org.utbot.framework.plugin.api.util.denotableType
40+ import org.utbot.framework.plugin.api.util.doubleClassId
41+ import org.utbot.framework.plugin.api.util.enclosingClass
42+ import org.utbot.framework.plugin.api.util.executable
43+ import org.utbot.framework.plugin.api.util.executableId
44+ import org.utbot.framework.plugin.api.util.floatClassId
45+ import org.utbot.framework.plugin.api.util.id
46+ import org.utbot.framework.plugin.api.util.intClassId
47+ import org.utbot.framework.plugin.api.util.isRefType
48+ import org.utbot.framework.plugin.api.util.isStatic
49+ import org.utbot.framework.plugin.api.util.isSubtypeOf
50+ import org.utbot.framework.plugin.api.util.jClass
51+ import org.utbot.framework.plugin.api.util.longClassId
5252import org.utbot.framework.plugin.api.util.methodId
5353import org.utbot.framework.plugin.api.util.objectArrayClassId
5454import org.utbot.framework.plugin.api.util.objectClassId
55+ import org.utbot.framework.plugin.api.util.shortClassId
56+ import org.utbot.framework.plugin.api.util.signature
57+ import org.utbot.framework.plugin.api.util.underlyingType
58+ import java.lang.reflect.Method
59+ import java.lang.reflect.Modifier
5560
5661data class EnvironmentFieldStateCache (
5762 val thisInstance : FieldStateCache ,
@@ -335,14 +340,62 @@ internal fun Class<*>.overridesEquals(): Boolean =
335340 else -> declaredMethods.any { it.name == " equals" && it.parameterTypes.contentEquals(arrayOf(Any ::class .java)) }
336341 }
337342
343+ /* *
344+ * Returns all methods of [this] class (including inherited), except base methods (i.e., if any method is overridden,
345+ * only the latest overriding will be included).
346+ * NOTE: for the reference [see also](https://stackoverflow.com/a/28408148)
347+ */
348+ private fun Class <* >.allMethodsWithoutBaseMethods (): Set <Method > {
349+ val collectedMethods = mutableSetOf<Method >(* methods)
350+ val types = collectedMethods.map { it.signature }.associateWithTo(mutableMapOf ()) { mutableSetOf<Package >() }
351+ val access = Modifier .PUBLIC or Modifier .PROTECTED or Modifier .PRIVATE
352+
353+ var currentClass: Class <* >? = this
354+ while (currentClass != null ) {
355+ for (method in currentClass.declaredMethods) {
356+ val modifiers = method.modifiers
357+
358+ if (! Modifier .isStatic(modifiers)) {
359+ when (modifiers and access) {
360+ Modifier .PUBLIC -> continue
361+ Modifier .PROTECTED -> {
362+ if (types.putIfAbsent(method.signature, mutableSetOf ()) != null ) {
363+ continue
364+ }
365+ }
366+ Modifier .PRIVATE -> {}
367+ else -> { // package-private
368+ val pkg = types.computeIfAbsent(method.signature) { mutableSetOf () }
369+
370+ if (pkg.isNotEmpty() && pkg.add(currentClass.getPackage())) {
371+ break
372+ } else {
373+ continue
374+ }
375+ }
376+ }
377+ }
378+
379+ collectedMethods + = method
380+ }
381+
382+ currentClass = currentClass.superclass
383+ }
384+
385+ return collectedMethods
386+ }
387+
338388// NOTE: this function does not consider executable return type because it is not important in our case
339389internal fun ClassId.getAmbiguousOverloadsOf (executableId : ExecutableId ): Sequence <ExecutableId > {
340390 val allExecutables = when (executableId) {
341- is MethodId -> allMethods
391+ is MethodId -> {
392+ // For method we should check all overloadings and inherited methods, but do not consider base methods
393+ // in case of overriding (for example, for ArrayList#add we should not take List#add and AbstractCollection#add)
394+ executableId.classId.jClass.allMethodsWithoutBaseMethods().map { it.executableId }.asSequence()
395+ }
342396 is ConstructorId -> allConstructors
343397 }
344398
345- // We should take here not only declared methods but also inherited
346399 return allExecutables.filter {
347400 it.name == executableId.name && it.parameters.size == executableId.executable.parameters.size
348401 }
0 commit comments