From dc46f73ecf84f1a71d0856c4fd5d9d89e6019059 Mon Sep 17 00:00:00 2001 From: Natalia Selezneva Date: Thu, 8 Aug 2019 13:47:39 +0300 Subject: [PATCH] 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 --- .../idea/caches/project/ScriptModuleInfos.kt | 2 +- .../highlighter/KotlinHighlightingUtil.kt | 2 +- .../ScriptExternalHighlightingPass.kt | 2 +- .../kotlin/idea/search/searchUtil.kt | 8 +- .../idea/core/script/IdeScriptReportSink.kt | 5 + .../script/ScriptDependenciesFileAttribute.kt | 14 +++ .../core/script/ScriptDependenciesManager.kt | 56 +++++----- .../ScriptNewDependenciesNotification.kt | 8 +- .../ScriptsCompilationConfigurationCache.kt | 100 ++++++++++++------ .../ScriptsCompilationConfigurationUpdater.kt | 58 ++++------ .../AsyncScriptDependenciesLoader.kt | 25 +++-- ...omFileAttributeScriptDependenciesLoader.kt | 28 ++--- .../KotlinScriptResolveScopeProvider.kt | 8 +- .../OutsiderFileDependenciesLoader.kt | 19 ++-- .../ScriptConfigurationFileAttributeCache.kt | 0 .../dependencies/ScriptDependenciesLoader.kt | 32 ++++-- .../SyncScriptDependenciesLoader.kt | 15 ++- .../gradle/GradleBuildFileHighlightingTest.kt | 2 +- .../compile/KtScratchExecutionSession.kt | 2 +- .../idea/util/ImportInsertHelperImpl.kt | 5 +- .../introduce/AbstractExtractionTest.kt | 11 +- .../StandaloneScriptRunConfigurationTest.kt | 4 +- .../scratch/AbstractScratchRunActionTest.kt | 4 +- .../idea/scratch/ScratchLineMarkersTest.kt | 2 +- .../script/AbstractScriptConfigurationTest.kt | 9 +- .../definitions/ScriptDependenciesProvider.kt | 23 ++-- .../scripting/definitions/definitions.kt | 10 +- .../definitions/dynamicConfigurations.kt | 12 --- .../ScriptExtraImportsProviderExtension.kt | 4 +- .../CliScriptDependenciesProvider.kt | 19 ++-- 30 files changed, 278 insertions(+), 211 deletions(-) create mode 100644 idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptConfigurationFileAttributeCache.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt index 2681dd5f174..9257cd331aa 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/ScriptModuleInfos.kt @@ -90,7 +90,7 @@ sealed class ScriptDependenciesInfo(val project: Project) : IdeaModuleInfo, Bina ) : ScriptDependenciesInfo(project) { override val sdk: Sdk? get() { - return ScriptDependenciesManager.getInstance(project).getScriptSdk(scriptFile, project) + return ScriptDependenciesManager.getInstance(project).getScriptSdk(scriptFile) } override fun contentScope(): GlobalSearchScope { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt index fe8dc15b111..f45450df9a9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinHighlightingUtil.kt @@ -71,7 +71,7 @@ object KotlinHighlightingUtil { 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 (!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 } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/ScriptExternalHighlightingPass.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/ScriptExternalHighlightingPass.kt index 60b72371a87..110af7cf71e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/ScriptExternalHighlightingPass.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/ScriptExternalHighlightingPass.kt @@ -53,7 +53,7 @@ class ScriptExternalHighlightingPass( if (!file.isScript()) return - val reports = IdeScriptReportSink.getReports(file.virtualFile) + val reports = IdeScriptReportSink.getReports(file) val annotations = reports.mapNotNull { scriptDiagnostic -> val (startOffset, endOffset) = scriptDiagnostic.location?.let { computeOffsets(document, it) } ?: 0 to 0 diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt index b0d6d0955d2..77902521844 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElement 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.IdIndexEntry import com.intellij.psi.search.GlobalSearchScope @@ -123,7 +124,7 @@ fun PsiSearchHelper.isCheapEnoughToSearchConsideringOperators( return isCheapEnoughToSearch(name, scope, fileToIgnoreOccurrencesIn, progress) } -fun findScriptsWithUsages(declaration: KtNamedDeclaration): List { +fun findScriptsWithUsages(declaration: KtNamedDeclaration): List { val project = declaration.project val scope = PsiSearchHelper.getInstance(project).getUseScope(declaration) as? GlobalSearchScope ?: return emptyList() @@ -138,5 +139,8 @@ fun findScriptsWithUsages(declaration: KtNamedDeclaration): List { 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() } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/IdeScriptReportSink.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/IdeScriptReportSink.kt index 42febbb2016..17a865e42c5 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/IdeScriptReportSink.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/IdeScriptReportSink.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.util.Key import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import com.intellij.ui.EditorNotifications +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.UserDataProperty import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink import kotlin.script.experimental.api.ScriptDiagnostic @@ -49,6 +50,10 @@ class IdeScriptReportSink(val project: Project) : ScriptReportSink { return file.scriptDiagnostics ?: emptyList() } + fun getReports(file: KtFile): List { + return file.originalFile.virtualFile?.scriptDiagnostics ?: emptyList() + } + private var VirtualFile.scriptDiagnostics: List? by UserDataProperty(Key.create("KOTLIN_SCRIPT_DIAGNOSTICS")) } } \ No newline at end of file diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt index e98817bd8b7..2ac2d82691e 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesFileAttribute.kt @@ -18,10 +18,18 @@ package org.jetbrains.kotlin.idea.core.script import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.core.util.* +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.scripting.definitions.getScriptOriginalFile import java.io.* import kotlin.script.experimental.api.ScriptCompilationConfiguration 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( name = "kotlin-script-dependencies", 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( name = "kotlin-script-compilation-configuration", version = 1, diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt index 8d4aab1842d..269f86594c6 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt @@ -23,16 +23,17 @@ import com.intellij.openapi.projectRoots.JavaSdkType import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager import com.intellij.util.io.URLUtil import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks 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.findScriptDefinition import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult -import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper import java.io.File import kotlin.script.experimental.api.valueOrNull @@ -40,28 +41,35 @@ import kotlin.script.experimental.api.valueOrNull // NOTE: this service exists exclusively because ScriptDependencyManager // cannot be registered as implementing two services (state would be duplicated) class IdeScriptDependenciesProvider( - private val scriptDependenciesManager: ScriptDependenciesManager -) : ScriptDependenciesProvider { - override fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = scriptDependenciesManager.getRefinedCompilationConfiguration(file) + private val scriptDependenciesManager: ScriptDependenciesManager, + project: Project +) : 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 class ScriptDependenciesManager internal constructor( private val cacheUpdater: ScriptsCompilationConfigurationUpdater, - private val cache: ScriptsCompilationConfigurationCache + private val cache: ScriptsCompilationConfigurationCache, + private val project: Project ) { - fun getScriptClasspath(file: VirtualFile): List = - toVfsRoots(cacheUpdater.getCurrentCompilationConfiguration(file)?.valueOrNull()?.dependenciesClassPath.orEmpty()) - fun getRefinedCompilationConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? = - cacheUpdater.getCurrentCompilationConfiguration(file) - - fun getScriptSdk(file: VirtualFile, project: Project): Sdk? { - return getScriptSdk(getRefinedCompilationConfiguration(file)?.valueOrNull()) - ?: getScriptDefaultSdk(project) + @Deprecated("Use getScriptClasspath(KtFile) instead") + fun getScriptClasspath(file: VirtualFile): List { + val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return emptyList() + return getScriptClasspath(ktFile) } + fun getScriptClasspath(file: KtFile): List = + toVfsRoots(cacheUpdater.getCurrentCompilationConfiguration(file)?.valueOrNull()?.dependenciesClassPath.orEmpty()) + + fun getRefinedCompilationConfiguration(file: KtFile): ScriptCompilationConfigurationResult? = + cacheUpdater.getCurrentCompilationConfiguration(file) + fun getScriptDependenciesClassFilesScope(file: VirtualFile) = cache.scriptDependenciesClassFilesScope(file) + fun getScriptSdk(file: VirtualFile) = cache.getScriptSdk(file) fun getAllScriptsSdks() = cache.allSdks @@ -76,17 +84,6 @@ class ScriptDependenciesManager internal constructor( fun getInstance(project: Project): ScriptDependenciesManager = 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? { val projectSdk = ProjectRootManager.getInstance(project).projectSdk?.takeIf { it.canBeUsedForScript() } if (projectSdk != null) return projectSdk @@ -124,10 +121,13 @@ class ScriptDependenciesManager internal constructor( internal val log = Logger.getInstance(ScriptDependenciesManager::class.java) @TestOnly - fun updateScriptDependenciesSynchronously(virtualFile: VirtualFile, project: Project) { + fun updateScriptDependenciesSynchronously(file: PsiFile, project: Project) { val loader = SyncScriptDependenciesLoader(project) - val scriptDefinition = virtualFile.findScriptDefinition(project) ?: return - loader.loadDependencies(virtualFile, scriptDefinition) + val scriptDefinition = file.findScriptDefinition() ?: return + assert(file is KtFile) { + "PsiFile should be a KtFile, otherwise script dependencies cannot be loaded" + } + loader.loadDependencies(file as KtFile, scriptDefinition) loader.notifyRootsChanged() } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptNewDependenciesNotification.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptNewDependenciesNotification.kt index 0c50a1dc733..59e6d510321 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptNewDependenciesNotification.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptNewDependenciesNotification.kt @@ -28,9 +28,9 @@ fun VirtualFile.removeScriptDependenciesNotificationPanel(project: Project) { } fun VirtualFile.addScriptDependenciesNotificationPanel( - compilationConfigurationResult: ScriptCompilationConfigurationResult?, + compilationConfigurationResult: ScriptCompilationConfigurationResult, project: Project, - onClick: (ScriptCompilationConfigurationResult?) -> Unit + onClick: (ScriptCompilationConfigurationResult) -> Unit ) { withSelectedEditor(project) { manager -> val existingPanel = notificationPanel @@ -61,8 +61,8 @@ private fun VirtualFile.withSelectedEditor(project: Project, f: FileEditor.(File private var FileEditor.notificationPanel: NewScriptDependenciesNotificationPanel? by UserDataProperty(Key.create("script.dependencies.panel")) private class NewScriptDependenciesNotificationPanel( - onClick: (ScriptCompilationConfigurationResult?) -> Unit, - val compilationConfigurationResult: ScriptCompilationConfigurationResult?, + onClick: (ScriptCompilationConfigurationResult) -> Unit, + val compilationConfigurationResult: ScriptCompilationConfigurationResult, project: Project ) : EditorNotificationPanel() { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationCache.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationCache.kt index bc4f8e72a33..45659f8575b 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationCache.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationCache.kt @@ -15,15 +15,19 @@ import com.intellij.openapi.roots.ModuleRootEvent import com.intellij.openapi.roots.ModuleRootListener import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.OrderRootType +import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiManager import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.NonClasspathDirectoriesScope +import com.intellij.util.containers.ConcurrentFactoryMap import com.intellij.util.containers.SLRUMap import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks 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.ScriptCompilationConfigurationWrapper import java.util.concurrent.locks.ReentrantReadWriteLock @@ -51,45 +55,79 @@ class ScriptsCompilationConfigurationCache(private val project: Project) { private val cacheLock = ReentrantReadWriteLock() - private val scriptDependenciesCache = SLRUCacheWithLock() - private val scriptsModificationStampsCache = SLRUCacheWithLock() + private val scriptDependenciesCache = SLRUCacheWithLock() + private val scriptsModificationStampsCache = SLRUCacheWithLock() - 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 } - private val scriptsDependenciesClasspathScopeCache = SLRUCacheWithLock() + private val scriptsDependenciesClasspathScopeCache: MutableMap = + 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 sdk = ScriptDependenciesManager.getScriptSdk(compilationConfiguration) + val sdk = getScriptSdk(file) @Suppress("FoldInitializerAndIfToElvis") 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() + ScriptDependenciesManager.toVfsRoots(roots) ) } + + fun scriptDependenciesClassFilesScope(file: VirtualFile): GlobalSearchScope { + return scriptsDependenciesClasspathScopeCache[file] ?: GlobalSearchScope.EMPTY_SCOPE + } + + private val scriptsSdksCache: MutableMap = + 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) { scriptDependenciesCache.getAll() - .mapNotNull { ScriptDependenciesManager.getInstance(project).getScriptSdk(it.key, project) } + .mapNotNull { getScriptSdk(it.key) } .distinct() } private val allNonIndexedSdks by ClearableLazyValue(cacheLock) { scriptDependenciesCache.getAll() - .mapNotNull { ScriptDependenciesManager.getInstance(project).getScriptSdk(it.key, project) } + .mapNotNull { getScriptSdk(it.key) } .filterNonModuleSdk() .distinct() } @@ -164,7 +202,7 @@ class ScriptsCompilationConfigurationCache(private val project: Project) { } 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)) || !allDependenciesClassFiles.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesClassPath)) || !allDependenciesSources.containsAll(ScriptDependenciesManager.toVfsRoots(compilationConfiguration.dependenciesSources)) @@ -176,23 +214,23 @@ class ScriptsCompilationConfigurationCache(private val project: Project) { scriptDependenciesCache.clear() scriptsModificationStampsCache.clear() - onChange(keys) + updateHighlighting(keys) } - fun save(virtualFile: VirtualFile, new: ScriptCompilationConfigurationResult): Boolean { - val old = scriptDependenciesCache.replace(virtualFile, new) + fun save(file: VirtualFile, new: ScriptCompilationConfigurationResult): Boolean { + val old = scriptDependenciesCache.replace(file, new) val changed = new != old if (changed) { - onChange(listOf(virtualFile)) + onChange(listOf(file)) } return changed } - fun delete(virtualFile: VirtualFile): Boolean { - val changed = scriptDependenciesCache.remove(virtualFile) + fun delete(file: VirtualFile): Boolean { + val changed = scriptDependenciesCache.remove(file) if (changed) { - onChange(listOf(virtualFile)) + onChange(listOf(file)) } return changed } @@ -226,20 +264,19 @@ private class ClearableLazyValue( } } - -private class SLRUCacheWithLock { +private class SLRUCacheWithLock { private val lock = ReentrantReadWriteLock() - val cache = SLRUMap( + val cache = SLRUMap( ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED, ScriptsCompilationConfigurationCache.MAX_SCRIPTS_CACHED ) - fun get(value: VirtualFile): T? = lock.write { + fun get(value: K): V? = lock.write { 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) return if (value == null) { val answer = defaultValue() @@ -250,11 +287,11 @@ private class SLRUCacheWithLock { } } - fun remove(file: VirtualFile) = lock.write { + fun remove(file: K) = lock.write { cache.remove(file) } - fun getAll(): Collection> = lock.write { + fun getAll(): Collection> = lock.write { cache.entrySet() } @@ -262,10 +299,9 @@ private class SLRUCacheWithLock { cache.clear() } - fun replace(file: VirtualFile, value: T): T? = lock.write { + fun replace(file: K, value: V): V? = lock.write { val old = get(file) cache.put(file, value) old } -} - +} \ No newline at end of file diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationUpdater.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationUpdater.kt index eef34638272..d4456fee99b 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationUpdater.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptsCompilationConfigurationUpdater.kt @@ -39,13 +39,9 @@ import org.jetbrains.kotlin.idea.core.script.dependencies.SyncScriptDependencies import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.psi.KtFile 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.isNonScript -import org.jetbrains.kotlin.scripting.resolve.LegacyResolverWrapper import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult -import kotlin.script.experimental.dependencies.AsyncDependenciesResolver class ScriptsCompilationConfigurationUpdater( private val project: Project, @@ -65,8 +61,10 @@ class ScriptsCompilationConfigurationUpdater( listenForChangesInScripts() } - fun getCurrentCompilationConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? { - cache[file]?.let { return it } + fun getCurrentCompilationConfiguration(file: KtFile): ScriptCompilationConfigurationResult? { + val virtualFile = file.originalFile.virtualFile + + cache[virtualFile]?.let { return it } // Try-catch block is a temporary workaround for ProcessCanceledException // that may happen during VirtualFile to PsiFile transformation @@ -76,10 +74,10 @@ class ScriptsCompilationConfigurationUpdater( makeRootsChangeIfNeeded() } - return cache[file] + return cache[virtualFile] } - fun updateDependenciesIfNeeded(files: List): Boolean { + fun updateDependenciesIfNeeded(files: List): Boolean { if (!ScriptDefinitionsManager.getInstance(project).isReady()) return false var wasDependenciesUpdateStarted = false @@ -97,11 +95,11 @@ class ScriptsCompilationConfigurationUpdater( return wasDependenciesUpdateStarted } - private fun updateDependencies(file: VirtualFile) { + private fun updateDependencies(file: KtFile) { if (!ScriptDefinitionsManager.getInstance(project).isReady()) 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) } } @@ -122,24 +120,18 @@ class ScriptsCompilationConfigurationUpdater( } private fun runScriptDependenciesUpdateIfNeeded(file: VirtualFile) { - if (!shouldStartUpdate(file)) return + val ktFile = getKtFileToStartConfigurationUpdate(file) ?: return - updateDependencies(file) + updateDependencies(ktFile) makeRootsChangeIfNeeded() } }) EditorFactory.getInstance().eventMulticaster.addDocumentListener(object : DocumentListener { override fun documentChanged(event: DocumentEvent) { - val document = event.document val file = FileDocumentManager.getInstance().getFile(document)?.takeIf { it.isInLocalFileSystem } ?: return - if (!file.isValid) { - cache.delete(file) - return - } - - if (!shouldStartUpdate(file)) return + val ktFile = getKtFileToStartConfigurationUpdate(file) ?: return // only update dependencies for scripts that were touched recently if (cache[file] == null) { @@ -151,7 +143,7 @@ class ScriptsCompilationConfigurationUpdater( scriptsQueue.addRequest( { FileDocumentManager.getInstance().saveDocument(document) - updateDependencies(file) + updateDependencies(ktFile) makeRootsChangeIfNeeded() }, scriptChangesListenerDelay, @@ -161,31 +153,30 @@ class ScriptsCompilationConfigurationUpdater( }, project.messageBus.connect()) } - private fun shouldStartUpdate(file: VirtualFile): Boolean { + private fun getKtFileToStartConfigurationUpdate(file: VirtualFile): KtFile? { if (project.isDisposed || !file.isValid || file.isNonScript()) { - return false + return null } if ( ApplicationManager.getApplication().isUnitTestMode && ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled == true ) { - return false + return null } - val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return false - return ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true) + val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null + if (ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)) { + return ktFile + } + + return null } 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()?.dependencyResolver?.let { - it is AsyncDependenciesResolver || it is LegacyResolverWrapper - } ?: false - companion object { @JvmStatic fun getInstance(project: Project): ScriptsCompilationConfigurationUpdater = @@ -194,11 +185,6 @@ class ScriptsCompilationConfigurationUpdater( fun areDependenciesCached(file: KtFile): Boolean { 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) - } } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/AsyncScriptDependenciesLoader.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/AsyncScriptDependenciesLoader.kt index 312bc5f0ab3..9e3f0b08333 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/AsyncScriptDependenciesLoader.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/AsyncScriptDependenciesLoader.kt @@ -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. */ @@ -10,13 +10,12 @@ import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.Task import com.intellij.openapi.progress.util.BackgroundTaskUtil import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile 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.psi.KtFile import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition 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 java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.locks.ReentrantReadWriteLock @@ -30,14 +29,14 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr private var backgroundTasksQueue: LoaderBackgroundTask? = null override fun isApplicable( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ): Boolean { - return ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition) + return isAsyncDependencyResolver(scriptDefinition) } override fun loadDependencies( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ) { lock.write { @@ -74,20 +73,20 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr return false } - private fun runDependenciesUpdate(file: VirtualFile) { - val scriptDef = file.findScriptDefinition(project) ?: return + private fun runDependenciesUpdate(file: KtFile) { + val scriptDef = file.findScriptDefinition() ?: return 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" } - processRefinedConfiguration(result, file) + processRefinedConfiguration(result, file.originalFile.virtualFile) } private inner class LoaderBackgroundTask { - private val sequenceOfFiles: ConcurrentLinkedQueue = ConcurrentLinkedQueue() + private val sequenceOfFiles: ConcurrentLinkedQueue = ConcurrentLinkedQueue() private var forceStop : Boolean = false private var startedSilently : Boolean = false @@ -124,7 +123,7 @@ class AsyncScriptDependenciesLoader internal constructor(project: Project) : Scr }.queue() } - fun addTask(file: VirtualFile) { + fun addTask(file: KtFile) { if (sequenceOfFiles.contains(file)) return debug(file) { "added to update queue" } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/FromFileAttributeScriptDependenciesLoader.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/FromFileAttributeScriptDependenciesLoader.kt index aa62aafc20a..1e5c46cffc7 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/FromFileAttributeScriptDependenciesLoader.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/FromFileAttributeScriptDependenciesLoader.kt @@ -9,39 +9,41 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.core.script.scriptCompilationConfiguration 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.resolve.KtFileScriptSource import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper -import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource import kotlin.script.experimental.api.asSuccess // TODO: rename and provide alias for compatibility - this is not only about dependencies anymore class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) { override fun isApplicable( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ): Boolean { return file.scriptDependencies != null || file.scriptCompilationConfiguration != null } override fun loadDependencies( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ) { - file.scriptCompilationConfiguration?.let { - ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(VirtualFileScriptSource(file), it).apply { - debug(file) { "refined configuration from fileAttributes = $it" } + val virtualFile = file.originalFile.virtualFile + virtualFile.scriptCompilationConfiguration?.let { + ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(KtFileScriptSource(file), it).apply { + debug(virtualFile) { "refined configuration from fileAttributes = $it" } } - } ?: file.scriptDependencies?.let { - ScriptCompilationConfigurationWrapper.FromLegacy(VirtualFileScriptSource(file), it, scriptDefinition).apply { - debug(file) { "dependencies from fileAttributes = $it" } + } ?: virtualFile.scriptDependencies?.let { + ScriptCompilationConfigurationWrapper.FromLegacy(KtFileScriptSource(file), it, scriptDefinition).apply { + debug(virtualFile) { "dependencies from fileAttributes = $it" } } }?.let { - if (areDependenciesValid(file, it)) { - saveToCache(file, it.asSuccess(), skipSaveToAttributes = true) + if (areDependenciesValid(virtualFile, it)) { + saveToCache(virtualFile, it.asSuccess(), skipSaveToAttributes = true) } else { - file.scriptCompilationConfiguration = null - file.scriptDependencies = null + virtualFile.scriptCompilationConfiguration = null + virtualFile.scriptDependencies = null } } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt index 9428f9a6886..d6a05cc26b2 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/KotlinScriptResolveScopeProvider.kt @@ -18,10 +18,13 @@ package org.jetbrains.kotlin.idea.core.script.dependencies import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiManager import com.intellij.psi.ResolveScopeProvider 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.StandardIdeScriptDefinition +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate @@ -33,7 +36,10 @@ class KotlinScriptResolveScopeProvider : ResolveScopeProvider() { } 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 { scriptDefinition == null -> null // This is a workaround for completion in scripts and REPL to provide module dependencies diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/OutsiderFileDependenciesLoader.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/OutsiderFileDependenciesLoader.kt index ea2ce778f46..92aaa59e79b 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/OutsiderFileDependenciesLoader.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/OutsiderFileDependenciesLoader.kt @@ -6,27 +6,32 @@ package org.jetbrains.kotlin.idea.core.script.dependencies 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.highlighter.OutsidersPsiFileSupportUtils import org.jetbrains.kotlin.idea.highlighter.OutsidersPsiFileSupportWrapper +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition class OutsiderFileDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) { override fun isApplicable( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ): Boolean { - return OutsidersPsiFileSupportWrapper.isOutsiderFile(file) + val virtualFile = file.virtualFile ?: return false + return OutsidersPsiFileSupportWrapper.isOutsiderFile(virtualFile) } override fun loadDependencies( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ) { - val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, file) ?: return - val compilationConfiguration = ScriptDependenciesManager.getInstance(project).getRefinedCompilationConfiguration(fileOrigin) ?: return - saveToCache(file, compilationConfiguration) + val virtualFile = file.virtualFile ?: return + val fileOrigin = OutsidersPsiFileSupportUtils.getOutsiderFileOrigin(project, virtualFile) ?: return + 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 diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptConfigurationFileAttributeCache.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptConfigurationFileAttributeCache.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptDependenciesLoader.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptDependenciesLoader.kt index cdf328283de..61ac106ccb8 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptDependenciesLoader.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/ScriptDependenciesLoader.kt @@ -15,18 +15,22 @@ import com.intellij.openapi.util.EmptyRunnable import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.core.script.* 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.resolve.LegacyResolverWrapper import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink import kotlin.script.experimental.api.ResultWithDiagnostics 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 abstract class ScriptDependenciesLoader(protected val project: Project) { - abstract fun isApplicable(file: VirtualFile, scriptDefinition: ScriptDefinition): Boolean - abstract fun loadDependencies(file: VirtualFile, scriptDefinition: ScriptDefinition) + abstract fun isApplicable(file: KtFile, scriptDefinition: ScriptDefinition): Boolean + abstract fun loadDependencies(file: KtFile, scriptDefinition: ScriptDefinition) protected abstract fun shouldShowNotification(): Boolean @@ -138,13 +142,23 @@ abstract class ScriptDependenciesLoader(protected val project: Project) { return true } - companion object { - private val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.script") + protected fun isAsyncDependencyResolver(scriptDef: ScriptDefinition): Boolean = + scriptDef.asLegacyOrNull()?.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()) } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/SyncScriptDependenciesLoader.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/SyncScriptDependenciesLoader.kt index 8a4fd0875c7..b10e88d16d3 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/SyncScriptDependenciesLoader.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/dependencies/SyncScriptDependenciesLoader.kt @@ -6,28 +6,27 @@ package org.jetbrains.kotlin.idea.core.script.dependencies import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.kotlin.idea.core.script.ScriptsCompilationConfigurationUpdater +import org.jetbrains.kotlin.psi.KtFile 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 class SyncScriptDependenciesLoader(project: Project) : ScriptDependenciesLoader(project) { override fun isApplicable( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ): Boolean { - return !ScriptsCompilationConfigurationUpdater.getInstance(project).isAsyncDependencyResolver(scriptDefinition) + return !isAsyncDependencyResolver(scriptDefinition) } override fun loadDependencies( - file: VirtualFile, + file: KtFile, scriptDefinition: ScriptDefinition ) { 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" } - processRefinedConfiguration(result, file) + processRefinedConfiguration(result, file.originalFile.virtualFile) } override fun shouldShowNotification(): Boolean = false diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleBuildFileHighlightingTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleBuildFileHighlightingTest.kt index 72365116024..9f9a85433a9 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleBuildFileHighlightingTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleBuildFileHighlightingTest.kt @@ -48,7 +48,7 @@ class GradleBuildFileHighlightingTest : GradleImportingTestCase() { val psiFile = PsiManager.getInstance(myProject).findFile(file) as? KtFile ?: error("Couldn't find psiFile for virtual file: ${file.canonicalPath}") - ScriptDependenciesManager.updateScriptDependenciesSynchronously(file, myProject) + ScriptDependenciesManager.updateScriptDependenciesSynchronously(psiFile, myProject) val bindingContext = psiFile.analyzeWithContent() diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchExecutionSession.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchExecutionSession.kt index d4ce0b3e060..ba914c3cca6 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchExecutionSession.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchExecutionSession.kt @@ -166,7 +166,7 @@ class KtScratchExecutionSession( } ScriptDependenciesManager.getInstance(originalFile.project) - .getRefinedCompilationConfiguration(originalFile.virtualFile)?.valueOrNull()?.let { + .getRefinedCompilationConfiguration(originalFile)?.valueOrNull()?.let { javaParameters.classPath.addAll(it.dependenciesClassPath.map { f -> f.absolutePath }) } diff --git a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt index cba13e052dd..c0b264354db 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt @@ -65,8 +65,9 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper( val allDefaultImports = platform.findAnalyzerServices.getDefaultImports(languageVersionSettings, includeLowPriorityImports = true) val scriptExtraImports = contextFile.takeIf { it.isScript() }?.let { ktFile -> - val scriptDependencies = - ScriptDependenciesProvider.getInstance(ktFile.project)?.getScriptConfigurationResult(ktFile.originalFile)?.valueOrNull() + val scriptDependencies = ScriptDependenciesProvider.getInstance(ktFile.project) + ?.getScriptConfigurationResult(ktFile.originalFile as KtFile) + ?.valueOrNull() scriptDependencies?.defaultImports?.map { ImportPath.fromString(it) } }.orEmpty() diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt index cd50ae192bf..8186018d3e0 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt @@ -12,10 +12,7 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.VfsUtil -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiJavaFile +import com.intellij.psi.* import com.intellij.psi.codeStyle.JavaCodeStyleManager import com.intellij.psi.codeStyle.VariableKind 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.LightCodeInsightFixtureTestCase 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.util.CodeInsightUtils import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively import org.jetbrains.kotlin.idea.refactoring.chooseMembers import org.jetbrains.kotlin.idea.refactoring.introduce.extractClass.ExtractSuperInfo @@ -325,7 +322,9 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase() PluginTestCaseBase.addJdk(myFixture.projectDisposable, PluginTestCaseBase::mockJdk) 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}" diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/StandaloneScriptRunConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/run/StandaloneScriptRunConfigurationTest.kt index 8a824662f56..c9ff690fda4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/run/StandaloneScriptRunConfigurationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/run/StandaloneScriptRunConfigurationTest.kt @@ -71,7 +71,7 @@ class StandaloneScriptRunConfigurationTest : KotlinCodeInsightTestCase() { fun testOnFileMoveWithDefaultWorkingDir() { 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 runConfiguration = createConfigurationFromElement(script, save = true) as KotlinStandaloneScriptRunConfiguration @@ -98,7 +98,7 @@ class StandaloneScriptRunConfigurationTest : KotlinCodeInsightTestCase() { fun testOnFileMoveWithNonDefaultWorkingDir() { 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 runConfiguration = createConfigurationFromElement(script, save = true) as KotlinStandaloneScriptRunConfiguration diff --git a/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt index d80d2f051a8..6f4b88505fe 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/scratch/AbstractScratchRunActionTest.kt @@ -204,7 +204,7 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() { myFixture.openFileInEditor(scratchVirtualFile) - ScriptDependenciesManager.updateScriptDependenciesSynchronously(scratchVirtualFile, project) + ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFixture.file, project) val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile) ?: error("Couldn't find scratch file") @@ -217,7 +217,7 @@ abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() { protected fun configureWorksheetByText(name: String, text: String): ScratchFile { val worksheetFile = myFixture.configureByText(name, text).virtualFile - ScriptDependenciesManager.updateScriptDependenciesSynchronously(worksheetFile, project) + ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFixture.file, project) val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile) ?: error("Couldn't find scratch panel") diff --git a/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt b/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt index 4b77a2c9f66..7151ee21402 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchLineMarkersTest.kt @@ -37,7 +37,7 @@ abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() { myFixture.openFileInEditor(scratchVirtualFile) - ScriptDependenciesManager.updateScriptDependenciesSynchronously(scratchVirtualFile, project) + ScriptDependenciesManager.updateScriptDependenciesSynchronously(myFixture.file, project) val scratchFileEditor = getScratchEditorForSelectedFile(FileEditorManager.getInstance(project), myFixture.file.virtualFile) ?: error("Couldn't find scratch panel") diff --git a/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt index d738f62b636..535e9aa56eb 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/script/AbstractScriptConfigurationTest.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingUtil import org.jetbrains.kotlin.idea.navigation.GotoCheck import org.jetbrains.kotlin.idea.test.PluginTestCaseBase 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.KotlinTestUtils 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) } } @@ -134,7 +135,7 @@ abstract class AbstractScriptDefinitionsOrderTest : AbstractScriptConfigurationT } ScriptDefinitionsManager.getInstance(project).reorderScriptDefinitions() - updateScriptDependenciesSynchronously(myFile.virtualFile, project) + updateScriptDependenciesSynchronously(myFile, project) 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") configureByExistingFile(script) - updateScriptDependenciesSynchronously(script, project) + updateScriptDependenciesSynchronously(myFile, project) VfsUtil.markDirtyAndRefresh(false, true, true, project.baseDir) // This is needed because updateScriptDependencies invalidates psiFile that was stored in myFile field 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)) { "Highlighting is switched off for ${myFile.virtualFile.path}" } diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptDependenciesProvider.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptDependenciesProvider.kt index b791c96929e..0dfa85c7ac8 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptDependenciesProvider.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptDependenciesProvider.kt @@ -9,24 +9,29 @@ import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiFile +import com.intellij.psi.PsiManager +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult import kotlin.script.experimental.api.valueOrNull import kotlin.script.experimental.dependencies.ScriptDependencies -interface ScriptDependenciesProvider { +open class ScriptDependenciesProvider constructor( + protected val project: Project +) { @Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR) - fun getScriptDependencies(file: VirtualFile): ScriptDependencies? = - getScriptConfigurationResult(file)?.valueOrNull()?.legacyDependencies + fun getScriptDependencies(file: VirtualFile): ScriptDependencies? { + val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null + return getScriptConfigurationResult(ktFile)?.valueOrNull()?.legacyDependencies + } @Deprecated("Migrating to configuration refinement", level = DeprecationLevel.ERROR) - fun getScriptDependencies(file: PsiFile): ScriptDependencies? = - getScriptConfigurationResult(file.virtualFile ?: file.originalFile.virtualFile)?.valueOrNull()?.legacyDependencies + fun getScriptDependencies(file: PsiFile): ScriptDependencies? { + if (file !is KtFile) return null + return getScriptConfigurationResult(file)?.valueOrNull()?.legacyDependencies + } - fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = null - - fun getScriptConfigurationResult(file: PsiFile): ScriptCompilationConfigurationResult? = - getScriptConfigurationResult(file.virtualFile ?: file.originalFile.virtualFile) + open fun getScriptConfigurationResult(file: KtFile): ScriptCompilationConfigurationResult? = null companion object { fun getInstance(project: Project): ScriptDependenciesProvider? = diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt index dac13d7b29f..2c2b1898e41 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt @@ -25,18 +25,20 @@ inline fun runReadAction(crossinline runnable: () -> T): T { fun PsiFile.findScriptDefinition(): ScriptDefinition? { // Do not use psiFile.script, see comments in findScriptDefinition 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? { if (!isValid || isNonScript()) return null + // Do not use psiFile.script here because this method can be called during indexes access // 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 - if (runReadAction { PsiManager.getInstance(project).findFile(this) as? KtFile }/*?.script*/ == null) return null return findScriptDefinitionByFilePath(project, File(path)) diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/dynamicConfigurations.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/dynamicConfigurations.kt index 587c3cd737b..b701019e739 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/dynamicConfigurations.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/dynamicConfigurations.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.scripting.definitions -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiFile import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult @@ -27,16 +25,6 @@ fun PsiFile.findScriptCompilationConfiguration(): ScriptCompilationConfiguration ?: 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 -> val singleCause = failure.reports.singleOrNull { it.severity == ScriptDiagnostic.Severity.ERROR } if (singleCause != null) diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/extensions/ScriptExtraImportsProviderExtension.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/extensions/ScriptExtraImportsProviderExtension.kt index b8b4fdb01f1..cb1c98d7d96 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/extensions/ScriptExtraImportsProviderExtension.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/extensions/ScriptExtraImportsProviderExtension.kt @@ -29,7 +29,9 @@ class ScriptExtraImportsProviderExtension : ExtraImportsProviderExtension { override fun getExtraImports(ktFile: KtFile): Collection = 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 { ScriptExtraImportImpl( ImportPath.fromString(it) diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/definitions/CliScriptDependenciesProvider.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/definitions/CliScriptDependenciesProvider.kt index 5ef92597d6e..4b653a560a6 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/definitions/CliScriptDependenciesProvider.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/definitions/CliScriptDependenciesProvider.kt @@ -8,38 +8,37 @@ package org.jetbrains.kotlin.scripting.compiler.plugin.definitions import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.diagnostic.Logger 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.findScriptDefinition +import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink -import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration import java.io.File import java.util.concurrent.locks.ReentrantReadWriteLock import kotlin.concurrent.read import kotlin.concurrent.write 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 cache = hashMapOf() - override fun getScriptConfigurationResult(file: VirtualFile): ScriptCompilationConfigurationResult? = cacheLock.read { + override fun getScriptConfigurationResult(file: KtFile): ScriptCompilationConfigurationResult? = cacheLock.read { calculateRefinedConfiguration(file) } - private fun calculateRefinedConfiguration(file: VirtualFile): ScriptCompilationConfigurationResult? { - val path = file.path + private fun calculateRefinedConfiguration(file: KtFile): ScriptCompilationConfigurationResult? { + val path = file.virtualFilePath val cached = cache[path] return if (cached != null) cached else { - val scriptDef = file.findScriptDefinition(project) + val scriptDef = file.findScriptDefinition() 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) { log.info("[kts] new cached deps for $path: ${result.value.dependenciesClassPath.joinToString(File.pathSeparator)}")