@@ -26,12 +26,18 @@ import org.utbot.intellij.plugin.util.isVisible
26
26
import java.util.*
27
27
import org.jetbrains.kotlin.j2k.getContainingClass
28
28
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
29
32
30
33
class GenerateTestsAction : AnAction (), UpdateInBackground {
31
34
override fun actionPerformed (e : AnActionEvent ) {
32
35
val project = e.project ? : return
36
+
33
37
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)
35
41
}
36
42
37
43
override fun update (e : AnActionEvent ) {
@@ -53,7 +59,6 @@ class GenerateTestsAction : AnAction(), UpdateInBackground {
53
59
54
60
if (psiElementHandler.isCreateTestActionAvailable(element)) {
55
61
val srcClass = psiElementHandler.containingClass(element) ? : return null
56
- if (srcClass.isInterface || ! srcClass.isVisible) return null
57
62
val srcSourceRoot = srcClass.getSourceRoot() ? : return null
58
63
val srcMembers = srcClass.extractFirstLevelMembers(false )
59
64
val focusedMethod = focusedMethodOrNull(element, srcMembers, psiElementHandler)
@@ -113,7 +118,7 @@ class GenerateTestsAction : AnAction(), UpdateInBackground {
113
118
}
114
119
}
115
120
}
116
- srcClasses.removeIf { it.isInterface }
121
+
117
122
if (srcClasses.size > 1 ) {
118
123
extractMembersFromSrcClasses = false
119
124
}
@@ -136,6 +141,45 @@ class GenerateTestsAction : AnAction(), UpdateInBackground {
136
141
return null
137
142
}
138
143
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
+
139
183
private fun PsiElement?.getSourceRoot () : VirtualFile ? {
140
184
val project = this ?.project? : return null
141
185
val virtualFile = this .containingFile?.originalFile?.virtualFile? : return null
0 commit comments