Introduce SourceType and use KotlinFacetSettings.isTestModule
Refactor dealing with production/test roots Remove ad-hoc code in KotlinMultiplatformRunLocationsProvider
This commit is contained in:
@@ -210,8 +210,6 @@ data class ModuleTestSourceInfo internal constructor(override val module: Module
|
||||
override fun <T> createCachedValueProvider(f: () -> CachedValueProvider.Result<T>) = CachedValueProvider { f() }
|
||||
}
|
||||
|
||||
internal fun ModuleSourceInfo.isTests() = this is ModuleTestSourceInfo
|
||||
|
||||
fun Module.productionSourceInfo(): ModuleProductionSourceInfo? = if (hasProductionRoots()) ModuleProductionSourceInfo(this) else null
|
||||
|
||||
fun Module.testSourceInfo(): ModuleTestSourceInfo? = if (hasTestRoots()) ModuleTestSourceInfo(this) else null
|
||||
@@ -444,3 +442,10 @@ data class PlatformModuleInfo(
|
||||
|
||||
fun IdeaModuleInfo.projectSourceModules(): List<ModuleSourceInfo>? =
|
||||
(this as? ModuleSourceInfo)?.let(::listOf) ?: (this as? PlatformModuleInfo)?.containedModules
|
||||
|
||||
enum class SourceType {
|
||||
PRODUCTION,
|
||||
TEST
|
||||
}
|
||||
|
||||
internal val ModuleSourceInfo.sourceType get() = if (this is ModuleTestSourceInfo) SourceType.TEST else SourceType.PRODUCTION
|
||||
|
||||
+11
-12
@@ -6,25 +6,24 @@
|
||||
package org.jetbrains.kotlin.idea.caches.project
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ModuleOrderEntry
|
||||
import gnu.trove.THashSet
|
||||
import com.intellij.util.containers.Queue
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import java.util.HashSet
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import com.intellij.util.containers.Queue
|
||||
import gnu.trove.THashSet
|
||||
import java.util.*
|
||||
|
||||
//NOTE: this is an approximation that may contain more module infos then the exact solution
|
||||
fun ModuleSourceInfo.getDependentModules(): Set<ModuleSourceInfo> {
|
||||
val dependents = getDependents(module)
|
||||
return if (isTests()) {
|
||||
dependents.mapNotNullTo(HashSet<ModuleSourceInfo>(), Module::testSourceInfo)
|
||||
} else {
|
||||
dependents.flatMapTo(HashSet<ModuleSourceInfo>()) { it.correspondingModuleInfos() }
|
||||
return when (sourceType) {
|
||||
SourceType.TEST -> dependents.mapNotNullTo(HashSet<ModuleSourceInfo>(), Module::testSourceInfo)
|
||||
SourceType.PRODUCTION -> dependents.flatMapTo(HashSet<ModuleSourceInfo>()) { it.correspondingModuleInfos() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-7
@@ -16,6 +16,8 @@ import com.intellij.psi.util.CachedValueProvider
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.project.SourceType.PRODUCTION
|
||||
import org.jetbrains.kotlin.idea.caches.project.SourceType.TEST
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacetType
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacetType.Companion.ID
|
||||
@@ -26,19 +28,24 @@ import org.jetbrains.kotlin.platform.impl.isCommon
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
|
||||
val Module.isNewMPPModule: Boolean
|
||||
get() = KotlinFacet.get(this)?.configuration?.settings?.kind?.isNewMPP ?: false
|
||||
get() = facetSettings?.kind?.isNewMPP ?: false
|
||||
|
||||
val Module.externalProjectId: String
|
||||
get() = KotlinFacet.get(this)?.configuration?.settings?.externalProjectId ?: ""
|
||||
get() = facetSettings?.externalProjectId ?: ""
|
||||
|
||||
val Module.sourceType: SourceType?
|
||||
get() = facetSettings?.isTestModule?.let { isTest -> if (isTest) SourceType.TEST else PRODUCTION }
|
||||
|
||||
val Module.isMPPModule: Boolean
|
||||
get() {
|
||||
val settings = KotlinFacet.get(this)?.configuration?.settings ?: return false
|
||||
val settings = facetSettings ?: return false
|
||||
return settings.platform.isCommon ||
|
||||
settings.implementedModuleNames.isNotEmpty() ||
|
||||
settings.kind.isNewMPP
|
||||
}
|
||||
|
||||
private val Module.facetSettings get() = KotlinFacet.get(this)?.configuration?.settings
|
||||
|
||||
val Module.implementingModules: List<Module>
|
||||
get() = cached(CachedValueProvider {
|
||||
val moduleManager = ModuleManager.getInstance(project)
|
||||
@@ -87,12 +94,15 @@ val ModuleDescriptor.implementingDescriptors: List<ModuleDescriptor>
|
||||
return listOf(this)
|
||||
}
|
||||
val moduleSourceInfo = moduleInfo as? ModuleSourceInfo ?: return emptyList()
|
||||
val implementingModuleInfos = moduleSourceInfo.module.implementingModules.mapNotNull { it.toInfo(moduleSourceInfo.isTests()) }
|
||||
val implementingModuleInfos = moduleSourceInfo.module.implementingModules.mapNotNull { it.toInfo(moduleSourceInfo.sourceType) }
|
||||
return implementingModuleInfos.mapNotNull { it.toDescriptor() }
|
||||
}
|
||||
|
||||
private fun Module.toInfo(isTests: Boolean): ModuleSourceInfo? =
|
||||
if (isTests) testSourceInfo() else productionSourceInfo()
|
||||
private fun Module.toInfo(type: SourceType): ModuleSourceInfo? = when (type) {
|
||||
PRODUCTION -> productionSourceInfo()
|
||||
TEST -> testSourceInfo()
|
||||
}
|
||||
|
||||
|
||||
val ModuleDescriptor.implementedDescriptors: List<ModuleDescriptor>
|
||||
get() {
|
||||
@@ -112,7 +122,7 @@ fun PsiElement.getPlatformModuleInfo(desiredPlatform: TargetPlatform): PlatformM
|
||||
val moduleInfo = getModuleInfo() as? ModuleSourceInfo ?: return null
|
||||
return when (moduleInfo.platform) {
|
||||
TargetPlatform.Common -> {
|
||||
val correspondingImplementingModule = moduleInfo.module.implementingModules.map { it.toInfo(moduleInfo.isTests()) }
|
||||
val correspondingImplementingModule = moduleInfo.module.implementingModules.map { it.toInfo(moduleInfo.sourceType) }
|
||||
.firstOrNull { it?.platform == desiredPlatform } ?: return null
|
||||
PlatformModuleInfo(correspondingImplementingModule, correspondingImplementingModule.expectedBy)
|
||||
}
|
||||
|
||||
@@ -12,12 +12,20 @@ import org.jetbrains.jps.model.java.JavaSourceRootType
|
||||
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
|
||||
import org.jetbrains.kotlin.config.KotlinResourceRootType
|
||||
import org.jetbrains.kotlin.config.KotlinSourceRootType
|
||||
import org.jetbrains.kotlin.idea.caches.project.SourceType
|
||||
import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected
|
||||
|
||||
private val testRootTypes: Set<JpsModuleSourceRootType<*>> = setOf(
|
||||
JavaSourceRootType.TEST_SOURCE,
|
||||
JavaResourceRootType.TEST_RESOURCE,
|
||||
KotlinSourceRootType.TestSource,
|
||||
KotlinResourceRootType.TestResource
|
||||
JavaSourceRootType.TEST_SOURCE,
|
||||
JavaResourceRootType.TEST_RESOURCE,
|
||||
KotlinSourceRootType.TestSource,
|
||||
KotlinResourceRootType.TestResource
|
||||
)
|
||||
|
||||
fun FileIndex.isInTestSourceContentKotlinAware(fileOrDir: VirtualFile) = isUnderSourceRootOfType(fileOrDir, testRootTypes)
|
||||
fun FileIndex.isInTestSourceContentKotlinAware(fileOrDir: VirtualFile) = isUnderSourceRootOfType(fileOrDir, testRootTypes)
|
||||
|
||||
fun FileIndex.getSourceType(fileOrDir: VirtualFile): SourceType? = when {
|
||||
isInTestSourceContentKotlinAware(fileOrDir) -> SourceType.TEST
|
||||
isInSourceContentWithoutInjected(fileOrDir) -> SourceType.PRODUCTION
|
||||
else -> null
|
||||
}
|
||||
+7
-11
@@ -9,13 +9,14 @@ import com.intellij.execution.Location
|
||||
import com.intellij.execution.PsiLocation
|
||||
import com.intellij.execution.actions.MultipleRunLocationsProvider
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import org.jetbrains.kotlin.config.KotlinModuleKind
|
||||
import org.jetbrains.kotlin.idea.caches.project.SourceType
|
||||
import org.jetbrains.kotlin.idea.caches.project.implementingModules
|
||||
import org.jetbrains.kotlin.idea.caches.project.isNewMPPModule
|
||||
import org.jetbrains.kotlin.idea.caches.project.sourceType
|
||||
import org.jetbrains.kotlin.idea.configuration.toModuleGroup
|
||||
import org.jetbrains.kotlin.idea.core.isInTestSourceContentKotlinAware
|
||||
import org.jetbrains.kotlin.idea.core.getSourceType
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||
|
||||
class KotlinMultiplatformRunLocationsProvider : MultipleRunLocationsProvider() {
|
||||
@@ -27,8 +28,8 @@ class KotlinMultiplatformRunLocationsProvider : MultipleRunLocationsProvider() {
|
||||
override fun getAlternativeLocations(originalLocation: Location<*>): List<Location<*>> {
|
||||
val originalModule = originalLocation.module ?: return emptyList()
|
||||
val virtualFile = originalLocation.virtualFile ?: return emptyList()
|
||||
val shouldRunAsTest = ModuleRootManager.getInstance(originalModule).fileIndex.isInTestSourceContentKotlinAware(virtualFile)
|
||||
return modulesToRunFrom(originalModule, shouldRunAsTest).map { PsiLocation(originalLocation.project, it, originalLocation.psiElement) }
|
||||
val sourceType = ModuleRootManager.getInstance(originalModule).fileIndex.getSourceType(virtualFile) ?: return emptyList()
|
||||
return modulesToRunFrom(originalModule, sourceType).map { PsiLocation(originalLocation.project, it, originalLocation.psiElement) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,17 +44,12 @@ private fun compactedGradleProjectId(module: Module): String? {
|
||||
|
||||
private fun modulesToRunFrom(
|
||||
originalModule: Module,
|
||||
shouldRunAsTest: Boolean
|
||||
originalSourceType: SourceType
|
||||
): List<Module> {
|
||||
val modules = originalModule.implementingModules
|
||||
if (!originalModule.isNewMPPModule) return modules
|
||||
val compilations = modules.filter {
|
||||
KotlinFacet.get(it)?.configuration?.settings?.kind == KotlinModuleKind.COMPILATION_AND_SOURCE_SET_HOLDER
|
||||
}
|
||||
|
||||
val project = originalModule.project
|
||||
// TODO: more robust way to get test/production compilations
|
||||
val baseName = originalModule.toModuleGroup().baseModule.name
|
||||
val commonTests = ModuleManager.getInstance(project).findModuleByName(baseName + "_commonTest") ?: return compilations
|
||||
return compilations.filter { ModuleRootManager.getInstance(it).isDependsOn(commonTests) == shouldRunAsTest }
|
||||
return compilations.filter { it.sourceType == originalSourceType }
|
||||
}
|
||||
Reference in New Issue
Block a user