Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import org.utbot.framework.codegen.model.constructor.context.CgContextOwner
import org.utbot.framework.codegen.model.constructor.util.CgComponents
import org.utbot.framework.codegen.model.constructor.util.CgStatementConstructor
import org.utbot.framework.codegen.model.constructor.util.get
import org.utbot.framework.codegen.model.constructor.util.isDefaultValueOf
import org.utbot.framework.codegen.model.constructor.util.isNotDefaultValueOf
import org.utbot.framework.codegen.model.constructor.util.typeCast
import org.utbot.framework.codegen.model.tree.CgAllocateArray
import org.utbot.framework.codegen.model.tree.CgAllocateInitializedArray
import org.utbot.framework.codegen.model.tree.CgDeclaration
import org.utbot.framework.codegen.model.tree.CgEnumConstantAccess
import org.utbot.framework.codegen.model.tree.CgExpression
Expand Down Expand Up @@ -222,49 +224,63 @@ internal class CgVariableConstructor(val context: CgContext) :
return CgLiteral(classId, paramModel.value)
}

private fun constructArray(model: UtArrayModel, baseName: String?): CgVariable {
val elementType = model.classId.elementClassId!!
val array = newVar(model.classId, baseName) { CgAllocateArray(model.classId, elementType, model.length) }
valueByModelId[model.id] = array
if (model.length <= 0) return array
if (model.length == 1) {
private fun constructArray(arrayModel: UtArrayModel, baseName: String?): CgVariable {
val elementType = arrayModel.classId.elementClassId!!
val elementModels = (0 until arrayModel.length).map {
if (it in arrayModel.stores) arrayModel.stores[it] else arrayModel.constModel
}

val canInitWithValues = elementModels.all { it is UtPrimitiveModel } || elementModels.all { it is UtNullModel }

val initializer = if (canInitWithValues) {
CgAllocateInitializedArray(arrayModel)
} else {
CgAllocateArray(arrayModel.classId, elementType, arrayModel.length)
}

val array = newVar(arrayModel.classId, baseName) { initializer }
valueByModelId[arrayModel.id] = array

if (canInitWithValues) {
return array
}

if (arrayModel.length <= 0) return array
if (arrayModel.length == 1) {
// take first element value if it is present, otherwise use default value from model
val elementModel = model[0]
val elementModel = arrayModel[0]
if (elementModel isNotDefaultValueOf elementType) {
array.setArrayElement(0, getOrCreateVariable(elementModel))
}
} else {
val indexedValuesFromStores = if (model.stores.size == model.length) {
// do not use constModel because stores fully cover array

// choose all not default values from stores
model.stores.entries.filter { (_, element) -> element isNotDefaultValueOf elementType }
} else {
val initialValue = when {
model.constModel isNotDefaultValueOf elementType -> model.constModel
else -> elementType.defaultValueModel()
}
val indexedValuesFromStores =
if (arrayModel.stores.size == arrayModel.length) {
// do not use constModel because stores fully cover array
arrayModel.stores.entries.filter { (_, element) -> element isNotDefaultValueOf elementType }
} else {
// fill array if constModel is not default type value
if (arrayModel.constModel isNotDefaultValueOf elementType) {
val defaultVariable = getOrCreateVariable(arrayModel.constModel, "defaultValue")
basicForLoop(arrayModel.length) { i ->
array.setArrayElement(i, defaultVariable)
}
}

// fill array via constModel if it is not default type value
if (model.constModel isNotDefaultValueOf elementType) {
// fill array with default values from model
val defaultValue = getOrCreateVariable(model.constModel, "defaultValue")
basicForLoop(model.length) { i ->
array.setArrayElement(i, defaultValue)
// choose all not default values
val defaultValue = if (arrayModel.constModel isDefaultValueOf elementType) {
arrayModel.constModel
} else {
elementType.defaultValueModel()
}
arrayModel.stores.entries.filter { (_, element) -> element != defaultValue }
}

// choose all not default values
model.stores.entries.filter { (_, element) -> element != initialValue }
}

val sortedByIndexValuesFromStores = indexedValuesFromStores.sortedBy { it.key }

// set all values from stores manually
sortedByIndexValuesFromStores.forEach { (index, element) ->
array.setArrayElement(index, getOrCreateVariable(element))
}
indexedValuesFromStores
.sortedBy { it.key }
.forEach { (index, element) -> array.setArrayElement(index, getOrCreateVariable(element)) }
}

return array
}

Expand Down Expand Up @@ -299,7 +315,10 @@ internal class CgVariableConstructor(val context: CgContext) :
/**
* [indexedValuesFromStores] have to be continuous sorted range
*/
private fun setStoresRange(array: CgVariable, indexedValuesFromStores: List<MutableMap.MutableEntry<Int, UtModel>>) {
private fun setStoresRange(
array: CgVariable,
indexedValuesFromStores: List<MutableMap.MutableEntry<Int, UtModel>>
) {
if (indexedValuesFromStores.size < 3) {
// range is too small, better set manually
indexedValuesFromStores.forEach { (index, element) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.utbot.framework.plugin.api.ExecutableId
import org.utbot.framework.plugin.api.FieldId
import org.utbot.framework.plugin.api.MethodId
import org.utbot.framework.plugin.api.TypeParameters
import org.utbot.framework.plugin.api.UtArrayModel
import org.utbot.framework.plugin.api.util.booleanClassId
import org.utbot.framework.plugin.api.util.id
import org.utbot.framework.plugin.api.util.intClassId
Expand Down Expand Up @@ -81,6 +82,7 @@ interface CgElement {
is CgLiteral -> visit(element)
is CgNonStaticRunnable -> visit(element)
is CgStaticRunnable -> visit(element)
is CgAllocateInitializedArray -> visit(element)
is CgAllocateArray -> visit(element)
is CgEnumConstantAccess -> visit(element)
is CgFieldAccess -> visit(element)
Expand Down Expand Up @@ -644,7 +646,7 @@ class CgStaticRunnable(type: ClassId, val classId: ClassId, methodId: MethodId):

// Array allocation

class CgAllocateArray(type: ClassId, elementType: ClassId, val size: Int)
open class CgAllocateArray(type: ClassId, elementType: ClassId, val size: Int)
: CgReferenceExpression {
override val type: ClassId by lazy { CgClassId(type.name, updateElementType(elementType), isNullable = type.isNullable) }
val elementType: ClassId by lazy {
Expand All @@ -662,6 +664,10 @@ class CgAllocateArray(type: ClassId, elementType: ClassId, val size: Int)
}
}

class CgAllocateInitializedArray(val model: UtArrayModel)
: CgAllocateArray(model.classId, model.classId.elementClassId!!, model.length)


// Spread operator (for Kotlin, empty for Java)

class CgSpread(override val type: ClassId, val array: CgExpression): CgExpression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.FieldId
import org.utbot.framework.plugin.api.MethodId
import org.utbot.framework.plugin.api.util.booleanClassId
import org.utbot.framework.plugin.api.util.byteClassId
import org.utbot.framework.plugin.api.util.charClassId
import org.utbot.framework.plugin.api.util.doubleClassId
import org.utbot.framework.plugin.api.util.floatClassId
Expand Down Expand Up @@ -53,7 +54,7 @@ fun intLiteral(num: Int) = CgLiteral(intClassId, num)

fun longLiteral(num: Long) = CgLiteral(longClassId, num)

fun byteLiteral(num: Byte) = CgLiteral(booleanClassId, num)
fun byteLiteral(num: Byte) = CgLiteral(byteClassId, num)

fun shortLiteral(num: Short) = CgLiteral(shortClassId, num)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.utbot.framework.codegen.model.visitor

import org.apache.commons.text.StringEscapeUtils
import org.utbot.common.WorkaroundReason.LONG_CODE_FRAGMENTS
import org.utbot.common.workaround
import org.utbot.framework.codegen.Import
Expand Down Expand Up @@ -77,11 +78,22 @@ import org.utbot.framework.codegen.model.tree.CgVariable
import org.utbot.framework.codegen.model.tree.CgWhileLoop
import org.utbot.framework.codegen.model.util.CgPrinter
import org.utbot.framework.codegen.model.util.CgPrinterImpl
import org.utbot.framework.codegen.model.util.resolve
import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.MethodId
import org.utbot.framework.plugin.api.TypeParameters
import org.apache.commons.text.StringEscapeUtils
import org.utbot.framework.plugin.api.UtArrayModel
import org.utbot.framework.plugin.api.UtModel
import org.utbot.framework.plugin.api.UtNullModel
import org.utbot.framework.plugin.api.UtPrimitiveModel
import org.utbot.framework.plugin.api.util.byteClassId
import org.utbot.framework.plugin.api.util.charClassId
import org.utbot.framework.plugin.api.util.doubleClassId
import org.utbot.framework.plugin.api.util.floatClassId
import org.utbot.framework.plugin.api.util.intClassId
import org.utbot.framework.plugin.api.util.longClassId
import org.utbot.framework.plugin.api.util.shortClassId

internal abstract class CgAbstractRenderer(val context: CgContext, val printer: CgPrinter = CgPrinterImpl()) : CgVisitor<Unit>,
CgPrinter by printer {
Expand All @@ -98,6 +110,22 @@ internal abstract class CgAbstractRenderer(val context: CgContext, val printer:

protected abstract val langPackage: String

//We may render array elements in initializer in one line or in separate lines:
//items count in one line depends on the value type.
protected fun arrayElementsInLine(constModel: UtModel): Int {
if (constModel is UtNullModel) return 10
return when (constModel.classId) {
intClassId,
byteClassId,
longClassId,
charClassId -> 8
shortClassId,
doubleClassId,
floatClassId -> 6
else -> 5
}
}

private val MethodId.accessibleByName: Boolean
get() = (context.shouldOptimizeImports && this in context.importedStaticMethods) || classId == context.currentTestClass

Expand Down Expand Up @@ -689,6 +717,17 @@ internal abstract class CgAbstractRenderer(val context: CgContext, val printer:

protected abstract fun renderExceptionCatchVariable(exception: CgVariable)

protected fun UtArrayModel.getElementExpr(index: Int): CgExpression {
val itemModel = if (index in this.stores) this.stores[index] else this.constModel
val cgValue: CgExpression = when (itemModel) {
is UtPrimitiveModel -> itemModel.value.resolve()
is UtNullModel -> null.resolve()
else -> error("Model $itemModel is not allowed here")
}

return cgValue
}

protected fun getEscapedImportRendering(import: Import): String =
import.qualifiedName
.split(".")
Expand Down Expand Up @@ -720,6 +759,18 @@ internal abstract class CgAbstractRenderer(val context: CgContext, val printer:
}
}

protected fun UtArrayModel.renderElements(length: Int, elementsInLine: Int) {
for (i in 0 until length) {
val expr = this.getElementExpr(i)

if (i == 0 && length >= elementsInLine || i != 0 && i % elementsInLine == 0) {
println()
}
expr.accept(this@CgAbstractRenderer)
if (i != length - 1) print(",")
}
}

protected inline fun withIndent(block: () -> Unit) {
try {
pushIndent()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.utbot.framework.codegen.model.visitor

import org.apache.commons.text.StringEscapeUtils
import org.utbot.framework.codegen.RegularImport
import org.utbot.framework.codegen.StaticImport
import org.utbot.framework.codegen.model.constructor.context.CgContext
import org.utbot.framework.codegen.model.tree.CgAllocateArray
import org.utbot.framework.codegen.model.tree.CgAllocateInitializedArray
import org.utbot.framework.codegen.model.tree.CgAnonymousFunction
import org.utbot.framework.codegen.model.tree.CgArrayAnnotationArgument
import org.utbot.framework.codegen.model.tree.CgBreakStatement
Expand Down Expand Up @@ -39,9 +41,9 @@ import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.TypeParameters
import org.utbot.framework.plugin.api.util.wrapperByPrimitive
import org.apache.commons.text.StringEscapeUtils

internal class CgJavaRenderer(context: CgContext, printer: CgPrinter = CgPrinterImpl()) : CgAbstractRenderer(context, printer) {
internal class CgJavaRenderer(context: CgContext, printer: CgPrinter = CgPrinterImpl()) :
CgAbstractRenderer(context, printer) {

override val statementEnding: String = ";"

Expand Down Expand Up @@ -154,11 +156,19 @@ internal class CgJavaRenderer(context: CgContext, printer: CgPrinter = CgPrinter
}

override fun visit(element: CgAllocateArray) {
// TODO: definitely rewrite later
// TODO: check array type rendering
val beforeLength = element.type.canonicalName.substringBefore("[")
val afterLength = element.type.canonicalName.substringAfter("]")
print("new $beforeLength[${element.size}]$afterLength")
// TODO: Arsen strongly required to rewrite later
val typeName = element.type.canonicalName.substringBefore("[")
val otherDimensions = element.type.canonicalName.substringAfter("]")
print("new $typeName[${element.size}]$otherDimensions")
}

override fun visit(element: CgAllocateInitializedArray) {
val arrayModel = element.model
val elementsInLine = arrayElementsInLine(arrayModel.constModel)

print("{")
arrayModel.renderElements(element.size, elementsInLine)
print("}")
}

override fun visit(element: CgGetLength) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.utbot.framework.codegen.model.visitor

import org.apache.commons.text.StringEscapeUtils
import org.utbot.common.WorkaroundReason
import org.utbot.common.workaround
import org.utbot.framework.codegen.RegularImport
import org.utbot.framework.codegen.StaticImport
import org.utbot.framework.codegen.isLanguageKeyword
import org.utbot.framework.codegen.model.constructor.context.CgContext
import org.utbot.framework.codegen.model.tree.CgAllocateArray
import org.utbot.framework.codegen.model.tree.CgAllocateInitializedArray
import org.utbot.framework.codegen.model.tree.CgAnonymousFunction
import org.utbot.framework.codegen.model.tree.CgArrayAnnotationArgument
import org.utbot.framework.codegen.model.tree.CgArrayElementAccess
Expand Down Expand Up @@ -43,14 +45,14 @@ import org.utbot.framework.plugin.api.BuiltinClassId
import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.TypeParameters
import org.utbot.framework.plugin.api.UtPrimitiveModel
import org.utbot.framework.plugin.api.WildcardTypeParameter
import org.utbot.framework.plugin.api.util.id
import org.utbot.framework.plugin.api.util.isArray
import org.utbot.framework.plugin.api.util.isPrimitive
import org.utbot.framework.plugin.api.util.isPrimitiveWrapper
import org.utbot.framework.plugin.api.util.kClass
import org.utbot.framework.plugin.api.util.voidClassId
import org.apache.commons.text.StringEscapeUtils

//TODO rewrite using KtPsiFactory?
internal class CgKotlinRenderer(context: CgContext, printer: CgPrinter = CgPrinterImpl()) : CgAbstractRenderer(context, printer) {
Expand Down Expand Up @@ -242,6 +244,22 @@ internal class CgKotlinRenderer(context: CgContext, printer: CgPrinter = CgPrint
}
}

override fun visit(element: CgAllocateInitializedArray) {
val arrayModel = element.model
val elementsInLine = arrayElementsInLine(arrayModel.constModel)

if (arrayModel.constModel is UtPrimitiveModel) {
val prefix = arrayModel.constModel.classId.name.toLowerCase()
print("${prefix}ArrayOf(")
arrayModel.renderElements(element.size, elementsInLine)
print(")")
} else {
print(getKotlinClassString(element.type))
print("(${element.size})")
if (!element.elementType.isPrimitive) print(" { null }")
}
}

override fun visit(element: CgGetLength) {
element.variable.accept(this)
print(".size")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.utbot.framework.codegen.model.visitor
import org.utbot.framework.codegen.model.tree.CgAbstractFieldAccess
import org.utbot.framework.codegen.model.tree.CgAbstractMultilineComment
import org.utbot.framework.codegen.model.tree.CgAllocateArray
import org.utbot.framework.codegen.model.tree.CgAllocateInitializedArray
import org.utbot.framework.codegen.model.tree.CgAnonymousFunction
import org.utbot.framework.codegen.model.tree.CgArrayAnnotationArgument
import org.utbot.framework.codegen.model.tree.CgArrayElementAccess
Expand Down Expand Up @@ -198,6 +199,7 @@ interface CgVisitor<R> {

// Array allocation
fun visit(element: CgAllocateArray): R
fun visit(element: CgAllocateInitializedArray): R

// Spread operator
fun visit(element: CgSpread): R
Expand Down