"Configure Kotlin in project" handles modules from Gradle source roots
THose modules are now always collapsed to their base modules. #KT-11828 Fixed
This commit is contained in:
@@ -33,7 +33,7 @@ abstract class ConfigureKotlinInProjectAction : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
|
||||
val modules = getModulesWithKotlinFiles(project).ifEmpty { project.allModules() }
|
||||
val modules = getConfigurableModulesWithKotlinFiles(project).ifEmpty { project.allModules() }
|
||||
if (modules.all(::isModuleConfigured)) {
|
||||
Messages.showInfoMessage("All modules with Kotlin files are configured", e.presentation.text!!)
|
||||
return
|
||||
|
||||
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.idea.configuration
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Computable
|
||||
@@ -71,8 +73,20 @@ fun getModulesWithKotlinFiles(project: Project): Collection<Module> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return project.allModules().filter { module ->
|
||||
FileTypeIndex.containsFileOfType(KotlinFileType.INSTANCE, module.getModuleScope(true))
|
||||
return project.allModules()
|
||||
.filter { module ->
|
||||
FileTypeIndex.containsFileOfType(KotlinFileType.INSTANCE, module.getModuleScope(true))
|
||||
}
|
||||
}
|
||||
|
||||
fun getConfigurableModulesWithKotlinFiles(project: Project): Collection<Module> {
|
||||
val modules = getModulesWithKotlinFiles(project)
|
||||
if (modules.isEmpty()) return modules
|
||||
|
||||
val pathMap = ModuleManager.getInstance(project).modules.asList().buildExternalPathMap()
|
||||
return modules.mapTo(HashSet()) { module ->
|
||||
val externalPath = module.externalProjectPath
|
||||
if (externalPath == null) module else (pathMap[externalPath] ?: module)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +99,7 @@ fun showConfigureKotlinNotificationIfNeeded(module: Module) {
|
||||
fun showConfigureKotlinNotificationIfNeeded(project: Project, excludeModules: List<Module> = emptyList()) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread {
|
||||
val notificationString = DumbService.getInstance(project).runReadActionInSmartMode(Computable {
|
||||
val modules = getModulesWithKotlinFiles(project) - excludeModules
|
||||
val modules = getConfigurableModulesWithKotlinFiles(project) - excludeModules
|
||||
if (modules.all(::isModuleConfigured)) null else ConfigureKotlinNotification.getNotificationString(project, excludeModules)
|
||||
})
|
||||
if (notificationString != null) {
|
||||
@@ -97,7 +111,7 @@ fun showConfigureKotlinNotificationIfNeeded(project: Project, excludeModules: Li
|
||||
}
|
||||
|
||||
fun getAbleToRunConfigurators(project: Project): Collection<KotlinProjectConfigurator> {
|
||||
val modules = getModulesWithKotlinFiles(project).ifEmpty { project.allModules() }
|
||||
val modules = getConfigurableModulesWithKotlinFiles(project).ifEmpty { project.allModules() }
|
||||
|
||||
return Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME).filter { configurator ->
|
||||
modules.any { module -> configurator.getStatus(module) == ConfigureKotlinStatus.CAN_BE_CONFIGURED }
|
||||
@@ -113,16 +127,48 @@ fun getConfiguratorByName(name: String): KotlinProjectConfigurator? {
|
||||
}
|
||||
|
||||
fun getNonConfiguredModules(project: Project, configurator: KotlinProjectConfigurator): List<Module> {
|
||||
return project.allModules().filter { module -> configurator.getStatus(module) == ConfigureKotlinStatus.CAN_BE_CONFIGURED }
|
||||
return project.allModules()
|
||||
.filter { module -> configurator.getStatus(module) == ConfigureKotlinStatus.CAN_BE_CONFIGURED }
|
||||
.excludeSourceRootModules()
|
||||
}
|
||||
|
||||
fun Collection<Module>.excludeSourceRootModules(): List<Module> {
|
||||
val pathMap = buildExternalPathMap()
|
||||
return filter { it.externalProjectId == null || it.externalProjectPath == null } + pathMap.values
|
||||
}
|
||||
|
||||
fun Collection<Module>.buildExternalPathMap(): Map<String, Module> {
|
||||
val pathMap = mutableMapOf<String, Module>()
|
||||
for (module in this) {
|
||||
val externalId = module.externalProjectId
|
||||
val externalPath = module.externalProjectPath
|
||||
if (externalId != null && externalPath != null) {
|
||||
val previousModule = pathMap[externalPath]
|
||||
// the module without the source root suffix will have the shortest name
|
||||
if (previousModule == null || isSourceRootPrefix(externalId, previousModule.externalProjectId!!)) {
|
||||
pathMap[externalPath] = module
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathMap
|
||||
}
|
||||
|
||||
private fun isSourceRootPrefix(externalId: String, previousModuleExternalId: String)
|
||||
= externalId.length < previousModuleExternalId.length && previousModuleExternalId.startsWith(externalId)
|
||||
|
||||
val Module.externalProjectId: String?
|
||||
get() = ExternalSystemApiUtil.getExternalProjectId(this)
|
||||
|
||||
val Module.externalProjectPath: String?
|
||||
get() = ExternalSystemApiUtil.getExternalProjectPath(this)
|
||||
|
||||
fun getNonConfiguredModulesWithKotlinFiles(project: Project, configurator: KotlinProjectConfigurator): List<Module> {
|
||||
val modules = getModulesWithKotlinFiles(project)
|
||||
val modules = getConfigurableModulesWithKotlinFiles(project)
|
||||
return modules.filter { module -> configurator.getStatus(module) == ConfigureKotlinStatus.CAN_BE_CONFIGURED }
|
||||
}
|
||||
|
||||
fun getNonConfiguredModules(project: Project, excludeModules: Collection<Module> = emptyList()): Collection<Module> {
|
||||
val modulesWithKotlinFiles = getModulesWithKotlinFiles(project) - excludeModules
|
||||
val modulesWithKotlinFiles = getConfigurableModulesWithKotlinFiles(project) - excludeModules
|
||||
val ableToRunConfigurators = getAbleToRunConfigurators(project)
|
||||
return modulesWithKotlinFiles.filter { module ->
|
||||
ableToRunConfigurators.any { it.getStatus(module) == ConfigureKotlinStatus.CAN_BE_CONFIGURED }
|
||||
|
||||
@@ -20,15 +20,14 @@ import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinStatus
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator
|
||||
import org.jetbrains.kotlin.idea.configuration.createConfigureKotlinNotificationCollector
|
||||
import org.jetbrains.kotlin.idea.configuration.*
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.test.testFramework.runInEdtAndWait
|
||||
import org.jetbrains.kotlin.test.testFramework.runWriteAction
|
||||
import org.junit.Test
|
||||
|
||||
class GradleConfiguratorTest : GradleImportingTestCase() {
|
||||
|
||||
@Test
|
||||
fun testProjectWithModule() {
|
||||
createProjectSubFile("settings.gradle", "include ':app'")
|
||||
@@ -58,8 +57,7 @@ class GradleConfiguratorTest : GradleImportingTestCase() {
|
||||
myProject.baseDir.createChildData(null, "build.gradle")
|
||||
|
||||
val module = ModuleManager.getInstance(myProject).findModuleByName("app")!!
|
||||
val configurator = Extensions.findExtension(KotlinProjectConfigurator.EP_NAME,
|
||||
KotlinGradleModuleConfigurator::class.java)
|
||||
val configurator = findGradleModuleConfigurator()
|
||||
// We have a Kotlin runtime in build.gradle but not in the classpath, so it doesn't make sense
|
||||
// to suggest configuring it
|
||||
assertEquals(ConfigureKotlinStatus.BROKEN, configurator.getStatus(module))
|
||||
@@ -84,8 +82,7 @@ class GradleConfiguratorTest : GradleImportingTestCase() {
|
||||
runInEdtAndWait {
|
||||
runWriteAction {
|
||||
val module = ModuleManager.getInstance(myProject).findModuleByName("app")!!
|
||||
val configurator = Extensions.findExtension(KotlinProjectConfigurator.EP_NAME,
|
||||
KotlinGradleModuleConfigurator::class.java)
|
||||
val configurator = findGradleModuleConfigurator()
|
||||
val collector = createConfigureKotlinNotificationCollector(myProject)
|
||||
configurator.configureWithVersion(myProject, listOf(module), "1.0.6", collector)
|
||||
|
||||
@@ -113,4 +110,34 @@ class GradleConfiguratorTest : GradleImportingTestCase() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findGradleModuleConfigurator() = Extensions.findExtension(KotlinProjectConfigurator.EP_NAME,
|
||||
KotlinGradleModuleConfigurator::class.java)
|
||||
|
||||
@Test
|
||||
fun testListNonConfiguredModules() {
|
||||
createProjectSubFile("settings.gradle", "include ':app'")
|
||||
createProjectSubFile("app/build.gradle", """
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
""".trimIndent())
|
||||
createProjectSubFile("app/src/main/java/foo.kt", "")
|
||||
|
||||
importProject()
|
||||
|
||||
runReadAction {
|
||||
val configurator = findGradleModuleConfigurator()
|
||||
val moduleNames = getNonConfiguredModules(myProject, configurator).map { it.name }
|
||||
assertSameElements(moduleNames, "app", "project")
|
||||
|
||||
val moduleNamesWithKotlinFiles = getNonConfiguredModulesWithKotlinFiles(myProject, configurator).map { it.name }
|
||||
assertSameElements(moduleNamesWithKotlinFiles, "app")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user