1
1
package org.utbot.framework.codegen.tree
2
2
3
+ import kotlinx.collections.immutable.PersistentList
4
+ import kotlinx.collections.immutable.PersistentSet
3
5
import org.utbot.framework.codegen.domain.RegularImport
4
6
import org.utbot.framework.codegen.domain.StaticImport
7
+ import org.utbot.framework.codegen.domain.builtin.setArrayElement
5
8
import 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
6
11
import org.utbot.framework.codegen.domain.models.CgClassId
7
12
import org.utbot.framework.codegen.domain.models.CgExpression
8
13
import org.utbot.framework.codegen.domain.models.CgTypeCast
9
14
import org.utbot.framework.codegen.domain.models.CgValue
10
15
import org.utbot.framework.codegen.domain.models.CgVariable
16
+ import org.utbot.framework.codegen.services.access.CgCallableAccessManager
17
+ import org.utbot.framework.codegen.util.at
11
18
import org.utbot.framework.codegen.util.isAccessibleFrom
12
19
import org.utbot.framework.fields.ArrayElementAccess
13
20
import org.utbot.framework.fields.FieldAccess
14
21
import 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
36
22
import org.utbot.framework.plugin.api.BuiltinClassId
37
23
import org.utbot.framework.plugin.api.BuiltinMethodId
38
24
import org.utbot.framework.plugin.api.ClassId
@@ -45,13 +31,32 @@ import org.utbot.framework.plugin.api.UtModel
45
31
import org.utbot.framework.plugin.api.UtNullModel
46
32
import org.utbot.framework.plugin.api.UtPrimitiveModel
47
33
import org.utbot.framework.plugin.api.WildcardTypeParameter
48
- import org.utbot.framework.plugin.api.util.isStatic
49
34
import org.utbot.framework.plugin.api.util.arrayLikeName
35
+ import org.utbot.framework.plugin.api.util.booleanClassId
50
36
import 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
51
39
import 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
52
52
import org.utbot.framework.plugin.api.util.methodId
53
53
import org.utbot.framework.plugin.api.util.objectArrayClassId
54
54
import 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
55
60
56
61
data class EnvironmentFieldStateCache (
57
62
val thisInstance : FieldStateCache ,
@@ -335,14 +340,62 @@ internal fun Class<*>.overridesEquals(): Boolean =
335
340
else -> declaredMethods.any { it.name == " equals" && it.parameterTypes.contentEquals(arrayOf(Any ::class .java)) }
336
341
}
337
342
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
+
338
388
// NOTE: this function does not consider executable return type because it is not important in our case
339
389
internal fun ClassId.getAmbiguousOverloadsOf (executableId : ExecutableId ): Sequence <ExecutableId > {
340
390
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
+ }
342
396
is ConstructorId -> allConstructors
343
397
}
344
398
345
- // We should take here not only declared methods but also inherited
346
399
return allExecutables.filter {
347
400
it.name == executableId.name && it.parameters.size == executableId.executable.parameters.size
348
401
}
0 commit comments