Skip to content

Commit 178b6fd

Browse files
committed
Fix type casts in Kotlin
1 parent 6ff9943 commit 178b6fd

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/visitor/CgKotlinRenderer.kt

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -191,32 +191,50 @@ internal class CgKotlinRenderer(context: CgContext, printer: CgPrinter = CgPrint
191191
element.right.accept(this)
192192
}
193193

194-
override fun visit(element: CgTypeCast) {
195-
print("(")
196-
element.expression.accept(this)
194+
/**
195+
* Sometimes we can omit rendering type cast and simply render its [CgTypeCast.expression] instead.
196+
* This method checks if the type cast can be omitted.
197+
*
198+
* For example, type cast can be omitted when a primitive wrapper is cast to its corresponding primitive (or vice versa),
199+
* because in Kotlin there are no primitive types as opposed to Java.
200+
*
201+
* Also, sometimes we can omit type cast when the [CgTypeCast.targetType] is the same as the type of [CgTypeCast.expression].
202+
*/
203+
private fun isCastNeeded(element: CgTypeCast): Boolean {
204+
val targetType = element.targetType
205+
val expressionType = element.expression.type
206+
207+
val isPrimitiveToWrapperCast = targetType.isPrimitiveWrapper && expressionType.isPrimitive
208+
val isWrapperToPrimitiveCast = targetType.isPrimitive && expressionType.isPrimitiveWrapper
209+
val isNullLiteral = element.expression == nullLiteral()
210+
211+
if (!isNullLiteral && element.isSafetyCast && (isPrimitiveToWrapperCast || isWrapperToPrimitiveCast)) {
212+
return false
213+
}
214+
197215
// perform type cast only if target type is not equal to expression type
198216
// but cast from nullable to not nullable should be performed
199217
// TODO SAT-1445 actually this safetyCast check looks like hack workaround and possibly does not work
200218
// so it should be carefully tested one day
201-
if (!element.isSafetyCast || element.expression.type != element.targetType) {
202-
// except for the case when a wrapper is cast to its primitive or vice versa
203-
204-
val isCastFromPrimitiveToWrapper = element.targetType.isPrimitiveWrapper &&
205-
element.expression.type.isPrimitive
206-
val isCastFromWrapperToPrimitive = element.targetType.isPrimitive &&
207-
element.expression.type.isPrimitiveWrapper
208-
val isNullLiteral = element.expression == nullLiteral()
209-
if (!isNullLiteral && element.isSafetyCast && (isCastFromPrimitiveToWrapper || isCastFromWrapperToPrimitive)) {
210-
return
211-
}
219+
return !element.isSafetyCast || expressionType != targetType
220+
}
221+
222+
override fun visit(element: CgTypeCast) {
223+
if (!isCastNeeded(element)) {
224+
element.expression.accept(this)
225+
} else {
226+
print("(")
227+
228+
element.expression.accept(this)
212229

213230
if (element.isSafetyCast) print(" as? ") else print(" as ")
214231
print(getKotlinClassString(element.targetType))
215232
renderTypeParameters(element.targetType.typeParameters)
216233
val initNullable = element.type.isNullable
217234
if (element.targetType.isNullable || initNullable) print("?")
235+
236+
print(")")
218237
}
219-
print(")")
220238
}
221239

222240
override fun visit(element: CgErrorWrapper) {

0 commit comments

Comments
 (0)