Split ScriptModuleInfo into script itself and its dependencies

For now include all dependencies of all scripts for every script, to be improved later
This commit is contained in:
Pavel V. Talanov
2016-06-16 19:29:20 +03:00
parent 1a9c46f34b
commit 693eeb9f0a
5 changed files with 34 additions and 44 deletions
@@ -23,7 +23,6 @@ import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.*
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.DelegatingGlobalSearchScope
@@ -31,14 +30,14 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.util.SmartList
import com.intellij.util.io.URLUtil
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.core.script.KotlinScriptConfigurationManager
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.script.KotlinScriptDefinition
import org.jetbrains.kotlin.utils.alwaysNull
import org.jetbrains.kotlin.utils.emptyOrSingletonList
import java.io.File
import java.lang.reflect.Method
import java.util.*
@@ -81,6 +80,8 @@ interface IdeaModuleInfo : ModuleInfo {
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
get() = mapOf(OriginCapability to moduleOrigin)
override fun dependencies(): List<IdeaModuleInfo>
}
private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, productionOnly: Boolean): List<IdeaModuleInfo> {
@@ -291,44 +292,29 @@ class ScriptModuleSearchScope(val scriptFile: VirtualFile, baseScope: GlobalSear
override fun hashCode() = scriptFile.hashCode() * 73 * super.hashCode()
}
internal data class ScriptModuleInfo(val project: Project, val module: Module?, val scriptFile: VirtualFile,
val scriptDefinition: KotlinScriptDefinition) : IdeaModuleInfo {
data class ScriptModuleInfo(val project: Project, val scriptFile: VirtualFile,
val scriptDefinition: KotlinScriptDefinition) : IdeaModuleInfo {
override val moduleOrigin: ModuleOrigin
get() = ModuleOrigin.OTHER
override val name: Name = Name.special("<$SCRIPT_NAME_PREFIX${scriptDefinition.name}>")
override fun contentScope(): ScriptModuleSearchScope {
val dependenciesRoots = dependenciesRoots()
return ScriptModuleSearchScope(
scriptFile,
if (dependenciesRoots.isEmpty()) GlobalSearchScope.EMPTY_SCOPE
else GlobalSearchScope.union(dependenciesRoots.map { FileLibraryScope(project, it) }.toTypedArray()))
}
override fun contentScope() = GlobalSearchScope.fileScope(project, scriptFile)
private fun dependenciesRoots(): List<VirtualFile> {
// TODO: find out whether it should be cashed (some changes listener should be implemented for the cached roots)
val jarfs = StandardFileSystems.jar()
return scriptDefinition.getDependenciesFor(scriptFile, project, null)?.classpath
?.map { it.canonicalFile }
?.distinct()
?.mapNotNull {
// TODO: ensure that the entries are checked elsewhere, so diagnostics is delivered to a user if files are not correctly specified
if (it.isFile)
jarfs.findFileByPath(it.absolutePath + URLUtil.JAR_SEPARATOR) ?: null // diag: Classpath entry points to a file that is not a JAR archive
else
StandardFileSystems.local().findFileByPath(it.absolutePath) ?: null // diag: Classpath entry points to a non-existent location
}
?: emptyList()
}
// TODO: only dependencies of this particular script
override fun dependencies() = listOf(this, ScriptDependenciesModuleInfo(project))
}
override fun dependencies() =
listOf(this) +
(module?.cached(CachedValueProvider {
CachedValueProvider.Result(
ideaModelDependencies(module, productionOnly = false),
ProjectRootModificationTracker.getInstance(module.project))
}) ?: emptyList())
data class ScriptDependenciesModuleInfo(val project: Project): IdeaModuleInfo {
override fun dependencies() = listOf(this)
override val name = Name.special("<Script dependencies>")
// TODO: this is not very efficient because KotlinSourceFilterScope already checks if the files are in scripts classpath
override fun contentScope() = KotlinSourceFilterScope.libraryClassFiles(KotlinScriptConfigurationManager.getInstance(project).getAllScriptsClasspathScope(), project)
override val moduleOrigin: ModuleOrigin
get() = ModuleOrigin.LIBRARY
}
class FileLibraryScope(project: Project, private val libraryRoot: VirtualFile) : GlobalSearchScope(project) {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -148,11 +148,9 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
}
}
syntheticFileModule is ScriptModuleInfo -> {
syntheticFileModule is ScriptModuleInfo || syntheticFileModule is ScriptDependenciesModuleInfo -> {
ProjectResolutionFacade(project, globalContext.storageManager) {
makeGlobalResolveSessionProvider(
reuseDataFrom = librariesFacade(targetPlatform, sdk)
)
makeGlobalResolveSessionProvider()
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ fun createModuleResolverProvider(
val syntheticFilesByModule = syntheticFiles.groupBy { it.getModuleInfo() }
val syntheticFilesModules = syntheticFilesByModule.keys
allModuleInfos.addAll(syntheticFilesModules)
allModuleInfos.addAll(syntheticFilesModules + syntheticFilesModules.flatMap { it.dependencies() })
val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter)
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.asJava.FakeLightClassForFileOfPackage
import org.jetbrains.kotlin.asJava.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.KtLightElement
import org.jetbrains.kotlin.idea.core.script.KotlinScriptConfigurationManager
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
@@ -123,8 +124,13 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil
}
val scriptDefinition = getScriptDefinition(virtualFile, project)
if (scriptDefinition != null)
return ScriptModuleInfo(project, module, virtualFile, scriptDefinition)
if (scriptDefinition != null) {
return ScriptModuleInfo(project, virtualFile, scriptDefinition)
}
if (KotlinScriptConfigurationManager.getInstance(project).getAllScriptsClasspathScope().contains(virtualFile)) {
return ScriptDependenciesModuleInfo(project)
}
return NotUnderContentRootModuleInfo
}
@@ -32,7 +32,7 @@ fun getResolveScope(file: KtFile): GlobalSearchScope {
return when (file.getModuleInfo()) {
is ModuleSourceInfo -> KotlinSourceFilterScope.projectSourceAndClassFiles(file.resolveScope, file.project)
is ScriptModuleInfo -> file.getModuleInfo().contentScope()
is ScriptModuleInfo -> file.getModuleInfo().dependencies().map { it.contentScope() }.let { GlobalSearchScope.union(it.toTypedArray()) }
else -> GlobalSearchScope.EMPTY_SCOPE
}
}