Provide a notification for gradle script that aren't related to any gradle project (KT-35268)
Add action to load/reload configuration for them manually ^KT-35268 Fixed
This commit is contained in:
+17
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiFile
|
||||
@@ -31,7 +32,9 @@ import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.AbstractScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationSnapshot
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoader
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||
@@ -70,6 +73,12 @@ interface ScriptConfigurationManager {
|
||||
*/
|
||||
fun getConfiguration(file: KtFile): ScriptCompilationConfigurationWrapper?
|
||||
|
||||
/**
|
||||
* Reload the configuration for [file] even it is already loaded.
|
||||
* [loader] is used to load configuration. Other loaders aren't taken into account.
|
||||
*/
|
||||
fun forceReloadConfiguration(file: VirtualFile, loader: ScriptConfigurationLoader): ScriptCompilationConfigurationWrapper?
|
||||
|
||||
@Deprecated("Use getScriptClasspath(KtFile) instead")
|
||||
fun getScriptClasspath(file: VirtualFile): List<VirtualFile>
|
||||
|
||||
@@ -165,5 +174,13 @@ interface ScriptConfigurationManager {
|
||||
fun clearCaches(project: Project) {
|
||||
(getInstance(project) as AbstractScriptConfigurationManager).clearCaches()
|
||||
}
|
||||
|
||||
fun markFileWithManualConfigurationLoading(file: VirtualFile) {
|
||||
file.LOAD_CONFIGURATION_MANUALLY = true
|
||||
}
|
||||
|
||||
fun isManualConfigurationLoading(file: VirtualFile): Boolean = file.LOAD_CONFIGURATION_MANUALLY ?: false
|
||||
|
||||
private var VirtualFile.LOAD_CONFIGURATION_MANUALLY: Boolean? by UserDataProperty(Key.create<Boolean>("MANUAL_CONFIGURATION_LOADING"))
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -29,7 +29,10 @@ class ScriptTrafficLightRendererContributor : TrafficLightRendererContributor {
|
||||
if (!ScriptDefinitionsManager.getInstance(file.project).isReady()) {
|
||||
status.reasonWhySuspended = "Loading kotlin script definitions"
|
||||
status.errorAnalyzingFinished = false
|
||||
} else if (!ScriptConfigurationManager.getInstance(project).hasConfiguration(file)) {
|
||||
} else if (
|
||||
!ScriptConfigurationManager.getInstance(project).hasConfiguration(file)
|
||||
&& !ScriptConfigurationManager.isManualConfigurationLoading(file.originalFile.virtualFile)
|
||||
) {
|
||||
status.reasonWhySuspended = "Loading kotlin script dependencies"
|
||||
status.errorAnalyzingFinished = false
|
||||
}
|
||||
|
||||
+25
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigura
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationSnapshot
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationState
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoader
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsIndexer
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.getKtFile
|
||||
@@ -82,6 +83,17 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
forceSync: Boolean = false
|
||||
)
|
||||
|
||||
/**
|
||||
* Will be called on user action
|
||||
* Load configuration event it is already cached or inputs are up-to-date
|
||||
*
|
||||
* @param loader is used to load configuration. Other loaders aren't taken into account.
|
||||
*/
|
||||
protected abstract fun forceReloadConfiguration(
|
||||
file: KtFile,
|
||||
loader: ScriptConfigurationLoader
|
||||
)
|
||||
|
||||
@Deprecated("Use getScriptClasspath(KtFile) instead")
|
||||
override fun getScriptClasspath(file: VirtualFile): List<VirtualFile> {
|
||||
val ktFile = project.getKtFile(file) ?: return emptyList()
|
||||
@@ -122,6 +134,19 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
return getAppliedConfiguration(virtualFile)?.configuration
|
||||
}
|
||||
|
||||
override fun forceReloadConfiguration(
|
||||
file: VirtualFile,
|
||||
loader: ScriptConfigurationLoader
|
||||
): ScriptCompilationConfigurationWrapper? {
|
||||
val ktFile = project.getKtFile(file, null) ?: return null
|
||||
|
||||
rootsIndexer.transaction {
|
||||
forceReloadConfiguration(ktFile, loader)
|
||||
}
|
||||
|
||||
return getAppliedConfiguration(file)?.configuration
|
||||
}
|
||||
|
||||
override val updater: ScriptConfigurationUpdater = object : ScriptConfigurationUpdater {
|
||||
override fun ensureUpToDatedConfigurationSuggested(file: KtFile) {
|
||||
reloadIfOutOfDate(listOf(file), true)
|
||||
|
||||
+17
-6
@@ -32,14 +32,10 @@ import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.jvm.impl.toClassPathOrEmpty
|
||||
import kotlin.script.experimental.jvm.jdkHome
|
||||
import kotlin.script.experimental.jvm.jvm
|
||||
|
||||
/**
|
||||
* Standard implementation of scripts configuration loading and caching
|
||||
@@ -184,7 +180,7 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
if (syncLoader == null) {
|
||||
// run async loader
|
||||
if (forceSync) {
|
||||
async.first { it.loadDependencies(isFirstLoad, file, scriptDefinition, loadingContext) }
|
||||
async.firstOrNull { it.loadDependencies(isFirstLoad, file, scriptDefinition, loadingContext) }
|
||||
} else {
|
||||
backgroundExecutor.ensureScheduled(virtualFile) {
|
||||
val cached = getCachedConfigurationState(virtualFile)
|
||||
@@ -197,13 +193,28 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
// don't start loading if nothing was changed
|
||||
// (in case we checking for up-to-date and loading concurrently)
|
||||
val actualIsFirstLoad = cached == null
|
||||
async.first { it.loadDependencies(actualIsFirstLoad, file, scriptDefinition, loadingContext) }
|
||||
async.firstOrNull { it.loadDependencies(actualIsFirstLoad, file, scriptDefinition, loadingContext) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun forceReloadConfiguration(file: KtFile, loader: ScriptConfigurationLoader) {
|
||||
val virtualFile = file.originalFile.virtualFile ?: return
|
||||
|
||||
if (!ScriptDefinitionsManager.getInstance(project).isReady()) return
|
||||
val scriptDefinition = file.findScriptDefinition() ?: return
|
||||
|
||||
if (!loader.shouldRunInBackground(scriptDefinition)) {
|
||||
loader.loadDependencies(false, file, scriptDefinition, loadingContext)
|
||||
} else {
|
||||
backgroundExecutor.ensureScheduled(virtualFile) {
|
||||
loader.loadDependencies(false, file, scriptDefinition, loadingContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save configurations into cache.
|
||||
* Start indexing for new class/source roots.
|
||||
|
||||
+3
@@ -16,6 +16,7 @@ import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.Alarm
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangeListener.Companion.LISTENER
|
||||
import org.jetbrains.kotlin.idea.core.script.isScriptChangesNotifierDisabled
|
||||
|
||||
@@ -76,6 +77,8 @@ internal class ScriptChangesNotifier(
|
||||
private fun getListener(project: Project, file: VirtualFile): ScriptChangeListener? {
|
||||
if (project.isDisposed || areListenersDisabled()) return null
|
||||
|
||||
if (ScriptConfigurationManager.isManualConfigurationLoading(file)) return null
|
||||
|
||||
return listeners.firstOrNull { it.isApplicable(file) }
|
||||
}
|
||||
|
||||
|
||||
+20
-8
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.core.script.configuration.loader
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationSnapshot
|
||||
import org.jetbrains.kotlin.idea.core.script.debug
|
||||
@@ -38,12 +39,26 @@ open class DefaultScriptConfigurationLoader(val project: Project) : ScriptConfig
|
||||
): Boolean {
|
||||
val virtualFile = ktFile.originalFile.virtualFile
|
||||
|
||||
debug(ktFile) { "start dependencies loading" }
|
||||
if (ScriptConfigurationManager.isManualConfigurationLoading(virtualFile)) return false
|
||||
|
||||
val inputs = getInputsStamp(virtualFile, ktFile)
|
||||
val result = getConfigurationThroughScriptingApi(ktFile, virtualFile, scriptDefinition)
|
||||
|
||||
context.suggestNewConfiguration(virtualFile, result)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
protected fun getConfigurationThroughScriptingApi(
|
||||
file: KtFile,
|
||||
vFile: VirtualFile,
|
||||
scriptDefinition: ScriptDefinition
|
||||
): ScriptConfigurationSnapshot {
|
||||
debug(file) { "start dependencies loading" }
|
||||
|
||||
val inputs = getInputsStamp(vFile, file)
|
||||
val scriptingApiResult = try {
|
||||
refineScriptCompilationConfiguration(
|
||||
KtFileScriptSource(ktFile), scriptDefinition, ktFile.project
|
||||
KtFileScriptSource(file), scriptDefinition, file.project
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
if (e is ControlFlowException) throw e
|
||||
@@ -57,11 +72,8 @@ open class DefaultScriptConfigurationLoader(val project: Project) : ScriptConfig
|
||||
scriptingApiResult.valueOrNull()
|
||||
)
|
||||
|
||||
context.suggestNewConfiguration(virtualFile, result)
|
||||
|
||||
debug(ktFile) { "finish dependencies loading" }
|
||||
|
||||
return true
|
||||
debug(file) { "finish dependencies loading" }
|
||||
return result
|
||||
}
|
||||
|
||||
protected open fun getInputsStamp(virtualFile: VirtualFile, file: KtFile): CachedConfigurationInputs {
|
||||
|
||||
Reference in New Issue
Block a user