Skip to content

Commit 5b7ffc7

Browse files
committed
Got rid of varargs processing stuff
1 parent e328d25 commit 5b7ffc7

File tree

3 files changed

+53
-79
lines changed

3 files changed

+53
-79
lines changed
Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,22 @@
11
package org.utbot.common
22

3-
import java.lang.reflect.Array
43
import java.lang.reflect.InvocationTargetException
54
import java.lang.reflect.Method
65
import kotlin.reflect.KClass
76

87
val Class<*>.nameOfPackage: String get() = `package`?.name?:""
98

9+
/**
10+
* Invokes [this] method of passed [obj] instance (null for static methods) with the passed [args] arguments.
11+
* NOTE: vararg parameters must be passed as an array of the corresponding type.
12+
*/
1013
fun Method.invokeCatching(obj: Any?, args: List<Any?>) = try {
11-
val invocation = if (isVarArgs) {
12-
// In java only last parameter could be vararg
13-
val firstNonVarargParametersCount = parameterCount - 1
14-
15-
val varargArray = constructVarargParameterArray(firstNonVarargParametersCount, args)
16-
17-
if (firstNonVarargParametersCount == 0) {
18-
// Only vararg parameter, just pass only it as an array
19-
invoke(obj, varargArray)
20-
} else {
21-
// Pass first non vararg parameters as vararg, and the vararg parameter as an array
22-
val firstNonVarargParameters = args.take(firstNonVarargParametersCount)
23-
24-
invoke(obj, *firstNonVarargParameters.toTypedArray(), varargArray)
25-
}
26-
} else {
27-
invoke(obj, *args.toTypedArray())
28-
}
14+
val invocation = invoke(obj, *args.toTypedArray())
2915

3016
Result.success(invocation)
3117
} catch (e: InvocationTargetException) {
3218
Result.failure<Nothing>(e.targetException)
3319
}
3420

35-
// https://stackoverflow.com/a/59857242
36-
private fun Method.constructVarargParameterArray(firstNonVarargParametersCount: Int, args: List<Any?>): Any {
37-
val varargCount = args.size - firstNonVarargParametersCount
38-
val varargElements = args.drop(firstNonVarargParametersCount)
39-
40-
val varargElementType = parameterTypes.last().componentType
41-
requireNotNull(varargElementType) {
42-
"Vararg parameter of method $this was expected to be array but ${parameterTypes.last()} found"
43-
}
44-
45-
val varargArray = Array.newInstance(parameterTypes.last().componentType, varargCount)
46-
47-
varargElements.forEachIndexed { index, value ->
48-
Array.set(varargArray, index, value)
49-
}
50-
51-
return varargArray
52-
}
53-
5421
val KClass<*>.allNestedClasses: List<KClass<*>>
5522
get() = listOf(this) + nestedClasses.flatMap { it.allNestedClasses }

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgCallableAccessManager.kt

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ import org.utbot.framework.plugin.api.util.isAbstract
5656
import org.utbot.framework.plugin.api.util.isArray
5757
import org.utbot.framework.plugin.api.util.isStatic
5858
import org.utbot.framework.plugin.api.util.isSubtypeOf
59-
import org.utbot.framework.plugin.api.util.isVarArgs
6059
import org.utbot.framework.plugin.api.util.jClass
6160
import org.utbot.framework.plugin.api.util.method
6261
import org.utbot.framework.plugin.api.util.objectArrayClassId
@@ -487,17 +486,8 @@ internal class CgCallableAccessManagerImpl(val context: CgContext) : CgCallableA
487486
executable: ExecutableId,
488487
args: List<CgExpression>,
489488
ambiguousOverloads: List<ExecutableId>
490-
): List<CgExpression> {
491-
val parametersCount = executable.parameters.size
492-
493-
val (nonVarargParameters, varargParameters) = if (executable.isVarArgs) {
494-
// Vararg is always the last parameter
495-
args.take(parametersCount - 1) to args.drop(parametersCount - 1)
496-
} else {
497-
args to emptyList()
498-
}
499-
500-
val castedNonVarargs = nonVarargParameters.withIndex().map { (i ,arg) ->
489+
): List<CgExpression> =
490+
args.withIndex().map { (i ,arg) ->
501491
val targetType = executable.parameters[i]
502492

503493
// always cast nulls
@@ -514,33 +504,6 @@ internal class CgCallableAccessManagerImpl(val context: CgContext) : CgCallableA
514504
if (ancestors.isNotEmpty()) typeCast(targetType, arg) else arg
515505
}
516506

517-
if (varargParameters.isEmpty()) {
518-
return castedNonVarargs
519-
}
520-
521-
// Vararg exist, create an array for them without inner casts
522-
523-
val varargClassId = executable.parameters.last()
524-
val varargElementClassId = varargClassId.elementClassId
525-
?: error("Vararg parameter of $executable has to be an array but ${executable.parameters.last()} found")
526-
527-
// Use a simple array initializer here since this situation is pretty rare
528-
val initializer = arrayInitializer(
529-
arrayType = varargClassId,
530-
elementType = varargElementClassId,
531-
values = varargParameters
532-
)
533-
534-
val arrayForVarargs = variableConstructor.newVar(
535-
baseType = varargElementClassId,
536-
baseName = "varargParameters"
537-
) {
538-
initializer
539-
}
540-
541-
return castedNonVarargs + arrayForVarargs
542-
}
543-
544507
/**
545508
* Receives a list of [CgExpression].
546509
* Transforms it into a list of [CgExpression] where:

utbot-framework/src/main/kotlin/org/utbot/framework/concrete/StreamConstructors.kt

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,38 @@ package org.utbot.framework.concrete
22

33
import org.utbot.framework.plugin.api.ClassId
44
import org.utbot.framework.plugin.api.MethodId
5+
import org.utbot.framework.plugin.api.UtArrayModel
56
import org.utbot.framework.plugin.api.UtAssembleModel
67
import org.utbot.framework.plugin.api.UtExecutableCallModel
8+
import org.utbot.framework.plugin.api.UtModel
9+
import org.utbot.framework.plugin.api.UtNullModel
10+
import org.utbot.framework.plugin.api.UtPrimitiveModel
711
import org.utbot.framework.plugin.api.UtStatementModel
12+
import org.utbot.framework.plugin.api.util.defaultValueModel
813
import org.utbot.framework.plugin.api.util.doubleArrayClassId
914
import org.utbot.framework.plugin.api.util.doubleStreamClassId
1015
import org.utbot.framework.plugin.api.util.intArrayClassId
1116
import org.utbot.framework.plugin.api.util.intStreamClassId
17+
import org.utbot.framework.plugin.api.util.isPrimitiveWrapper
1218
import org.utbot.framework.plugin.api.util.longArrayClassId
1319
import org.utbot.framework.plugin.api.util.longStreamClassId
1420
import org.utbot.framework.plugin.api.util.methodId
1521
import org.utbot.framework.plugin.api.util.objectArrayClassId
1622
import org.utbot.framework.plugin.api.util.streamClassId
23+
import org.utbot.framework.util.modelIdCounter
1724
import org.utbot.framework.util.valueToClassId
1825

1926
/**
2027
* Max number of elements in any concrete stream.
2128
*/
2229
private const val STREAM_ELEMENTS_LIMIT: Int = 1_000_000
2330

