Refactor GradleScriptingSupport to support multiple gradle projects linked to one idea project

For each externalGradleProject separate GradleScriptingSupport is created.
This allows to save script configurations by gradle projects

^KT-37806 Obsolete
^KT-35151 Fixed
This commit is contained in:
Sergey Rostov
2020-04-22 16:13:00 +03:00
committed by Natalia Selezneva
parent 34df3066b3
commit 73760effee
19 changed files with 458 additions and 286 deletions
@@ -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.roots.ProjectRootManager.*
import com.intellij.openapi.util.Key
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile
@@ -30,7 +31,6 @@ 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.configuration.CompositeScriptConfigurationManager
import org.jetbrains.kotlin.idea.core.script.configuration.DefaultScriptingSupport
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
@@ -38,7 +38,6 @@ 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
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import java.io.File
import kotlin.script.experimental.api.asSuccess
import kotlin.script.experimental.api.makeFailureResult
@@ -162,15 +161,13 @@ interface ScriptConfigurationManager {
@TestOnly
fun updateScriptDependenciesSynchronously(file: PsiFile) {
// TODO: review the usages of this method
(getInstance(file.project) as CompositeScriptConfigurationManager).managers
.firstIsInstance<DefaultScriptingSupport>()
(getInstance(file.project) as CompositeScriptConfigurationManager).default
.updateScriptDependenciesSynchronously(file)
}
@TestOnly
fun clearCaches(project: Project) {
(getInstance(project) as CompositeScriptConfigurationManager).managers
.firstIsInstance<DefaultScriptingSupport>()
(getInstance(project) as CompositeScriptConfigurationManager).default
.clearCaches()
}
@@ -22,16 +22,25 @@ import org.jetbrains.kotlin.idea.core.script.configuration.utils.getKtFile
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.scripting.definitions.isNonScript
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigurationManager {
@Suppress("unused")
private val notifier = ScriptChangesNotifier(project, updater)
// todo public for tests
val managers = ScriptingSupport.SCRIPTING_SUPPORT.getPoint(project).extensionList
private val providers = ScriptingSupport.Provider.EPN.getPoint(project).extensionList
val default = DefaultScriptingSupport(project)
private val managers
get() = mutableListOf<ScriptingSupport>().also { managers ->
managers.add(default)
providers.forEach { managers.addAll(it.all) }
}
private fun getRelatedManager(file: VirtualFile): ScriptingSupport =
providers.firstNotNullResult { it.getSupport(file) } ?: default
private fun getRelatedManager(file: VirtualFile): ScriptingSupport = managers.first { it.isRelated(file) }
private fun getRelatedManager(file: KtFile): ScriptingSupport =
getRelatedManager(file.originalFile.virtualFile)
@@ -76,14 +85,16 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
* Loads script configuration if classpath roots don't contain [file] yet
*/
private fun getActualClasspathRoots(file: VirtualFile): ScriptClassRootsCache {
val classpathRoots = getRelatedManager(file).classpathRoots
val manager = getRelatedManager(file)
val classpathRoots = manager.classpathRoots
if (classpathRoots.contains(file)) {
return classpathRoots
}
getOrLoadConfiguration(file)
return getRelatedManager(file).classpathRoots
return manager.classpathRoots
}
override fun getScriptSdk(file: VirtualFile): Sdk? =
@@ -115,7 +126,7 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
override fun forceReloadConfiguration(file: VirtualFile, loader: ScriptConfigurationLoader): ScriptCompilationConfigurationWrapper? {
val ktFile = project.getKtFile(file, null) ?: return null
return managers.firstIsInstanceOrNull<DefaultScriptingSupport>()?.forceReloadConfiguration(ktFile, loader)
return default.forceReloadConfiguration(ktFile, loader)
}
///////////////////
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
import kotlin.script.experimental.api.ScriptDiagnostic
@@ -312,8 +311,6 @@ abstract class DefaultScriptingSupportBase(val project: Project) : ScriptingSupp
fun getAppliedConfiguration(file: VirtualFile?): ScriptConfigurationSnapshot? =
getCachedConfigurationState(file)?.applied
override fun isRelated(file: VirtualFile): Boolean = true
override fun hasCachedConfiguration(file: KtFile): Boolean =
getAppliedConfiguration(file.originalFile.virtualFile) != null
@@ -438,6 +435,5 @@ object DefaultScriptConfigurationManagerExtensions {
}
val ScriptConfigurationManager.testingBackgroundExecutor
get() = (this as CompositeScriptConfigurationManager).managers
.firstIsInstance<DefaultScriptingSupport>()
get() = (this as CompositeScriptConfigurationManager).default
.backgroundExecutor as TestingBackgroundExecutor
@@ -21,7 +21,16 @@ import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
abstract class ScriptingSupport {
abstract fun isRelated(file: VirtualFile): Boolean
abstract class Provider {
abstract val all: Collection<ScriptingSupport>
abstract fun getSupport(file: VirtualFile): ScriptingSupport?
companion object {
val EPN: ExtensionPointName<Provider> =
ExtensionPointName.create("org.jetbrains.kotlin.scripting.idea.scriptingSupportProvider")
}
}
abstract fun clearCaches()
abstract fun hasCachedConfiguration(file: KtFile): Boolean
@@ -68,9 +77,4 @@ abstract class ScriptingSupport {
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
}
companion object {
val SCRIPTING_SUPPORT: ExtensionPointName<ScriptingSupport> =
ExtensionPointName.create("org.jetbrains.kotlin.scripting.idea.scriptingSupport")
}
}
@@ -16,15 +16,16 @@ import java.io.File
internal class DefaultClassRootsCache(
project: Project,
private val all: Map<VirtualFile, ScriptCompilationConfigurationWrapper>
) : ScriptClassRootsCache(project, extractRoots(all, project)) {
) : ScriptClassRootsCache(
project,
ScriptClassRootsStorage.Companion.Key("default"),
extractRoots(all, project)
) {
override val fileToConfiguration: (VirtualFile) -> ScriptCompilationConfigurationWrapper?
get() = { all[it] }
override fun getConfiguration(file: VirtualFile) = all[file]
override fun contains(file: VirtualFile): Boolean = file in all
override val rootsCacheKey = ScriptClassRootsStorage.Companion.Key("default")
private val scriptsSdksCache: Map<VirtualFile, Sdk?> =
ConcurrentFactoryMap.createWeakMap { file ->
return@createWeakMap getScriptSdk(
@@ -44,30 +45,18 @@ internal class DefaultClassRootsCache(
project: Project,
configuration: ScriptCompilationConfigurationWrapper
): ScriptClassRootsStorage.Companion.ScriptClassRoots {
val scriptSdk =
getScriptSdkOfDefault(
configuration.javaHome,
project
)
val scriptSdk = getScriptSdk(configuration.javaHome)
if (scriptSdk != null && !scriptSdk.isAlreadyIndexed(project)) {
return ScriptClassRootsStorage.Companion.ScriptClassRoots(
toStringValues(
configuration.dependenciesClassPath
),
toStringValues(
configuration.dependenciesSources
),
toStringValues(configuration.dependenciesClassPath),
toStringValues(configuration.dependenciesSources),
setOf(scriptSdk)
)
}
return ScriptClassRootsStorage.Companion.ScriptClassRoots(
toStringValues(
configuration.dependenciesClassPath
),
toStringValues(
configuration.dependenciesSources
),
toStringValues(configuration.dependenciesClassPath),
toStringValues(configuration.dependenciesSources),
emptySet()
)
}
@@ -18,15 +18,13 @@ import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import java.io.File
import java.nio.file.FileSystems
abstract class ScriptClassRootsCache(
private val project: Project,
private val rootsCacheKey: ScriptClassRootsStorage.Companion.Key,
private val roots: ScriptClassRootsStorage.Companion.ScriptClassRoots
) {
protected abstract val fileToConfiguration: (VirtualFile) -> ScriptCompilationConfigurationWrapper?
protected abstract val rootsCacheKey: ScriptClassRootsStorage.Companion.Key
protected abstract fun getConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper?
abstract val firstScriptSdk: Sdk?
@@ -34,7 +32,7 @@ abstract class ScriptClassRootsCache(
abstract fun contains(file: VirtualFile): Boolean
class Fat(
private class Fat(
val scriptConfiguration: ScriptCompilationConfigurationWrapper,
val classFilesScope: GlobalSearchScope
)
@@ -57,7 +55,7 @@ abstract class ScriptClassRootsCache(
private val scriptsDependenciesCache: MutableMap<VirtualFile, Fat> =
ConcurrentFactoryMap.createWeakMap { file ->
val configuration = fileToConfiguration(file) ?: return@createWeakMap null
val configuration = getConfiguration(file) ?: return@createWeakMap null
val roots = configuration.dependenciesClassPath
val sdk = getScriptSdk(file)
@@ -120,6 +118,24 @@ abstract class ScriptClassRootsCache(
fun Sdk.isAlreadyIndexed(project: Project): Boolean {
return ModuleManager.getInstance(project).modules.any { ModuleRootManager.getInstance(it).sdk == this }
}
fun empty(project: Project) = object : ScriptClassRootsCache(
project,
ScriptClassRootsStorage.Companion.Key("empty"),
ScriptClassRootsStorage.Companion.ScriptClassRoots(
setOf(),
setOf(),
setOf()
)
) {
override fun getConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper? = null
override val firstScriptSdk: Sdk? = null
override fun getScriptSdk(file: VirtualFile): Sdk? = null
override fun contains(file: VirtualFile): Boolean = true
}
}
}