Skip to content

Commit 3c1fd09

Browse files
sofurihafeEgorkaKulikov
authored andcommitted
Add support for class fields rendering with annotations
1 parent bfc2de9 commit 3c1fd09

File tree

23 files changed

+339
-90
lines changed

23 files changed

+339
-90
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/CodeGenerator.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ open class CodeGenerator(
9090

9191
private fun generateForSimpleClass(testSets: List<CgMethodTestSet>): CodeGeneratorResult {
9292
val astConstructor = CgSimpleTestClassConstructor(context)
93-
val testClassModel = SimpleTestClassModelBuilder().createTestClassModel(classUnderTest, testSets)
93+
val testClassModel = SimpleTestClassModelBuilder(context).createTestClassModel(classUnderTest, testSets)
9494

9595
logger.info { "Code generation phase started at ${now()}" }
9696
val testClassFile = astConstructor.construct(testClassModel)
@@ -107,7 +107,7 @@ open class CodeGenerator(
107107

108108
private fun generateForSpringClass(testSets: List<CgMethodTestSet>): CodeGeneratorResult {
109109
val astConstructor = CgSpringTestClassConstructor(context)
110-
val testClassModel = SpringTestClassModelBuilder().createTestClassModel(classUnderTest, testSets)
110+
val testClassModel = SpringTestClassModelBuilder(context).createTestClassModel(classUnderTest, testSets)
111111

112112
logger.info { "Code generation phase started at ${now()}" }
113113
val testClassFile = astConstructor.construct(testClassModel)

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.utbot.framework.codegen.domain
33
import org.utbot.framework.DEFAULT_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
44
import org.utbot.framework.codegen.domain.builtin.mockitoClassId
55
import org.utbot.framework.codegen.domain.builtin.ongoingStubbingClassId
6+
import org.utbot.framework.codegen.domain.context.CgContext
67
import org.utbot.framework.codegen.domain.models.CgClassId
78
import org.utbot.framework.codegen.tree.argumentsClassId
89
import org.utbot.framework.plugin.api.BuiltinClassId
@@ -11,6 +12,8 @@ import org.utbot.framework.plugin.api.CodeGenerationSettingBox
1112
import org.utbot.framework.plugin.api.CodeGenerationSettingItem
1213
import org.utbot.framework.plugin.api.MethodId
1314
import org.utbot.framework.plugin.api.TypeParameters
15+
import org.utbot.framework.plugin.api.UtModel
16+
import org.utbot.framework.plugin.api.idOrNull
1417
import org.utbot.framework.plugin.api.isolateCommandLineArgumentsToArgumentFile
1518
import org.utbot.framework.plugin.api.util.booleanArrayClassId
1619
import org.utbot.framework.plugin.api.util.booleanClassId
@@ -773,3 +776,17 @@ object SpringBoot : DependencyInjectionFramework(
773776
id = "spring-boot",
774777
displayName = "Spring Boot"
775778
)
779+
780+
/**
781+
* Extended id of [UtModel], unique for whole test set.
782+
*
783+
* Allows to distinguish models from different executions,
784+
* even if they have the same value of `UtModel.id`.
785+
*/
786+
data class ModelId(
787+
private val id: Int?,
788+
private val executionId: Int,
789+
)
790+
791+
fun UtModel.modelId(executionId: Int = -1): ModelId = ModelId(this.idOrNull(), executionId)
792+

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoBuiltins.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ internal val mockitoClassId = BuiltinClassId(
2020
simpleName = "Mockito",
2121
)
2222

23+
internal val mockClassId = BuiltinClassId(
24+
canonicalName = "org.mockito.Mock",
25+
simpleName = "Mock",
26+
)
27+
28+
internal val injectMocksClassId = BuiltinClassId(
29+
canonicalName = "org.mockito.InjectMocks",
30+
simpleName = "InjectMocks",
31+
)
32+
2333
internal val ongoingStubbingClassId = BuiltinClassId(
2434
canonicalName = "org.mockito.stubbing.OngoingStubbing",
2535
simpleName = "OngoingStubbing",

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/context/CgContext.kt

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ import kotlinx.collections.immutable.PersistentSet
2222
import kotlinx.collections.immutable.persistentListOf
2323
import kotlinx.collections.immutable.persistentMapOf
2424
import kotlinx.collections.immutable.persistentSetOf
25+
import org.utbot.framework.codegen.domain.ModelId
2526
import org.utbot.framework.codegen.domain.ProjectType
2627
import org.utbot.framework.codegen.domain.models.CgMethodTestSet
2728
import org.utbot.framework.codegen.domain.builtin.TestClassUtilMethodProvider
2829
import org.utbot.framework.codegen.domain.builtin.UtilClassFileMethodProvider
2930
import org.utbot.framework.codegen.domain.builtin.UtilMethodProvider
3031
import org.utbot.framework.codegen.domain.models.SimpleTestClassModel
3132
import org.utbot.framework.codegen.domain.models.CgParameterKind
33+
import org.utbot.framework.codegen.domain.modelId
3234
import org.utbot.framework.codegen.services.access.Block
3335
import org.utbot.framework.codegen.tree.EnvironmentFieldStateCache
3436
import org.utbot.framework.codegen.tree.importIfNeeded
@@ -197,7 +199,7 @@ interface CgContextOwner {
197199
var valueByModel: IdentityHashMap<UtModel, CgValue>
198200

199201
// use it to compare stateBefore and result variables - in case of equality do not create new variable
200-
var valueByModelId: MutableMap<Int?, CgValue>
202+
var valueByModelId: MutableMap<ModelId, CgValue>
201203

202204
// parameters of the method currently being generated
203205
val currentMethodParameters: MutableMap<CgParameterKind, CgVariable>
@@ -226,6 +228,12 @@ interface CgContextOwner {
226228
*/
227229
var successfulExecutionsModels: List<UtModel>
228230

231+
/**
232+
* Gives a unique identifier to model in test set.
233+
* Determines which execution current model belongs to.
234+
*/
235+
var modelIds: Map<UtModel, ModelId>
236+
229237
fun block(init: () -> Unit): Block {
230238
val prevBlock = currentBlock
231239
return try {
@@ -311,7 +319,10 @@ interface CgContextOwner {
311319
model?.let {
312320
valueByModel[it] = variable
313321
(model as UtReferenceModel).let { refModel ->
314-
refModel.id.let { id -> valueByModelId[id] = variable }
322+
refModel.id.let {
323+
val modelId = getIdByModel(model)
324+
valueByModelId[modelId] = variable
325+
}
315326
}
316327
}
317328
}
@@ -428,6 +439,8 @@ interface CgContextOwner {
428439

429440
val getLambdaMethod: MethodId
430441
get() = utilMethodProvider.getLambdaMethodMethodId
442+
443+
fun getIdByModel(model: UtModel): ModelId
431444
}
432445

433446
/**
@@ -478,6 +491,7 @@ data class CgContext(
478491
override lateinit var statesCache: EnvironmentFieldStateCache
479492
override lateinit var actual: CgVariable
480493
override lateinit var successfulExecutionsModels: List<UtModel>
494+
override lateinit var modelIds: Map<UtModel, ModelId>
481495

482496
/**
483497
* This property cannot be accessed outside of test class file scope
@@ -556,6 +570,15 @@ data class CgContext(
556570
}
557571
}
558572

573+
override fun getIdByModel(model: UtModel): ModelId {
574+
if (model !in this.modelIds) {
575+
this.modelIds += model to model.modelId()
576+
}
577+
578+
return modelIds[model]
579+
?: error("ModelId for $model should have also been created")
580+
}
581+
559582
private fun createClassIdForNestedClass(testClassModel: SimpleTestClassModel): ClassId {
560583
val simpleName = "${testClassModel.classUnderTest.simpleName}Test"
561584
return BuiltinClassId(
@@ -580,7 +603,7 @@ data class CgContext(
580603

581604
override var valueByModel: IdentityHashMap<UtModel, CgValue> = IdentityHashMap()
582605

583-
override var valueByModelId: MutableMap<Int?, CgValue> = mutableMapOf()
606+
override var valueByModelId: MutableMap<ModelId, CgValue> = mutableMapOf()
584607

585608
override val currentMethodParameters: MutableMap<CgParameterKind, CgVariable> = mutableMapOf()
586609

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/models/CgElement.kt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.utbot.framework.codegen.renderer.CgRendererContext
77
import org.utbot.framework.codegen.renderer.CgVisitor
88
import org.utbot.framework.codegen.renderer.auxiliaryClassTextById
99
import org.utbot.framework.codegen.renderer.utilMethodTextById
10+
import org.utbot.framework.codegen.tree.VisibilityModifier
1011
import org.utbot.framework.plugin.api.BuiltinClassId
1112
import org.utbot.framework.plugin.api.ClassId
1213
import org.utbot.framework.plugin.api.ConstructorId
@@ -82,6 +83,7 @@ interface CgElement {
8283
is CgBreakStatement -> visit(element)
8384
is CgContinueStatement -> visit(element)
8485
is CgDeclaration -> visit(element)
86+
is CgFieldDeclaration -> visit(element)
8587
is CgAssignment -> visit(element)
8688
is CgTypeCast -> visit(element)
8789
is CgIsInstance -> visit(element)
@@ -134,6 +136,7 @@ class CgClass(
134136
val body: CgClassBody,
135137
val isStatic: Boolean,
136138
val isNested: Boolean,
139+
val visibility: VisibilityModifier = VisibilityModifier.PUBLIC,
137140
): CgElement {
138141
val packageName
139142
get() = id.packageName
@@ -156,8 +159,21 @@ class CgClassBody(
156159
val methodRegions: List<CgMethodsCluster>,
157160
val staticDeclarationRegions: List<CgStaticsRegion>,
158161
val nestedClassRegions: List<CgNestedClassesRegion<*>>,
159-
//TODO: use [CgFieldDeclaration] after PR-1788 merge
160-
val fields: List<CgDeclaration> = emptyList(),
162+
val fields: Set<CgFieldDeclaration> = emptySet(),
163+
) : CgElement
164+
165+
/**
166+
* Field of a class.
167+
* @property ownerClassId [ClassId] of the field owner class.
168+
* @property declaration declaration itself.
169+
* @property annotation optional annotation.
170+
* @property visibility field visibility.
171+
*/
172+
class CgFieldDeclaration(
173+
val ownerClassId: ClassId,
174+
val declaration: CgDeclaration,
175+
val annotation: CgAnnotation? = null,
176+
val visibility: VisibilityModifier = VisibilityModifier.PUBLIC,
161177
) : CgElement
162178

163179
/**
@@ -272,6 +288,7 @@ sealed class CgMethod(open val isStatic: Boolean) : CgElement {
272288
abstract val annotations: List<CgAnnotation>
273289
abstract val documentation: CgDocumentationComment
274290
abstract val requiredFields: List<CgParameterDeclaration>
291+
abstract val visibility: VisibilityModifier
275292
}
276293

277294
class CgTestMethod(
@@ -281,6 +298,7 @@ class CgTestMethod(
281298
override val statements: List<CgStatement>,
282299
override val exceptions: Set<ClassId>,
283300
override val annotations: List<CgAnnotation>,
301+
override val visibility: VisibilityModifier = VisibilityModifier.PUBLIC,
284302
val type: CgTestMethodType,
285303
override val documentation: CgDocumentationComment = CgDocumentationComment(emptyList()),
286304
override val requiredFields: List<CgParameterDeclaration> = emptyList(),
@@ -291,6 +309,7 @@ class CgFrameworkUtilMethod(
291309
override val statements: List<CgStatement>,
292310
override val exceptions: Set<ClassId>,
293311
override val annotations: List<CgAnnotation>,
312+
override val visibility: VisibilityModifier = VisibilityModifier.PUBLIC,
294313
) : CgMethod(isStatic = false) {
295314
override val returnType: ClassId = voidClassId
296315
override val parameters: List<CgParameterDeclaration> = emptyList()
@@ -301,7 +320,8 @@ class CgFrameworkUtilMethod(
301320
class CgErrorTestMethod(
302321
override val name: String,
303322
override val statements: List<CgStatement>,
304-
override val documentation: CgDocumentationComment = CgDocumentationComment(emptyList())
323+
override val documentation: CgDocumentationComment = CgDocumentationComment(emptyList()),
324+
override val visibility: VisibilityModifier = VisibilityModifier.PUBLIC,
305325
) : CgMethod(isStatic = false) {
306326
override val exceptions: Set<ClassId> = emptySet()
307327
override val returnType: ClassId = voidClassId
@@ -316,6 +336,7 @@ class CgParameterizedTestDataProviderMethod(
316336
override val returnType: ClassId,
317337
override val annotations: List<CgAnnotation>,
318338
override val exceptions: Set<ClassId>,
339+
override val visibility: VisibilityModifier = VisibilityModifier.PUBLIC,
319340
) : CgMethod(isStatic = true) {
320341
override val parameters: List<CgParameterDeclaration> = emptyList()
321342
override val documentation: CgDocumentationComment = CgDocumentationComment(emptyList())

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/models/TestClassModel.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.utbot.framework.codegen.domain.models
22

33
import org.utbot.framework.plugin.api.ClassId
4+
import org.utbot.framework.plugin.api.UtModel
45

56
/**
67
* Stores method test sets in a structure that replicates structure of their methods in [classUnderTest].
@@ -13,7 +14,7 @@ abstract class TestClassModel(
1314
val nestedClasses: List<SimpleTestClassModel>,
1415
)
1516

16-
open class SimpleTestClassModel(
17+
class SimpleTestClassModel(
1718
classUnderTest: ClassId,
1819
methodTestSets: List<CgMethodTestSet>,
1920
nestedClasses: List<SimpleTestClassModel> = listOf(),
@@ -29,7 +30,7 @@ class SpringTestClassModel(
2930
classUnderTest: ClassId,
3031
methodTestSets: List<CgMethodTestSet>,
3132
nestedClasses: List<SimpleTestClassModel>,
32-
val injectingMocksClass: ClassId? = null,
33-
val mockedClasses: Set<ClassId> = setOf(),
33+
val injectedMockModels: Map<ClassId, Set<UtModel>> = mapOf(),
34+
val mockedModels: Map<ClassId, Set<UtModel>> = mapOf(),
3435
): TestClassModel(classUnderTest, methodTestSets, nestedClasses)
3536

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/models/builders/SimpleTestClassModelBuilder.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package org.utbot.framework.codegen.domain.models.builders
22

3+
import org.utbot.framework.codegen.domain.context.CgContext
34
import org.utbot.framework.codegen.domain.models.CgMethodTestSet
45
import org.utbot.framework.codegen.domain.models.SimpleTestClassModel
56
import org.utbot.framework.plugin.api.ClassId
67
import org.utbot.framework.plugin.api.util.enclosingClass
78

8-
open class SimpleTestClassModelBuilder: TestClassModelBuilder() {
9-
override fun createTestClassModel(classUnderTest: ClassId, testSets: List<CgMethodTestSet>): SimpleTestClassModel {
9+
open class SimpleTestClassModelBuilder(context: CgContext): TestClassModelBuilder() {
10+
override fun createTestClassModel(
11+
classUnderTest: ClassId,
12+
testSets: List<CgMethodTestSet>,
13+
): SimpleTestClassModel {
1014
// For each class stores list of methods declared in this class (methods from nested classes are excluded)
1115
val class2methodTestSets = testSets.groupBy { it.executableId.classId }
1216

0 commit comments

Comments
 (0)