Skip to content

Commit 98e0b54

Browse files
committed
Android Studio fixes (#634, #635)
Multiple test modules supported. Removed unused jdkVersion from model, added for convenience to JdkPathService. Removed unnecessary classpath modification parts for Android.
1 parent 2c69326 commit 98e0b54

File tree

9 files changed

+68
-48
lines changed

9 files changed

+68
-48
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/JdkPathDefaultProvider.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ import java.nio.file.Paths
66
open class JdkPathDefaultProvider: JdkPathProvider() {
77
override val jdkPath: Path
88
get() = Paths.get(System.getProperty("java.home"))
9+
10+
override val jdkVersion: String
11+
get() = System.getProperty("java.version")
912
}

utbot-framework-api/src/main/kotlin/org/utbot/framework/JdkPathProvider.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ abstract class JdkPathProvider {
99
}
1010

1111
abstract val jdkPath: Path
12+
13+
abstract val jdkVersion: String
1214
}

utbot-framework-api/src/main/kotlin/org/utbot/framework/JdkPathService.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,7 @@ object JdkPathService {
1616
// Kotlin delegates do not support changing in runtime, so use simple getter
1717
val jdkPath: Path
1818
get() = jdkPathProvider.jdkPath
19+
20+
val jdkVersion: String
21+
get() = jdkPathProvider.jdkVersion
1922
}

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

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ import org.utbot.framework.plugin.api.util.withUtContext
3939
import org.utbot.intellij.plugin.generator.CodeGenerationController.generateTests
4040
import org.utbot.intellij.plugin.models.GenerateTestsModel
4141
import org.utbot.intellij.plugin.ui.GenerateTestsDialogWindow
42-
import org.utbot.intellij.plugin.ui.utils.jdkVersion
4342
import org.utbot.intellij.plugin.ui.utils.showErrorDialogLater
44-
import org.utbot.intellij.plugin.ui.utils.testModule
4543
import org.utbot.intellij.plugin.util.AndroidApiHelper
4644
import org.utbot.intellij.plugin.util.PluginJdkPathProvider
4745
import org.utbot.intellij.plugin.util.signature
@@ -56,6 +54,7 @@ import org.utbot.engine.util.mockListeners.ForceStaticMockListener
5654
import org.utbot.framework.plugin.api.testFlow
5755
import org.utbot.intellij.plugin.settings.Settings
5856
import org.utbot.intellij.plugin.util.isAbstract
57+
import org.utbot.intellij.plugin.ui.utils.testModules
5958
import kotlin.reflect.KClass
6059
import kotlin.reflect.full.functions
6160

