Skip to content

Commit bc8b627

Browse files
Allow to use UtUtils for different languages in one project #1080 (#1296)
1 parent 55c3a82 commit bc8b627

File tree

8 files changed

+108
-59
lines changed

8 files changed

+108
-59
lines changed

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

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.utbot.framework.plugin.api.UtMethodTestSet
2424
import org.utbot.framework.codegen.model.constructor.TestClassModel
2525
import org.utbot.framework.codegen.model.tree.CgDocRegularStmt
2626
import org.utbot.framework.codegen.model.tree.CgDocumentationComment
27+
import java.util.*
2728

2829
class CodeGenerator(
2930
private val classUnderTest: ClassId,
@@ -147,20 +148,20 @@ sealed class UtilClassKind(
147148
/**
148149
* Contains comments specifying the version and the kind of util class being generated and
149150
*/
150-
val utilClassDocumentation: CgDocumentationComment
151-
get() = CgDocumentationComment(
151+
fun utilClassDocumentation(codegenLanguage: CodegenLanguage): CgDocumentationComment
152+
= CgDocumentationComment(
152153
listOf(
153154
CgDocRegularStmt(utilClassKindCommentText),
154-
CgDocRegularStmt("$UTIL_CLASS_VERSION_COMMENT_PREFIX${utilClassVersion}"),
155+
CgDocRegularStmt("$UTIL_CLASS_VERSION_COMMENT_PREFIX${utilClassVersion(codegenLanguage)}"),
155156
)
156157
)
157158

158159
/**
159160
* The version of util class being generated.
160161
* For more details see [UtilClassFileMethodProvider.UTIL_CLASS_VERSION].
161162
*/
162-
val utilClassVersion: String
163-
get() = UtilClassFileMethodProvider.UTIL_CLASS_VERSION
163+
fun utilClassVersion(codegenLanguage: CodegenLanguage): String
164+
= UtilClassFileMethodProvider(codegenLanguage).UTIL_CLASS_VERSION
164165

165166
/**
166167
* The text of comment specifying the kind of util class.
@@ -175,15 +176,21 @@ sealed class UtilClassKind(
175176
/**
176177
* A kind of regular UtUtils class. "Regular" here means that this class does not use a mock framework.
177178
*/
178-
object RegularUtUtils : UtilClassKind(UtilClassFileMethodProvider, mockFrameworkUsed = false, priority = 0) {
179+
class RegularUtUtils(val codegenLanguage: CodegenLanguage) :
180+
UtilClassKind(
181+
UtilClassFileMethodProvider(codegenLanguage),
182+
mockFrameworkUsed = false,
183+
priority = 0,
184+
) {
179185
override val utilClassKindCommentText: String
180186
get() = "This is a regular UtUtils class (without mock framework usage)"
181187
}
182188

183189
/**
184190
* A kind of UtUtils class that uses a mock framework. At the moment the framework is Mockito.
185191
*/
186-
object UtUtilsWithMockito : UtilClassKind(UtilClassFileMethodProvider, mockFrameworkUsed = true, priority = 1) {
192+
class UtUtilsWithMockito(val codegenLanguage: CodegenLanguage) :
193+
UtilClassKind(UtilClassFileMethodProvider(codegenLanguage), mockFrameworkUsed = true, priority = 1) {
187194
override val utilClassKindCommentText: String
188195
get() = "This is UtUtils class with Mockito support"
189196
}
@@ -197,7 +204,7 @@ sealed class UtilClassKind(
197204
* @return the text of the generated util class file.
198205
*/
199206
fun getUtilClassText(codegenLanguage: CodegenLanguage): String {
200-
val utilClassFile = CgUtilClassConstructor.constructUtilsClassFile(this)
207+
val utilClassFile = CgUtilClassConstructor.constructUtilsClassFile(this, codegenLanguage)
201208
val renderer = CgAbstractRenderer.makeRenderer(this, codegenLanguage)
202209
utilClassFile.accept(renderer)
203210
return renderer.toString()
@@ -212,10 +219,13 @@ sealed class UtilClassKind(
212219
*/
213220
const val UTIL_CLASS_VERSION_COMMENT_PREFIX = "UtUtils class version: "
214221

215-
fun utilClassKindByCommentOrNull(comment: String): UtilClassKind? {
222+
fun utilClassKindByCommentOrNull(
223+
comment: String,
224+
codegenLanguage: CodegenLanguage)
225+
: UtilClassKind? {
216226
return when (comment) {
217-
RegularUtUtils.utilClassKindCommentText -> RegularUtUtils
218-
UtUtilsWithMockito.utilClassKindCommentText -> UtUtilsWithMockito
227+
RegularUtUtils(codegenLanguage).utilClassKindCommentText -> RegularUtUtils(codegenLanguage)
228+
UtUtilsWithMockito(codegenLanguage).utilClassKindCommentText -> UtUtilsWithMockito(codegenLanguage)
219229
else -> null
220230
}
221231
}
@@ -228,24 +238,27 @@ sealed class UtilClassKind(
228238
internal fun fromCgContextOrNull(context: CgContext): UtilClassKind? {
229239
if (context.requiredUtilMethods.isEmpty()) return null
230240
if (!context.mockFrameworkUsed) {
231-
return RegularUtUtils
241+
return RegularUtUtils(context.codegenLanguage)
232242
}
233243
return when (context.mockFramework) {
234-
MockFramework.MOCKITO -> UtUtilsWithMockito
244+
MockFramework.MOCKITO -> UtUtilsWithMockito(context.codegenLanguage)
235245
// in case we will add any other mock frameworks, newer Kotlin compiler versions
236246
// will report a non-exhaustive 'when', so we will not forget to support them here as well
237247
}
238248
}
239249

240-
const val UT_UTILS_PACKAGE_NAME = "org.utbot.runtime.utils"
241-
const val UT_UTILS_CLASS_NAME = "UtUtils"
250+
const val UT_UTILS_BASE_PACKAGE_NAME = "org.utbot.runtime.utils"
251+
const val UT_UTILS_INSTANCE_NAME = "UtUtils"
242252
const val PACKAGE_DELIMITER = "."
243253

244254
/**
245-
* List of package names of UtUtils class.
246-
* See whole package name at [UT_UTILS_PACKAGE_NAME].
255+
* List of package name components of UtUtils class.
256+
* See whole package name at [UT_UTILS_BASE_PACKAGE_NAME].
247257
*/
248-
val utilsPackages: List<String>
249-
get() = UT_UTILS_PACKAGE_NAME.split(PACKAGE_DELIMITER)
258+
fun utilsPackageNames(codegenLanguage: CodegenLanguage): List<String>
259+
= UT_UTILS_BASE_PACKAGE_NAME.split(PACKAGE_DELIMITER) + codegenLanguage.name.lowercase(Locale.getDefault())
260+
261+
fun utilsPackageFullName(codegenLanguage: CodegenLanguage): String
262+
= utilsPackageNames(codegenLanguage).joinToString { PACKAGE_DELIMITER }
250263
}
251264
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package org.utbot.framework.codegen.model.constructor.builtin
22

33
import org.utbot.framework.codegen.MockitoStaticMocking
4+
import org.utbot.framework.codegen.model.UtilClassKind.Companion.PACKAGE_DELIMITER
5+
import org.utbot.framework.codegen.model.UtilClassKind.Companion.UT_UTILS_BASE_PACKAGE_NAME
46
import org.utbot.framework.codegen.model.constructor.util.arrayTypeOf
57
import org.utbot.framework.codegen.model.constructor.util.utilMethodId
68
import org.utbot.framework.codegen.model.tree.CgClassId
79
import org.utbot.framework.codegen.model.visitor.utilMethodTextById
810
import org.utbot.framework.plugin.api.BuiltinClassId
911
import org.utbot.framework.plugin.api.BuiltinConstructorId
1012
import org.utbot.framework.plugin.api.ClassId
13+
import org.utbot.framework.plugin.api.CodegenLanguage
1114
import org.utbot.framework.plugin.api.MethodId
1215
import org.utbot.framework.plugin.api.util.baseStreamClassId
1316
import org.utbot.framework.plugin.api.util.booleanClassId
@@ -253,11 +256,12 @@ internal abstract class UtilMethodProvider(val utilClassId: ClassId) {
253256

254257
/**
255258
* This provider represents an util class file that is generated and put into the user's test module.
256-
* The generated class is UtUtils (its id is defined at [utUtilsClassId]).
259+
* The generated class is UtUtils (its id is defined at [utJavaUtilsClassId] or [utKotlinUtilsClassId]).
257260
*
258261
* Content of this util class may be different (due to mocks in deepEquals), but the methods (and their ids) are the same.
259262
*/
260-
internal object UtilClassFileMethodProvider : UtilMethodProvider(utUtilsClassId) {
263+
internal class UtilClassFileMethodProvider(language: CodegenLanguage)
264+
: UtilMethodProvider(selectUtilClassId(language)) {
261265
/**
262266
* This property contains the current version of util class.
263267
* This version will be written to the util class file inside a comment.
@@ -270,14 +274,27 @@ internal object UtilClassFileMethodProvider : UtilMethodProvider(utUtilsClassId)
270274
*
271275
* **IMPORTANT** if you make any changes to util methods (see [utilMethodTextById]), do not forget to update this version.
272276
*/
273-
const val UTIL_CLASS_VERSION = "1.0"
277+
val UTIL_CLASS_VERSION = "2.0"
274278
}
275279

276280
internal class TestClassUtilMethodProvider(testClassId: ClassId) : UtilMethodProvider(testClassId)
277281

278-
internal val utUtilsClassId: ClassId
282+
internal fun selectUtilClassId(codegenLanguage: CodegenLanguage): ClassId =
283+
when (codegenLanguage) {
284+
CodegenLanguage.JAVA -> utJavaUtilsClassId
285+
CodegenLanguage.KOTLIN -> utKotlinUtilsClassId
286+
}
287+
288+
internal val utJavaUtilsClassId: ClassId
289+
get() = BuiltinClassId(
290+
canonicalName = UT_UTILS_BASE_PACKAGE_NAME + PACKAGE_DELIMITER + "java" + PACKAGE_DELIMITER + "UtUtils",
291+
simpleName = "UtUtils",
292+
isFinal = true,
293+
)
294+
295+
internal val utKotlinUtilsClassId: ClassId
279296
get() = BuiltinClassId(
280-
canonicalName = "org.utbot.runtime.utils.UtUtils",
297+
canonicalName = UT_UTILS_BASE_PACKAGE_NAME + PACKAGE_DELIMITER + "kotlin" + PACKAGE_DELIMITER + "UtUtils",
281298
simpleName = "UtUtils",
282299
isFinal = true,
283300
isKotlinObject = true

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ internal data class CgContext(
508508
*/
509509
override val utilMethodProvider: UtilMethodProvider
510510
get() = if (generateUtilClassFile) {
511-
UtilClassFileMethodProvider
511+
UtilClassFileMethodProvider(codegenLanguage)
512512
} else {
513513
TestClassUtilMethodProvider(outerMostTestClass)
514514
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgUtilClassConstructor.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package org.utbot.framework.codegen.model.constructor.tree
22

33
import org.utbot.framework.codegen.model.CodeGenerator
44
import org.utbot.framework.codegen.model.UtilClassKind
5-
import org.utbot.framework.codegen.model.constructor.builtin.utUtilsClassId
5+
import org.utbot.framework.codegen.model.constructor.builtin.selectUtilClassId
6+
import org.utbot.framework.codegen.model.constructor.builtin.utJavaUtilsClassId
7+
import org.utbot.framework.codegen.model.constructor.builtin.utKotlinUtilsClassId
68
import org.utbot.framework.codegen.model.tree.CgAuxiliaryClass
79
import org.utbot.framework.codegen.model.tree.CgAuxiliaryNestedClassesRegion
810
import org.utbot.framework.codegen.model.tree.CgClassFile
@@ -11,21 +13,26 @@ import org.utbot.framework.codegen.model.tree.CgUtilMethod
1113
import org.utbot.framework.codegen.model.tree.buildClass
1214
import org.utbot.framework.codegen.model.tree.buildClassBody
1315
import org.utbot.framework.codegen.model.tree.buildClassFile
16+
import org.utbot.framework.plugin.api.CodegenLanguage
1417

1518
/**
1619
* This class is used to construct a file containing an util class UtUtils.
1720
* The util class is constructed when the argument `generateUtilClassFile` in the [CodeGenerator] is true.
1821
*/
1922
internal object CgUtilClassConstructor {
20-
fun constructUtilsClassFile(utilClassKind: UtilClassKind): CgClassFile {
23+
fun constructUtilsClassFile(
24+
utilClassKind: UtilClassKind,
25+
codegenLanguage: CodegenLanguage,
26+
): CgClassFile {
2127
val utilMethodProvider = utilClassKind.utilMethodProvider
28+
val utilsClassId = selectUtilClassId(codegenLanguage)
2229
return buildClassFile {
2330
// imports are empty, because we use fully qualified classes and static methods,
2431
// so they will be imported once IDEA reformatting action has worked
2532
declaredClass = buildClass {
26-
id = utUtilsClassId
27-
body = buildClassBody(utUtilsClassId) {
28-
documentation = utilClassKind.utilClassDocumentation
33+
id = utilsClassId
34+
body = buildClassBody(utilsClassId) {
35+
documentation = utilClassKind.utilClassDocumentation(codegenLanguage)
2936
staticDeclarationRegions += CgStaticsRegion("Util methods", utilMethodProvider.utilMethodIds.map { CgUtilMethod(it) })
3037
nestedClassRegions += CgAuxiliaryNestedClassesRegion(
3138
nestedClasses = listOf(

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package org.utbot.framework.codegen.model.visitor
22

33
import org.utbot.framework.codegen.model.UtilClassKind
4-
import org.utbot.framework.codegen.model.UtilClassKind.Companion.UT_UTILS_PACKAGE_NAME
4+
import org.utbot.framework.codegen.model.UtilClassKind.Companion.utilsPackageFullName
55
import org.utbot.framework.codegen.model.constructor.builtin.UtilMethodProvider
6-
import org.utbot.framework.codegen.model.constructor.builtin.utUtilsClassId
6+
import org.utbot.framework.codegen.model.constructor.builtin.selectUtilClassId
7+
import org.utbot.framework.codegen.model.constructor.builtin.utJavaUtilsClassId
8+
import org.utbot.framework.codegen.model.constructor.builtin.utKotlinUtilsClassId
79
import org.utbot.framework.codegen.model.constructor.context.CgContext
810
import org.utbot.framework.plugin.api.ClassId
911
import org.utbot.framework.plugin.api.CodegenLanguage
@@ -46,8 +48,8 @@ internal class CgRendererContext(
4648
shouldOptimizeImports = false,
4749
importedClasses = emptySet(),
4850
importedStaticMethods = emptySet(),
49-
classPackageName = UT_UTILS_PACKAGE_NAME,
50-
generatedClass = utUtilsClassId,
51+
classPackageName = utilsPackageFullName(language),
52+
generatedClass = selectUtilClassId(language),
5153
utilMethodProvider = utilClassKind.utilMethodProvider,
5254
codegenLanguage = language,
5355
mockFrameworkUsed = utilClassKind.mockFrameworkUsed,

utbot-framework/src/main/kotlin/org/utbot/tests/infrastructure/TestCodeGeneratorPipeline.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import org.utbot.framework.codegen.TestFramework
1212
import org.utbot.framework.codegen.model.CodeGenerator
1313
import org.utbot.framework.codegen.model.CodeGeneratorResult
1414
import org.utbot.framework.codegen.model.UtilClassKind
15-
import org.utbot.framework.codegen.model.UtilClassKind.Companion.UT_UTILS_CLASS_NAME
15+
import org.utbot.framework.codegen.model.UtilClassKind.Companion.UT_UTILS_INSTANCE_NAME
1616
import org.utbot.framework.plugin.api.CodegenLanguage
1717
import org.utbot.framework.plugin.api.ExecutableId
1818
import org.utbot.framework.plugin.api.MockFramework
@@ -171,7 +171,7 @@ class TestCodeGeneratorPipeline(private val testFrameworkConfiguration: TestFram
171171
}
172172

173173
private fun UtilClassKind.writeUtilClassToFile(buildDirectory: Path, language: CodegenLanguage): File {
174-
val utilClassFile = File(buildDirectory.toFile(), "$UT_UTILS_CLASS_NAME${language.extension}")
174+
val utilClassFile = File(buildDirectory.toFile(), "$UT_UTILS_INSTANCE_NAME${language.extension}")
175175
val utilClassText = getUtilClassText(language)
176176
return writeFile(utilClassText, utilClassFile)
177177
}

0 commit comments

Comments
 (0)