Skip to content

Commit 78473a4

Browse files
committed
uncommit (from ArsenHD/support-anonymous-classes)
1 parent 05fef58 commit 78473a4

File tree

5 files changed

+45
-18
lines changed

5 files changed

+45
-18
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/util/IdUtil.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,28 @@ import kotlin.reflect.jvm.javaMethod
3030

3131
// ClassId utils
3232

33+
/**
34+
* A type is called **non-denotable** if its name cannot be used in the source code.
35+
* For example, anonymous classes **are** non-denotable types.
36+
* On the other hand, [java.lang.Integer], for example, **is** denotable.
37+
*
38+
* This property returns the same type for denotable types,
39+
* and it returns the supertype when given an anonymous class.
40+
*
41+
* **NOTE** that in Java there are non-denotable types other than anonymous classes.
42+
* For example, null-type, intersection types, capture types.
43+
* But [ClassId] cannot contain any of these (at least at the moment).
44+
* So we only consider the case of anonymous classes.
45+
*/
46+
val ClassId.denotableType: ClassId
47+
get() {
48+
return when {
49+
this.isAnonymous -> this.supertypeOfAnonymousClass
50+
else -> this
51+
}
52+
}
53+
54+
3355
@Suppress("unused")
3456
val ClassId.enclosingClass: ClassId?
3557
get() = jClass.enclosingClass?.id

utbot-framework/src/main/kotlin/org/utbot/engine/TypeResolver.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
113113
if (numDimensions == 0) baseType else baseType.makeArrayType(numDimensions)
114114
}
115115

116-
return TypeStorage(type, concretePossibleTypes).filterInappropriateClassesForCodeGeneration()
116+
return TypeStorage(type, concretePossibleTypes)//.filterInappropriateClassesForCodeGeneration()
117117
}
118118

119119
private fun isInappropriateOrArrayOfMocksOrLocals(numDimensions: Int, baseType: Type?): Boolean {
@@ -183,7 +183,7 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
183183
else -> error("Unexpected type $type")
184184
}
185185

186-
return TypeStorage(type, possibleTypes).filterInappropriateClassesForCodeGeneration()
186+
return TypeStorage(type, possibleTypes)//.filterInappropriateClassesForCodeGeneration()
187187
}
188188

189189
/**
@@ -211,7 +211,7 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
211211
return@forEach
212212
}
213213
when {
214-
sootClass.isAnonymous || sootClass.isUtMock -> unwantedTypes += it
214+
// sootClass.isAnonymous || sootClass.isUtMock -> unwantedTypes += it
215215
sootClass.isArtificialEntity -> {
216216
// if (sootClass.isLambda) {
217217
// unwantedTypes += it

utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssembleModelGenerator.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@ class AssembleModelGenerator(private val methodUnderTest: UtMethod<*>) {
107107
}
108108

109109
return IdentityHashMap<UtModel, UtModel>().apply {
110-
models
111-
.filterNot { it.classId.isAnonymous } // we cannot create an assemble model for an anonymous class instance
112-
.forEach { getOrPut(it) { assembleModel(it) } }
110+
models.forEach { getOrPut(it) { assembleModel(it) } }
113111
}
114112
}
115113

@@ -175,6 +173,11 @@ class AssembleModelGenerator(private val methodUnderTest: UtMethod<*>) {
175173
private fun assembleModel(utModel: UtModel): UtModel {
176174
val collectedCallChain = callChain.toMutableList()
177175

176+
// we cannot create an assemble model for an anonymous class instance
177+
if (utModel.classId.isAnonymous) {
178+
return utModel
179+
}
180+
178181
val assembledModel = withCleanState {
179182
try {
180183
when (utModel) {

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/util/CgStatementConstructor.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import fj.data.Either
6060
import org.utbot.framework.codegen.model.tree.CgArrayInitializer
6161
import org.utbot.framework.codegen.model.tree.CgIsInstance
6262
import org.utbot.framework.plugin.api.util.classClassId
63+
import org.utbot.framework.plugin.api.util.denotableType
6364
import java.lang.reflect.Constructor
6465
import java.lang.reflect.Method
6566
import kotlin.reflect.KFunction
@@ -221,9 +222,12 @@ internal class CgStatementConstructorImpl(context: CgContext) :
221222
isMutable: Boolean,
222223
init: () -> CgExpression
223224
): CgVariable {
225+
// it is important that we use a denotable type for declaration, because that allows
226+
// us to avoid creating `Object` variables for instances of anonymous classes,
227+
// where we can instead use the supertype of the anonymous class
224228
val declarationOrVar: Either<CgDeclaration, CgVariable> =
225229
createDeclarationForNewVarAndUpdateVariableScopeOrGetExistingVariable(
226-
baseType,
230+
baseType.denotableType,
227231
model,
228232
baseName,
229233
isMock,

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/util/ConstructorUtils.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import org.utbot.framework.plugin.api.UtPrimitiveModel
4949
import org.utbot.framework.plugin.api.WildcardTypeParameter
5050
import org.utbot.framework.plugin.api.util.arrayLikeName
5151
import org.utbot.framework.plugin.api.util.builtinStaticMethodId
52+
import org.utbot.framework.plugin.api.util.denotableType
5253
import org.utbot.framework.plugin.api.util.methodId
5354
import org.utbot.framework.plugin.api.util.objectArrayClassId
5455
import org.utbot.framework.plugin.api.util.objectClassId
@@ -250,26 +251,23 @@ internal fun CgContextOwner.importIfNeeded(method: MethodId) {
250251
/**
251252
* Casts [expression] to [targetType].
252253
*
253-
* If [targetType] is anonymous, then we cannot use it in type cast,
254-
* because anonymous classes cannot be accessed in the source code.
255-
* So, in this case we find the supertype of anonymous class and use it as the [targetType] instead.
254+
* This method uses [denotableType] of the given [targetType] to ensure
255+
* that we are using a denotable type in the type cast.
256+
*
257+
* Specifically, if we attempt to do a type cast to an anonymous class,
258+
* then we will actually perform a type cast to its supertype.
259+
*
260+
* @see denotableType
256261
*
257262
* @param isSafetyCast shows if we should render "as?" instead of "as" in Kotlin
258263
*/
259264
internal fun CgContextOwner.typeCast(
260265
targetType: ClassId,
261266
expression: CgExpression,
262267
isSafetyCast: Boolean = false
263-
//): CgTypeCast {
264268
): CgExpression {
265269
@Suppress("NAME_SHADOWING")
266-
val targetType = when {
267-
targetType.isAnonymous -> targetType.supertypeOfAnonymousClass
268-
else -> targetType
269-
}
270-
// if (targetType.simpleName.isEmpty()) {
271-
// error("Cannot cast an expression to the anonymous type $targetType")
272-
// }
270+
val targetType = targetType.denotableType
273271
importIfNeeded(targetType)
274272
return CgTypeCast(targetType, expression, isSafetyCast)
275273
}

0 commit comments

Comments
 (0)