Skip to content

Commit b9c740d

Browse files
committed
Store version of util class in a comment and use it to decide whether to overwrite an existing util class or not
1 parent 694e018 commit b9c740d

File tree

4 files changed

+57
-21
lines changed

4 files changed

+57
-21
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import org.utbot.framework.plugin.api.ExecutableId
2323
import org.utbot.framework.plugin.api.MockFramework
2424
import org.utbot.framework.plugin.api.UtMethodTestSet
2525
import org.utbot.framework.codegen.model.constructor.TestClassModel
26+
import org.utbot.framework.codegen.model.tree.CgComment
27+
import org.utbot.framework.codegen.model.tree.CgSingleLineComment
2628

2729
class CodeGenerator(
2830
private val classUnderTest: ClassId,
@@ -145,6 +147,21 @@ sealed class UtilClassKind(
145147
private val priority: Int
146148
) : Comparable<UtilClassKind> {
147149

150+
/**
151+
* The version of util class being generated.
152+
* For more details see [UtilClassFileMethodProvider.UTIL_CLASS_VERSION].
153+
*/
154+
val utilClassVersion: String
155+
get() = UtilClassFileMethodProvider.UTIL_CLASS_VERSION
156+
157+
/**
158+
* The comment specifying the version of util class being generated.
159+
*
160+
* @see UtilClassFileMethodProvider.UTIL_CLASS_VERSION
161+
*/
162+
val utilClassVersionComment: CgComment
163+
get() = CgSingleLineComment("$UTIL_CLASS_VERSION_COMMENT_PREFIX${utilClassVersion}")
164+
148165
/**
149166
* A kind of regular UtUtils class. "Regular" here means that this class does not use a mock framework.
150167
*/
@@ -171,6 +188,14 @@ sealed class UtilClassKind(
171188
}
172189

173190
companion object {
191+
192+
/**
193+
* Class UtUtils will contain a comment specifying the version of this util class
194+
* (if we ever change util methods, then util class will be different, hence the update of its version).
195+
* This is a prefix that will go before the version in the comment.
196+
*/
197+
const val UTIL_CLASS_VERSION_COMMENT_PREFIX = "UtUtils class version: "
198+
174199
/**
175200
* Check if an util class is required, and if so, what kind.
176201
* @return `null` if [CgContext.utilMethodProvider] is not [UtilClassFileMethodProvider],

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.utbot.framework.codegen.model.constructor.builtin
33
import org.utbot.framework.codegen.MockitoStaticMocking
44
import org.utbot.framework.codegen.model.constructor.util.utilMethodId
55
import org.utbot.framework.codegen.model.tree.CgClassId
6+
import org.utbot.framework.codegen.model.visitor.utilMethodTextById
67
import org.utbot.framework.plugin.api.BuiltinClassId
78
import org.utbot.framework.plugin.api.ClassId
89
import org.utbot.framework.plugin.api.MethodId
@@ -155,7 +156,21 @@ internal abstract class UtilMethodProvider(val utilClassId: ClassId) {
155156
*
156157
* Content of this util class may be different (due to mocks in deepEquals), but the methods (and their ids) are the same.
157158
*/
158-
internal object UtilClassFileMethodProvider : UtilMethodProvider(utUtilsClassId)
159+
internal object UtilClassFileMethodProvider : UtilMethodProvider(utUtilsClassId) {
160+
/**
161+
* This property contains the current version of util class.
162+
* This version will be written to the util class file inside a comment.
163+
*
164+
* Whenever we want to create an util class, we first check if there is an already existing one.
165+
* If there is, then we decide whether we need to overwrite it or not. One of the factors here
166+
* is the version of this existing class. If the version of existing class is older than the one
167+
* that is currently stored in [UtilClassFileMethodProvider.UTIL_CLASS_VERSION], then we need to
168+
* overwrite an util class, because it might have been changed in the new version.
169+
*
170+
* **IMPORTANT** if you make any changes to util methods (see [utilMethodTextById]), do not forget to update this version.
171+
*/
172+
const val UTIL_CLASS_VERSION = "1.0"
173+
}
159174

160175
internal class TestClassUtilMethodProvider(testClassId: ClassId) : UtilMethodProvider(testClassId)
161176

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import org.utbot.framework.codegen.model.CodeGenerator
44
import org.utbot.framework.codegen.model.UtilClassKind
55
import org.utbot.framework.codegen.model.constructor.builtin.utUtilsClassId
66
import org.utbot.framework.codegen.model.tree.CgRegularClassFile
7-
import org.utbot.framework.codegen.model.tree.CgSingleLineComment
87
import org.utbot.framework.codegen.model.tree.CgUtilMethod
98
import org.utbot.framework.codegen.model.tree.buildRegularClass
109
import org.utbot.framework.codegen.model.tree.buildRegularClassBody
@@ -23,8 +22,7 @@ internal object CgUtilClassConstructor {
2322
declaredClass = buildRegularClass {
2423
id = utUtilsClassId
2524
body = buildRegularClassBody {
26-
// TODO: get actual UTBot version and use it instead of the hardcoded one
27-
content += CgSingleLineComment("UTBot version: 1.0-SNAPSHOT")
25+
content += utilClassKind.utilClassVersionComment
2826
content += utilMethodProvider.utilMethodIds.map { CgUtilMethod(it) }
2927
}
3028
}

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import com.intellij.psi.PsiMethod
3333
import com.intellij.psi.codeStyle.CodeStyleManager
3434
import com.intellij.psi.codeStyle.JavaCodeStyleManager
3535
import com.intellij.psi.search.GlobalSearchScopesCore
36+
import com.intellij.psi.util.childrenOfType
3637
import com.intellij.refactoring.util.classMembers.MemberInfo
3738
import com.intellij.testIntegration.TestIntegrationUtils
3839
import com.intellij.util.IncorrectOperationException
@@ -50,7 +51,6 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
5051
import org.jetbrains.kotlin.psi.psiUtil.endOffset
5152
import org.jetbrains.kotlin.psi.psiUtil.startOffset
5253
import org.jetbrains.kotlin.scripting.resolve.classId
53-
import org.jetbrains.plugins.groovy.lang.psi.util.childrenOfType
5454
import org.utbot.common.HTML_LINE_SEPARATOR
5555
import org.utbot.common.PathUtil.toHtmlLinkTag
5656
import org.utbot.common.allNestedClasses
@@ -161,11 +161,12 @@ object CodeGenerationController {
161161

162162
run(EDT_LATER) {
163163
waitForCountDown(latch, timeout = 100, timeUnit = TimeUnit.MILLISECONDS) {
164+
val mockFrameworkUsed = utilClassListener.mockFrameworkUsed
164165
val utilClassKind = utilClassListener.requiredUtilClassKind
165166
?: return@waitForCountDown // no util class needed
166167

167168
val existingUtilClass = model.codegenLanguage.getUtilClassOrNull(model.project, model.testModule)
168-
if (shouldCreateOrUpdateUtilClass(existingUtilClass, utilClassListener)) {
169+
if (shouldCreateOrUpdateUtilClass(existingUtilClass, mockFrameworkUsed, utilClassKind)) {
169170
createOrUpdateUtilClass(
170171
testDirectory = baseTestDirectory,
171172
utilClassKind = utilClassKind,
@@ -203,13 +204,12 @@ object CodeGenerationController {
203204
}
204205
}
205206

206-
private fun shouldCreateOrUpdateUtilClass(existingUtilClass: PsiFile?, utilClassListener: UtilClassListener): Boolean {
207-
val existingUtilClassVersion = existingUtilClass?.utilClassVersionOrNull
208-
// TODO: here should be the current version of UTBot
209-
val newUtilClassVersion = "1.0-SNAPSHOT"
210-
val versionIsUpdated = existingUtilClassVersion != newUtilClassVersion
211-
212-
val mockFrameworkNotUsed = !utilClassListener.mockFrameworkUsed
207+
private fun shouldCreateOrUpdateUtilClass(
208+
existingUtilClass: PsiFile?,
209+
mockFrameworkUsed: Boolean,
210+
requiredUtilClassKind: UtilClassKind
211+
): Boolean {
212+
val mockFrameworkNotUsed = !mockFrameworkUsed
213213

214214
val utilClassExists = existingUtilClass != null
215215

@@ -218,6 +218,10 @@ object CodeGenerationController {
218218
return true
219219
}
220220

221+
val existingUtilClassVersion = existingUtilClass?.utilClassVersionOrNull
222+
val newUtilClassVersion = requiredUtilClassKind.utilClassVersion
223+
val versionIsUpdated = existingUtilClassVersion != newUtilClassVersion
224+
221225
if (versionIsUpdated) {
222226
// If an existing util class is out of date,
223227
// then we must overwrite it with a newer version.
@@ -353,17 +357,11 @@ object CodeGenerationController {
353357

354358
utilClass.childrenOfType<PsiComment>()
355359
.map { comment -> comment.text }
356-
.firstOrNull { text -> UTBOT_VERSION_PREFIX in text }
357-
?.substringAfterLast(UTBOT_VERSION_PREFIX)
360+
.firstOrNull { text -> UtilClassKind.UTIL_CLASS_VERSION_COMMENT_PREFIX in text }
361+
?.substringAfterLast(UtilClassKind.UTIL_CLASS_VERSION_COMMENT_PREFIX)
358362
?.trim()
359363
}
360364

361-
/**
362-
* Util class must have a comment that specifies the version of UTBot it was generated with.
363-
* This prefix is the start of this comment. The version of UTBot goes after it in the comment.
364-
*/
365-
private const val UTBOT_VERSION_PREFIX = "UTBot version:"
366-
367365
/**
368366
* @param srcClass class under test
369367
* @return name of the package of a given [srcClass].

0 commit comments

Comments
 (0)