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() }
|
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.productionSourceInfo(): ModuleProductionSourceInfo? = if (hasProductionRoots()) ModuleProductionSourceInfo(this) else null
|
||||||
|
|
||||||
fun Module.testSourceInfo(): ModuleTestSourceInfo? = if (hasTestRoots()) ModuleTestSourceInfo(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>? =
|
fun IdeaModuleInfo.projectSourceModules(): List<ModuleSourceInfo>? =
|
||||||
(this as? ModuleSourceInfo)?.let(::listOf) ?: (this as? PlatformModuleInfo)?.containedModules
|
(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
|
package org.jetbrains.kotlin.idea.caches.project
|
||||||
|
|
||||||
import com.intellij.openapi.module.Module
|
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.module.ModuleManager
|
||||||
import com.intellij.openapi.roots.ModuleRootManager
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.roots.ModuleOrderEntry
|
import com.intellij.openapi.roots.ModuleOrderEntry
|
||||||
import gnu.trove.THashSet
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
import com.intellij.util.containers.Queue
|
|
||||||
import com.intellij.psi.util.CachedValuesManager
|
|
||||||
import com.intellij.psi.util.CachedValueProvider
|
|
||||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
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
|
//NOTE: this is an approximation that may contain more module infos then the exact solution
|
||||||
fun ModuleSourceInfo.getDependentModules(): Set<ModuleSourceInfo> {
|
fun ModuleSourceInfo.getDependentModules(): Set<ModuleSourceInfo> {
|
||||||
val dependents = getDependents(module)
|
val dependents = getDependents(module)
|
||||||
return if (isTests()) {
|
return when (sourceType) {
|
||||||
dependents.mapNotNullTo(HashSet<ModuleSourceInfo>(), Module::testSourceInfo)
|
SourceType.TEST -> dependents.mapNotNullTo(HashSet<ModuleSourceInfo>(), Module::testSourceInfo)
|
||||||
} else {
|
SourceType.PRODUCTION -> dependents.flatMapTo(HashSet<ModuleSourceInfo>()) { it.correspondingModuleInfos() }
|
||||||
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.analyzer.ModuleInfo
|
||||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
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.KotlinFacet
|
||||||
import org.jetbrains.kotlin.idea.facet.KotlinFacetType
|
import org.jetbrains.kotlin.idea.facet.KotlinFacetType
|
||||||
import org.jetbrains.kotlin.idea.facet.KotlinFacetType.Companion.ID
|
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
|
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||||
|
|
||||||
val Module.isNewMPPModule: Boolean
|
val Module.isNewMPPModule: Boolean
|
||||||
get() = KotlinFacet.get(this)?.configuration?.settings?.kind?.isNewMPP ?: false
|
get() = facetSettings?.kind?.isNewMPP ?: false
|
||||||
|
|
||||||
val Module.externalProjectId: String
|
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
|
val Module.isMPPModule: Boolean
|
||||||
get() {
|
get() {
|
||||||
val settings = KotlinFacet.get(this)?.configuration?.settings ?: return false
|
val settings = facetSettings ?: return false
|
||||||
return settings.platform.isCommon ||
|
return settings.platform.isCommon ||
|
||||||
settings.implementedModuleNames.isNotEmpty() ||
|
settings.implementedModuleNames.isNotEmpty() ||
|
||||||
settings.kind.isNewMPP
|
settings.kind.isNewMPP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val Module.facetSettings get() = KotlinFacet.get(this)?.configuration?.settings
|
||||||
|
|
||||||
val Module.implementingModules: List<Module>
|
val Module.implementingModules: List<Module>
|
||||||
get() = cached(CachedValueProvider {
|
get() = cached(CachedValueProvider {
|
||||||
val moduleManager = ModuleManager.getInstance(project)
|
val moduleManager = ModuleManager.getInstance(project)
|
||||||
@@ -87,12 +94,15 @@ val ModuleDescriptor.implementingDescriptors: List<ModuleDescriptor>
|
|||||||
return listOf(this)
|
return listOf(this)
|
||||||
}
|
}
|
||||||
val moduleSourceInfo = moduleInfo as? ModuleSourceInfo ?: return emptyList()
|
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() }
|
return implementingModuleInfos.mapNotNull { it.toDescriptor() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Module.toInfo(isTests: Boolean): ModuleSourceInfo? =
|
private fun Module.toInfo(type: SourceType): ModuleSourceInfo? = when (type) {
|
||||||
if (isTests) testSourceInfo() else productionSourceInfo()
|
PRODUCTION -> productionSourceInfo()
|
||||||
|
TEST -> testSourceInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val ModuleDescriptor.implementedDescriptors: List<ModuleDescriptor>
|
val ModuleDescriptor.implementedDescriptors: List<ModuleDescriptor>
|
||||||
get() {
|
get() {
|
||||||
@@ -112,7 +122,7 @@ fun PsiElement.getPlatformModuleInfo(desiredPlatform: TargetPlatform): PlatformM
|
|||||||
val moduleInfo = getModuleInfo() as? ModuleSourceInfo ?: return null
|
val moduleInfo = getModuleInfo() as? ModuleSourceInfo ?: return null
|
||||||
return when (moduleInfo.platform) {
|
return when (moduleInfo.platform) {
|
||||||
TargetPlatform.Common -> {
|
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
|
.firstOrNull { it?.platform == desiredPlatform } ?: return null
|
||||||
PlatformModuleInfo(correspondingImplementingModule, correspondingImplementingModule.expectedBy)
|
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.jps.model.module.JpsModuleSourceRootType
|
||||||
import org.jetbrains.kotlin.config.KotlinResourceRootType
|
import org.jetbrains.kotlin.config.KotlinResourceRootType
|
||||||
import org.jetbrains.kotlin.config.KotlinSourceRootType
|
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(
|
private val testRootTypes: Set<JpsModuleSourceRootType<*>> = setOf(
|
||||||
JavaSourceRootType.TEST_SOURCE,
|
JavaSourceRootType.TEST_SOURCE,
|
||||||
JavaResourceRootType.TEST_RESOURCE,
|
JavaResourceRootType.TEST_RESOURCE,
|
||||||
KotlinSourceRootType.TestSource,
|
KotlinSourceRootType.TestSource,
|
||||||
KotlinResourceRootType.TestResource
|
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.PsiLocation
|
||||||
import com.intellij.execution.actions.MultipleRunLocationsProvider
|
import com.intellij.execution.actions.MultipleRunLocationsProvider
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.module.ModuleManager
|
|
||||||
import com.intellij.openapi.roots.ModuleRootManager
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
import org.jetbrains.kotlin.config.KotlinModuleKind
|
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.implementingModules
|
||||||
import org.jetbrains.kotlin.idea.caches.project.isNewMPPModule
|
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.configuration.toModuleGroup
|
||||||
import org.jetbrains.kotlin.idea.core.isInTestSourceContentKotlinAware
|
import org.jetbrains.kotlin.idea.core.getSourceType
|
||||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||||
|
|
||||||
class KotlinMultiplatformRunLocationsProvider : MultipleRunLocationsProvider() {
|
class KotlinMultiplatformRunLocationsProvider : MultipleRunLocationsProvider() {
|
||||||
@@ -27,8 +28,8 @@ class KotlinMultiplatformRunLocationsProvider : MultipleRunLocationsProvider() {
|
|||||||
override fun getAlternativeLocations(originalLocation: Location<*>): List<Location<*>> {
|
override fun getAlternativeLocations(originalLocation: Location<*>): List<Location<*>> {
|
||||||
val originalModule = originalLocation.module ?: return emptyList()
|
val originalModule = originalLocation.module ?: return emptyList()
|
||||||
val virtualFile = originalLocation.virtualFile ?: return emptyList()
|
val virtualFile = originalLocation.virtualFile ?: return emptyList()
|
||||||
val shouldRunAsTest = ModuleRootManager.getInstance(originalModule).fileIndex.isInTestSourceContentKotlinAware(virtualFile)
|
val sourceType = ModuleRootManager.getInstance(originalModule).fileIndex.getSourceType(virtualFile) ?: return emptyList()
|
||||||
return modulesToRunFrom(originalModule, shouldRunAsTest).map { PsiLocation(originalLocation.project, it, originalLocation.psiElement) }
|
return modulesToRunFrom(originalModule, sourceType).map { PsiLocation(originalLocation.project, it, originalLocation.psiElement) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,17 +44,12 @@ private fun compactedGradleProjectId(module: Module): String? {
|
|||||||
|
|
||||||
private fun modulesToRunFrom(
|
private fun modulesToRunFrom(
|
||||||
originalModule: Module,
|
originalModule: Module,
|
||||||
shouldRunAsTest: Boolean
|
originalSourceType: SourceType
|
||||||
): List<Module> {
|
): List<Module> {
|
||||||
val modules = originalModule.implementingModules
|
val modules = originalModule.implementingModules
|
||||||
if (!originalModule.isNewMPPModule) return modules
|
if (!originalModule.isNewMPPModule) return modules
|
||||||
val compilations = modules.filter {
|
val compilations = modules.filter {
|
||||||
KotlinFacet.get(it)?.configuration?.settings?.kind == KotlinModuleKind.COMPILATION_AND_SOURCE_SET_HOLDER
|
KotlinFacet.get(it)?.configuration?.settings?.kind == KotlinModuleKind.COMPILATION_AND_SOURCE_SET_HOLDER
|
||||||
}
|
}
|
||||||
|
return compilations.filter { it.sourceType == originalSourceType }
|
||||||
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 }
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user