Add initial prototype of custom script support in IDE
This commit is contained in:
@@ -23,20 +23,28 @@ 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.openapi.vfs.VirtualFileManager
|
||||
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.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.io.FileNotFoundException
|
||||
import java.lang.reflect.Method
|
||||
import java.util.*
|
||||
|
||||
private val LIBRARY_NAME_PREFIX: String = "library "
|
||||
private val SCRIPT_NAME_PREFIX: String = "script "
|
||||
|
||||
// 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
|
||||
@@ -271,6 +279,56 @@ internal object NotUnderContentRootModuleInfo : IdeaModuleInfo {
|
||||
override fun dependencies(): List<IdeaModuleInfo> = listOf(this)
|
||||
}
|
||||
|
||||
internal data class CustomizedScriptModuleInfo(val project: Project, val virtualFile: 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() = GlobalSearchScope.union(dependenciesRoots().map { FileLibraryScope(project, it) }.toTypedArray())
|
||||
|
||||
private fun dependenciesRoots(): List<VirtualFile> {
|
||||
// TODO: find out whether it should be cashed
|
||||
val virtualFileManager = VirtualFileManager.getInstance()
|
||||
val jarfs = StandardFileSystems.jar()
|
||||
return scriptDefinition.getScriptDependenciesClasspath().map {
|
||||
if (File(it).isFile)
|
||||
jarfs.findFileByPath(it + URLUtil.JAR_SEPARATOR) ?: throw FileNotFoundException("Classpath entry points to a file that is not a JAR archive: $it")
|
||||
else
|
||||
virtualFileManager.findFileByUrl("file://$it") ?: throw FileNotFoundException("Classpath entry points to a non-existent location: $it")
|
||||
}
|
||||
}
|
||||
override fun dependencies(): List<IdeaModuleInfo> = listOf(this)
|
||||
}
|
||||
|
||||
private class FileLibraryScope(project: Project, private val libraryRoot: VirtualFile) : GlobalSearchScope(project) {
|
||||
val cachedEntries : MutableSet<VirtualFile> = hashSetOf()
|
||||
|
||||
override fun contains(file: VirtualFile): Boolean =
|
||||
VfsUtilCore.isAncestor(libraryRoot, file, false)
|
||||
|
||||
override fun isSearchInLibraries(): Boolean = true
|
||||
override fun isSearchInModuleContent(aModule: Module): Boolean = false
|
||||
|
||||
// TODO: check if this is a valid decision for the case of a single root
|
||||
override fun compare(file1: VirtualFile, file2: VirtualFile): Int = 0
|
||||
|
||||
override fun equals(other: Any?) = other is FileLibraryScope && libraryRoot == other.libraryRoot
|
||||
|
||||
override fun hashCode() = libraryRoot.hashCode()
|
||||
}
|
||||
|
||||
private class FileLibraryModuleInfo(val project: Project, val libraryRoot: VirtualFile) :IdeaModuleInfo {
|
||||
override val moduleOrigin: ModuleOrigin
|
||||
get() = ModuleOrigin.OTHER
|
||||
|
||||
override val name: Name = Name.special(libraryRoot.nameWithoutExtension)
|
||||
|
||||
override fun contentScope() = FileLibraryScope(project, libraryRoot)
|
||||
|
||||
override fun dependencies(): List<IdeaModuleInfo> = emptyList()
|
||||
}
|
||||
|
||||
private class LibraryWithoutSourceScope(project: Project, private val library: Library) :
|
||||
LibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||
|
||||
|
||||
+16
@@ -139,6 +139,22 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
}
|
||||
}
|
||||
|
||||
syntheticFileModule is CustomizedScriptModuleInfo -> {
|
||||
ProjectResolutionFacade(project, globalContext.storageManager) {
|
||||
globalResolveSessionProvider(
|
||||
debugName,
|
||||
project,
|
||||
targetPlatform,
|
||||
sdk,
|
||||
commonGlobalContext = globalContext,
|
||||
syntheticFiles = files,
|
||||
reuseDataFrom = librariesFacade(targetPlatform, sdk),
|
||||
moduleFilter = { true },
|
||||
dependencies = dependenciesForSyntheticFileCache
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
syntheticFileModule is LibrarySourceInfo || syntheticFileModule is NotUnderContentRootModuleInfo -> {
|
||||
ProjectResolutionFacade(project, globalContext.storageManager) {
|
||||
globalResolveSessionProvider(
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.asJava.KtLightElement
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
fun PsiElement.getModuleInfo(): IdeaModuleInfo = this.getModuleInfo { reason ->
|
||||
@@ -120,6 +121,11 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val scriptDefinition = KotlinScriptDefinitionProvider.getInstance(project).findScriptDefinition(virtualFile)
|
||||
if (scriptDefinition != null)
|
||||
return CustomizedScriptModuleInfo(project, virtualFile, scriptDefinition)
|
||||
|
||||
return NotUnderContentRootModuleInfo
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user