Skip to content

Commit a2ca8ae

Browse files
committed
Replace constructors with static methods for TypeStorage
1 parent 2a586f7 commit a2ca8ae

File tree

9 files changed

+95
-36
lines changed

9 files changed

+95
-36
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ class AssociativeArrayWrapper : WrapperInterface {
501501
stores = (0 until sizeValue).associateWithTo(mutableMapOf()) { i ->
502502
resolver.resolveModel(
503503
ObjectValue(
504-
TypeStorage(OBJECT_TYPE),
504+
TypeStorage.constructTypeStorageWithSingleType(OBJECT_TYPE),
505505
UtAddrExpression(touchedArrayExpression.select(mkInt(i)))
506506
)
507507
)
@@ -527,7 +527,7 @@ class AssociativeArrayWrapper : WrapperInterface {
527527
val addr = model.getIdOrThrow()
528528
addr to resolver.resolveModel(
529529
ObjectValue(
530-
TypeStorage(OBJECT_TYPE),
530+
TypeStorage.constructTypeStorageWithSingleType(OBJECT_TYPE),
531531
UtAddrExpression(storageArrayExpression.select(mkInt(addr)))
532532
)
533533
)

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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,25 @@ inline fun <R> SymbolicFailure.fold(
8383
data class Parameter(private val localVariable: LocalVariable, private val type: Type, val value: SymbolicValue)
8484

8585
/**
86-
* Keeps most common type and possible types, to resolve types in uncertain situations, like virtual invokes.
86+
* Contains type information about some object: set of its [possibleConcreteTypes] and their [leastCommonType].
87+
* Note that in some situations [leastCommonType] will not present in [possibleConcreteTypes] set, and
88+
* it should not be used to encode this type information into a solver.
8789
*
8890
* Note: [leastCommonType] might be an interface or abstract type in opposite to the [possibleConcreteTypes]
8991
* that **usually** contains only concrete types (so-called appropriate). The only way to create [TypeStorage] with
90-
* inappropriate possibleType is to create it using constructor with the only type.
92+
* inappropriate possibleType is to create it using static methods [constructTypeStorageUnsafe] and
93+
* [constructTypeStorageWithSingleType].
94+
*
95+
* The right way to create an instance of TypeStorage is to use methods provided by [TypeResolver], e.g.,
96+
* [TypeResolver.constructTypeStorage].
9197
*
9298
* @see isAppropriate
99+
* @see TypeResolver.constructTypeStorage
93100
*/
94-
data class TypeStorage(val leastCommonType: Type, val possibleConcreteTypes: Set<Type>) {
101+
class TypeStorage private constructor(val leastCommonType: Type, val possibleConcreteTypes: Set<Type>) {
95102
private val hashCode = Objects.hash(leastCommonType, possibleConcreteTypes)
96103

97-
/**
98-
* Construct a type storage with some type. In this case [possibleConcreteTypes] might contains
99-
* abstract class or interface. Usually it means such typeStorage represents wrapper object type.
100-
*/
101-
constructor(concreteType: Type) : this(concreteType, setOf(concreteType))
104+
private constructor(concreteType: Type) : this(concreteType, setOf(concreteType))
102105

103106
fun isObjectTypeStorage(): Boolean = possibleConcreteTypes.size == objectTypeStorage.possibleConcreteTypes.size
104107

@@ -121,6 +124,29 @@ data class TypeStorage(val leastCommonType: Type, val possibleConcreteTypes: Set
121124
} else {
122125
"(leastCommonType=$leastCommonType, ${possibleConcreteTypes.size} possibleTypes=${possibleConcreteTypes.take(10)})"
123126
}
127+
128+
companion object {
129+
/**
130+
* Constructs a type storage with particular leastCommonType and set of possibleConcreteTypes.
131+
* This method doesn't give any guarantee on correctness of the constructed type storage and
132+
* should not be used directly except the situations where you want to create abnormal type storage,
133+
* for example, a one that contains interfaces in [possibleConcreteTypes].
134+
*
135+
* In regular cases you should use [TypeResolver.constructTypeStorage] method instead.
136+
*/
137+
fun constructTypeStorageUnsafe(
138+
leastCommonType: Type,
139+
possibleConcreteTypes: Set<Type>
140+
): TypeStorage = TypeStorage(leastCommonType, possibleConcreteTypes)
141+
142+
/**
143+
* Constructs a type storage with some type. In this case [possibleConcreteTypes] might contains
144+
* abstract class or interface. Usually it means such typeStorage represents wrapper object type.
145+
*/
146+
fun constructTypeStorageWithSingleType(
147+
leastCommonType: Type
148+
): TypeStorage = TypeStorage(leastCommonType)
149+
}
124150
}
125151

126152
sealed class InvokeResult

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,12 @@ data class Memory( // TODO: split purely symbolic memory and information about s
365365
*/
366366
class TypeRegistry {
367367
init {
368+
// TODO mistake
368369
// initializes type storage for OBJECT_TYPE from current scene
369-
objectTypeStorage = TypeStorage(OBJECT_TYPE, Scene.v().classes.mapTo(mutableSetOf()) { it.type })
370+
objectTypeStorage = TypeStorage.constructTypeStorageUnsafe(
371+
OBJECT_TYPE,
372+
Scene.v().classes.mapTo(mutableSetOf()) { it.type }
373+
)
370374
}
371375

372376
private val typeIdBiMap = HashBiMap.create<Type, Int>()
@@ -612,9 +616,11 @@ class TypeRegistry {
612616
fun createClassRef(baseType: Type, numDimensions: Int = 0): MethodResult {
613617
val addr = classRefBiMap.getOrPut(baseType) { nextClassRefAddr() }
614618

615-
val objectValue = ObjectValue(TypeStorage(CLASS_REF_TYPE), addr)
619+
val objectTypeStorage = TypeStorage.constructTypeStorageWithSingleType(CLASS_REF_TYPE)
620+
val objectValue = ObjectValue(objectTypeStorage, addr)
616621

617-
val typeConstraint = typeConstraint(addr, TypeStorage(CLASS_REF_TYPE)).all()
622+
val classRefTypeStorage = TypeStorage.constructTypeStorageWithSingleType(CLASS_REF_TYPE)
623+
val typeConstraint = typeConstraint(addr, classRefTypeStorage).all()
618624

619625
val typeId = mkInt(findTypeId(baseType))
620626
val symNumDimensions = mkInt(numDimensions)

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri
6565
): List<InvokeResult>? {
6666
when (method.signature) {
6767
AS_OPTIONAL_METHOD_SIGNATURE -> {
68-
return listOf(MethodResult(wrapper.copy(typeStorage = TypeStorage(method.returnType))))
68+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(method.returnType)
69+
val resultingWrapper = wrapper.copy(typeStorage = typeStorage)
70+
val methodResult = MethodResult(resultingWrapper)
71+
72+
return listOf(methodResult)
6973
}
7074
UT_OPTIONAL_EQ_GENERIC_TYPE_SIGNATURE -> {
7175
return listOf(

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ class Resolver(
427427
// if the value is Object, we have to construct array or an object depending on the number of dimensions
428428
// it is possible if we had an object and we casted it into array
429429
val constructedType = holder.constructTypeOrNull(value.addr, value.type) ?: return UtNullModel(value.type.id)
430-
val typeStorage = TypeStorage(constructedType)
430+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(constructedType)
431431

432432
return if (constructedType is ArrayType) {
433433
constructArrayModel(ArrayValue(typeStorage, value.addr))
@@ -1034,7 +1034,9 @@ class Resolver(
10341034
val constructedType = holder.constructTypeOrNull(addr, defaultType) ?: return UtNullModel(defaultType.id)
10351035

10361036
if (defaultType.isJavaLangObject() && constructedType is ArrayType) {
1037-
return constructArrayModel(ArrayValue(TypeStorage(constructedType), addr))
1037+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(constructedType)
1038+
val arrayValue = ArrayValue(typeStorage, addr)
1039+
return constructArrayModel(arrayValue)
10381040
} else {
10391041
val concreteType = typeResolver.findAnyConcreteInheritorIncludingOrDefault(
10401042
constructedType as RefType,

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import org.utbot.framework.plugin.api.UtAssembleModel
2323
import org.utbot.framework.plugin.api.UtExecutableCallModel
2424
import org.utbot.framework.plugin.api.UtModel
2525
import org.utbot.framework.plugin.api.UtPrimitiveModel
26-
import org.utbot.framework.plugin.api.UtStatementModel
2726
import org.utbot.framework.plugin.api.classId
2827
import org.utbot.framework.plugin.api.id
2928
import org.utbot.framework.plugin.api.util.charArrayClassId
@@ -60,7 +59,8 @@ class StringWrapper : BaseOverriddenWrapper(utStringClass.name) {
6059
): List<InvokeResult>? {
6160
return when (method.subSignature) {
6261
toStringMethodSignature -> {
63-
listOf(MethodResult(wrapper.copy(typeStorage = TypeStorage(method.returnType))))
62+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(method.returnType)
63+
listOf(MethodResult(wrapper.copy(typeStorage = typeStorage)))
6464
}
6565
matchesMethodSignature -> {
6666
symbolicMatchesMethodImpl(wrapper, parameters)
@@ -200,7 +200,11 @@ sealed class UtAbstractStringBuilderWrapper(className: String) : BaseOverriddenW
200200
parameters: List<SymbolicValue>
201201
): List<InvokeResult>? {
202202
if (method.subSignature == asStringBuilderMethodSignature) {
203-
return listOf(MethodResult(wrapper.copy(typeStorage = TypeStorage(method.returnType))))
203+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(method.returnType)
204+
val resultingWrapper = wrapper.copy(typeStorage = typeStorage)
205+
val methodResult = MethodResult(resultingWrapper)
206+
207+
return listOf(methodResult)
204208
}
205209

206210
return null

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ data class PrimitiveValue(
5151
val expr: UtExpression,
5252
override val concrete: Concrete? = null
5353
) : SymbolicValue() {
54-
constructor(type: Type, expr: UtExpression) : this(TypeStorage(type), expr)
54+
constructor(type: Type, expr: UtExpression) : this(TypeStorage.constructTypeStorageWithSingleType(type), expr)
5555

5656
override val type get() = typeStorage.leastCommonType
5757

@@ -179,7 +179,7 @@ fun SymbolicValue.toConcrete(): Any = when (this) {
179179

180180
// TODO: one more constructor?
181181
fun objectValue(type: RefType, addr: UtAddrExpression, implementation: WrapperInterface) =
182-
ObjectValue(TypeStorage(type), addr, Concrete(implementation))
182+
ObjectValue(TypeStorage.constructTypeStorageWithSingleType(type), addr, Concrete(implementation))
183183

184184
val voidValue
185185
get() = PrimitiveValue(VoidType.v(), nullObjectAddr)

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

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ class Traverser(
897897
// Ignores the result of resolve().
898898
resolve(fieldRef)
899899
val baseObject = resolve(fieldRef.base) as ObjectValue
900-
val typeStorage = TypeStorage(fieldRef.field.declaringClass.type)
900+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(fieldRef.field.declaringClass.type)
901901
baseObject.copy(typeStorage = typeStorage)
902902
}
903903
is StaticFieldRef -> {
@@ -1250,7 +1250,12 @@ class Traverser(
12501250
// It is required because we do not want to have situations when some object might have
12511251
// only artificial classes as their possible, that would cause problems in the type constraints.
12521252
val typeStorage = if (leastCommonType in wrapperToClass.keys) {
1253-
typeStoragePossiblyWithOverriddenTypes.copy(possibleConcreteTypes = wrapperToClass.getValue(leastCommonType))
1253+
val possibleConcreteTypes = wrapperToClass.getValue(leastCommonType)
1254+
1255+
TypeStorage.constructTypeStorageUnsafe(
1256+
typeStoragePossiblyWithOverriddenTypes.leastCommonType,
1257+
possibleConcreteTypes
1258+
)
12541259
} else {
12551260
typeStoragePossiblyWithOverriddenTypes
12561261
}
@@ -1307,7 +1312,10 @@ class Traverser(
13071312
createObject(addr, refType, useConcreteType = true)
13081313
}
13091314
} else {
1310-
queuedSymbolicStateUpdates += typeRegistry.typeConstraint(addr, TypeStorage(refType)).all().asHardConstraint()
1315+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(refType)
1316+
val typeConstraint = typeRegistry.typeConstraint(addr, typeStorage).all().asHardConstraint()
1317+
1318+
queuedSymbolicStateUpdates += typeConstraint
13111319

13121320
objectValue(refType, addr, StringWrapper()).also {
13131321
initStringLiteral(it, constant.value)
@@ -1417,8 +1425,10 @@ class Traverser(
14171425
}
14181426

14191427
private fun initStringLiteral(stringWrapper: ObjectValue, value: String) {
1428+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(utStringClass.type)
1429+
14201430
queuedSymbolicStateUpdates += objectUpdate(
1421-
stringWrapper.copy(typeStorage = TypeStorage(utStringClass.type)),
1431+
stringWrapper.copy(typeStorage = typeStorage),
14221432
STRING_LENGTH,
14231433
mkInt(value.length)
14241434
)
@@ -1431,7 +1441,7 @@ class Traverser(
14311441
queuedSymbolicStateUpdates += arrayUpdateWithValue(it.addr, arrayType, defaultValue as UtArrayExpressionBase)
14321442
}
14331443
queuedSymbolicStateUpdates += objectUpdate(
1434-
stringWrapper.copy(typeStorage = TypeStorage(utStringClass.type)),
1444+
stringWrapper.copy(typeStorage = typeStorage),
14351445
STRING_VALUE,
14361446
arrayValue.addr
14371447
)
@@ -1719,7 +1729,8 @@ class Traverser(
17191729
val chunkId = typeRegistry.arrayChunkId(type)
17201730
touchMemoryChunk(MemoryChunkDescriptor(chunkId, type, elementType))
17211731

1722-
return ArrayValue(TypeStorage(type), addr).also {
1732+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(type)
1733+
return ArrayValue(typeStorage, addr).also {
17231734
queuedSymbolicStateUpdates += typeRegistry.typeConstraint(addr, it.typeStorage).all().asHardConstraint()
17241735
}
17251736
}
@@ -2941,7 +2952,9 @@ class Traverser(
29412952

29422953
val memoryUpdate = MemoryUpdate(touchedChunkDescriptors = persistentSetOf(descriptor))
29432954

2944-
val clone = ArrayValue(TypeStorage(array.type), addr)
2955+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(array.type)
2956+
val clone = ArrayValue(typeStorage, addr)
2957+
29452958
return MethodResult(clone, constraints.asHardConstraint(), memoryUpdates = memoryUpdate)
29462959
}
29472960

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

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

115-
return TypeStorage(type, concretePossibleTypes).removeInappropriateTypes()
115+
return TypeStorage.constructTypeStorageUnsafe(type, concretePossibleTypes).removeInappropriateTypes()
116116
}
117117

118118
private fun isInappropriateOrArrayOfMocksOrLocals(numDimensions: Int, baseType: Type?): Boolean {
@@ -160,7 +160,7 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
160160
*/
161161
fun constructTypeStorage(type: Type, useConcreteType: Boolean): TypeStorage {
162162
// create a typeStorage with concreteType even if the type belongs to an interface or an abstract class
163-
if (useConcreteType) return TypeStorage(type)
163+
if (useConcreteType) return TypeStorage.constructTypeStorageWithSingleType(type)
164164

165165
val baseType = type.baseType
166166

@@ -190,7 +190,7 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
190190
else -> error("Unexpected type $type")
191191
}
192192

193-
return TypeStorage(type, possibleTypes).removeInappropriateTypes()
193+
return TypeStorage.constructTypeStorageUnsafe(type, possibleTypes).removeInappropriateTypes()
194194
}
195195

196196
/**
@@ -223,16 +223,20 @@ class TypeResolver(private val typeRegistry: TypeRegistry, private val hierarchy
223223
return@filter true
224224
}.toSet()
225225

226-
return copy(possibleConcreteTypes = appropriateTypes)
226+
return TypeStorage.constructTypeStorageUnsafe(leastCommonType, appropriateTypes)
227227
}
228228

229229
/**
230230
* Constructs a nullObject with TypeStorage containing all the inheritors for the given type
231231
*/
232-
fun nullObject(type: Type) = when (type) {
233-
is RefType, is NullType, is VoidType -> ObjectValue(TypeStorage(type), nullObjectAddr)
234-
is ArrayType -> ArrayValue(TypeStorage(type), nullObjectAddr)
235-
else -> error("Unsupported nullType $type")
232+
fun nullObject(type: Type): ReferenceValue {
233+
val typeStorage = TypeStorage.constructTypeStorageWithSingleType(type)
234+
235+
return when (type) {
236+
is RefType, is NullType, is VoidType -> ObjectValue(typeStorage, nullObjectAddr)
237+
is ArrayType -> ArrayValue(typeStorage, nullObjectAddr)
238+
else -> error("Unsupported nullType $type")
239+
}
236240
}
237241

238242
fun downCast(arrayValue: ArrayValue, typeToCast: ArrayType): ArrayValue {

0 commit comments

Comments
 (0)