@@ -79,23 +78,15 @@ object UtTestsDialogProcessor {
7978
focusedMethod: MemberInfo?,
8079
): GenerateTestsDialogWindow? {
8180
val srcModule = findSrcModule(srcClasses)
82-
val testModule = srcModule.testModule(project)
83-
84-
JdkPathService.jdkPathProvider = PluginJdkPathProvider(project, testModule)
85-
val jdkVersion = try {
86-
testModule.jdkVersion()
87-
} catch (e: IllegalStateException) {
88-
// Just ignore it here, notification will be shown in
89-
// org.utbot.intellij.plugin.ui.utils.ModuleUtilsKt.jdkVersionBy
90-
return null
91-
}
81+
val testModules = srcModule.testModules(project)
82+
83+
JdkPathService.jdkPathProvider = PluginJdkPathProvider(project)
9284

9385
return GenerateTestsDialogWindow(
9486
GenerateTestsModel(
9587
project,
9688
srcModule,
97-
testModule,
98-
jdkVersion,
89+
testModules,
9990
srcClasses,
10091
if (focusedMethod != null) setOf(focusedMethod) else null,
10192
UtSettings.utBotGenerationTimeoutInMillis,
@@ -286,12 +277,6 @@ object UtTestsDialogProcessor {
286277
val pathsList = OrderEnumerator.orderEntries(srcModule).recursively().pathsList
287278

288279
val (classpath, classpathList) = if (AndroidApiHelper.isAndroidStudio()) {
289-
// Add $JAVA_HOME/jre/lib/rt.jar to path.
290-
// This allows Soot to analyze real java instead of stub version in Android SDK on local machine.
291-
pathsList.add(
292-
System.getenv("JAVA_HOME") + File.separator + Paths.get("jre", "lib", "rt.jar")
293-
)
294-
295280
// Filter out manifests from classpath.
296281
val filterPredicate = { it: String ->
297282
!it.contains("manifest", ignoreCase = true)

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/models/GenerateTestsModel.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,40 @@ import org.utbot.framework.plugin.api.CodegenLanguage
1111
import org.utbot.framework.plugin.api.MockFramework
1212
import org.utbot.framework.plugin.api.MockStrategyApi
1313
import com.intellij.openapi.module.Module
14+
import com.intellij.openapi.module.ModuleUtil
1415
import com.intellij.openapi.project.Project
1516
import com.intellij.openapi.projectRoots.JavaSdkVersion
1617
import com.intellij.openapi.vfs.VirtualFile
1718
import com.intellij.psi.PsiClass
1819
import com.intellij.refactoring.util.classMembers.MemberInfo
1920
import org.jetbrains.kotlin.idea.core.getPackage
2021
import org.utbot.framework.util.ConflictTriggers
22+
import org.utbot.intellij.plugin.ui.utils.jdkVersion
2123

2224
data class GenerateTestsModel(
2325
val project: Project,
2426
val srcModule: Module,
25-
val testModule: Module,
26-
val jdkVersion: JavaSdkVersion,
27+
val potentialTestModules: List<Module>,
2728
var srcClasses: Set<PsiClass>,
2829
var selectedMethods: Set<MemberInfo>?,
2930
var timeout:Long,
3031
var generateWarningsForStaticMocking: Boolean = false,
3132
var fuzzingValue: Double = 0.05
3233
) {
34+
var testModule: Module = potentialTestModules.first()
35+
val jdkVersion: JavaSdkVersion?
36+
get() = try {
37+
testModule.jdkVersion()
38+
} catch (e: IllegalStateException) {
39+
null
40+
}
41+
3342
var testSourceRoot: VirtualFile? = null
43+
set(value) {
44+
requireNotNull(value)
45+
testModule = ModuleUtil.findModuleForFile(value, project) ?: error("Could not find module for $value")
46+
field = value
47+
}
3448
var testPackageName: String? = null
3549
lateinit var testFramework: TestFramework
3650
lateinit var mockStrategy: MockStrategyApi

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.intellij.openapi.command.WriteCommandAction
1010
import com.intellij.openapi.components.service
1111
import com.intellij.openapi.editor.colors.EditorColorsManager
1212
import com.intellij.openapi.module.Module
13+
import com.intellij.openapi.module.ModuleUtil
1314
import com.intellij.openapi.options.ShowSettingsUtil
1415
import com.intellij.openapi.projectRoots.JavaSdkVersion
1516
import com.intellij.openapi.roots.ContentEntry
@@ -510,6 +511,8 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
510511
private fun createTestRootAndPackages(): Boolean {
511512
model.testSourceRoot = createDirectoryIfMissing(model.testSourceRoot)
512513
val testSourceRoot = model.testSourceRoot ?: return false
514+
model.testModule = ModuleUtil.findModuleForFile(testSourceRoot, model.project) ?: error("Could not find module")
515+
513516
if (model.testSourceRoot?.isDirectory != true) return false
514517
if (getOrCreateTestRoot(testSourceRoot)) {
515518
if (cbSpecifyTestPackage.isSelected) {

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.utbot.intellij.plugin.ui.components
33
import com.intellij.openapi.application.ReadAction
44
import com.intellij.openapi.fileChooser.FileChooser
55
import com.intellij.openapi.fileChooser.FileChooserDescriptor
6+
import com.intellij.openapi.module.ModuleUtil
67
import com.intellij.openapi.project.guessProjectDir
78
import com.intellij.openapi.vfs.VirtualFile
89
import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile
@@ -50,8 +51,11 @@ class TestFolderComboWithBrowseButton(private val model: GenerateTestsModel) : C
5051
}
5152
}
5253

53-
val testRoots = model.testModule.suitableTestSourceRoots().toMutableList()
54-
model.testModule.addDedicatedTestRoot(testRoots)
54+
// this part is blocked for Gradle, where multiple test modules can exist
55+
val defaultModuleTestRoots = model.testModule.suitableTestSourceRoots().toMutableList()
56+
model.testModule.addDedicatedTestRoot(defaultModuleTestRoots)
57+
58+
val testRoots = model.potentialTestModules.flatMap { it.suitableTestSourceRoots().toMutableList() }
5559
if (testRoots.isNotEmpty()) {
5660
configureRootsCombo(testRoots)
5761
} else {

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,35 +83,37 @@ fun Module.getOrCreateSarifReportsPath(testSourceRoot: VirtualFile?): Path {
8383
}
8484

8585
/**
86-
* Find test module by current source module.
86+
* Find test modules by current source module.
8787
*/
88-
fun Module.testModule(project: Project): Module {
89-
var testModule = findPotentialModuleForTests(project, this)
90-
val testRootUrls = testModule.suitableTestSourceRoots()
88+
fun Module.testModules(project: Project): List<Module> {
89+
var testModules = findPotentialModulesForTests(project, this)
90+
val testRootUrls = testModules.flatMap { it.suitableTestSourceRoots() }
9191

9292
//if no suitable module for tests is found, create tests in the same root
93-
if (testRootUrls.isEmpty() && testModule.suitableTestSourceFolders().isEmpty()) {
94-
testModule = this
93+
if (testRootUrls.isEmpty() && testModules.flatMap { it.suitableTestSourceFolders() }.isEmpty()) {
94+
testModules = listOf(this)
9595
}
96-
return testModule
96+
return testModules
9797
}
9898

99-
private fun findPotentialModuleForTests(project: Project, srcModule: Module): Module {
99+
private fun findPotentialModulesForTests(project: Project, srcModule: Module): List<Module> {
100+
val modules = mutableListOf<Module>()
100101
for (module in ModuleManager.getInstance(project).modules) {
101102
if (srcModule == TestModuleProperties.getInstance(module).productionModule) {
102-
return module
103+
modules += module
103104
}
104105
}
106+
if (modules.isNotEmpty()) return modules
105107

106108
if (srcModule.suitableTestSourceFolders().isEmpty()) {
107109
val modules = mutableSetOf<Module>()
108110
ModuleUtilCore.collectModulesDependsOn(srcModule, modules)
109111
modules.remove(srcModule)
110112

111113
val modulesWithTestRoot = modules.filter { it.suitableTestSourceFolders().isNotEmpty() }
112-
if (modulesWithTestRoot.size == 1) return modulesWithTestRoot[0]
114+
if (modulesWithTestRoot.size == 1) return modulesWithTestRoot
113115
}
114-
return srcModule
116+
return listOf(srcModule)
115117
}
116118

117119
/**

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

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,35 @@ package org.utbot.intellij.plugin.util
22

33
import org.utbot.common.PathUtil.toPath
44
import org.utbot.framework.JdkPathDefaultProvider
5-
import com.intellij.openapi.module.Module
65
import com.intellij.openapi.project.Project
76
import com.intellij.openapi.projectRoots.ProjectJdkTable
8-
import com.intellij.openapi.roots.ModuleRootManager
7+
import com.intellij.openapi.projectRoots.Sdk
98
import com.intellij.openapi.roots.ProjectRootManager
109
import java.nio.file.Path
1110

1211
class PluginJdkPathProvider(
13-
private val project: Project,
14-
private val testModule: Module,
12+
private val project: Project
1513
) : JdkPathDefaultProvider() {
1614

17-
override val jdkPath: Path
18-
get() =
15+
private val sdk: Sdk?
16+
get() {
1917
if (AndroidApiHelper.isAndroidStudio()) {
2018
// Get Gradle JDK for Android
2119
AndroidApiHelper.gradleSDK(project)
2220
?.let { sdkName ->
23-
ProjectJdkTable.getInstance().findJdk(sdkName)?.homePath?.toPath()
21+
ProjectJdkTable.getInstance().findJdk(sdkName) ?.let {
22+
return it
23+
}
2424
}
25-
} else {
26-
// Use testModule JDK (or Project SDK) as analyzed JDK
27-
(ModuleRootManager.getInstance(testModule).sdk
28-
?.homePath ?: ProjectRootManager.getInstance(project).projectSdk?.homePath)
29-
?.toPath()
30-
} ?: super.jdkPath // Return default JDK in case of failure
25+
}
26+
27+
// Use Project SDK as analyzed JDK
28+
return ProjectRootManager.getInstance(project).projectSdk
29+
}
30+
31+
override val jdkPath: Path
32+
get() = sdk?.let { it.homePath?.toPath() } ?: super.jdkPath // Return default JDK in case of failure
3133

34+
override val jdkVersion: String
35+
get() = sdk?.versionString ?: super.jdkVersion // Return default JDK in case of failure
3236
}

0 commit comments

Comments
 (0)