Rewrite scripting related API to PsiFile instead of VirtualFile
There were several places where we converted virtualFile to PsiFile. This operation need a read access and may throw ProcessCanceledException, so we want to minimize its usages in IDE
This commit is contained in:
+1
-1
@@ -90,7 +90,7 @@ sealed class ScriptDependenciesInfo(val project: Project) : IdeaModuleInfo, Bina
|
|||||||
) : ScriptDependenciesInfo(project) {
|
) : ScriptDependenciesInfo(project) {
|
||||||
override val sdk: Sdk?
|
override val sdk: Sdk?
|
||||||
get() {
|
get() {
|
||||||
return ScriptDependenciesManager.getInstance(project).getScriptSdk(scriptFile, project)
|
return ScriptDependenciesManager.getInstance(project).getScriptSdk(scriptFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun contentScope(): GlobalSearchScope {
|
override fun contentScope(): GlobalSearchScope {
|
||||||
|
|||||||
+1
-1
@@ -71,7 +71,7 @@ object KotlinHighlightingUtil {
|
|||||||
private fun shouldHighlightScript(ktFile: KtFile): Boolean {
|
private fun shouldHighlightScript(ktFile: KtFile): Boolean {
|
||||||
if (isRunningInCidrIde) return false // There is no Java support in CIDR. So do not highlight errors in KTS if running in CIDR.
|
if (isRunningInCidrIde) return false // There is no Java support in CIDR. So do not highlight errors in KTS if running in CIDR.
|
||||||
if (!ScriptsCompilationConfigurationUpdater.areDependenciesCached(ktFile)) return false
|
if (!ScriptsCompilationConfigurationUpdater.areDependenciesCached(ktFile)) return false
|
||||||
if (IdeScriptReportSink.getReports(ktFile.virtualFile).any { it.severity == ScriptDiagnostic.Severity.FATAL }) {
|
if (IdeScriptReportSink.getReports(ktFile).any { it.severity == ScriptDiagnostic.Severity.FATAL }) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ class ScriptExternalHighlightingPass(
|
|||||||
|
|
||||||
if (!file.isScript()) return
|
if (!file.isScript()) return
|
||||||
|
|
||||||
val reports = IdeScriptReportSink.getReports(file.virtualFile)
|
val reports = IdeScriptReportSink.getReports(file)
|
||||||
|
|
||||||
val annotations = reports.mapNotNull { scriptDiagnostic ->
|
val annotations = reports.mapNotNull { scriptDiagnostic ->
|
||||||
val (startOffset, endOffset) = scriptDiagnostic.location?.let { computeOffsets(document, it) } ?: 0 to 0
|
val (startOffset, endOffset) = scriptDiagnostic.location?.let { computeOffsets(document, it) } ?: 0 to 0
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.impl.cache.impl.id.IdIndex
|
import com.intellij.psi.impl.cache.impl.id.IdIndex
|
||||||
import com.intellij.psi.impl.cache.impl.id.IdIndexEntry
|
import com.intellij.psi.impl.cache.impl.id.IdIndexEntry
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
@@ -123,7 +124,7 @@ fun PsiSearchHelper.isCheapEnoughToSearchConsideringOperators(
|
|||||||
return isCheapEnoughToSearch(name, scope, fileToIgnoreOccurrencesIn, progress)
|
return isCheapEnoughToSearch(name, scope, fileToIgnoreOccurrencesIn, progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findScriptsWithUsages(declaration: KtNamedDeclaration): List<VirtualFile> {
|
fun findScriptsWithUsages(declaration: KtNamedDeclaration): List<KtFile> {
|
||||||
val project = declaration.project
|
val project = declaration.project
|
||||||
val scope = PsiSearchHelper.getInstance(project).getUseScope(declaration) as? GlobalSearchScope
|
val scope = PsiSearchHelper.getInstance(project).getUseScope(declaration) as? GlobalSearchScope
|
||||||
?: return emptyList()
|
?: return emptyList()
|
||||||
@@ -138,5 +139,8 @@ fun findScriptsWithUsages(declaration: KtNamedDeclaration): List<VirtualFile> {
|
|||||||
scope
|
scope
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return collector.results.filter { it.findScriptDefinition(project) != null }.toList()
|
return collector.results
|
||||||
|
.mapNotNull { PsiManager.getInstance(project).findFile(it) as? KtFile }
|
||||||
|
.filter { it.findScriptDefinition() != null }
|
||||||
|
.toList()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Key
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.ui.EditorNotifications
|
import com.intellij.ui.EditorNotifications
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||||
import kotlin.script.experimental.api.ScriptDiagnostic
|
import kotlin.script.experimental.api.ScriptDiagnostic
|
||||||
@@ -49,6 +50,10 @@ class IdeScriptReportSink(val project: Project) : ScriptReportSink {
|
|||||||
return file.scriptDiagnostics ?: emptyList()
|
return file.scriptDiagnostics ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getReports(file: KtFile): List<ScriptDiagnostic> {
|
||||||
|
return file.originalFile.virtualFile?.scriptDiagnostics ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
private var VirtualFile.scriptDiagnostics: List<ScriptDiagnostic>? by UserDataProperty(Key.create("KOTLIN_SCRIPT_DIAGNOSTICS"))
|
private var VirtualFile.scriptDiagnostics: List<ScriptDiagnostic>? by UserDataProperty(Key.create("KOTLIN_SCRIPT_DIAGNOSTICS"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+14
@@ -18,10 +18,18 @@ package org.jetbrains.kotlin.idea.core.script
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.util.*
|
import org.jetbrains.kotlin.idea.core.util.*
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.getScriptOriginalFile
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
|
var KtFile.scriptDependencies: ScriptDependencies?
|
||||||
|
get() = this.getScriptOriginalFile()?.virtualFile?.scriptDependencies
|
||||||
|
set(value) {
|
||||||
|
this.getScriptOriginalFile()?.virtualFile?.scriptDependencies = value
|
||||||
|
}
|
||||||
|
|
||||||
var VirtualFile.scriptDependencies: ScriptDependencies? by cachedFileAttribute(
|
var VirtualFile.scriptDependencies: ScriptDependencies? by cachedFileAttribute(
|
||||||
name = "kotlin-script-dependencies",
|
name = "kotlin-script-dependencies",
|
||||||
version = 3,
|
version = 3,
|
||||||
@@ -45,6 +53,12 @@ var VirtualFile.scriptDependencies: ScriptDependencies? by cachedFileAttribute(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var KtFile.scriptCompilationConfiguration: ScriptCompilationConfiguration?
|
||||||
|
get() = this.getScriptOriginalFile()?.virtualFile?.scriptCompilationConfiguration
|
||||||
|
set(value) {
|
||||||
|
this.getScriptOriginalFile()?.virtualFile?.scriptCompilationConfiguration = value
|
||||||
|
}
|
||||||
|
|
||||||
var VirtualFile.scriptCompilationConfiguration: ScriptCompilationConfiguration? by cachedFileAttribute(
|
var VirtualFile.scriptCompilationConfiguration: ScriptCompilationConfiguration? by cachedFileAttribute(
|
||||||
name = "kotlin-script-compilation-configuration",
|
name = "kotlin-script-compilation-configuration",
|
||||||
version = 1,
|
version = 1,
|
||||||
|
|||||||
+28
-28
@@ -23,16 +23,17 @@ import com.intellij.openapi.projectRoots.JavaSdkType
|
|||||||
import com.intellij.openapi.projectRoots.Sdk
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.roots.ProjectRootManager
|
import com.intellij.openapi.roots.ProjectRootManager
|
||||||
import com.intellij.openapi.vfs.StandardFileSystems
|
import com.intellij.openapi.vfs.StandardFileSystems
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.util.io.URLUtil
|
import com.intellij.util.io.URLUtil
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
||||||
import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependenciesLoader
|
import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependenciesLoader
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.experimental.api.valueOrNull
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
|
||||||
@@ -40,28 +41,35 @@ import kotlin.script.experimental.api.valueOrNull
|
|||||||
// NOTE: this service exists exclusively because ScriptDependencyManager
|
// NOTE: this service exists exclusively because ScriptDependencyManager
|
||||||
// cannot be registered as implementing two services (state would be duplicated)
|
// cannot be registered as implementing two services (state would be duplicated)
|
||||||
class IdeScriptDependenciesProvider(
|
class IdeScriptDependenciesProvider(
|
||||||
private val scriptDependenciesManager: ScriptDependenciesManager
|
private val scriptDependenciesManager: ScriptDependenciesManager,
|
||||||
) : ScriptDependenciesProvider {
|
project: Project
|
||||||
override fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = scriptDependenciesManager.getRefinedCompilationConfiguration(file)
|
) : ScriptDependenciesProvider(project) {
|
||||||
|
override fun getScriptConfigurationResult(file: KtFile): ScriptCompilationConfigurationResult? {
|
||||||
|
return scriptDependenciesManager.getRefinedCompilationConfiguration(file)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
||||||
class ScriptDependenciesManager internal constructor(
|
class ScriptDependenciesManager internal constructor(
|
||||||
private val cacheUpdater: ScriptsCompilationConfigurationUpdater,
|
private val cacheUpdater: ScriptsCompilationConfigurationUpdater,
|
||||||
private val cache: ScriptsCompilationConfigurationCache
|
private val cache: ScriptsCompilationConfigurationCache,
|
||||||
|
private val project: Project
|
||||||
) {
|
) {
|
||||||
fun getScriptClasspath(file: VirtualFile): List<VirtualFile> =
|
|
||||||
toVfsRoots(cacheUpdater.getCurrentCompilationConfiguration(file)?.valueOrNull()?.dependenciesClassPath.orEmpty())
|
|
||||||
|
|
||||||
fun getRefinedCompilationConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? =
|
@Deprecated("Use getScriptClasspath(KtFile) instead")
|
||||||
cacheUpdater.getCurrentCompilationConfiguration(file)
|
fun getScriptClasspath(file: VirtualFile): List<VirtualFile> {
|
||||||
|
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return emptyList()
|
||||||
fun getScriptSdk(file: VirtualFile, project: Project): Sdk? {
|
return getScriptClasspath(ktFile)
|
||||||
return getScriptSdk(getRefinedCompilationConfiguration(file)?.valueOrNull())
|
|
||||||
?: getScriptDefaultSdk(project)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getScriptClasspath(file: KtFile): List<VirtualFile> =
|
||||||
|
toVfsRoots(cacheUpdater.getCurrentCompilationConfiguration(file)?.valueOrNull()?.dependenciesClassPath.orEmpty())
|
||||||
|
|
||||||
|
fun getRefinedCompilationConfiguration(file: KtFile): ScriptCompilationConfigurationResult? =
|
||||||
|
cacheUpdater.getCurrentCompilationConfiguration(file)
|
||||||
|
|
||||||
fun getScriptDependenciesClassFilesScope(file: VirtualFile) = cache.scriptDependenciesClassFilesScope(file)
|
fun getScriptDependenciesClassFilesScope(file: VirtualFile) = cache.scriptDependenciesClassFilesScope(file)
|
||||||
|
fun getScriptSdk(file: VirtualFile) = cache.getScriptSdk(file)
|
||||||
|
|
||||||
fun getAllScriptsSdks() = cache.allSdks
|
fun getAllScriptsSdks() = cache.allSdks
|
||||||
|
|
||||||
@@ -76,17 +84,6 @@ class ScriptDependenciesManager internal constructor(
|
|||||||
fun getInstance(project: Project): ScriptDependenciesManager =
|
fun getInstance(project: Project): ScriptDependenciesManager =
|
||||||
ServiceManager.getService(project, ScriptDependenciesManager::class.java)
|
ServiceManager.getService(project, ScriptDependenciesManager::class.java)
|
||||||
|
|
||||||
fun getScriptSdk(compilationConfiguration: ScriptCompilationConfigurationWrapper?): Sdk? {
|
|
||||||
// workaround for mismatched gradle wrapper and plugin version
|
|
||||||
val javaHome = try {
|
|
||||||
compilationConfiguration?.javaHome?.let { VfsUtil.findFileByIoFile(it, true) }
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
null
|
|
||||||
} ?: return null
|
|
||||||
|
|
||||||
return getAllProjectSdks().find { it.homeDirectory == javaHome }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getScriptDefaultSdk(project: Project): Sdk? {
|
fun getScriptDefaultSdk(project: Project): Sdk? {
|
||||||
val projectSdk = ProjectRootManager.getInstance(project).projectSdk?.takeIf { it.canBeUsedForScript() }
|
val projectSdk = ProjectRootManager.getInstance(project).projectSdk?.takeIf { it.canBeUsedForScript() }
|
||||||
if (projectSdk != null) return projectSdk
|
if (projectSdk != null) return projectSdk
|
||||||
@@ -124,10 +121,13 @@ class ScriptDependenciesManager internal constructor(
|
|||||||
internal val log = Logger.getInstance(ScriptDependenciesManager::class.java)
|
internal val log = Logger.getInstance(ScriptDependenciesManager::class.java)
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
fun updateScriptDependenciesSynchronously(virtualFile: VirtualFile, project: Project) {
|
fun updateScriptDependenciesSynchronously(file: PsiFile, project: Project) {
|
||||||
val loader = SyncScriptDependenciesLoader(project)
|
val loader = SyncScriptDependenciesLoader(project)
|
||||||
val scriptDefinition = virtualFile.findScriptDefinition(project) ?: return
|
val scriptDefinition = file.findScriptDefinition() ?: return
|
||||||
loader.loadDependencies(virtualFile, scriptDefinition)
|
assert(file is KtFile) {
|
||||||
|
"PsiFile should be a KtFile, otherwise script dependencies cannot be loaded"
|
||||||
|
}
|
||||||
|
loader.loadDependencies(file as KtFile, scriptDefinition)
|
||||||
loader.notifyRootsChanged()
|
loader.notifyRootsChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -28,9 +28,9 @@ fun VirtualFile.removeScriptDependenciesNotificationPanel(project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun VirtualFile.addScriptDependenciesNotificationPanel(
|
fun VirtualFile.addScriptDependenciesNotificationPanel(
|
||||||
compilationConfigurationResult: ScriptCompilationConfigurationResult?,
|
compilationConfigurationResult: ScriptCompilationConfigurationResult,
|
||||||
project: Project,
|
project: Project,
|
||||||
onClick: (ScriptCompilationConfigurationResult?) -> Unit
|
onClick: (ScriptCompilationConfigurationResult) -> Unit
|
||||||
) {
|
) {
|
||||||
withSelectedEditor(project) { manager ->
|
withSelectedEditor(project) { manager ->
|
||||||
val existingPanel = notificationPanel
|
val existingPanel = notificationPanel
|
||||||
@@ -61,8 +61,8 @@ private fun VirtualFile.withSelectedEditor(project: Project, f: FileEditor.(File
|
|||||||
private var FileEditor.notificationPanel: NewScriptDependenciesNotificationPanel? by UserDataProperty<FileEditor, NewScriptDependenciesNotificationPanel>(Key.create("script.dependencies.panel"))
|
private var FileEditor.notificationPanel: NewScriptDependenciesNotificationPanel? by UserDataProperty<FileEditor, NewScriptDependenciesNotificationPanel>(Key.create("script.dependencies.panel"))
|
||||||
|
|
||||||
private class NewScriptDependenciesNotificationPanel(
|
private class NewScriptDependenciesNotificationPanel(
|
||||||
onClick: (ScriptCompilationConfigurationResult?) -> Unit,
|
onClick: (ScriptCompilationConfigurationResult) -> Unit,
|
||||||
val compilationConfigurationResult: ScriptCompilationConfigurationResult?,
|
val compilationConfigurationResult: ScriptCompilationConfigurationResult,
|
||||||
project: Project
|
project: Project
|
||||||
) : EditorNotificationPanel() {
|
) : EditorNotificationPanel() {
|
||||||
|
|
||||||
|
|||||||
+67
-31
@@ -15,15 +15,19 @@ import com.intellij.openapi.roots.ModuleRootEvent
|
|||||||
import com.intellij.openapi.roots.ModuleRootListener
|
import com.intellij.openapi.roots.ModuleRootListener
|
||||||
import com.intellij.openapi.roots.ModuleRootManager
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
import com.intellij.openapi.roots.OrderRootType
|
import com.intellij.openapi.roots.OrderRootType
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiElementFinder
|
import com.intellij.psi.PsiElementFinder
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.NonClasspathDirectoriesScope
|
import com.intellij.psi.search.NonClasspathDirectoriesScope
|
||||||
|
import com.intellij.util.containers.ConcurrentFactoryMap
|
||||||
import com.intellij.util.containers.SLRUMap
|
import com.intellij.util.containers.SLRUMap
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
@@ -51,45 +55,79 @@ class ScriptsCompilationConfigurationCache(private val project: Project) {
|
|||||||
|
|
||||||
private val cacheLock = ReentrantReadWriteLock()
|
private val cacheLock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
private val scriptDependenciesCache = SLRUCacheWithLock<ScriptCompilationConfigurationResult>()
|
private val scriptDependenciesCache = SLRUCacheWithLock<VirtualFile, ScriptCompilationConfigurationResult>()
|
||||||
private val scriptsModificationStampsCache = SLRUCacheWithLock<Long>()
|
private val scriptsModificationStampsCache = SLRUCacheWithLock<KtFile, Long>()
|
||||||
|
|
||||||
operator fun get(virtualFile: VirtualFile): ScriptCompilationConfigurationResult? = scriptDependenciesCache.get(virtualFile)
|
operator fun get(file: VirtualFile): ScriptCompilationConfigurationResult? = scriptDependenciesCache.get(file)
|
||||||
|
|
||||||
fun shouldRunDependenciesUpdate(file: VirtualFile): Boolean {
|
fun shouldRunDependenciesUpdate(file: KtFile): Boolean {
|
||||||
return scriptsModificationStampsCache.replace(file, file.modificationStamp) != file.modificationStamp
|
return scriptsModificationStampsCache.replace(file, file.modificationStamp) != file.modificationStamp
|
||||||
}
|
}
|
||||||
|
|
||||||
private val scriptsDependenciesClasspathScopeCache = SLRUCacheWithLock<GlobalSearchScope>()
|
private val scriptsDependenciesClasspathScopeCache: MutableMap<VirtualFile, GlobalSearchScope> =
|
||||||
|
ConcurrentFactoryMap.createWeakMap { file ->
|
||||||
|
val compilationConfiguration = getCachedConfigurationOrLoad(file)
|
||||||
|
?: return@createWeakMap null
|
||||||
|
|
||||||
fun scriptDependenciesClassFilesScope(file: VirtualFile): GlobalSearchScope {
|
|
||||||
return scriptsDependenciesClasspathScopeCache.getOrPut(file) {
|
|
||||||
val compilationConfiguration = scriptDependenciesCache.get(file)?.valueOrNull() ?: return@getOrPut GlobalSearchScope.EMPTY_SCOPE
|
|
||||||
val roots = compilationConfiguration.dependenciesClassPath
|
val roots = compilationConfiguration.dependenciesClassPath
|
||||||
|
val sdk = getScriptSdk(file)
|
||||||
val sdk = ScriptDependenciesManager.getScriptSdk(compilationConfiguration)
|
|
||||||
|
|
||||||
@Suppress("FoldInitializerAndIfToElvis")
|
@Suppress("FoldInitializerAndIfToElvis")
|
||||||
if (sdk == null) {
|
if (sdk == null) {
|
||||||
return@getOrPut NonClasspathDirectoriesScope.compose(ScriptDependenciesManager.toVfsRoots(roots))
|
return@createWeakMap NonClasspathDirectoriesScope.compose(ScriptDependenciesManager.toVfsRoots(roots))
|
||||||
}
|
}
|
||||||
|
|
||||||
return@getOrPut NonClasspathDirectoriesScope.compose(
|
return@createWeakMap NonClasspathDirectoriesScope.compose(
|
||||||
sdk.rootProvider.getFiles(OrderRootType.CLASSES).toList() +
|
sdk.rootProvider.getFiles(OrderRootType.CLASSES).toList() +
|
||||||
ScriptDependenciesManager.toVfsRoots(roots)
|
ScriptDependenciesManager.toVfsRoots(roots)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun scriptDependenciesClassFilesScope(file: VirtualFile): GlobalSearchScope {
|
||||||
|
return scriptsDependenciesClasspathScopeCache[file] ?: GlobalSearchScope.EMPTY_SCOPE
|
||||||
|
}
|
||||||
|
|
||||||
|
private val scriptsSdksCache: MutableMap<VirtualFile, Sdk?> =
|
||||||
|
ConcurrentFactoryMap.createWeakMap { file ->
|
||||||
|
val compilationConfiguration = getCachedConfigurationOrLoad(file)
|
||||||
|
return@createWeakMap getScriptSdk(compilationConfiguration) ?: ScriptDependenciesManager.getScriptDefaultSdk(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getScriptSdk(file: VirtualFile): Sdk? {
|
||||||
|
return scriptsSdksCache[file]
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCachedConfigurationOrLoad(file: VirtualFile): ScriptCompilationConfigurationWrapper? {
|
||||||
|
val compilationConfiguration = scriptDependenciesCache.get(file)?.valueOrNull()
|
||||||
|
|
||||||
|
if (compilationConfiguration != null) {
|
||||||
|
return compilationConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null
|
||||||
|
return ScriptDependenciesManager.getInstance(project).getRefinedCompilationConfiguration(ktFile)?.valueOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getScriptSdk(compilationConfiguration: ScriptCompilationConfigurationWrapper?): Sdk? {
|
||||||
|
// workaround for mismatched gradle wrapper and plugin version
|
||||||
|
val javaHome = try {
|
||||||
|
compilationConfiguration?.javaHome?.let { VfsUtil.findFileByIoFile(it, true) }
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
null
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
|
return getAllProjectSdks().find { it.homeDirectory == javaHome }
|
||||||
}
|
}
|
||||||
|
|
||||||
val allSdks by ClearableLazyValue(cacheLock) {
|
val allSdks by ClearableLazyValue(cacheLock) {
|
||||||
scriptDependenciesCache.getAll()
|
scriptDependenciesCache.getAll()
|
||||||
.mapNotNull { ScriptDependenciesManager.getInstance(project).getScriptSdk(it.key, project) }
|
.mapNotNull { getScriptSdk(it.key) }
|
||||||
.distinct()
|
.distinct()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val allNonIndexedSdks by ClearableLazyValue(cacheLock) {
|
private val allNonIndexedSdks by ClearableLazyValue(cacheLock) {
|
||||||
scriptDependenciesCache.getAll()
|
scriptDependenciesCache.getAll()
|
||||||
.mapNotNull { ScriptDependenciesManager.getInstance(project).getScriptSdk(it.key, project) }
|
.mapNotNull { getScriptSdk(it.key) }
|
||||||
.filterNonModuleSdk()
|
.filterNonModuleSdk()
|
||||||
.distinct()
|
.distinct()
|
||||||
}
|
}
|
||||||
@@ -164,7 +202,7 @@ class ScriptsCompilationConfigurationCache(private val project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun hasNotCachedRoots(compilationConfiguration: ScriptCompilationConfigurationWrapper): Boolean {
|
fun hasNotCachedRoots(compilationConfiguration: ScriptCompilationConfigurationWrapper): Boolean {
|
||||||
val scriptSdk = ScriptDependenciesManager.getScriptSdk(compilationConfiguration) ?: ScriptDependenciesManager.getScriptDefaultSdk(project)
|
val scriptSdk = getScriptSdk(compilationConfiguration) ?: ScriptDependenciesManager.getScriptDefaultSdk(project)
|
||||||
return (scriptSdk != null && !allSdks.contains(scriptSdk)) ||
|
return (scriptSdk != null && !allSdks.contains(scriptSdk)) ||
|
||||||
!allDependenciesClassFiles.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesClassPath)) ||
|
!allDependenciesClassFiles.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesClassPath)) ||
|
||||||
!allDependenciesSources.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesSources))
|
!allDependenciesSources.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesSources))
|
||||||
@@ -176,23 +214,23 @@ class ScriptsCompilationConfigurationCache(private val project: Project) {
|
|||||||
scriptDependenciesCache.clear()
|
scriptDependenciesCache.clear()
|
||||||
scriptsModificationStampsCache.clear()
|
scriptsModificationStampsCache.clear()
|
||||||
|
|
||||||
onChange(keys)
|
updateHighlighting(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save(virtualFile: VirtualFile, new: ScriptCompilationConfigurationResult): Boolean {
|
fun save(file: VirtualFile, new: ScriptCompilationConfigurationResult): Boolean {
|
||||||
val old = scriptDependenciesCache.replace(virtualFile, new)
|
val old = scriptDependenciesCache.replace(file, new)
|
||||||
val changed = new != old
|
val changed = new != old
|
||||||
if (changed) {
|
if (changed) {
|
||||||
onChange(listOf(virtualFile))
|
onChange(listOf(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(virtualFile: VirtualFile): Boolean {
|
fun delete(file: VirtualFile): Boolean {
|
||||||
val changed = scriptDependenciesCache.remove(virtualFile)
|
val changed = scriptDependenciesCache.remove(file)
|
||||||
if (changed) {
|
if (changed) {
|
||||||
onChange(listOf(virtualFile))
|
onChange(listOf(file))
|
||||||
}
|
}
|
||||||
return changed
|
return changed
|
||||||
}
|
}
|
||||||
@@ -226,20 +264,19 @@ private class ClearableLazyValue<in R, out T : Any>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SLRUCacheWithLock<K, V> {
|
||||||
private class SLRUCacheWithLock<T> {
|
|
||||||
private val lock = ReentrantReadWriteLock()
|
private val lock = ReentrantReadWriteLock()
|
||||||
|
|
||||||
val cache = SLRUMap<VirtualFile, T>(
|
val cache = SLRUMap<K, V>(
|
||||||
ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED,
|
ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED,
|
||||||
ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED
|
ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED
|
||||||
)
|
)
|
||||||
|
|
||||||
fun get(value: VirtualFile): T? = lock.write {
|
fun get(value: K): V? = lock.write {
|
||||||
cache[value]
|
cache[value]
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrPut(key: VirtualFile, defaultValue: () -> T): T = lock.write {
|
fun getOrPut(key: K, defaultValue: () -> V): V = lock.write {
|
||||||
val value = cache.get(key)
|
val value = cache.get(key)
|
||||||
return if (value == null) {
|
return if (value == null) {
|
||||||
val answer = defaultValue()
|
val answer = defaultValue()
|
||||||
@@ -250,11 +287,11 @@ private class SLRUCacheWithLock<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remove(file: VirtualFile) = lock.write {
|
fun remove(file: K) = lock.write {
|
||||||
cache.remove(file)
|
cache.remove(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAll(): Collection<Map.Entry<VirtualFile, T>> = lock.write {
|
fun getAll(): Collection<Map.Entry<K, V>> = lock.write {
|
||||||
cache.entrySet()
|
cache.entrySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,10 +299,9 @@ private class SLRUCacheWithLock<T> {
|
|||||||
cache.clear()
|
cache.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun replace(file: VirtualFile, value: T): T? = lock.write {
|
fun replace(file: K, value: V): V? = lock.write {
|
||||||
val old = get(file)
|
val old = get(file)
|
||||||
cache.put(file, value)
|
cache.put(file, value)
|
||||||
old
|
old
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-36
@@ -39,13 +39,9 @@ import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependencies
|
|||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
||||||
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.isNonScript
|
import org.jetbrains.kotlin.scripting.definitions.isNonScript
|
||||||
import org.jetbrains.kotlin.scripting.resolve.LegacyResolverWrapper
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
|
||||||
|
|
||||||
class ScriptsCompilationConfigurationUpdater(
|
class ScriptsCompilationConfigurationUpdater(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
@@ -65,8 +61,10 @@ class ScriptsCompilationConfigurationUpdater(
|
|||||||
listenForChangesInScripts()
|
listenForChangesInScripts()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentCompilationConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? {
|
fun getCurrentCompilationConfiguration(file: KtFile): ScriptCompilationConfigurationResult? {
|
||||||
cache[file]?.let { return it }
|
val virtualFile = file.originalFile.virtualFile
|
||||||
|
|
||||||
|
cache[virtualFile]?.let { return it }
|
||||||
|
|
||||||
// Try-catch block is a temporary workaround for ProcessCanceledException
|
// Try-catch block is a temporary workaround for ProcessCanceledException
|
||||||
// that may happen during VirtualFile to PsiFile transformation
|
// that may happen during VirtualFile to PsiFile transformation
|
||||||
@@ -76,10 +74,10 @@ class ScriptsCompilationConfigurationUpdater(
|
|||||||
makeRootsChangeIfNeeded()
|
makeRootsChangeIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache[file]
|
return cache[virtualFile]
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateDependenciesIfNeeded(files: List<VirtualFile>): Boolean {
|
fun updateDependenciesIfNeeded(files: List<KtFile>): Boolean {
|
||||||
if (!ScriptDefinitionsManager.getInstance(project).isReady()) return false
|
if (!ScriptDefinitionsManager.getInstance(project).isReady()) return false
|
||||||
|
|
||||||
var wasDependenciesUpdateStarted = false
|
var wasDependenciesUpdateStarted = false
|
||||||
@@ -97,11 +95,11 @@ class ScriptsCompilationConfigurationUpdater(
|
|||||||
return wasDependenciesUpdateStarted
|
return wasDependenciesUpdateStarted
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDependencies(file: VirtualFile) {
|
private fun updateDependencies(file: KtFile) {
|
||||||
if (!ScriptDefinitionsManager.getInstance(project).isReady()) return
|
if (!ScriptDefinitionsManager.getInstance(project).isReady()) return
|
||||||
if (!cache.shouldRunDependenciesUpdate(file)) return
|
if (!cache.shouldRunDependenciesUpdate(file)) return
|
||||||
|
|
||||||
val scriptDefinition = file.findScriptDefinition(project) ?: return
|
val scriptDefinition = file.findScriptDefinition() ?: return
|
||||||
loaders.filter { it.isApplicable(file, scriptDefinition) }.forEach { it.loadDependencies(file, scriptDefinition) }
|
loaders.filter { it.isApplicable(file, scriptDefinition) }.forEach { it.loadDependencies(file, scriptDefinition) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,24 +120,18 @@ class ScriptsCompilationConfigurationUpdater(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun runScriptDependenciesUpdateIfNeeded(file: VirtualFile) {
|
private fun runScriptDependenciesUpdateIfNeeded(file: VirtualFile) {
|
||||||
if (!shouldStartUpdate(file)) return
|
val ktFile = getKtFileToStartConfigurationUpdate(file) ?: return
|
||||||
|
|
||||||
updateDependencies(file)
|
updateDependencies(ktFile)
|
||||||
makeRootsChangeIfNeeded()
|
makeRootsChangeIfNeeded()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
EditorFactory.getInstance().eventMulticaster.addDocumentListener(object : DocumentListener {
|
EditorFactory.getInstance().eventMulticaster.addDocumentListener(object : DocumentListener {
|
||||||
override fun documentChanged(event: DocumentEvent) {
|
override fun documentChanged(event: DocumentEvent) {
|
||||||
|
|
||||||
val document = event.document
|
val document = event.document
|
||||||
val file = FileDocumentManager.getInstance().getFile(document)?.takeIf { it.isInLocalFileSystem } ?: return
|
val file = FileDocumentManager.getInstance().getFile(document)?.takeIf { it.isInLocalFileSystem } ?: return
|
||||||
if (!file.isValid) {
|
val ktFile = getKtFileToStartConfigurationUpdate(file) ?: return
|
||||||
cache.delete(file)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shouldStartUpdate(file)) return
|
|
||||||
|
|
||||||
// only update dependencies for scripts that were touched recently
|
// only update dependencies for scripts that were touched recently
|
||||||
if (cache[file] == null) {
|
if (cache[file] == null) {
|
||||||
@@ -151,7 +143,7 @@ class ScriptsCompilationConfigurationUpdater(
|
|||||||
scriptsQueue.addRequest(
|
scriptsQueue.addRequest(
|
||||||
{
|
{
|
||||||
FileDocumentManager.getInstance().saveDocument(document)
|
FileDocumentManager.getInstance().saveDocument(document)
|
||||||
updateDependencies(file)
|
updateDependencies(ktFile)
|
||||||
makeRootsChangeIfNeeded()
|
makeRootsChangeIfNeeded()
|
||||||
},
|
},
|
||||||
scriptChangesListenerDelay,
|
scriptChangesListenerDelay,
|
||||||
@@ -161,31 +153,30 @@ class ScriptsCompilationConfigurationUpdater(
|
|||||||
}, project.messageBus.connect())
|
}, project.messageBus.connect())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldStartUpdate(file: VirtualFile): Boolean {
|
private fun getKtFileToStartConfigurationUpdate(file: VirtualFile): KtFile? {
|
||||||
if (project.isDisposed || !file.isValid || file.isNonScript()) {
|
if (project.isDisposed || !file.isValid || file.isNonScript()) {
|
||||||
return false
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ApplicationManager.getApplication().isUnitTestMode &&
|
ApplicationManager.getApplication().isUnitTestMode &&
|
||||||
ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled == true
|
ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled == true
|
||||||
) {
|
) {
|
||||||
return false
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return false
|
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null
|
||||||
return ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)
|
if (ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)) {
|
||||||
|
return ktFile
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areDependenciesCached(file: VirtualFile): Boolean {
|
private fun areDependenciesCached(file: VirtualFile): Boolean {
|
||||||
return cache[file] != null || file.scriptDependencies != null
|
return cache[file] != null || file.scriptDependencies != null || file.scriptCompilationConfiguration != null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isAsyncDependencyResolver(scriptDef: ScriptDefinition): Boolean =
|
|
||||||
scriptDef.asLegacyOrNull<KotlinScriptDefinition>()?.dependencyResolver?.let {
|
|
||||||
it is AsyncDependenciesResolver || it is LegacyResolverWrapper
|
|
||||||
} ?: false
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getInstance(project: Project): ScriptsCompilationConfigurationUpdater =
|
fun getInstance(project: Project): ScriptsCompilationConfigurationUpdater =
|
||||||
@@ -194,11 +185,6 @@ class ScriptsCompilationConfigurationUpdater(
|
|||||||
fun areDependenciesCached(file: KtFile): Boolean {
|
fun areDependenciesCached(file: KtFile): Boolean {
|
||||||
return getInstance(file.project).areDependenciesCached(file.virtualFile)
|
return getInstance(file.project).areDependenciesCached(file.virtualFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isAsyncDependencyResolver(file: KtFile): Boolean {
|
|
||||||
val scriptDefinition = file.virtualFile.findScriptDefinition(file.project) ?: return false
|
|
||||||
return getInstance(file.project).isAsyncDependencyResolver(scriptDefinition)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-13
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,13 +10,12 @@ import com.intellij.openapi.progress.ProgressIndicator
|
|||||||
import com.intellij.openapi.progress.Task
|
import com.intellij.openapi.progress.Task
|
||||||
import com.intellij.openapi.progress.util.BackgroundTaskUtil
|
import com.intellij.openapi.progress.util.BackgroundTaskUtil
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import kotlinx.coroutines.Runnable
|
import kotlinx.coroutines.Runnable
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource
|
||||||
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
@@ -30,14 +29,14 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr
|
|||||||
private var backgroundTasksQueue: LoaderBackgroundTask? = null
|
private var backgroundTasksQueue: LoaderBackgroundTask? = null
|
||||||
|
|
||||||
override fun isApplicable(
|
override fun isApplicable(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
|
return isAsyncDependencyResolver(scriptDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDependencies(
|
override fun loadDependencies(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
) {
|
) {
|
||||||
lock.write {
|
lock.write {
|
||||||
@@ -74,20 +73,20 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runDependenciesUpdate(file: VirtualFile) {
|
private fun runDependenciesUpdate(file: KtFile) {
|
||||||
val scriptDef = file.findScriptDefinition(project) ?: return
|
val scriptDef = file.findScriptDefinition() ?: return
|
||||||
|
|
||||||
debug(file) { "start async dependencies loading" }
|
debug(file) { "start async dependencies loading" }
|
||||||
|
|
||||||
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDef, project)
|
val result = refineScriptCompilationConfiguration(KtFileScriptSource(file), scriptDef, project)
|
||||||
|
|
||||||
debug(file) { "finish async dependencies loading" }
|
debug(file) { "finish async dependencies loading" }
|
||||||
|
|
||||||
processRefinedConfiguration(result, file)
|
processRefinedConfiguration(result, file.originalFile.virtualFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class LoaderBackgroundTask {
|
private inner class LoaderBackgroundTask {
|
||||||
private val sequenceOfFiles: ConcurrentLinkedQueue<VirtualFile> = ConcurrentLinkedQueue()
|
private val sequenceOfFiles: ConcurrentLinkedQueue<KtFile> = ConcurrentLinkedQueue()
|
||||||
private var forceStop : Boolean = false
|
private var forceStop : Boolean = false
|
||||||
private var startedSilently : Boolean = false
|
private var startedSilently : Boolean = false
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr
|
|||||||
}.queue()
|
}.queue()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addTask(file: VirtualFile) {
|
fun addTask(file: KtFile) {
|
||||||
if (sequenceOfFiles.contains(file)) return
|
if (sequenceOfFiles.contains(file)) return
|
||||||
|
|
||||||
debug(file) { "added to update queue" }
|
debug(file) { "added to update queue" }
|
||||||
|
|||||||
+15
-13
@@ -9,39 +9,41 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.scriptCompilationConfiguration
|
import org.jetbrains.kotlin.idea.core.script.scriptCompilationConfiguration
|
||||||
import org.jetbrains.kotlin.idea.core.script.scriptDependencies
|
import org.jetbrains.kotlin.idea.core.script.scriptDependencies
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
|
||||||
import kotlin.script.experimental.api.asSuccess
|
import kotlin.script.experimental.api.asSuccess
|
||||||
|
|
||||||
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
||||||
class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
||||||
|
|
||||||
override fun isApplicable(
|
override fun isApplicable(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return file.scriptDependencies != null || file.scriptCompilationConfiguration != null
|
return file.scriptDependencies != null || file.scriptCompilationConfiguration != null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDependencies(
|
override fun loadDependencies(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
) {
|
) {
|
||||||
file.scriptCompilationConfiguration?.let {
|
val virtualFile = file.originalFile.virtualFile
|
||||||
ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(VirtualFileScriptSource(file), it).apply {
|
virtualFile.scriptCompilationConfiguration?.let {
|
||||||
debug(file) { "refined configuration from fileAttributes = $it" }
|
ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(KtFileScriptSource(file), it).apply {
|
||||||
|
debug(virtualFile) { "refined configuration from fileAttributes = $it" }
|
||||||
}
|
}
|
||||||
} ?: file.scriptDependencies?.let {
|
} ?: virtualFile.scriptDependencies?.let {
|
||||||
ScriptCompilationConfigurationWrapper.FromLegacy(VirtualFileScriptSource(file), it, scriptDefinition).apply {
|
ScriptCompilationConfigurationWrapper.FromLegacy(KtFileScriptSource(file), it, scriptDefinition).apply {
|
||||||
debug(file) { "dependencies from fileAttributes = $it" }
|
debug(virtualFile) { "dependencies from fileAttributes = $it" }
|
||||||
}
|
}
|
||||||
}?.let {
|
}?.let {
|
||||||
if (areDependenciesValid(file, it)) {
|
if (areDependenciesValid(virtualFile, it)) {
|
||||||
saveToCache(file, it.asSuccess(), skipSaveToAttributes = true)
|
saveToCache(virtualFile, it.asSuccess(), skipSaveToAttributes = true)
|
||||||
} else {
|
} else {
|
||||||
file.scriptCompilationConfiguration = null
|
virtualFile.scriptCompilationConfiguration = null
|
||||||
file.scriptDependencies = null
|
virtualFile.scriptDependencies = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -18,10 +18,13 @@ package org.jetbrains.kotlin.idea.core.script.dependencies
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.ResolveScopeProvider
|
import com.intellij.psi.ResolveScopeProvider
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
|
import org.jetbrains.kotlin.idea.core.script.StandardIdeScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
@@ -33,7 +36,10 @@ class KotlinScriptResolveScopeProvider : ResolveScopeProvider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getResolveScope(file: VirtualFile, project: Project): GlobalSearchScope? {
|
override fun getResolveScope(file: VirtualFile, project: Project): GlobalSearchScope? {
|
||||||
val scriptDefinition = file.findScriptDefinition(project)
|
if (file.fileType != KotlinFileType.INSTANCE) return null
|
||||||
|
|
||||||
|
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null
|
||||||
|
val scriptDefinition = ktFile.findScriptDefinition()
|
||||||
return when {
|
return when {
|
||||||
scriptDefinition == null -> null
|
scriptDefinition == null -> null
|
||||||
// This is a workaround for completion in scripts and REPL to provide module dependencies
|
// This is a workaround for completion in scripts and REPL to provide module dependencies
|
||||||
|
|||||||
+12
-7
@@ -6,27 +6,32 @@
|
|||||||
package org.jetbrains.kotlin.idea.core.script.dependencies
|
package org.jetbrains.kotlin.idea.core.script.dependencies
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.psi.PsiManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
||||||
import org.jetbrains.kotlin.idea.highlighter.OutsidersPsiFileSupportUtils
|
import org.jetbrains.kotlin.idea.highlighter.OutsidersPsiFileSupportUtils
|
||||||
import org.jetbrains.kotlin.idea.highlighter.OutsidersPsiFileSupportWrapper
|
import org.jetbrains.kotlin.idea.highlighter.OutsidersPsiFileSupportWrapper
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
|
||||||
class OutsiderFileDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
class OutsiderFileDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
||||||
override fun isApplicable(
|
override fun isApplicable(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return OutsidersPsiFileSupportWrapper.isOutsiderFile(file)
|
val virtualFile = file.virtualFile ?: return false
|
||||||
|
return OutsidersPsiFileSupportWrapper.isOutsiderFile(virtualFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDependencies(
|
override fun loadDependencies(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
) {
|
) {
|
||||||
val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, file) ?: return
|
val virtualFile = file.virtualFile ?: return
|
||||||
val compilationConfiguration = ScriptDependenciesManager.getInstance(project).getRefinedCompilationConfiguration(fileOrigin) ?: return
|
val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, virtualFile) ?: return
|
||||||
saveToCache(file, compilationConfiguration)
|
val psiFileOrigin = PsiManager.getInstance(project).findFile(fileOrigin) as? KtFile ?: return
|
||||||
|
val compilationConfiguration =
|
||||||
|
ScriptDependenciesManager.getInstance(project).getRefinedCompilationConfiguration(psiFileOrigin) ?: return
|
||||||
|
saveToCache(virtualFile, compilationConfiguration)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldShowNotification(): Boolean = false
|
override fun shouldShowNotification(): Boolean = false
|
||||||
|
|||||||
+23
-9
@@ -15,18 +15,22 @@ import com.intellij.openapi.util.EmptyRunnable
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.*
|
import org.jetbrains.kotlin.idea.core.script.*
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.LegacyResolverWrapper
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
import kotlin.script.experimental.api.valueOrNull
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
|
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
||||||
|
|
||||||
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
// TODO: rename and provide alias for compatibility - this is not only about dependencies anymore
|
||||||
abstract class ScriptDependenciesLoader(protected val project: Project) {
|
abstract class ScriptDependenciesLoader(protected val project: Project) {
|
||||||
|
|
||||||
abstract fun isApplicable(file: VirtualFile, scriptDefinition: ScriptDefinition): Boolean
|
abstract fun isApplicable(file: KtFile, scriptDefinition: ScriptDefinition): Boolean
|
||||||
abstract fun loadDependencies(file: VirtualFile, scriptDefinition: ScriptDefinition)
|
abstract fun loadDependencies(file: KtFile, scriptDefinition: ScriptDefinition)
|
||||||
|
|
||||||
protected abstract fun shouldShowNotification(): Boolean
|
protected abstract fun shouldShowNotification(): Boolean
|
||||||
|
|
||||||
@@ -138,13 +142,23 @@ abstract class ScriptDependenciesLoader(protected val project: Project) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
protected fun isAsyncDependencyResolver(scriptDef: ScriptDefinition): Boolean =
|
||||||
private val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.script")
|
scriptDef.asLegacyOrNull<KotlinScriptDefinition>()?.dependencyResolver?.let {
|
||||||
|
it is AsyncDependenciesResolver || it is LegacyResolverWrapper
|
||||||
|
} ?: false
|
||||||
|
|
||||||
internal fun debug(file: VirtualFile? = null, message: () -> String) {
|
}
|
||||||
if (LOG.isDebugEnabled) {
|
|
||||||
LOG.debug("[KOTLIN SCRIPT] " + (file?.let { "file = ${file.path}, " } ?: "") + message())
|
private val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.script")
|
||||||
}
|
|
||||||
}
|
internal fun debug(file: VirtualFile? = null, message: () -> String) {
|
||||||
|
if (LOG.isDebugEnabled) {
|
||||||
|
LOG.debug("[KOTLIN SCRIPT] ${file?.path} " + message())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun debug(file: KtFile, message: () -> String) {
|
||||||
|
if (LOG.isDebugEnabled) {
|
||||||
|
LOG.debug("[KOTLIN SCRIPT] ${file.originalFile.virtualFile?.path} " + message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-8
@@ -6,28 +6,27 @@
|
|||||||
package org.jetbrains.kotlin.idea.core.script.dependencies
|
package org.jetbrains.kotlin.idea.core.script.dependencies
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource
|
||||||
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
||||||
|
|
||||||
class SyncScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
class SyncScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) {
|
||||||
override fun isApplicable(
|
override fun isApplicable(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return !ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition)
|
return !isAsyncDependencyResolver(scriptDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadDependencies(
|
override fun loadDependencies(
|
||||||
file: VirtualFile,
|
file: KtFile,
|
||||||
scriptDefinition: ScriptDefinition
|
scriptDefinition: ScriptDefinition
|
||||||
) {
|
) {
|
||||||
debug(file) { "start sync dependencies loading" }
|
debug(file) { "start sync dependencies loading" }
|
||||||
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDefinition, project)
|
val result = refineScriptCompilationConfiguration(KtFileScriptSource(file), scriptDefinition, project)
|
||||||
debug(file) { "finish sync dependencies loading" }
|
debug(file) { "finish sync dependencies loading" }
|
||||||
processRefinedConfiguration(result, file)
|
processRefinedConfiguration(result, file.originalFile.virtualFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldShowNotification(): Boolean = false
|
override fun shouldShowNotification(): Boolean = false
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ class GradleBuildFileHighlightingTest : GradleImportingTestCase() {
|
|||||||
val psiFile = PsiManager.getInstance(myProject).findFile(file) as? KtFile
|
val psiFile = PsiManager.getInstance(myProject).findFile(file) as? KtFile
|
||||||
?: error("Couldn't find psiFile for virtual file: ${file.canonicalPath}")
|
?: error("Couldn't find psiFile for virtual file: ${file.canonicalPath}")
|
||||||
|
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(file, myProject)
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(psiFile, myProject)
|
||||||
|
|
||||||
val bindingContext = psiFile.analyzeWithContent()
|
val bindingContext = psiFile.analyzeWithContent()
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -166,7 +166,7 @@ class KtScratchExecutionSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScriptDependenciesManager.getInstance(originalFile.project)
|
ScriptDependenciesManager.getInstance(originalFile.project)
|
||||||
.getRefinedCompilationConfiguration(originalFile.virtualFile)?.valueOrNull()?.let {
|
.getRefinedCompilationConfiguration(originalFile)?.valueOrNull()?.let {
|
||||||
javaParameters.classPath.addAll(it.dependenciesClassPath.map { f -> f.absolutePath })
|
javaParameters.classPath.addAll(it.dependenciesClassPath.map { f -> f.absolutePath })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,8 +65,9 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
|
|||||||
val allDefaultImports = platform.findAnalyzerServices.getDefaultImports(languageVersionSettings, includeLowPriorityImports = true)
|
val allDefaultImports = platform.findAnalyzerServices.getDefaultImports(languageVersionSettings, includeLowPriorityImports = true)
|
||||||
|
|
||||||
val scriptExtraImports = contextFile.takeIf { it.isScript() }?.let { ktFile ->
|
val scriptExtraImports = contextFile.takeIf { it.isScript() }?.let { ktFile ->
|
||||||
val scriptDependencies =
|
val scriptDependencies = ScriptDependenciesProvider.getInstance(ktFile.project)
|
||||||
ScriptDependenciesProvider.getInstance(ktFile.project)?.getScriptConfigurationResult(ktFile.originalFile)?.valueOrNull()
|
?.getScriptConfigurationResult(ktFile.originalFile as KtFile)
|
||||||
|
?.valueOrNull()
|
||||||
scriptDependencies?.defaultImports?.map { ImportPath.fromString(it) }
|
scriptDependencies?.defaultImports?.map { ImportPath.fromString(it) }
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
|
|
||||||
|
|||||||
+5
-6
@@ -12,10 +12,7 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.psi.PsiComment
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import com.intellij.psi.PsiJavaFile
|
|
||||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||||
import com.intellij.psi.codeStyle.VariableKind
|
import com.intellij.psi.codeStyle.VariableKind
|
||||||
import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException
|
import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException
|
||||||
@@ -32,8 +29,8 @@ import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
|||||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
||||||
|
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
|
||||||
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
|
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
|
||||||
import org.jetbrains.kotlin.idea.refactoring.chooseMembers
|
import org.jetbrains.kotlin.idea.refactoring.chooseMembers
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractClass.ExtractSuperInfo
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractClass.ExtractSuperInfo
|
||||||
@@ -325,7 +322,9 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase()
|
|||||||
PluginTestCaseBase.addJdk(myFixture.projectDisposable, PluginTestCaseBase::mockJdk)
|
PluginTestCaseBase.addJdk(myFixture.projectDisposable, PluginTestCaseBase::mockJdk)
|
||||||
|
|
||||||
if (mainFile.extension == KotlinParserDefinition.STD_SCRIPT_SUFFIX) {
|
if (mainFile.extension == KotlinParserDefinition.STD_SCRIPT_SUFFIX) {
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(VfsUtil.findFileByIoFile(mainFile, true)!!, project)
|
val virtualFile = VfsUtil.findFileByIoFile(mainFile, true)!!
|
||||||
|
val ktFile = PsiManager.getInstance(project).findFile(virtualFile)!!
|
||||||
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(ktFile, project)
|
||||||
}
|
}
|
||||||
|
|
||||||
fixture.testDataPath = "${KotlinTestUtils.getHomeDirectory()}/${mainFile.parent}"
|
fixture.testDataPath = "${KotlinTestUtils.getHomeDirectory()}/${mainFile.parent}"
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class StandaloneScriptRunConfigurationTest : KotlinCodeInsightTestCase() {
|
|||||||
fun testOnFileMoveWithDefaultWorkingDir() {
|
fun testOnFileMoveWithDefaultWorkingDir() {
|
||||||
configureByFile("move/script.kts")
|
configureByFile("move/script.kts")
|
||||||
|
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFile.virtualFile, project)
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFile, project)
|
||||||
|
|
||||||
val script = KotlinScriptFqnIndex.instance.get("foo.Script", project, project.allScope()).single()
|
val script = KotlinScriptFqnIndex.instance.get("foo.Script", project, project.allScope()).single()
|
||||||
val runConfiguration = createConfigurationFromElement(script, save = true) as KotlinStandaloneScriptRunConfiguration
|
val runConfiguration = createConfigurationFromElement(script, save = true) as KotlinStandaloneScriptRunConfiguration
|
||||||
@@ -98,7 +98,7 @@ class StandaloneScriptRunConfigurationTest : KotlinCodeInsightTestCase() {
|
|||||||
fun testOnFileMoveWithNonDefaultWorkingDir() {
|
fun testOnFileMoveWithNonDefaultWorkingDir() {
|
||||||
configureByFile("move/script.kts")
|
configureByFile("move/script.kts")
|
||||||
|
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFile.virtualFile, project)
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFile, project)
|
||||||
|
|
||||||
val script = KotlinScriptFqnIndex.instance.get("foo.Script", project, project.allScope()).single()
|
val script = KotlinScriptFqnIndex.instance.get("foo.Script", project, project.allScope()).single()
|
||||||
val runConfiguration = createConfigurationFromElement(script, save = true) as KotlinStandaloneScriptRunConfiguration
|
val runConfiguration = createConfigurationFromElement(script, save = true) as KotlinStandaloneScriptRunConfiguration
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
|
|||||||
|
|
||||||
myFixture.openFileInEditor(scratchVirtualFile)
|
myFixture.openFileInEditor(scratchVirtualFile)
|
||||||
|
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(scratchVirtualFile, project)
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFixture.file, project)
|
||||||
|
|
||||||
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
|
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
|
||||||
?: error("Couldn't find scratch file")
|
?: error("Couldn't find scratch file")
|
||||||
@@ -217,7 +217,7 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
|
|||||||
protected fun configureWorksheetByText(name: String, text: String): ScratchFile {
|
protected fun configureWorksheetByText(name: String, text: String): ScratchFile {
|
||||||
val worksheetFile = myFixture.configureByText(name, text).virtualFile
|
val worksheetFile = myFixture.configureByText(name, text).virtualFile
|
||||||
|
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(worksheetFile, project)
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFixture.file, project)
|
||||||
|
|
||||||
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
|
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
|
||||||
?: error("Couldn't find scratch panel")
|
?: error("Couldn't find scratch panel")
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() {
|
|||||||
|
|
||||||
myFixture.openFileInEditor(scratchVirtualFile)
|
myFixture.openFileInEditor(scratchVirtualFile)
|
||||||
|
|
||||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(scratchVirtualFile, project)
|
ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFixture.file, project)
|
||||||
|
|
||||||
val scratchFileEditor = getScratchEditorForSelectedFile(FileEditorManager.getInstance(project), myFixture.file.virtualFile)
|
val scratchFileEditor = getScratchEditorForSelectedFile(FileEditorManager.getInstance(project), myFixture.file.virtualFile)
|
||||||
?: error("Couldn't find scratch panel")
|
?: error("Couldn't find scratch panel")
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingUtil
|
|||||||
import org.jetbrains.kotlin.idea.navigation.GotoCheck
|
import org.jetbrains.kotlin.idea.navigation.GotoCheck
|
||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.MockLibraryUtil
|
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||||
@@ -78,7 +79,7 @@ abstract class AbstractScriptConfigurationHighlightingTest : AbstractScriptConfi
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
updateScriptDependenciesSynchronously(myFile.virtualFile, project)
|
updateScriptDependenciesSynchronously(myFile, project)
|
||||||
checkHighlighting(editor, false, false)
|
checkHighlighting(editor, false, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +135,7 @@ abstract class AbstractScriptDefinitionsOrderTest : AbstractScriptConfigurationT
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScriptDefinitionsManager.getInstance(project).reorderScriptDefinitions()
|
ScriptDefinitionsManager.getInstance(project).reorderScriptDefinitions()
|
||||||
updateScriptDependenciesSynchronously(myFile.virtualFile, project)
|
updateScriptDependenciesSynchronously(myFile, project)
|
||||||
|
|
||||||
checkHighlighting(editor, false, false)
|
checkHighlighting(editor, false, false)
|
||||||
}
|
}
|
||||||
@@ -345,13 +346,13 @@ abstract class AbstractScriptConfigurationTest : KotlinCompletionTestCase() {
|
|||||||
if (script == null) error("Test file with script couldn't be found in test project")
|
if (script == null) error("Test file with script couldn't be found in test project")
|
||||||
|
|
||||||
configureByExistingFile(script)
|
configureByExistingFile(script)
|
||||||
updateScriptDependenciesSynchronously(script, project)
|
updateScriptDependenciesSynchronously(myFile, project)
|
||||||
|
|
||||||
VfsUtil.markDirtyAndRefresh(false, true, true, project.baseDir)
|
VfsUtil.markDirtyAndRefresh(false, true, true, project.baseDir)
|
||||||
// This is needed because updateScriptDependencies invalidates psiFile that was stored in myFile field
|
// This is needed because updateScriptDependencies invalidates psiFile that was stored in myFile field
|
||||||
myFile = psiManager.findFile(script)
|
myFile = psiManager.findFile(script)
|
||||||
|
|
||||||
val isFatalErrorPresent = IdeScriptReportSink.getReports(script).any { it.severity == ScriptDiagnostic.Severity.FATAL }
|
val isFatalErrorPresent = IdeScriptReportSink.getReports(myFile as KtFile).any { it.severity == ScriptDiagnostic.Severity.FATAL }
|
||||||
assert(isFatalErrorPresent || KotlinHighlightingUtil.shouldHighlight(myFile)) {
|
assert(isFatalErrorPresent || KotlinHighlightingUtil.shouldHighlight(myFile)) {
|
||||||
"Highlighting is switched off for ${myFile.virtualFile.path}"
|
"Highlighting is switched off for ${myFile.virtualFile.path}"
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-9
@@ -9,24 +9,29 @@ import com.intellij.openapi.components.ServiceManager
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import kotlin.script.experimental.api.valueOrNull
|
import kotlin.script.experimental.api.valueOrNull
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
|
||||||
interface ScriptDependenciesProvider {
|
open class ScriptDependenciesProvider constructor(
|
||||||
|
protected val project: Project
|
||||||
|
) {
|
||||||
|
|
||||||
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
||||||
fun getScriptDependencies(file: VirtualFile): ScriptDependencies? =
|
fun getScriptDependencies(file: VirtualFile): ScriptDependencies? {
|
||||||
getScriptConfigurationResult(file)?.valueOrNull()?.legacyDependencies
|
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null
|
||||||
|
return getScriptConfigurationResult(ktFile)?.valueOrNull()?.legacyDependencies
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
@Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR)
|
||||||
fun getScriptDependencies(file: PsiFile): ScriptDependencies? =
|
fun getScriptDependencies(file: PsiFile): ScriptDependencies? {
|
||||||
getScriptConfigurationResult(file.virtualFile ?: file.originalFile.virtualFile)?.valueOrNull()?.legacyDependencies
|
if (file !is KtFile) return null
|
||||||
|
return getScriptConfigurationResult(file)?.valueOrNull()?.legacyDependencies
|
||||||
|
}
|
||||||
|
|
||||||
fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = null
|
open fun getScriptConfigurationResult(file: KtFile): ScriptCompilationConfigurationResult? = null
|
||||||
|
|
||||||
fun getScriptConfigurationResult(file: PsiFile): ScriptCompilationConfigurationResult? =
|
|
||||||
getScriptConfigurationResult(file.virtualFile ?: file.originalFile.virtualFile)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(project: Project): ScriptDependenciesProvider? =
|
fun getInstance(project: Project): ScriptDependenciesProvider? =
|
||||||
|
|||||||
+6
-4
@@ -25,18 +25,20 @@ inline fun <T> runReadAction(crossinline runnable: () -> T): T {
|
|||||||
fun PsiFile.findScriptDefinition(): ScriptDefinition? {
|
fun PsiFile.findScriptDefinition(): ScriptDefinition? {
|
||||||
// Do not use psiFile.script, see comments in findScriptDefinition
|
// Do not use psiFile.script, see comments in findScriptDefinition
|
||||||
if (this !is KtFile/* || this.script == null*/) return null
|
if (this !is KtFile/* || this.script == null*/) return null
|
||||||
val file = virtualFile ?: originalFile.virtualFile ?: return null
|
|
||||||
if (file.isNonScript()) return null
|
|
||||||
|
|
||||||
return findScriptDefinitionByFilePath(project, File(file.path))
|
val virtualFile = this.virtualFile ?: this.originalFile.virtualFile ?: return null
|
||||||
|
if (virtualFile.isNonScript()) return null
|
||||||
|
|
||||||
|
return findScriptDefinitionByFilePath(project, File(virtualFile.path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use PsiFile.findScriptDefinition() instead")
|
||||||
fun VirtualFile.findScriptDefinition(project: Project): ScriptDefinition? {
|
fun VirtualFile.findScriptDefinition(project: Project): ScriptDefinition? {
|
||||||
if (!isValid || isNonScript()) return null
|
if (!isValid || isNonScript()) return null
|
||||||
|
|
||||||
// Do not use psiFile.script here because this method can be called during indexes access
|
// Do not use psiFile.script here because this method can be called during indexes access
|
||||||
// and accessing stubs may cause deadlock
|
// and accessing stubs may cause deadlock
|
||||||
// TODO: measure performance effect and if necessary consider detecting indexing here or using separate logic for non-IDE operations to speed up filtering
|
// TODO: measure performance effect and if necessary consider detecting indexing here or using separate logic for non-IDE operations to speed up filtering
|
||||||
|
|
||||||
if (runReadAction { PsiManager.getInstance(project).findFile(this) as? KtFile }/*?.script*/ == null) return null
|
if (runReadAction { PsiManager.getInstance(project).findFile(this) as? KtFile }/*?.script*/ == null) return null
|
||||||
|
|
||||||
return findScriptDefinitionByFilePath(project, File(path))
|
return findScriptDefinitionByFilePath(project, File(path))
|
||||||
|
|||||||
-12
@@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripting.definitions
|
package org.jetbrains.kotlin.scripting.definitions
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
@@ -27,16 +25,6 @@ fun PsiFile.findScriptCompilationConfiguration(): ScriptCompilationConfiguration
|
|||||||
?: findScriptDefinition()?.compilationConfiguration
|
?: findScriptDefinition()?.compilationConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VirtualFile.findScriptCompilationConfiguration(project: Project): ScriptCompilationConfiguration? {
|
|
||||||
if (!isValid || isNonScript()) return null
|
|
||||||
// see comments in findScriptDefinition
|
|
||||||
// we do not need expensive check as in findScriptDefinition here, since it is assumed that this function is called only for known scripts
|
|
||||||
|
|
||||||
val provider = ScriptDependenciesProvider.getInstance(project)
|
|
||||||
return provider?.getScriptConfigurationResult(this)?.valueOrError()?.configuration
|
|
||||||
?: findScriptDefinition(project)?.compilationConfiguration
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ScriptCompilationConfigurationResult.valueOrError() = valueOr { failure ->
|
private fun ScriptCompilationConfigurationResult.valueOrError() = valueOr { failure ->
|
||||||
val singleCause = failure.reports.singleOrNull { it.severity == ScriptDiagnostic.Severity.ERROR }
|
val singleCause = failure.reports.singleOrNull { it.severity == ScriptDiagnostic.Severity.ERROR }
|
||||||
if (singleCause != null)
|
if (singleCause != null)
|
||||||
|
|||||||
+3
-1
@@ -29,7 +29,9 @@ class ScriptExtraImportsProviderExtension : ExtraImportsProviderExtension {
|
|||||||
|
|
||||||
override fun getExtraImports(ktFile: KtFile): Collection<KtImportInfo> =
|
override fun getExtraImports(ktFile: KtFile): Collection<KtImportInfo> =
|
||||||
ktFile.takeIf { it.isScript() }?.let { file ->
|
ktFile.takeIf { it.isScript() }?.let { file ->
|
||||||
val refinedConfiguration = ScriptDependenciesProvider.getInstance(file.project)?.getScriptConfigurationResult(file.originalFile)?.valueOrNull()
|
val refinedConfiguration = ScriptDependenciesProvider.getInstance(file.project)
|
||||||
|
?.getScriptConfigurationResult(file.originalFile as KtFile)
|
||||||
|
?.valueOrNull()
|
||||||
refinedConfiguration?.defaultImports?.map {
|
refinedConfiguration?.defaultImports?.map {
|
||||||
ScriptExtraImportImpl(
|
ScriptExtraImportImpl(
|
||||||
ImportPath.fromString(it)
|
ImportPath.fromString(it)
|
||||||
|
|||||||
+9
-10
@@ -8,38 +8,37 @@ package org.jetbrains.kotlin.scripting.compiler.plugin.definitions
|
|||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||||
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import kotlin.concurrent.read
|
import kotlin.concurrent.read
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
import kotlin.script.experimental.jvm.compat.mapToLegacyReports
|
|
||||||
|
|
||||||
class CliScriptDependenciesProvider(private val project: Project) : ScriptDependenciesProvider {
|
class CliScriptDependenciesProvider(project: Project) : ScriptDependenciesProvider(project) {
|
||||||
private val cacheLock = ReentrantReadWriteLock()
|
private val cacheLock = ReentrantReadWriteLock()
|
||||||
private val cache = hashMapOf<String, ScriptCompilationConfigurationResult?>()
|
private val cache = hashMapOf<String, ScriptCompilationConfigurationResult?>()
|
||||||
|
|
||||||
override fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = cacheLock.read {
|
override fun getScriptConfigurationResult(file: KtFile): ScriptCompilationConfigurationResult? = cacheLock.read {
|
||||||
calculateRefinedConfiguration(file)
|
calculateRefinedConfiguration(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateRefinedConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? {
|
private fun calculateRefinedConfiguration(file: KtFile): ScriptCompilationConfigurationResult? {
|
||||||
val path = file.path
|
val path = file.virtualFilePath
|
||||||
val cached = cache[path]
|
val cached = cache[path]
|
||||||
return if (cached != null) cached
|
return if (cached != null) cached
|
||||||
else {
|
else {
|
||||||
val scriptDef = file.findScriptDefinition(project)
|
val scriptDef = file.findScriptDefinition()
|
||||||
if (scriptDef != null) {
|
if (scriptDef != null) {
|
||||||
val result = refineScriptCompilationConfiguration(VirtualFileScriptSource(file), scriptDef, project)
|
val result = refineScriptCompilationConfiguration(KtFileScriptSource(file), scriptDef, project)
|
||||||
|
|
||||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file.virtualFile, result.reports)
|
||||||
|
|
||||||
if (result is ResultWithDiagnostics.Success) {
|
if (result is ResultWithDiagnostics.Success) {
|
||||||
log.info("[kts] new cached deps for $path: ${result.value.dependenciesClassPath.joinToString(File.pathSeparator)}")
|
log.info("[kts] new cached deps for $path: ${result.value.dependenciesClassPath.joinToString(File.pathSeparator)}")
|
||||||
|
|||||||
Reference in New Issue
Block a user