Allow to use internal declarations from special modules in IDEA

(e.g. IDEA 16 gradle tests loaded in separate module)

 #KT-10595 Fixed
This commit is contained in:
Zalim Bashorov
2016-02-03 20:40:01 +03:00
parent 5968ce96df
commit 2c1d1e84a6
3 changed files with 53 additions and 10 deletions
@@ -26,13 +26,44 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.util.SmartList
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.alwaysNull
import org.jetbrains.kotlin.utils.emptyOrSingletonList
import java.lang.reflect.Method
import java.util.*
val LIBRARY_NAME_PREFIX: String = "library "
private val LIBRARY_NAME_PREFIX: String = "library "
// TODO used reflection to be compatible with IDEA from both 143 and 144 branches,
// TODO switch to directly using when "since-build" will be >= 144.3357.4
private val getRelatedProductionModule: (Module) -> Module? = run {
val klass =
try {
Class.forName("com.intellij.openapi.roots.TestModuleProperties")
} catch (e: ClassNotFoundException) {
return@run alwaysNull()
}
val getInstanceMethod: Method
val getProductionModuleMethod: Method
try {
getInstanceMethod = klass.getDeclaredMethod("getInstance", Module::class.java)
getProductionModuleMethod = klass.getDeclaredMethod("getProductionModule")
}
catch (e: NoSuchMethodException) {
return@run alwaysNull()
}
return@run { module ->
val instance = getInstanceMethod(null, module)
getProductionModuleMethod(instance) as Module?
}
}
interface IdeaModuleInfo : ModuleInfo {
fun contentScope(): GlobalSearchScope
@@ -71,7 +102,7 @@ private fun <T> Module.cached(provider: CachedValueProvider<T>): T {
return CachedValuesManager.getManager(project).getCachedValue(this, provider)
}
fun ideaModelDependencies(module: Module, productionOnly: Boolean): List<IdeaModuleInfo> {
private fun ideaModelDependencies(module: Module, productionOnly: Boolean): List<IdeaModuleInfo> {
//NOTE: lib dependencies can be processed several times during recursive traversal
val result = LinkedHashSet<IdeaModuleInfo>()
val dependencyEnumerator = ModuleRootManager.getInstance(module).orderEntries().compileOnly().recursively().exportedOnly()
@@ -102,8 +133,6 @@ data class ModuleProductionSourceInfo(override val module: Module) : ModuleSourc
ideaModelDependencies(module, productionOnly = true),
ProjectRootModificationTracker.getInstance(module.project))
})
override fun friends() = listOf(module.testSourceInfo())
}
//TODO: (module refactoring) do not create ModuleTestSourceInfo when there are no test roots for module
@@ -117,6 +146,16 @@ data class ModuleTestSourceInfo(override val module: Module) : ModuleSourceInfo
ideaModelDependencies(module, productionOnly = false),
ProjectRootModificationTracker.getInstance(module.project))
})
override fun modulesWhichInternalsAreVisible() = module.cached(CachedValueProvider {
val list = SmartList<ModuleInfo>(module.productionSourceInfo())
getRelatedProductionModule(module)?.let {
list.add(it.productionSourceInfo())
}
CachedValueProvider.Result(list, ProjectRootModificationTracker.getInstance(module.project))
})
}
internal fun ModuleSourceInfo.isTests() = this is ModuleTestSourceInfo
@@ -249,4 +288,4 @@ enum class ModuleOrigin {
MODULE,
LIBRARY,
OTHER
}
}