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:
committed by
Natalia Selezneva
parent
34df3066b3
commit
73760effee
+3
-6
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.projectRoots.JavaSdkType
|
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.roots.ProjectRootManager.*
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.openapi.vfs.StandardFileSystems
|
import com.intellij.openapi.vfs.StandardFileSystems
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
@@ -30,7 +31,6 @@ 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.configuration.CompositeScriptConfigurationManager
|
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.listener.ScriptConfigurationUpdater
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoader
|
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoader
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
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.definitions.ScriptDependenciesProvider
|
||||||
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.utils.addToStdlib.firstIsInstance
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.experimental.api.asSuccess
|
import kotlin.script.experimental.api.asSuccess
|
||||||
import kotlin.script.experimental.api.makeFailureResult
|
import kotlin.script.experimental.api.makeFailureResult
|
||||||
@@ -162,15 +161,13 @@ interface ScriptConfigurationManager {
|
|||||||
@TestOnly
|
@TestOnly
|
||||||
fun updateScriptDependenciesSynchronously(file: PsiFile) {
|
fun updateScriptDependenciesSynchronously(file: PsiFile) {
|
||||||
// TODO: review the usages of this method
|
// TODO: review the usages of this method
|
||||||
(getInstance(file.project) as CompositeScriptConfigurationManager).managers
|
(getInstance(file.project) as CompositeScriptConfigurationManager).default
|
||||||
.firstIsInstance<DefaultScriptingSupport>()
|
|
||||||
.updateScriptDependenciesSynchronously(file)
|
.updateScriptDependenciesSynchronously(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
fun clearCaches(project: Project) {
|
fun clearCaches(project: Project) {
|
||||||
(getInstance(project) as CompositeScriptConfigurationManager).managers
|
(getInstance(project) as CompositeScriptConfigurationManager).default
|
||||||
.firstIsInstance<DefaultScriptingSupport>()
|
|
||||||
.clearCaches()
|
.clearCaches()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-7
@@ -22,16 +22,25 @@ import org.jetbrains.kotlin.idea.core.script.configuration.utils.getKtFile
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.isNonScript
|
import org.jetbrains.kotlin.scripting.definitions.isNonScript
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
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 {
|
class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigurationManager {
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private val notifier = ScriptChangesNotifier(project, updater)
|
private val notifier = ScriptChangesNotifier(project, updater)
|
||||||
|
|
||||||
// todo public for tests
|
private val providers = ScriptingSupport.Provider.EPN.getPoint(project).extensionList
|
||||||
val managers = ScriptingSupport.SCRIPTING_SUPPORT.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 =
|
private fun getRelatedManager(file: KtFile): ScriptingSupport =
|
||||||
getRelatedManager(file.originalFile.virtualFile)
|
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
|
* Loads script configuration if classpath roots don't contain [file] yet
|
||||||
*/
|
*/
|
||||||
private fun getActualClasspathRoots(file: VirtualFile): ScriptClassRootsCache {
|
private fun getActualClasspathRoots(file: VirtualFile): ScriptClassRootsCache {
|
||||||
val classpathRoots = getRelatedManager(file).classpathRoots
|
val manager = getRelatedManager(file)
|
||||||
|
|
||||||
|
val classpathRoots = manager.classpathRoots
|
||||||
if (classpathRoots.contains(file)) {
|
if (classpathRoots.contains(file)) {
|
||||||
return classpathRoots
|
return classpathRoots
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrLoadConfiguration(file)
|
getOrLoadConfiguration(file)
|
||||||
|
|
||||||
return getRelatedManager(file).classpathRoots
|
return manager.classpathRoots
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getScriptSdk(file: VirtualFile): Sdk? =
|
override fun getScriptSdk(file: VirtualFile): Sdk? =
|
||||||
@@ -115,7 +126,7 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
|
|||||||
override fun forceReloadConfiguration(file: VirtualFile, loader: ScriptConfigurationLoader): ScriptCompilationConfigurationWrapper? {
|
override fun forceReloadConfiguration(file: VirtualFile, loader: ScriptConfigurationLoader): ScriptCompilationConfigurationWrapper? {
|
||||||
val ktFile = project.getKtFile(file, null) ?: return null
|
val ktFile = project.getKtFile(file, null) ?: return null
|
||||||
|
|
||||||
return managers.firstIsInstanceOrNull<DefaultScriptingSupport>()?.forceReloadConfiguration(ktFile, loader)
|
return default.forceReloadConfiguration(ktFile, loader)
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|||||||
+1
-5
@@ -33,7 +33,6 @@ 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.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
import org.jetbrains.kotlin.scripting.resolve.ScriptReportSink
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
import kotlin.script.experimental.api.ScriptDiagnostic
|
import kotlin.script.experimental.api.ScriptDiagnostic
|
||||||
@@ -312,8 +311,6 @@ abstract class DefaultScriptingSupportBase(val project: Project) : ScriptingSupp
|
|||||||
fun getAppliedConfiguration(file: VirtualFile?): ScriptConfigurationSnapshot? =
|
fun getAppliedConfiguration(file: VirtualFile?): ScriptConfigurationSnapshot? =
|
||||||
getCachedConfigurationState(file)?.applied
|
getCachedConfigurationState(file)?.applied
|
||||||
|
|
||||||
override fun isRelated(file: VirtualFile): Boolean = true
|
|
||||||
|
|
||||||
override fun hasCachedConfiguration(file: KtFile): Boolean =
|
override fun hasCachedConfiguration(file: KtFile): Boolean =
|
||||||
getAppliedConfiguration(file.originalFile.virtualFile) != null
|
getAppliedConfiguration(file.originalFile.virtualFile) != null
|
||||||
|
|
||||||
@@ -438,6 +435,5 @@ object DefaultScriptConfigurationManagerExtensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val ScriptConfigurationManager.testingBackgroundExecutor
|
val ScriptConfigurationManager.testingBackgroundExecutor
|
||||||
get() = (this as CompositeScriptConfigurationManager).managers
|
get() = (this as CompositeScriptConfigurationManager).default
|
||||||
.firstIsInstance<DefaultScriptingSupport>()
|
|
||||||
.backgroundExecutor as TestingBackgroundExecutor
|
.backgroundExecutor as TestingBackgroundExecutor
|
||||||
+10
-6
@@ -21,7 +21,16 @@ import java.util.concurrent.locks.ReentrantLock
|
|||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
abstract class ScriptingSupport {
|
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 clearCaches()
|
||||||
abstract fun hasCachedConfiguration(file: KtFile): Boolean
|
abstract fun hasCachedConfiguration(file: KtFile): Boolean
|
||||||
@@ -68,9 +77,4 @@ abstract class ScriptingSupport {
|
|||||||
|
|
||||||
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
val SCRIPTING_SUPPORT: ExtensionPointName<ScriptingSupport> =
|
|
||||||
ExtensionPointName.create("org.jetbrains.kotlin.scripting.idea.scriptingSupport")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+11
-22
@@ -16,15 +16,16 @@ import java.io.File
|
|||||||
internal class DefaultClassRootsCache(
|
internal class DefaultClassRootsCache(
|
||||||
project: Project,
|
project: Project,
|
||||||
private val all: Map<VirtualFile, ScriptCompilationConfigurationWrapper>
|
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?
|
override fun getConfiguration(file: VirtualFile) = all[file]
|
||||||
get() = { all[it] }
|
|
||||||
|
|
||||||
override fun contains(file: VirtualFile): Boolean = file in all
|
override fun contains(file: VirtualFile): Boolean = file in all
|
||||||
|
|
||||||
override val rootsCacheKey = ScriptClassRootsStorage.Companion.Key("default")
|
|
||||||
|
|
||||||
private val scriptsSdksCache: Map<VirtualFile, Sdk?> =
|
private val scriptsSdksCache: Map<VirtualFile, Sdk?> =
|
||||||
ConcurrentFactoryMap.createWeakMap { file ->
|
ConcurrentFactoryMap.createWeakMap { file ->
|
||||||
return@createWeakMap getScriptSdk(
|
return@createWeakMap getScriptSdk(
|
||||||
@@ -44,30 +45,18 @@ internal class DefaultClassRootsCache(
|
|||||||
project: Project,
|
project: Project,
|
||||||
configuration: ScriptCompilationConfigurationWrapper
|
configuration: ScriptCompilationConfigurationWrapper
|
||||||
): ScriptClassRootsStorage.Companion.ScriptClassRoots {
|
): ScriptClassRootsStorage.Companion.ScriptClassRoots {
|
||||||
val scriptSdk =
|
val scriptSdk = getScriptSdk(configuration.javaHome)
|
||||||
getScriptSdkOfDefault(
|
|
||||||
configuration.javaHome,
|
|
||||||
project
|
|
||||||
)
|
|
||||||
if (scriptSdk != null && !scriptSdk.isAlreadyIndexed(project)) {
|
if (scriptSdk != null && !scriptSdk.isAlreadyIndexed(project)) {
|
||||||
return ScriptClassRootsStorage.Companion.ScriptClassRoots(
|
return ScriptClassRootsStorage.Companion.ScriptClassRoots(
|
||||||
toStringValues(
|
toStringValues(configuration.dependenciesClassPath),
|
||||||
configuration.dependenciesClassPath
|
toStringValues(configuration.dependenciesSources),
|
||||||
),
|
|
||||||
toStringValues(
|
|
||||||
configuration.dependenciesSources
|
|
||||||
),
|
|
||||||
setOf(scriptSdk)
|
setOf(scriptSdk)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ScriptClassRootsStorage.Companion.ScriptClassRoots(
|
return ScriptClassRootsStorage.Companion.ScriptClassRoots(
|
||||||
toStringValues(
|
toStringValues(configuration.dependenciesClassPath),
|
||||||
configuration.dependenciesClassPath
|
toStringValues(configuration.dependenciesSources),
|
||||||
),
|
|
||||||
toStringValues(
|
|
||||||
configuration.dependenciesSources
|
|
||||||
),
|
|
||||||
emptySet()
|
emptySet()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-6
@@ -18,15 +18,13 @@ import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
|||||||
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
|
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.FileSystems
|
|
||||||
|
|
||||||
abstract class ScriptClassRootsCache(
|
abstract class ScriptClassRootsCache(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
|
private val rootsCacheKey: ScriptClassRootsStorage.Companion.Key,
|
||||||
private val roots: ScriptClassRootsStorage.Companion.ScriptClassRoots
|
private val roots: ScriptClassRootsStorage.Companion.ScriptClassRoots
|
||||||
) {
|
) {
|
||||||
protected abstract val fileToConfiguration: (VirtualFile) -> ScriptCompilationConfigurationWrapper?
|
protected abstract fun getConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper?
|
||||||
|
|
||||||
protected abstract val rootsCacheKey: ScriptClassRootsStorage.Companion.Key
|
|
||||||
|
|
||||||
abstract val firstScriptSdk: Sdk?
|
abstract val firstScriptSdk: Sdk?
|
||||||
|
|
||||||
@@ -34,7 +32,7 @@ abstract class ScriptClassRootsCache(
|
|||||||
|
|
||||||
abstract fun contains(file: VirtualFile): Boolean
|
abstract fun contains(file: VirtualFile): Boolean
|
||||||
|
|
||||||
class Fat(
|
private class Fat(
|
||||||
val scriptConfiguration: ScriptCompilationConfigurationWrapper,
|
val scriptConfiguration: ScriptCompilationConfigurationWrapper,
|
||||||
val classFilesScope: GlobalSearchScope
|
val classFilesScope: GlobalSearchScope
|
||||||
)
|
)
|
||||||
@@ -57,7 +55,7 @@ abstract class ScriptClassRootsCache(
|
|||||||
|
|
||||||
private val scriptsDependenciesCache: MutableMap<VirtualFile, Fat> =
|
private val scriptsDependenciesCache: MutableMap<VirtualFile, Fat> =
|
||||||
ConcurrentFactoryMap.createWeakMap { file ->
|
ConcurrentFactoryMap.createWeakMap { file ->
|
||||||
val configuration = fileToConfiguration(file) ?: return@createWeakMap null
|
val configuration = getConfiguration(file) ?: return@createWeakMap null
|
||||||
|
|
||||||
val roots = configuration.dependenciesClassPath
|
val roots = configuration.dependenciesClassPath
|
||||||
val sdk = getScriptSdk(file)
|
val sdk = getScriptSdk(file)
|
||||||
@@ -120,6 +118,24 @@ abstract class ScriptClassRootsCache(
|
|||||||
fun Sdk.isAlreadyIndexed(project: Project): Boolean {
|
fun Sdk.isAlreadyIndexed(project: Project): Boolean {
|
||||||
return ModuleManager.getInstance(project).modules.any { ModuleRootManager.getInstance(it).sdk == this }
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+44
-10
@@ -7,31 +7,65 @@ package org.jetbrains.kotlin.idea.scripting.gradle
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.projectRoots.Sdk
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage.Companion.ScriptClassRoots
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage.Companion.ScriptClassRoots
|
||||||
|
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.jvm.JvmDependency
|
||||||
|
import kotlin.script.experimental.jvm.jdkHome
|
||||||
|
import kotlin.script.experimental.jvm.jvm
|
||||||
|
|
||||||
internal class GradleClassRootsCache(
|
class GradleClassRootsCache(
|
||||||
project: Project,
|
val project: Project,
|
||||||
configuration: Configuration?,
|
val context: GradleKtsContext,
|
||||||
override val fileToConfiguration: (VirtualFile) -> ScriptCompilationConfigurationWrapper?
|
val configuration: Configuration
|
||||||
) : ScriptClassRootsCache(project, extractRoots(configuration)) {
|
) : ScriptClassRootsCache(
|
||||||
|
project,
|
||||||
|
ScriptClassRootsStorage.Companion.Key("gradle"),
|
||||||
|
extractRoots(context, configuration, project)
|
||||||
|
) {
|
||||||
|
override fun getConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper? =
|
||||||
|
configuration.scriptModel(file)?.toScriptConfiguration()
|
||||||
|
|
||||||
override val rootsCacheKey = ScriptClassRootsStorage.Companion.Key("gradle")
|
private fun KotlinDslScriptModel.toScriptConfiguration(): ScriptCompilationConfigurationWrapper? {
|
||||||
|
val scriptFile = File(file)
|
||||||
|
val virtualFile = VfsUtil.findFile(scriptFile.toPath(), true)!!
|
||||||
|
|
||||||
|
val definition = virtualFile.findScriptDefinition(project) ?: return null
|
||||||
|
|
||||||
|
return ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(
|
||||||
|
VirtualFileScriptSource(virtualFile),
|
||||||
|
definition.compilationConfiguration.with {
|
||||||
|
if (context.javaHome != null) {
|
||||||
|
jvm.jdkHome(context.javaHome)
|
||||||
|
}
|
||||||
|
defaultImports(imports)
|
||||||
|
dependencies(JvmDependency(classPath.map { File(it) }))
|
||||||
|
ide.dependenciesSources(JvmDependency(sourcePath.map { File(it) }))
|
||||||
|
}.adjustByDefinition(definition)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getScriptSdk(file: VirtualFile): Sdk? {
|
override fun getScriptSdk(file: VirtualFile): Sdk? {
|
||||||
return firstScriptSdk
|
return firstScriptSdk
|
||||||
}
|
}
|
||||||
|
|
||||||
override val firstScriptSdk: Sdk? = configuration?.let { getScriptSdk(configuration.context.javaHome) }
|
override val firstScriptSdk: Sdk? = configuration?.let { getScriptSdk(context.javaHome) }
|
||||||
|
|
||||||
// TODO what should we do if no configuration is loaded yet
|
// called to ensure that configuration for file is loaded
|
||||||
|
// as we cannot force loading, we always return true
|
||||||
override fun contains(file: VirtualFile): Boolean = true
|
override fun contains(file: VirtualFile): Boolean = true
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun extractRoots(configuration: Configuration?): ScriptClassRoots {
|
fun extractRoots(context: GradleKtsContext, configuration: Configuration?, project: Project): ScriptClassRoots {
|
||||||
if (configuration == null) {
|
if (configuration == null) {
|
||||||
return ScriptClassRootsStorage.EMPTY
|
return ScriptClassRootsStorage.EMPTY
|
||||||
}
|
}
|
||||||
@@ -46,7 +80,7 @@ internal class GradleClassRootsCache(
|
|||||||
return ScriptClassRoots(
|
return ScriptClassRoots(
|
||||||
configuration.classFilePath,
|
configuration.classFilePath,
|
||||||
configuration.sourcePath,
|
configuration.sourcePath,
|
||||||
getScriptSdk(configuration.context.javaHome)?.let { setOf(it) } ?: setOf()
|
getScriptSdk(context.javaHome)?.let { setOf(it) } ?: setOf()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class GradleKtsContext(val javaHome: File?)
|
||||||
+25
-96
@@ -5,42 +5,37 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
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.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupport
|
import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupport
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupportHelper
|
import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupportHelper
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
|
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
|
||||||
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.ScriptClassRootsIndexer
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.GradleKtsContext
|
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.createGradleKtsContextIfPossible
|
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.toScriptConfiguration
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
import java.nio.file.Paths
|
|
||||||
|
|
||||||
|
data class ConfigurationData(
|
||||||
internal data class ConfigurationData(
|
|
||||||
val templateClasspath: List<String>,
|
val templateClasspath: List<String>,
|
||||||
val models: List<KotlinDslScriptModel>
|
val models: List<KotlinDslScriptModel>
|
||||||
)
|
)
|
||||||
|
|
||||||
internal class Configuration(val context: GradleKtsContext, data: ConfigurationData) {
|
class Configuration(val data: ConfigurationData) {
|
||||||
val scripts = data.models.associateBy { it.file }
|
private val scripts: Map<String, KotlinDslScriptModel>
|
||||||
val sourcePath = data.models.flatMapTo(mutableSetOf()) { it.sourcePath }
|
|
||||||
|
|
||||||
|
val sourcePath: MutableSet<String>
|
||||||
val classFilePath: MutableSet<String> = mutableSetOf()
|
val classFilePath: MutableSet<String> = mutableSetOf()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
val allModels = data.models
|
||||||
|
|
||||||
|
scripts = allModels.associateBy { it.file }
|
||||||
|
sourcePath = allModels.flatMapTo(mutableSetOf()) { it.sourcePath }
|
||||||
|
|
||||||
classFilePath.addAll(data.templateClasspath)
|
classFilePath.addAll(data.templateClasspath)
|
||||||
data.models.flatMapTo(classFilePath) { it.classPath }
|
allModels.flatMapTo(classFilePath) { it.classPath }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scriptModel(file: VirtualFile): KotlinDslScriptModel? {
|
fun scriptModel(file: VirtualFile): KotlinDslScriptModel? {
|
||||||
@@ -48,74 +43,33 @@ internal class Configuration(val context: GradleKtsContext, data: ConfigurationD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GradleScriptingSupport(val project: Project) : ScriptingSupport() {
|
class GradleScriptingSupport(
|
||||||
@Volatile
|
private val rootsIndexer: ScriptClassRootsIndexer,
|
||||||
private var configuration: Configuration? = null
|
val project: Project,
|
||||||
|
val buildRoot: VirtualFile,
|
||||||
private val rootsIndexer = ScriptClassRootsIndexer(project)
|
val context: GradleKtsContext,
|
||||||
|
val configuration: Configuration
|
||||||
|
) : ScriptingSupport() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (isKotlinDslScriptsModelImportSupported(project)) {
|
|
||||||
ApplicationManager.getApplication().executeOnPooledThread {
|
|
||||||
val data = KotlinDslScriptModels.read(project)
|
|
||||||
val gradleKtsContext = createGradleKtsContextIfPossible(project)
|
|
||||||
if (data != null && gradleKtsContext != null) {
|
|
||||||
val newConfiguration = Configuration(
|
|
||||||
gradleKtsContext,
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
configuration = newConfiguration
|
|
||||||
configurationChangedCallback(newConfiguration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun recreateRootsCache(): ScriptClassRootsCache {
|
|
||||||
return GradleClassRootsCache(project, configuration) {
|
|
||||||
configuration?.let { conf ->
|
|
||||||
val model = conf.scriptModel(it)
|
|
||||||
model?.toScriptConfiguration(conf.context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun replace(context: GradleKtsContext, models: List<KotlinDslScriptModel>) {
|
|
||||||
if (models.isEmpty()) return
|
|
||||||
|
|
||||||
val anyScript = VfsUtil.findFile(Paths.get(models.first().file), true)!!
|
|
||||||
|
|
||||||
val definition = anyScript.findScriptDefinition(context.project) ?: return
|
|
||||||
val templateClasspath = definition.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()
|
|
||||||
?.templateClasspath?.map { it.path } ?: return
|
|
||||||
|
|
||||||
val data = ConfigurationData(templateClasspath, models)
|
|
||||||
KotlinDslScriptModels.write(project, data)
|
|
||||||
|
|
||||||
val newConfiguration = Configuration(context, data)
|
|
||||||
configuration = newConfiguration
|
|
||||||
|
|
||||||
configurationChangedCallback(newConfiguration)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun configurationChangedCallback(newConfiguration: Configuration) {
|
|
||||||
rootsIndexer.transaction {
|
rootsIndexer.transaction {
|
||||||
if (classpathRoots.hasNotCachedRoots(GradleClassRootsCache.extractRoots(newConfiguration))) {
|
if (classpathRoots.hasNotCachedRoots(GradleClassRootsCache.extractRoots(context, configuration, project))) {
|
||||||
rootsIndexer.markNewRoot()
|
rootsIndexer.markNewRoot()
|
||||||
}
|
}
|
||||||
|
|
||||||
clearClassRootsCaches(project)
|
clearClassRootsCaches(project)
|
||||||
|
|
||||||
ScriptingSupportHelper.updateHighlighting(project) {
|
ScriptingSupportHelper.updateHighlighting(project) {
|
||||||
configuration?.scriptModel(it) != null
|
configuration.scriptModel(it) != null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hideNotificationForProjectImport(project)
|
hideNotificationForProjectImport(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateNotification(file: KtFile) {
|
override fun recreateRootsCache() = GradleClassRootsCache(project, context, configuration)
|
||||||
|
|
||||||
|
private fun updateNotification(file: KtFile) {
|
||||||
val vFile = file.originalFile.virtualFile
|
val vFile = file.originalFile.virtualFile
|
||||||
val scriptModel = configuration?.scriptModel(vFile) ?: return
|
val scriptModel = configuration?.scriptModel(vFile) ?: return
|
||||||
|
|
||||||
@@ -126,34 +80,15 @@ class GradleScriptingSupport(val project: Project) : ScriptingSupport() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isRelated(file: VirtualFile): Boolean {
|
|
||||||
if (isGradleKotlinScript(file)) {
|
|
||||||
return isKotlinDslScriptsModelImportSupported(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isKotlinDslScriptsModelImportSupported(project: Project): Boolean {
|
|
||||||
val gradleVersion = getGradleVersion(project)
|
|
||||||
return gradleVersion != null && kotlinDslScriptsModelImportSupported(gradleVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clearCaches() {
|
override fun clearCaches() {
|
||||||
// todo should clear up to date
|
// todo: should clear up to date
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasCachedConfiguration(file: KtFile): Boolean =
|
override fun hasCachedConfiguration(file: KtFile): Boolean =
|
||||||
configuration?.scriptModel(file.originalFile.virtualFile) != null
|
configuration.scriptModel(file.originalFile.virtualFile) != null
|
||||||
|
|
||||||
override fun getOrLoadConfiguration(virtualFile: VirtualFile, preloadedKtFile: KtFile?): ScriptCompilationConfigurationWrapper? {
|
override fun getOrLoadConfiguration(virtualFile: VirtualFile, preloadedKtFile: KtFile?): ScriptCompilationConfigurationWrapper? {
|
||||||
val configuration = configuration
|
return classpathRoots.getScriptConfiguration(virtualFile)
|
||||||
if (configuration == null) {
|
|
||||||
// todo: show notification "Import gradle project"
|
|
||||||
return null
|
|
||||||
} else {
|
|
||||||
return classpathRoots.getScriptConfiguration(virtualFile)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val updater: ScriptConfigurationUpdater
|
override val updater: ScriptConfigurationUpdater
|
||||||
@@ -169,10 +104,4 @@ class GradleScriptingSupport(val project: Project) : ScriptingSupport() {
|
|||||||
updateNotification(file)
|
updateNotification(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getInstance(project: Project): GradleScriptingSupport {
|
|
||||||
return SCRIPTING_SUPPORT.getPoint(project).extensionList.firstIsInstance()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+173
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupport
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
|
||||||
|
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.scripting.gradle.importing.KotlinDslGradleBuildSync
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
|
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter
|
||||||
|
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
|
||||||
|
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||||
|
import org.jetbrains.plugins.gradle.settings.GradleSettingsListener
|
||||||
|
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates [GradleScriptingSupport] per each linked Gradle build.
|
||||||
|
* Gradle project sync should call [update].
|
||||||
|
*/
|
||||||
|
class GradleScriptingSupportProvider(val project: Project) : ScriptingSupport.Provider() {
|
||||||
|
private val rootsIndexer = ScriptClassRootsIndexer(project)
|
||||||
|
|
||||||
|
val roots = RootsIndex<GradleScriptingSupport>()
|
||||||
|
override val all get() = roots.values
|
||||||
|
|
||||||
|
private val VirtualFile.localPath
|
||||||
|
get() = path
|
||||||
|
|
||||||
|
private fun findRoot(file: VirtualFile) = roots.findRoot(file.localPath)
|
||||||
|
|
||||||
|
override fun getSupport(file: VirtualFile): ScriptingSupport? {
|
||||||
|
if (isGradleKotlinScript(file)) {
|
||||||
|
findRoot(file)?.let { return it }
|
||||||
|
|
||||||
|
val externalProjectSettings = findExternalProjectSettings(file) ?: return null
|
||||||
|
if (kotlinDslScriptsModelImportSupported(getGradleVersion(project, externalProjectSettings))) {
|
||||||
|
return unlinkedFilesSupport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findExternalProjectSettings(file: VirtualFile): GradleProjectSettings? {
|
||||||
|
return getGradleProjectSettings(project)
|
||||||
|
.filter { file.localPath.startsWith(it.externalProjectPath) }
|
||||||
|
.maxBy { it.externalProjectPath.length }
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
ApplicationManager.getApplication().executeOnPooledThread {
|
||||||
|
roots.update { set ->
|
||||||
|
getGradleProjectSettings(project).forEach { gradleProjectSettings ->
|
||||||
|
if (kotlinDslScriptsModelImportSupported(getGradleVersion(project, gradleProjectSettings))) {
|
||||||
|
val support = createSupport(gradleProjectSettings.externalProjectPath) {
|
||||||
|
KotlinDslScriptModels.read(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (support != null) {
|
||||||
|
set(support.buildRoot.localPath, support)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// subscribe to gradle build unlink
|
||||||
|
val listener = object : GradleSettingsListenerAdapter() {
|
||||||
|
override fun onProjectsUnlinked(linkedProjectPaths: MutableSet<String>) {
|
||||||
|
linkedProjectPaths.forEach {
|
||||||
|
val buildRoot = VfsUtil.findFile(Paths.get(it), false)
|
||||||
|
if (buildRoot != null) {
|
||||||
|
if (roots.remove(buildRoot.localPath) != null) {
|
||||||
|
KotlinDslScriptModels.remove(buildRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.messageBus.connect(project).subscribe(GradleSettingsListener.TOPIC, listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(build: KotlinDslGradleBuildSync) {
|
||||||
|
// fast path for linked gradle builds without .gradle.kts support
|
||||||
|
if (build.models.isEmpty()) {
|
||||||
|
val root = roots.findRoot(build.workingDir) ?: return
|
||||||
|
if (root.configuration.data.models.isEmpty()) return
|
||||||
|
}
|
||||||
|
|
||||||
|
val templateClasspath = findTemplateClasspath(build) ?: return
|
||||||
|
val data = ConfigurationData(templateClasspath, build.models)
|
||||||
|
val newSupport = createSupport(build.workingDir) { data } ?: return
|
||||||
|
KotlinDslScriptModels.write(newSupport.buildRoot, data)
|
||||||
|
|
||||||
|
roots[newSupport.buildRoot.localPath] = newSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createSupport(
|
||||||
|
externalProjectPath: String,
|
||||||
|
dataProvider: (buildRoot: VirtualFile) -> ConfigurationData?
|
||||||
|
): GradleScriptingSupport? {
|
||||||
|
val gradleExeSettings =
|
||||||
|
ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
||||||
|
project,
|
||||||
|
externalProjectPath,
|
||||||
|
GradleConstants.SYSTEM_ID
|
||||||
|
)
|
||||||
|
|
||||||
|
val buildRoot = VfsUtil.findFile(Paths.get(externalProjectPath), true) ?: return null
|
||||||
|
val data = dataProvider(buildRoot) ?: return null
|
||||||
|
|
||||||
|
return GradleScriptingSupport(
|
||||||
|
rootsIndexer,
|
||||||
|
project,
|
||||||
|
buildRoot,
|
||||||
|
GradleKtsContext(gradleExeSettings.javaHome?.let { File(it) }),
|
||||||
|
Configuration(data)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findTemplateClasspath(build: KotlinDslGradleBuildSync): List<String>? {
|
||||||
|
val anyScript = VfsUtil.findFile(Paths.get(build.models.first().file), true)!!
|
||||||
|
// todo: find definition according to build.workingDir
|
||||||
|
val definition = anyScript.findScriptDefinition(project) ?: return null
|
||||||
|
return definition.asLegacyOrNull<KotlinScriptDefinitionFromAnnotatedTemplate>()
|
||||||
|
?.templateClasspath?.map { it.path }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val unlinkedFilesSupport = object : ScriptingSupport() {
|
||||||
|
override fun clearCaches() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasCachedConfiguration(file: KtFile): Boolean = false
|
||||||
|
|
||||||
|
override fun getOrLoadConfiguration(
|
||||||
|
virtualFile: VirtualFile,
|
||||||
|
preloadedKtFile: KtFile?
|
||||||
|
): ScriptCompilationConfigurationWrapper? = null
|
||||||
|
|
||||||
|
override val updater: ScriptConfigurationUpdater
|
||||||
|
get() = object : ScriptConfigurationUpdater {
|
||||||
|
override fun ensureUpToDatedConfigurationSuggested(file: KtFile) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ensureConfigurationUpToDate(files: List<KtFile>): Boolean = false
|
||||||
|
|
||||||
|
override fun suggestToUpdateConfigurationIfOutOfDate(file: KtFile) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun recreateRootsCache(): ScriptClassRootsCache = ScriptClassRootsCache.empty(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getInstance(project: Project): GradleScriptingSupportProvider =
|
||||||
|
EPN.getPoint(project).extensionList.firstIsInstance()
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-58
@@ -9,29 +9,22 @@ import com.intellij.openapi.components.service
|
|||||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import org.gradle.tooling.model.kotlin.dsl.EditorReportSeverity
|
import org.gradle.tooling.model.kotlin.dsl.EditorReportSeverity
|
||||||
import org.gradle.tooling.model.kotlin.dsl.KotlinDslScriptsModel
|
import org.gradle.tooling.model.kotlin.dsl.KotlinDslScriptsModel
|
||||||
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
|
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptInputsWatcher
|
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptInputsWatcher
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptingSupport
|
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptingSupportProvider
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp
|
import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.getJavaHomeForGradleProject
|
|
||||||
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
||||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition
|
|
||||||
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
|
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.script.experimental.api.*
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import kotlin.script.experimental.jvm.JvmDependency
|
|
||||||
import kotlin.script.experimental.jvm.jdkHome
|
|
||||||
import kotlin.script.experimental.jvm.jvm
|
|
||||||
|
|
||||||
var Project.kotlinDslModels: ArrayList<KotlinDslScriptModel>
|
var Project.kotlinGradleDslSync: MutableMap<ExternalSystemTaskId, KotlinDslGradleBuildSync>
|
||||||
by NotNullableUserDataProperty<Project, ArrayList<KotlinDslScriptModel>>(
|
by NotNullableUserDataProperty<Project, MutableMap<ExternalSystemTaskId, KotlinDslGradleBuildSync>>(
|
||||||
Key("Kotlin DSL Scripts Models"), arrayListOf()
|
Key("Kotlin DSL Scripts Models"), ConcurrentHashMap()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun processScriptModel(
|
fun processScriptModel(
|
||||||
@@ -44,14 +37,11 @@ fun processScriptModel(
|
|||||||
"Couldn't get KotlinDslScriptsModel for $projectName:\n${model.message}\n${model.stackTrace}"
|
"Couldn't get KotlinDslScriptsModel for $projectName:\n${model.message}\n${model.stackTrace}"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val project = resolverCtx.externalSystemTaskId.findProject() ?: return
|
val task = resolverCtx.externalSystemTaskId
|
||||||
|
val project = task.findProject() ?: return
|
||||||
val models = model.toListOfScriptModels(project)
|
val models = model.toListOfScriptModels(project)
|
||||||
project.kotlinDslModels.addAll(
|
|
||||||
models
|
project.kotlinGradleDslSync[task]?.models?.addAll(models)
|
||||||
)
|
|
||||||
if (models.containsErrors()) {
|
|
||||||
throw IllegalStateException(KotlinIdeaGradleBundle.message("title.kotlin.build.script"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (models.containsErrors()) {
|
if (models.containsErrors()) {
|
||||||
throw IllegalStateException(KotlinIdeaGradleBundle.message("title.kotlin.build.script"))
|
throw IllegalStateException(KotlinIdeaGradleBundle.message("title.kotlin.build.script"))
|
||||||
@@ -111,52 +101,22 @@ private fun KotlinDslScriptsModel.toListOfScriptModels(project: Project): List<K
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createGradleKtsContextIfPossible(project: Project): GradleKtsContext? {
|
class KotlinDslGradleBuildSync(val workingDir: String, val taskId: ExternalSystemTaskId) {
|
||||||
val javaHome = getJavaHomeForGradleProject(project)?.let { File(it)}
|
val models = mutableListOf<KotlinDslScriptModel>()
|
||||||
|
|
||||||
return GradleKtsContext(project, javaHome)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GradleKtsContext(val project: Project, val javaHome: File?)
|
fun saveScriptModels(project: Project, build: KotlinDslGradleBuildSync) {
|
||||||
|
val errorReporter = KotlinGradleDslErrorReporter(project, build.taskId)
|
||||||
|
|
||||||
fun KotlinDslScriptModel.toScriptConfiguration(context: GradleKtsContext): ScriptCompilationConfigurationWrapper? {
|
build.models.forEach { model ->
|
||||||
val scriptFile = File(file)
|
|
||||||
val virtualFile = VfsUtil.findFile(scriptFile.toPath(), true)!!
|
|
||||||
|
|
||||||
val definition = virtualFile.findScriptDefinition(context.project) ?: return null
|
|
||||||
|
|
||||||
return ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(
|
|
||||||
VirtualFileScriptSource(virtualFile),
|
|
||||||
definition.compilationConfiguration.with {
|
|
||||||
if (context.javaHome != null) {
|
|
||||||
jvm.jdkHome(context.javaHome)
|
|
||||||
}
|
|
||||||
defaultImports(imports)
|
|
||||||
dependencies(JvmDependency(classPath.map { File(it) }))
|
|
||||||
ide.dependenciesSources(JvmDependency(sourcePath.map { File(it) }))
|
|
||||||
}.adjustByDefinition(definition)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveScriptModels(
|
|
||||||
project: Project,
|
|
||||||
task: ExternalSystemTaskId,
|
|
||||||
javaHomeStr: String?,
|
|
||||||
models: List<KotlinDslScriptModel>
|
|
||||||
) {
|
|
||||||
val errorReporter = KotlinGradleDslErrorReporter(project, task)
|
|
||||||
|
|
||||||
val javaHome = javaHomeStr?.let { File(it) }
|
|
||||||
val context = GradleKtsContext(project, javaHome)
|
|
||||||
|
|
||||||
models.forEach { model ->
|
|
||||||
errorReporter.reportError(File(model.file), model)
|
errorReporter.reportError(File(model.file), model)
|
||||||
}
|
}
|
||||||
|
|
||||||
project.service<GradleScriptInputsWatcher>().saveGradleProjectRootsAfterImport(
|
project.service<GradleScriptInputsWatcher>().saveGradleProjectRootsAfterImport(
|
||||||
models.map { File(it.file).parent }.toSet()
|
build.models.map { FileUtil.toSystemIndependentName(File(it.file).parent) }.toSet()
|
||||||
)
|
)
|
||||||
|
|
||||||
GradleScriptingSupport.getInstance(project).replace(context, models)
|
GradleScriptingSupportProvider.getInstance(project).update(build)
|
||||||
|
|
||||||
project.service<GradleScriptInputsWatcher>().clearState()
|
project.service<GradleScriptInputsWatcher>().clearState()
|
||||||
}
|
}
|
||||||
+12
-10
@@ -9,23 +9,25 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
|||||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
|
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
|
||||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
|
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
|
||||||
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.getJavaHomeForGradleProject
|
|
||||||
|
|
||||||
class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
|
class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
|
||||||
override fun onEnd(id: ExternalSystemTaskId) {
|
override fun onStart(id: ExternalSystemTaskId, workingDir: String?) {
|
||||||
if (id.type != ExternalSystemTaskType.RESOLVE_PROJECT || id.projectSystemId != GRADLE_SYSTEM_ID) {
|
if (id.type != ExternalSystemTaskType.RESOLVE_PROJECT) return
|
||||||
return
|
if (id.projectSystemId != GRADLE_SYSTEM_ID) return
|
||||||
}
|
|
||||||
|
|
||||||
|
if (workingDir == null) return
|
||||||
val project = id.findProject() ?: return
|
val project = id.findProject() ?: return
|
||||||
|
|
||||||
val models: List<KotlinDslScriptModel> = project.kotlinDslModels
|
project.kotlinGradleDslSync[id] = KotlinDslGradleBuildSync(workingDir, id)
|
||||||
project.kotlinDslModels = arrayListOf()
|
}
|
||||||
|
|
||||||
if (models.isEmpty()) return
|
override fun onEnd(id: ExternalSystemTaskId) {
|
||||||
|
if (id.type != ExternalSystemTaskType.RESOLVE_PROJECT) return
|
||||||
|
if (id.projectSystemId != GRADLE_SYSTEM_ID) return
|
||||||
|
|
||||||
val javaHome = getJavaHomeForGradleProject(project)
|
val project = id.findProject() ?: return
|
||||||
|
val sync = project.kotlinGradleDslSync.remove(id) ?: return
|
||||||
|
|
||||||
saveScriptModels(project, id, javaHome, models)
|
saveScriptModels(project, sync)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,35 +5,45 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.openapi.vfs.newvfs.FileAttribute
|
import com.intellij.openapi.vfs.newvfs.FileAttribute
|
||||||
|
import org.jetbrains.kotlin.idea.core.util.readNullable
|
||||||
import org.jetbrains.kotlin.idea.core.util.readString
|
import org.jetbrains.kotlin.idea.core.util.readString
|
||||||
|
import org.jetbrains.kotlin.idea.core.util.writeNullable
|
||||||
import org.jetbrains.kotlin.idea.core.util.writeString
|
import org.jetbrains.kotlin.idea.core.util.writeString
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
||||||
|
import java.io.DataInput
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
import java.io.DataOutputStream
|
import java.io.DataOutput
|
||||||
|
|
||||||
internal object KotlinDslScriptModels {
|
internal object KotlinDslScriptModels {
|
||||||
private val attribute = FileAttribute("kotlin-dsl-script-models", 2, false)
|
private val attribute = FileAttribute("kotlin-dsl-script-models", 3, false)
|
||||||
|
|
||||||
fun read(project: Project): ConfigurationData? {
|
fun read(buildRoot: VirtualFile): ConfigurationData? {
|
||||||
return attribute.readAttribute(project.projectFile ?: return null)?.use {
|
return attribute.readAttribute(buildRoot)?.use {
|
||||||
readKotlinDslScriptModels(it)
|
it.readNullable {
|
||||||
|
readKotlinDslScriptModels(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun write(project: Project, configuration: ConfigurationData) {
|
fun write(buildRoot: VirtualFile, configuration: ConfigurationData?) {
|
||||||
attribute.writeAttribute(project.projectFile ?: return).use {
|
attribute.writeAttribute(buildRoot).use {
|
||||||
writeKotlinDslScriptModels(it, configuration)
|
it.writeNullable(configuration) {
|
||||||
|
writeKotlinDslScriptModels(this, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun remove(buildRoot: VirtualFile) {
|
||||||
|
write(buildRoot, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun writeKotlinDslScriptModels(output: DataOutputStream, data: ConfigurationData) {
|
internal fun writeKotlinDslScriptModels(output: DataOutput, data: ConfigurationData) {
|
||||||
val strings = StringsPool.writer(output)
|
val strings = StringsPool.writer(output)
|
||||||
strings.addStrings(data.templateClasspath)
|
strings.addStrings(data.templateClasspath)
|
||||||
val scriptModels = data.models
|
data.models.forEach {
|
||||||
scriptModels.forEach {
|
|
||||||
strings.addString(it.file)
|
strings.addString(it.file)
|
||||||
strings.addStrings(it.classPath)
|
strings.addStrings(it.classPath)
|
||||||
strings.addStrings(it.sourcePath)
|
strings.addStrings(it.sourcePath)
|
||||||
@@ -41,7 +51,7 @@ internal fun writeKotlinDslScriptModels(output: DataOutputStream, data: Configur
|
|||||||
}
|
}
|
||||||
strings.writeHeader()
|
strings.writeHeader()
|
||||||
strings.writeStringIds(data.templateClasspath)
|
strings.writeStringIds(data.templateClasspath)
|
||||||
output.writeList(scriptModels) {
|
output.writeList(data.models) {
|
||||||
strings.writeStringId(it.file)
|
strings.writeStringId(it.file)
|
||||||
output.writeString(it.inputs.sections)
|
output.writeString(it.inputs.sections)
|
||||||
output.writeLong(it.inputs.inputsTS)
|
output.writeLong(it.inputs.inputsTS)
|
||||||
@@ -71,9 +81,9 @@ internal fun readKotlinDslScriptModels(input: DataInputStream): ConfigurationDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
private object StringsPool {
|
private object StringsPool {
|
||||||
fun writer(output: DataOutputStream) = Writer(output)
|
fun writer(output: DataOutput) = Writer(output)
|
||||||
|
|
||||||
class Writer(val output: DataOutputStream) {
|
class Writer(val output: DataOutput) {
|
||||||
var freeze = false
|
var freeze = false
|
||||||
val ids = mutableMapOf<String, Int>()
|
val ids = mutableMapOf<String, Int>()
|
||||||
|
|
||||||
@@ -106,7 +116,7 @@ private object StringsPool {
|
|||||||
output.writeInt(getStringId(it))
|
output.writeInt(getStringId(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeStringIds(strings: List<String>) {
|
fun writeStringIds(strings: Collection<String>) {
|
||||||
output.writeInt(strings.size)
|
output.writeInt(strings.size)
|
||||||
strings.forEach {
|
strings.forEach {
|
||||||
writeStringId(it)
|
writeStringId(it)
|
||||||
@@ -128,12 +138,12 @@ private object StringsPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <T> DataOutputStream.writeList(list: Collection<T>, write: (T) -> Unit) {
|
private inline fun <T> DataOutput.writeList(list: Collection<T>, write: (T) -> Unit) {
|
||||||
writeInt(list.size)
|
writeInt(list.size)
|
||||||
list.forEach { write(it) }
|
list.forEach { write(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <T> DataInputStream.readList(read: () -> T): List<T> {
|
private inline fun <T> DataInput.readList(read: () -> T): List<T> {
|
||||||
val n = readInt()
|
val n = readInt()
|
||||||
val result = ArrayList<T>(n)
|
val result = ArrayList<T>(n)
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
||||||
import org.jetbrains.plugins.gradle.settings.GradleLocalSettings
|
import org.jetbrains.plugins.gradle.settings.GradleLocalSettings
|
||||||
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
|
|
||||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
private val sections = arrayListOf("buildscript", "plugins", "initscript", "pluginManagement")
|
private val sections = arrayListOf("buildscript", "plugins", "initscript", "pluginManagement")
|
||||||
|
|
||||||
@@ -95,34 +95,50 @@ fun useScriptConfigurationFromImportOnly(): Boolean {
|
|||||||
return Registry.`is`("kotlin.gradle.scripts.useIdeaProjectImport", false)
|
return Registry.`is`("kotlin.gradle.scripts.useIdeaProjectImport", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGradleVersion(project: Project, externalProjectPath: String): String? {
|
fun getGradleVersion(project: Project, settings: GradleProjectSettings): String {
|
||||||
val localVersion = GradleLocalSettings.getInstance(project).getGradleVersion(externalProjectPath)
|
val localVersion = GradleLocalSettings.getInstance(project).getGradleVersion(settings.externalProjectPath)
|
||||||
if (localVersion != null) return localVersion
|
if (localVersion != null) return localVersion
|
||||||
|
|
||||||
return GradleSettings.getInstance(project).getLinkedProjectSettings(externalProjectPath)?.resolveGradleVersion()?.version
|
return settings.resolveGradleVersion().version
|
||||||
}
|
|
||||||
|
|
||||||
fun getGradleVersion(project: Project): String? {
|
|
||||||
val projectSettings = getGradleProjectSettings(project).firstOrNull()
|
|
||||||
|
|
||||||
if (projectSettings != null) {
|
|
||||||
return getGradleVersion(projectSettings.externalProjectPath)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getJavaHomeForGradleProject(project: Project): String? {
|
|
||||||
val projectSettings = getGradleProjectSettings(project).firstOrNull() ?: return null
|
|
||||||
|
|
||||||
val gradleExeSettings = ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
|
||||||
project,
|
|
||||||
projectSettings.externalProjectPath,
|
|
||||||
GradleConstants.SYSTEM_ID
|
|
||||||
)
|
|
||||||
return gradleExeSettings.javaHome
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGradleProjectSettings(project: Project): Collection<GradleProjectSettings> {
|
fun getGradleProjectSettings(project: Project): Collection<GradleProjectSettings> {
|
||||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID) as GradleSettings
|
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID) as GradleSettings
|
||||||
return gradleSettings.getLinkedProjectsSettings()
|
return gradleSettings.getLinkedProjectsSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RootsIndex<T : Any> {
|
||||||
|
internal val tree = TreeMap<String, T>()
|
||||||
|
var values: Collection<T> = listOf()
|
||||||
|
internal set
|
||||||
|
|
||||||
|
fun findRoot(path: String): T? {
|
||||||
|
// race condition can be ignored
|
||||||
|
val values = values
|
||||||
|
val size = values.size
|
||||||
|
if (size == 0) return null
|
||||||
|
if (size == 1) return values.single() // we can omit prefix check
|
||||||
|
return tree.floorEntry(path).takeIf { path.startsWith(it.key) }?.value
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun update(updater: (insert: (prefix: String, value: T) -> Unit) -> Unit) {
|
||||||
|
synchronized(this) {
|
||||||
|
updater { prefix, value -> tree[prefix] = value }
|
||||||
|
values = tree.values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
operator fun set(prefix: String, value: T) {
|
||||||
|
val moreCommon = tree.lowerKey(prefix)
|
||||||
|
check(moreCommon == null || !prefix.startsWith(moreCommon)) {
|
||||||
|
"Cannot add root `${prefix}`. More common root already added: `$moreCommon`"
|
||||||
|
}
|
||||||
|
|
||||||
|
tree[prefix] = value
|
||||||
|
values = tree.values
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun remove(prefix: String) = tree.remove(prefix)
|
||||||
|
}
|
||||||
+4
-5
@@ -16,9 +16,7 @@ import kotlin.test.assertEquals
|
|||||||
class KotlinDslScriptModelsTest {
|
class KotlinDslScriptModelsTest {
|
||||||
@Test
|
@Test
|
||||||
fun write() {
|
fun write() {
|
||||||
val buffer = ByteArrayOutputStream()
|
val data = ConfigurationData(
|
||||||
|
|
||||||
val conf = ConfigurationData(
|
|
||||||
listOf("a", "b", "c"),
|
listOf("a", "b", "c"),
|
||||||
listOf(
|
listOf(
|
||||||
KotlinDslScriptModel(
|
KotlinDslScriptModel(
|
||||||
@@ -40,10 +38,11 @@ class KotlinDslScriptModelsTest {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
writeKotlinDslScriptModels(DataOutputStream(buffer), conf)
|
val buffer = ByteArrayOutputStream()
|
||||||
|
writeKotlinDslScriptModels(DataOutputStream(buffer), data)
|
||||||
|
|
||||||
val restored = readKotlinDslScriptModels(DataInputStream(ByteArrayInputStream(buffer.toByteArray())))
|
val restored = readKotlinDslScriptModels(DataInputStream(ByteArrayInputStream(buffer.toByteArray())))
|
||||||
|
|
||||||
assertEquals(conf.toString(), restored.toString())
|
assertEquals(data.toString(), restored.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFails
|
||||||
|
|
||||||
|
class RootsIndexTest {
|
||||||
|
@Test
|
||||||
|
fun findRoot() {
|
||||||
|
val roots = RootsIndex<Int>()
|
||||||
|
roots["a/b/c"] = 1
|
||||||
|
assertFails { roots["a/b/c/d"] = 2 }
|
||||||
|
roots["a/c"] = 3
|
||||||
|
roots["d"] = 4
|
||||||
|
|
||||||
|
assertEquals(1, roots.findRoot("a/b/c/x"))
|
||||||
|
assertEquals(1, roots.findRoot("a/b/c"))
|
||||||
|
assertEquals(3, roots.findRoot("a/c/x"))
|
||||||
|
assertEquals(3, roots.findRoot("a/c"))
|
||||||
|
assertEquals(4, roots.findRoot("d"))
|
||||||
|
assertEquals(4, roots.findRoot("d/x"))
|
||||||
|
assertEquals(null, roots.findRoot("e"))
|
||||||
|
assertEquals(null, roots.findRoot("e/f"))
|
||||||
|
|
||||||
|
roots["d"] = 5
|
||||||
|
assertEquals(5, roots.findRoot("d"))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
|
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
|
||||||
<listener order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptListener"/>
|
<listener order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptListener"/>
|
||||||
<loader order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptConfigurationLoader"/>
|
<loader order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptConfigurationLoader"/>
|
||||||
<scriptingSupport
|
<scriptingSupportProvider
|
||||||
implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptingSupport"
|
implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptingSupportProvider"
|
||||||
/>
|
/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
|
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
|
||||||
<listener order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptListener"/>
|
<listener order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptListener"/>
|
||||||
<loader order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptConfigurationLoader"/>
|
<loader order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptConfigurationLoader"/>
|
||||||
<scriptingSupport
|
<scriptingSupportProvider
|
||||||
implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptingSupport"
|
implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptingSupportProvider"
|
||||||
/>
|
/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<extensionPoints>
|
<extensionPoints>
|
||||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.scripting.idea.scriptingSupport"
|
<extensionPoint qualifiedName="org.jetbrains.kotlin.scripting.idea.scriptingSupportProvider"
|
||||||
interface="org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupport"
|
interface="org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupport$Provider"
|
||||||
area="IDEA_PROJECT"/>
|
area="IDEA_PROJECT"/>
|
||||||
</extensionPoints>
|
</extensionPoints>
|
||||||
|
|
||||||
@@ -10,11 +10,4 @@
|
|||||||
|
|
||||||
<trafficLightRendererContributor implementation="org.jetbrains.kotlin.idea.core.script.ScriptTrafficLightRendererContributor"/>
|
<trafficLightRendererContributor implementation="org.jetbrains.kotlin.idea.core.script.ScriptTrafficLightRendererContributor"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
|
|
||||||
<scriptingSupport
|
|
||||||
implementation="org.jetbrains.kotlin.idea.core.script.configuration.DefaultScriptingSupport"
|
|
||||||
order="last"
|
|
||||||
/>
|
|
||||||
</extensions>
|
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
Reference in New Issue
Block a user