Skip to content

Commit 4ce788d

Browse files
EgorkaKulikovAbdullinAM
authored andcommitted
Notify and reason to the user that UtBot can't be run on the class in editor (UnitTestBot#1105)
* Notify and reason to the user that UtBot can't be run on the edited class * Improve previous implementation
1 parent fc61391 commit 4ce788d

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/Notifications.kt

+6
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ object UnsupportedJdkNotifier : ErrorNotifier() {
6464
"JDK versions older than 8 are not supported. This project's JDK version is $info"
6565
}
6666

67+
object InvalidClassNotifier : WarningNotifier() {
68+
override val displayId: String = "Invalid class"
69+
override fun content(project: Project?, module: Module?, info: String): String =
70+
"Generate tests with UtBot for the $info is not supported."
71+
}
72+
6773
object MissingLibrariesNotifier : WarningNotifier() {
6874
override val displayId: String = "Missing libraries"
6975
override fun content(project: Project?, module: Module?, info: String): String =

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/actions/GenerateTestsAction.kt

+47-3
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ import org.utbot.intellij.plugin.util.isVisible
2626
import java.util.*
2727
import org.jetbrains.kotlin.j2k.getContainingClass
2828
import org.jetbrains.kotlin.utils.addIfNotNull
29+
import org.utbot.intellij.plugin.models.packageName
30+
import org.utbot.intellij.plugin.ui.InvalidClassNotifier
31+
import org.utbot.intellij.plugin.util.isAbstract
2932

3033
class GenerateTestsAction : AnAction(), UpdateInBackground {
3134
override fun actionPerformed(e: AnActionEvent) {
3235
val project = e.project ?: return
36+
3337
val (srcClasses, focusedMethods, extractMembersFromSrcClasses) = getPsiTargets(e) ?: return
34-
UtTestsDialogProcessor.createDialogAndGenerateTests(project, srcClasses, extractMembersFromSrcClasses, focusedMethods)
38+
val validatedSrcClasses = validateSrcClasses(srcClasses) ?: return
39+
40+
UtTestsDialogProcessor.createDialogAndGenerateTests(project, validatedSrcClasses, extractMembersFromSrcClasses, focusedMethods)
3541
}
3642

3743
override fun update(e: AnActionEvent) {
@@ -53,7 +59,6 @@ class GenerateTestsAction : AnAction(), UpdateInBackground {
5359

5460
if (psiElementHandler.isCreateTestActionAvailable(element)) {
5561
val srcClass = psiElementHandler.containingClass(element) ?: return null
56-
if (srcClass.isInterface || !srcClass.isVisible) return null
5762
val srcSourceRoot = srcClass.getSourceRoot() ?: return null
5863
val srcMembers = srcClass.extractFirstLevelMembers(false)
5964
val focusedMethod = focusedMethodOrNull(element, srcMembers, psiElementHandler)
@@ -113,7 +118,7 @@ class GenerateTestsAction : AnAction(), UpdateInBackground {
113118
}
114119
}
115120
}
116-
srcClasses.removeIf { it.isInterface }
121+
117122
if (srcClasses.size > 1) {
118123
extractMembersFromSrcClasses = false
119124
}
@@ -136,6 +141,45 @@ class GenerateTestsAction : AnAction(), UpdateInBackground {
136141
return null
137142
}
138143

144+
/**
145+
* Validates that a set of source classes matches some requirements from [isInvalid].
146+
* If no one of them matches, shows a warning about the first mismatch reason.
147+
*/
148+
private fun validateSrcClasses(srcClasses: Set<PsiClass>): Set<PsiClass>? {
149+
val filteredClasses = srcClasses
150+
.filterNot { it.isInvalid(withWarnings = false) }
151+
.toSet()
152+
153+
if (filteredClasses.isEmpty()) {
154+
srcClasses.first().isInvalid(withWarnings = true)
155+
return null
156+
}
157+
158+
return filteredClasses
159+
}
160+
161+
private fun PsiClass.isInvalid(withWarnings: Boolean): Boolean {
162+
val isAbstractOrInterface = this.isInterface || this.isAbstract
163+
if (isAbstractOrInterface) {
164+
if (withWarnings) InvalidClassNotifier.notify("abstract class or interface ${this.name}")
165+
return true
166+
}
167+
168+
val isInvisible = !this.isVisible
169+
if (isInvisible) {
170+
if (withWarnings) InvalidClassNotifier.notify("private or protected class ${this.name}")
171+
return true
172+
}
173+
174+
val packageIsIncorrect = this.packageName.startsWith("java")
175+
if (packageIsIncorrect) {
176+
if (withWarnings) InvalidClassNotifier.notify("class ${this.name} located in java.* package")
177+
return true
178+
}
179+
180+
return false
181+
}
182+
139183
private fun PsiElement?.getSourceRoot() : VirtualFile? {
140184
val project = this?.project?: return null
141185
val virtualFile = this.containingFile?.originalFile?.virtualFile?: return null

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/PsiClassHelper.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ import org.jetbrains.kotlin.asJava.elements.isSetter
1212
import org.utbot.common.filterWhen
1313
import org.utbot.framework.UtSettings
1414

15-
private val PsiMember.isAbstract: Boolean
15+
val PsiMember.isAbstract: Boolean
1616
get() = modifierList?.hasModifierProperty(PsiModifier.ABSTRACT)?: false
1717

18-
1918
private val PsiMember.isKotlinGetterOrSetter: Boolean
2019
get() {
2120
if (this !is KtLightMethod)

0 commit comments

Comments
 (0)