24-
internal abstract class AbstractStreamConstructor(private val streamClassId: ClassId, elementsClassId: ClassId) : UtAssembleModelConstructorBase() {
31+
internal abstract class AbstractStreamConstructor(private val streamClassId: ClassId, private val elementsClassId: ClassId) : UtAssembleModelConstructorBase() {
32+
private val singleElementClassId: ClassId = elementsClassId.elementClassId
33+
?: error("Stream $streamClassId elements have to be an array but $elementsClassId found")
34+
35+
private val elementDefaultValueModel: UtModel = singleElementClassId.defaultValueModel()
36+
2537
override fun provideInstantiationCall(
2638
internalConstructor: UtModelConstructorInterface,
2739
value: Any,
@@ -46,10 +58,18 @@ internal abstract class AbstractStreamConstructor(private val streamClassId: Cla
4658
)
4759
}
4860

61+
val varargModelsArray = UtArrayModel(
62+
id = modelIdCounter.incrementAndGet(),
63+
classId = elementsClassId,
64+
length = models.size,
65+
constModel = elementDefaultValueModel,
66+
stores = models.mapIndexed { i, model -> i to model.wrapperModelToPrimitiveModel() }.toMap(mutableMapOf())
67+
)
68+
4969
return UtExecutableCallModel(
5070
instance = null,
5171
executable = ofMethodId,
52-
params = models
72+
params = listOf(varargModelsArray)
5373
)
5474
}
5575

@@ -71,6 +91,30 @@ internal abstract class AbstractStreamConstructor(private val streamClassId: Cla
7191
returnType = this.streamClassId,
7292
arguments = arrayOf(elementsClassId) // vararg
7393
)
94+
95+
/**
96+
* Transforms [this] to [UtPrimitiveModel] if it is an [UtAssembleModel] for the corresponding wrapper
97+
* (primitive int and wrapper Integer, etc.), and throws an error otherwise.
98+
*/
99+
private fun UtModel.wrapperModelToPrimitiveModel(): UtModel {
100+
if (!classId.isPrimitiveWrapper) {
101+
// We do not need to transform classes other than primitive wrappers
102+
return this
103+
}
104+
105+
require(this !is UtNullModel) {
106+
"Unexpected null value in wrapper for primitive stream ${this@AbstractStreamConstructor}"
107+
}
108+
109+
require(this is UtAssembleModel) {
110+
"Unexpected not wrapper assemble model $this for value in wrapper " +
111+
"for primitive stream ${this@AbstractStreamConstructor.streamClassId}"
112+
}
113+
114+
return (instantiationCall.params.firstOrNull() as? UtPrimitiveModel)
115+
?: error("No primitive value parameter for wrapper constructor $instantiationCall in model $this " +
116+
"in wrapper for primitive stream ${this@AbstractStreamConstructor.streamClassId}")
117+
}
74118
}
75119

76120
internal class BaseStreamConstructor : AbstractStreamConstructor(streamClassId, objectArrayClassId)

0 commit comments

Comments
 (0)