CompositeScriptConfigurationManager: unified caching
This commit is contained in:
@@ -5,33 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
||||
|
||||
data class ConfigurationData(
|
||||
data class GradleImportedBuildRootData(
|
||||
val templateClasspath: List<String>,
|
||||
val models: List<KotlinDslScriptModel>
|
||||
)
|
||||
|
||||
class Configuration(val data: ConfigurationData) {
|
||||
|
||||
private val scripts: Map<String, KotlinDslScriptModel>
|
||||
val sourcePath: MutableSet<String>
|
||||
|
||||
val classFilePath: MutableSet<String> = mutableSetOf()
|
||||
|
||||
init {
|
||||
val allModels = data.models
|
||||
|
||||
scripts = allModels.associateBy { it.file }
|
||||
sourcePath = allModels.flatMapTo(mutableSetOf()) { it.sourcePath }
|
||||
|
||||
classFilePath.addAll(data.templateClasspath)
|
||||
allModels.flatMapTo(classFilePath) { it.classPath }
|
||||
}
|
||||
fun scriptModel(file: VirtualFile): KotlinDslScriptModel? {
|
||||
return scripts[FileUtil.toSystemDependentName(file.path)]
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.project.Project
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
||||
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.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
|
||||
|
||||
sealed class GradleBuildRoot {
|
||||
abstract val pathPrefix: String
|
||||
|
||||
abstract class Unlinked : GradleBuildRoot()
|
||||
|
||||
class UnlinkedUnknown(override val pathPrefix: String) : Unlinked()
|
||||
|
||||
class UnlinkedLegacy(override val pathPrefix: String) : Unlinked()
|
||||
|
||||
class UnlinkedSupported(override val pathPrefix: String) : Unlinked()
|
||||
|
||||
abstract class Linked : GradleBuildRoot() {
|
||||
@Volatile
|
||||
var importing = false
|
||||
}
|
||||
|
||||
class Legacy(override val pathPrefix: String) : Linked()
|
||||
|
||||
class New(override val pathPrefix: String) : Linked()
|
||||
|
||||
class Imported(
|
||||
val project: Project,
|
||||
val dir: VirtualFile,
|
||||
val context: GradleKtsContext,
|
||||
val data: GradleImportedBuildRootData
|
||||
) : Linked() {
|
||||
override val pathPrefix: String = dir.path
|
||||
|
||||
fun collectConfigurations(builder: ScriptClassRootsCache.Builder) {
|
||||
val javaHome = context.javaHome
|
||||
javaHome?.let { builder.addSdk(it) }
|
||||
|
||||
val anyScript = data.models.firstOrNull()?.let {
|
||||
LocalFileSystem.getInstance().findFileByPath(it.file)
|
||||
}
|
||||
|
||||
val scriptDefinition: ScriptDefinition? = anyScript?.findScriptDefinition(project)
|
||||
|
||||
if (scriptDefinition != null) {
|
||||
builder.classes.addAll(data.templateClasspath)
|
||||
}
|
||||
|
||||
val root = ScriptInfoRoot(this, scriptDefinition)
|
||||
|
||||
data.models.forEach {
|
||||
builder.scripts[it.file] = ScriptInfo(root, it)
|
||||
|
||||
builder.classes.addAll(it.classPath)
|
||||
builder.sources.addAll(it.sourcePath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Common info between scripts (to save bits inside ScriptInfo)
|
||||
*/
|
||||
data class ScriptInfoRoot(
|
||||
val buildRoot: Imported,
|
||||
val scriptDefinition: ScriptDefinition?
|
||||
)
|
||||
|
||||
data class ScriptInfo(
|
||||
val root: ScriptInfoRoot,
|
||||
val model: KotlinDslScriptModel
|
||||
) : ScriptClassRootsCache.LightScriptInfo() {
|
||||
val buildRoot get() = root.buildRoot
|
||||
|
||||
override fun buildConfiguration(): ScriptCompilationConfigurationWrapper? {
|
||||
val javaHome = buildRoot.context.javaHome
|
||||
val scriptDefinition = root.scriptDefinition
|
||||
|
||||
val scriptFile = File(model.file)
|
||||
val virtualFile = VfsUtil.findFile(scriptFile.toPath(), true)!!
|
||||
|
||||
if (scriptDefinition == null) return null
|
||||
|
||||
return ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(
|
||||
VirtualFileScriptSource(virtualFile),
|
||||
scriptDefinition.compilationConfiguration.with {
|
||||
if (javaHome != null) {
|
||||
jvm.jdkHome(javaHome)
|
||||
}
|
||||
defaultImports(model.imports)
|
||||
dependencies(JvmDependency(model.classPath.map { File(it) }))
|
||||
ide.dependenciesSources(JvmDependency(model.sourcePath.map { File(it) }))
|
||||
}.adjustByDefinition(scriptDefinition)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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.project.Project
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
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.Companion.getScriptSdkOrDefault
|
||||
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.scripting.gradle.importing.KotlinDslScriptModel
|
||||
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 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
|
||||
|
||||
class GradleClassRootsCache(
|
||||
val project: Project,
|
||||
val context: GradleKtsContext,
|
||||
val configuration: Configuration
|
||||
) : ScriptClassRootsCache(
|
||||
project,
|
||||
ScriptClassRootsStorage.Companion.Key("gradle"),
|
||||
extractRoots(context, configuration, project)
|
||||
) {
|
||||
override fun getConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper? =
|
||||
configuration.scriptModel(file)?.toScriptConfiguration()
|
||||
|
||||
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? {
|
||||
return firstScriptSdk
|
||||
}
|
||||
|
||||
override val firstScriptSdk: Sdk? = getScriptSdkOrDefault(context.javaHome, project)
|
||||
|
||||
// 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
|
||||
|
||||
companion object {
|
||||
fun extractRoots(context: GradleKtsContext, configuration: Configuration?, project: Project): ScriptClassRoots {
|
||||
if (configuration == null) {
|
||||
return ScriptClassRootsStorage.EMPTY
|
||||
}
|
||||
val scriptSdk = getScriptSdkOrDefault(context.javaHome, project)
|
||||
if (scriptSdk != null && !scriptSdk.isAlreadyIndexed(project)) {
|
||||
return ScriptClassRootsStorage.Companion.ScriptClassRoots(
|
||||
configuration.classFilePath,
|
||||
configuration.sourcePath,
|
||||
setOf(scriptSdk)
|
||||
)
|
||||
}
|
||||
return ScriptClassRoots(
|
||||
configuration.classFilePath,
|
||||
configuration.sourcePath,
|
||||
getScriptSdkOrDefault(context.javaHome, project)?.let { setOf(it) } ?: setOf()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -9,36 +9,23 @@ import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangeListener
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
|
||||
|
||||
open class GradleScriptListener(project: Project) : ScriptChangeListener(project) {
|
||||
class GradleScriptListener(project: Project) : ScriptChangeListener(project) {
|
||||
init {
|
||||
// start GradleScriptInputsWatcher to track changes in gradle-configuration related files
|
||||
project.service<GradleScriptInputsWatcher>().startWatching()
|
||||
}
|
||||
|
||||
override fun editorActivated(vFile: VirtualFile, updater: ScriptConfigurationUpdater) {
|
||||
if (!isInAffectedGradleProjectFiles(project, vFile.path)) return
|
||||
|
||||
if (useScriptConfigurationFromImportOnly()) {
|
||||
// do nothing
|
||||
} else {
|
||||
val file = getAnalyzableKtFileForScript(vFile) ?: return
|
||||
updater.suggestToUpdateConfigurationIfOutOfDate(file)
|
||||
}
|
||||
}
|
||||
|
||||
override fun documentChanged(vFile: VirtualFile, updater: ScriptConfigurationUpdater) {
|
||||
if (!isInAffectedGradleProjectFiles(project, vFile.path)) return
|
||||
|
||||
val file = getAnalyzableKtFileForScript(vFile)
|
||||
if (file != null) {
|
||||
// *.gradle.kts file was changed
|
||||
updater.suggestToUpdateConfigurationIfOutOfDate(file)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isApplicable(vFile: VirtualFile): Boolean {
|
||||
return isGradleKotlinScript(vFile)
|
||||
return GradleScriptingSupportProvider.getInstance(project).isApplicable(vFile)
|
||||
}
|
||||
|
||||
override fun editorActivated(vFile: VirtualFile) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun documentChanged(vFile: VirtualFile) {
|
||||
|
||||
GradleScriptingSupportProvider.getInstance(project).getScriptInfo(vFile)?.model?.inputs
|
||||
}
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
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.psi.KtFile
|
||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||
|
||||
class GradleScriptingSupport(
|
||||
val project: Project,
|
||||
val buildRoot: VirtualFile,
|
||||
val context: GradleKtsContext,
|
||||
val configuration: Configuration
|
||||
) : ScriptingSupport() {
|
||||
|
||||
override fun recreateRootsCache() = GradleClassRootsCache(project, context, configuration)
|
||||
|
||||
fun isConfigurationOutOfDate(file: VirtualFile): Boolean {
|
||||
val scriptModel = configuration.scriptModel(file) ?: return false
|
||||
return !scriptModel.inputs.isUpToDate(project, file)
|
||||
}
|
||||
|
||||
override fun clearCaches() {
|
||||
// todo: should clear up to date
|
||||
}
|
||||
|
||||
override fun hasCachedConfiguration(file: KtFile): Boolean =
|
||||
configuration.scriptModel(file.originalFile.virtualFile) != null
|
||||
|
||||
// TODO: can be true during import
|
||||
override fun isConfigurationLoadingInProgress(file: KtFile): Boolean = false
|
||||
|
||||
override fun getOrLoadConfiguration(virtualFile: VirtualFile, preloadedKtFile: KtFile?): ScriptCompilationConfigurationWrapper? {
|
||||
return classpathRoots.getScriptConfiguration(virtualFile)
|
||||
}
|
||||
|
||||
override val updater: ScriptConfigurationUpdater
|
||||
get() = object : ScriptConfigurationUpdater {
|
||||
override fun ensureUpToDatedConfigurationSuggested(file: KtFile) {
|
||||
// do nothing for gradle scripts
|
||||
}
|
||||
|
||||
// unused symbol inspection should not initiate loading
|
||||
override fun ensureConfigurationUpToDate(files: List<KtFile>): Boolean = true
|
||||
|
||||
override fun suggestToUpdateConfigurationIfOutOfDate(file: KtFile) {
|
||||
val vFile = file.originalFile.virtualFile
|
||||
|
||||
if (isConfigurationOutOfDate(vFile)) {
|
||||
showNotificationForProjectImport(project)
|
||||
} else {
|
||||
hideNotificationForProjectImport(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+156
-100
@@ -5,82 +5,146 @@
|
||||
|
||||
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.ScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
|
||||
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.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.settings.*
|
||||
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].
|
||||
* Manages [roots] gradle build roots:
|
||||
* - populated after Gradle project sync, by calling [update]
|
||||
* - stored in FS and loaded in [init]
|
||||
*/
|
||||
class GradleScriptingSupportProvider(val project: Project) : ScriptingSupport.Provider() {
|
||||
private val rootsIndexer = ScriptClassRootsIndexer(project)
|
||||
val manager: CompositeScriptConfigurationManager
|
||||
get() = ScriptConfigurationManager.getInstance(project) as CompositeScriptConfigurationManager
|
||||
|
||||
val roots = RootsIndex<GradleScriptingSupport>()
|
||||
override val all get() = roots.values
|
||||
private val updater
|
||||
get() = manager.updater
|
||||
|
||||
val roots = RootsIndex()
|
||||
|
||||
////////////
|
||||
/// ScriptingSupport.Provider implementation:
|
||||
|
||||
override fun updateScriptDefinitions() {
|
||||
// nothing related to script definition and project roots are cached
|
||||
}
|
||||
|
||||
override fun isApplicable(file: VirtualFile): Boolean {
|
||||
val buildRoot = findScriptBuildRoot(file) ?: return false
|
||||
if (buildRoot is GradleBuildRoot.Legacy) return false
|
||||
if (buildRoot is GradleBuildRoot.UnlinkedLegacy) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isConfigurationLoadingInProgress(file: KtFile): Boolean {
|
||||
return when (val root = findScriptBuildRoot(file.originalFile.virtualFile)) {
|
||||
is GradleBuildRoot.Linked -> root.importing
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun collectConfigurations(builder: ScriptClassRootsCache.Builder) {
|
||||
roots.values.forEach { root ->
|
||||
if (root is GradleBuildRoot.Imported) {
|
||||
root.collectConfigurations(builder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////
|
||||
|
||||
private val VirtualFile.localPath
|
||||
get() = path
|
||||
|
||||
private fun findRoot(file: VirtualFile) = roots.findRoot(file.localPath)
|
||||
fun getScriptInfo(file: VirtualFile): GradleBuildRoot.Imported.ScriptInfo? =
|
||||
manager.getLightScriptInfo(file.localPath) as? GradleBuildRoot.Imported.ScriptInfo
|
||||
|
||||
override fun getSupport(file: VirtualFile): ScriptingSupport? {
|
||||
if (isGradleKotlinScript(file)) {
|
||||
findRoot(file)?.let { return it }
|
||||
fun findScriptBuildRoot(file: VirtualFile): GradleBuildRoot? {
|
||||
if (!isGradleKotlinScript(file)) return null
|
||||
|
||||
val externalProjectSettings = findExternalProjectSettings(file) ?: return null
|
||||
if (kotlinDslScriptsModelImportSupported(getGradleVersion(project, externalProjectSettings))) {
|
||||
return unlinkedFilesSupport
|
||||
}
|
||||
}
|
||||
return null
|
||||
val path = file.localPath
|
||||
val found = roots.findNearestRoot(path)
|
||||
if (found != null) return found
|
||||
|
||||
return findNewScriptBuildRoot(path)
|
||||
}
|
||||
|
||||
private fun findExternalProjectSettings(file: VirtualFile): GradleProjectSettings? {
|
||||
private fun findNewScriptBuildRoot(scriptPath: String): GradleBuildRoot {
|
||||
val newRoot = updater.update {
|
||||
loadScriptBuildRoot(scriptPath)
|
||||
}
|
||||
roots[newRoot.pathPrefix] = newRoot
|
||||
return newRoot
|
||||
}
|
||||
|
||||
private fun updateBuildRoot(rootPath: String) {
|
||||
val settings = getGradleProjectSettings(rootPath) ?: return
|
||||
val newRoot = loadLinkedRoot(settings)
|
||||
roots[newRoot.pathPrefix] = newRoot
|
||||
if (newRoot is GradleBuildRoot.Imported) {
|
||||
updater.ensureUpdateScheduled()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadScriptBuildRoot(scriptPath: String): GradleBuildRoot {
|
||||
val settings = findNearestGradleProjectSettings(scriptPath) ?: return detectUnlinkedGradleBuildRoot(scriptPath)
|
||||
return loadLinkedRoot(settings)
|
||||
}
|
||||
|
||||
private fun loadLinkedRoot(settings: GradleProjectSettings) =
|
||||
tryLoadFromFsCache(settings) ?: createOtherLinkedRoot(settings)
|
||||
|
||||
private fun createOtherLinkedRoot(settings: GradleProjectSettings): GradleBuildRoot.Linked {
|
||||
val supported = kotlinDslScriptsModelImportSupported(settings.resolveGradleVersion().version)
|
||||
return when {
|
||||
supported -> GradleBuildRoot.New(settings.externalProjectPath)
|
||||
else -> GradleBuildRoot.Legacy(settings.externalProjectPath)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGradleProjectSettings(workingDir: String): GradleProjectSettings? {
|
||||
return (ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID) as GradleSettings)
|
||||
.getLinkedProjectSettings(workingDir)
|
||||
}
|
||||
|
||||
private fun findNearestGradleProjectSettings(localPath: String): GradleProjectSettings? {
|
||||
return getGradleProjectSettings(project)
|
||||
.filter { file.localPath.startsWith(it.externalProjectPath) }
|
||||
.filter { 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)
|
||||
}
|
||||
private fun detectUnlinkedGradleBuildRoot(file: String): GradleBuildRoot.Unlinked =
|
||||
GradleBuildRoot.UnlinkedUnknown(file)
|
||||
|
||||
if (support != null) {
|
||||
set(support.buildRoot.localPath, support)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
init {
|
||||
getGradleProjectSettings(project).forEach {
|
||||
roots[it.externalProjectPath] = loadLinkedRoot(it)
|
||||
}
|
||||
|
||||
// subscribe to gradle build unlink
|
||||
val listener = object : GradleSettingsListenerAdapter() {
|
||||
override fun onProjectsLinked(settings: MutableCollection<GradleProjectSettings>) {
|
||||
settings.forEach {
|
||||
loadLinkedRoot(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProjectsUnlinked(linkedProjectPaths: MutableSet<String>) {
|
||||
linkedProjectPaths.forEach {
|
||||
val buildRoot = VfsUtil.findFile(Paths.get(it), false)
|
||||
@@ -91,30 +155,68 @@ class GradleScriptingSupportProvider(val project: Project) : ScriptingSupport.Pr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGradleHomeChange(oldPath: String?, newPath: String?, linkedProjectPath: String) {
|
||||
updateBuildRoot(linkedProjectPath)
|
||||
manager.updater.ensureUpdateScheduled()
|
||||
}
|
||||
|
||||
override fun onGradleDistributionTypeChange(currentValue: DistributionType?, linkedProjectPath: String) {
|
||||
updateBuildRoot(linkedProjectPath)
|
||||
manager.updater.ensureUpdateScheduled()
|
||||
}
|
||||
}
|
||||
|
||||
project.messageBus.connect(project).subscribe(GradleSettingsListener.TOPIC, listener)
|
||||
}
|
||||
|
||||
private fun tryLoadFromFsCache(settings: GradleProjectSettings) =
|
||||
tryCreateImportedRoot(settings.externalProjectPath) {
|
||||
KotlinDslScriptModels.read(it)
|
||||
}
|
||||
|
||||
fun markImportingInProgress(workingDir: String) {
|
||||
val linked = roots.getBuildRoot(workingDir) as? GradleBuildRoot.Linked
|
||||
if (linked != null) {
|
||||
linked.importing = true
|
||||
} else {
|
||||
val settings = getGradleProjectSettings(workingDir)
|
||||
if (settings != null) {
|
||||
val root = createOtherLinkedRoot(settings)
|
||||
root.importing = true
|
||||
roots[workingDir] = root
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun update(build: KotlinDslGradleBuildSync) {
|
||||
val settings = getGradleProjectSettings(build.workingDir) ?: return
|
||||
|
||||
(roots.getBuildRoot(build.workingDir) as? GradleBuildRoot.Linked)?.importing = false
|
||||
|
||||
if (!kotlinDslScriptsModelImportSupported(settings.resolveGradleVersion().version)) {
|
||||
roots[build.workingDir] = GradleBuildRoot.Legacy(build.workingDir)
|
||||
return
|
||||
}
|
||||
|
||||
// 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 root = roots.findNearestRoot(build.workingDir) ?: return
|
||||
if (root is GradleBuildRoot.Imported && root.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
|
||||
val data = GradleImportedBuildRootData(templateClasspath, build.models)
|
||||
val newSupport = tryCreateImportedRoot(build.workingDir) { data } ?: return
|
||||
KotlinDslScriptModels.write(newSupport.dir, data)
|
||||
roots[build.workingDir] = newSupport
|
||||
manager.updater.ensureUpdateScheduled()
|
||||
}
|
||||
|
||||
private fun createSupport(
|
||||
private fun tryCreateImportedRoot(
|
||||
externalProjectPath: String,
|
||||
dataProvider: (buildRoot: VirtualFile) -> ConfigurationData?
|
||||
): GradleScriptingSupport? {
|
||||
dataProvider: (buildRoot: VirtualFile) -> GradleImportedBuildRootData?
|
||||
): GradleBuildRoot.Imported? {
|
||||
val gradleExeSettings =
|
||||
ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
||||
project,
|
||||
@@ -125,28 +227,15 @@ class GradleScriptingSupportProvider(val project: Project) : ScriptingSupport.Pr
|
||||
val buildRoot = VfsUtil.findFile(Paths.get(externalProjectPath), true) ?: return null
|
||||
val data = dataProvider(buildRoot) ?: return null
|
||||
|
||||
val newSupport = GradleScriptingSupport(
|
||||
val newSupport = GradleBuildRoot.Imported(
|
||||
project,
|
||||
buildRoot,
|
||||
GradleKtsContext(gradleExeSettings.javaHome?.let { File(it) }),
|
||||
Configuration(data)
|
||||
data
|
||||
)
|
||||
|
||||
val oldSupport = roots.findRoot(externalProjectPath)
|
||||
val oldSupport = roots.findNearestRoot(externalProjectPath)
|
||||
if (oldSupport != null) {
|
||||
rootsIndexer.transaction {
|
||||
val newRoots = GradleClassRootsCache.extractRoots(newSupport.context, newSupport.configuration, project)
|
||||
if (oldSupport.classpathRoots.hasNotCachedRoots(newRoots)) {
|
||||
rootsIndexer.markNewRoot()
|
||||
}
|
||||
|
||||
newSupport.clearClassRootsCaches(project)
|
||||
|
||||
ScriptingSupportHelper.updateHighlighting(project) {
|
||||
newSupport.configuration.scriptModel(it) != null
|
||||
}
|
||||
}
|
||||
|
||||
hideNotificationForProjectImport(project)
|
||||
}
|
||||
|
||||
@@ -161,44 +250,11 @@ class GradleScriptingSupportProvider(val project: Project) : ScriptingSupport.Pr
|
||||
?.templateClasspath?.map { it.path }
|
||||
}
|
||||
|
||||
private val unlinkedFilesSupport = object : ScriptingSupport() {
|
||||
override fun clearCaches() {
|
||||
}
|
||||
|
||||
override fun hasCachedConfiguration(file: KtFile): Boolean = false
|
||||
override fun isConfigurationLoadingInProgress(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)
|
||||
}
|
||||
|
||||
fun isMissingConfigurationCanBeLoadedDuringImport(file: VirtualFile): Boolean {
|
||||
findRoot(file)?.let { return false }
|
||||
|
||||
val externalProjectSettings = findExternalProjectSettings(file) ?: return false
|
||||
return kotlinDslScriptsModelImportSupported(getGradleVersion(project, externalProjectSettings))
|
||||
}
|
||||
|
||||
// used in 201
|
||||
@Suppress("UNUSED")
|
||||
fun isConfigurationOutOfDate(file: VirtualFile): Boolean {
|
||||
val support = findRoot(file) ?: return false
|
||||
return support.isConfigurationOutOfDate(file)
|
||||
val script = getScriptInfo(file) ?: return false
|
||||
return script.model.inputs.isUpToDate(project, file)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+10
-10
@@ -16,18 +16,20 @@ import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotifications
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.legacy.GradleLegacyScriptConfigurationLoaderForOutOfProjectScripts
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
|
||||
class MissingGradleScriptConfigurationNotificationProvider(private val project: Project) : EditorNotifications.Provider<EditorNotificationPanel>() {
|
||||
class MissingGradleScriptConfigurationNotificationProvider(private val project: Project) :
|
||||
EditorNotifications.Provider<EditorNotificationPanel>() {
|
||||
override fun getKey(): Key<EditorNotificationPanel> = KEY
|
||||
|
||||
override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor): EditorNotificationPanel? {
|
||||
if (!isGradleKotlinScript(file)) return null
|
||||
if (file.fileType != KotlinFileType.INSTANCE) return null
|
||||
|
||||
if (!isInAffectedGradleProjectFiles(project, file.path)) {
|
||||
return EditorNotificationPanel().apply {
|
||||
return when (GradleScriptingSupportProvider.getInstance(project).findScriptBuildRoot(file)) {
|
||||
is GradleBuildRoot.UnlinkedSupported -> EditorNotificationPanel().apply {
|
||||
text(KotlinIdeaGradleBundle.message("text.the.associated.gradle.project.isn.t.imported"))
|
||||
|
||||
val linkProjectText = KotlinIdeaGradleBundle.message("action.label.text.load.script.configuration")
|
||||
@@ -53,22 +55,20 @@ class MissingGradleScriptConfigurationNotificationProvider(private val project:
|
||||
linkProjectText
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (GradleScriptingSupportProvider.getInstance(project).isMissingConfigurationCanBeLoadedDuringImport(file)) {
|
||||
return EditorNotificationPanel().apply {
|
||||
is GradleBuildRoot.Linked -> EditorNotificationPanel().apply {
|
||||
text(getMissingConfigurationNotificationText())
|
||||
createActionLabel(getMissingConfigurationActionText()) {
|
||||
runPartialGradleImport(project)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private val loaderForOutOfProjectScripts by lazy {
|
||||
GradleScriptConfigurationLoaderForOutOfProjectScripts(project)
|
||||
GradleLegacyScriptConfigurationLoaderForOutOfProjectScripts(
|
||||
project
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+2
@@ -9,6 +9,7 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
|
||||
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptingSupportProvider
|
||||
|
||||
class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
|
||||
override fun onStart(id: ExternalSystemTaskId, workingDir: String?) {
|
||||
@@ -18,6 +19,7 @@ class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
|
||||
if (workingDir == null) return
|
||||
val project = id.findProject() ?: return
|
||||
|
||||
GradleScriptingSupportProvider.getInstance(project).markImportingInProgress(workingDir)
|
||||
project.kotlinGradleDslSync[id] = KotlinDslGradleBuildSync(workingDir, id)
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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
|
||||
package org.jetbrains.kotlin.idea.scripting.gradle.legacy
|
||||
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
@@ -15,6 +15,10 @@ import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigura
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.DefaultScriptConfigurationLoader
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoadingContext
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.isGradleKotlinScript
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.isInAffectedGradleProjectFiles
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.useScriptConfigurationFromImportOnly
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||
@@ -24,7 +28,7 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||
*
|
||||
* TODO(gradle6): remove
|
||||
*/
|
||||
class GradleScriptConfigurationLoaderForOutOfProjectScripts(project: Project) : DefaultScriptConfigurationLoader(project) {
|
||||
class GradleLegacyScriptConfigurationLoaderForOutOfProjectScripts(project: Project) : DefaultScriptConfigurationLoader(project) {
|
||||
override fun loadDependencies(
|
||||
isFirstLoad: Boolean,
|
||||
ktFile: KtFile,
|
||||
@@ -53,7 +57,7 @@ class GradleScriptConfigurationLoaderForOutOfProjectScripts(project: Project) :
|
||||
*
|
||||
* TODO(gradle6): remove
|
||||
*/
|
||||
class GradleScriptConfigurationLoader(project: Project) : DefaultScriptConfigurationLoader(project) {
|
||||
class GradleLegacyScriptConfigurationLoader(project: Project) : DefaultScriptConfigurationLoader(project) {
|
||||
override fun shouldRunInBackground(scriptDefinition: ScriptDefinition): Boolean {
|
||||
return if (useScriptConfigurationFromImportOnly()) false else super.shouldRunInBackground(scriptDefinition)
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.legacy
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangeListener
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.*
|
||||
|
||||
class GradleLegacyScriptListener(project: Project) : ScriptChangeListener(project) {
|
||||
override fun isApplicable(vFile: VirtualFile): Boolean {
|
||||
return isGradleKotlinScript(vFile)
|
||||
}
|
||||
|
||||
override fun editorActivated(vFile: VirtualFile) {
|
||||
if (!isInAffectedGradleProjectFiles(project, vFile.path)) return
|
||||
|
||||
if (useScriptConfigurationFromImportOnly()) {
|
||||
// do nothing
|
||||
} else {
|
||||
val file = getAnalyzableKtFileForScript(vFile) ?: return
|
||||
default.suggestToUpdateConfigurationIfOutOfDate(file)
|
||||
}
|
||||
}
|
||||
|
||||
override fun documentChanged(vFile: VirtualFile) {
|
||||
if (!isInAffectedGradleProjectFiles(project, vFile.path)) return
|
||||
|
||||
val file = getAnalyzableKtFileForScript(vFile)
|
||||
if (file != null) {
|
||||
// *.gradle.kts file was changed
|
||||
default.suggestToUpdateConfigurationIfOutOfDate(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import java.io.DataOutput
|
||||
internal object KotlinDslScriptModels {
|
||||
private val attribute = FileAttribute("kotlin-dsl-script-models", 3, false)
|
||||
|
||||
fun read(buildRoot: VirtualFile): ConfigurationData? {
|
||||
fun read(buildRoot: VirtualFile): GradleImportedBuildRootData? {
|
||||
return attribute.readAttribute(buildRoot)?.use {
|
||||
it.readNullable {
|
||||
readKotlinDslScriptModels(it)
|
||||
@@ -27,9 +27,9 @@ internal object KotlinDslScriptModels {
|
||||
}
|
||||
}
|
||||
|
||||
fun write(buildRoot: VirtualFile, configuration: ConfigurationData?) {
|
||||
fun write(buildRoot: VirtualFile, data: GradleImportedBuildRootData?) {
|
||||
attribute.writeAttribute(buildRoot).use {
|
||||
it.writeNullable(configuration) {
|
||||
it.writeNullable(data) {
|
||||
writeKotlinDslScriptModels(this, it)
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ internal object KotlinDslScriptModels {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun writeKotlinDslScriptModels(output: DataOutput, data: ConfigurationData) {
|
||||
internal fun writeKotlinDslScriptModels(output: DataOutput, data: GradleImportedBuildRootData) {
|
||||
val strings = StringsPool.writer(output)
|
||||
strings.addStrings(data.templateClasspath)
|
||||
data.models.forEach {
|
||||
@@ -61,7 +61,7 @@ internal fun writeKotlinDslScriptModels(output: DataOutput, data: ConfigurationD
|
||||
}
|
||||
}
|
||||
|
||||
internal fun readKotlinDslScriptModels(input: DataInputStream): ConfigurationData {
|
||||
internal fun readKotlinDslScriptModels(input: DataInputStream): GradleImportedBuildRootData {
|
||||
val strings = StringsPool.reader(input)
|
||||
|
||||
val templateClasspath = strings.readStrings()
|
||||
@@ -77,7 +77,7 @@ internal fun readKotlinDslScriptModels(input: DataInputStream): ConfigurationDat
|
||||
)
|
||||
}
|
||||
|
||||
return ConfigurationData(templateClasspath, models)
|
||||
return GradleImportedBuildRootData(templateClasspath, models)
|
||||
}
|
||||
|
||||
private object StringsPool {
|
||||
|
||||
@@ -23,7 +23,8 @@ import org.jetbrains.plugins.gradle.settings.GradleLocalSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import java.util.*
|
||||
import org.slf4j.LoggerFactory
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
private val sections = arrayListOf("buildscript", "plugins", "initscript", "pluginManagement")
|
||||
|
||||
@@ -107,38 +108,45 @@ fun getGradleProjectSettings(project: Project): Collection<GradleProjectSettings
|
||||
return gradleSettings.getLinkedProjectsSettings()
|
||||
}
|
||||
|
||||
class RootsIndex<T : Any> {
|
||||
internal val tree = TreeMap<String, T>()
|
||||
var values: Collection<T> = listOf()
|
||||
internal set
|
||||
class RootsIndex {
|
||||
private val log = LoggerFactory.getLogger(RootsIndex::class.java)
|
||||
|
||||
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
|
||||
}
|
||||
private val buildRoots = HashMap<String, GradleBuildRoot>()
|
||||
private val scripts = HashMap<String, GradleBuildRoot>()
|
||||
val values: Collection<GradleBuildRoot>
|
||||
get() = buildRoots.values
|
||||
|
||||
internal inline fun update(updater: (insert: (prefix: String, value: T) -> Unit) -> Unit) {
|
||||
synchronized(this) {
|
||||
updater { prefix, value -> tree[prefix] = value }
|
||||
values = tree.values
|
||||
}
|
||||
@Synchronized
|
||||
fun rebuildProjectRoots() {
|
||||
// values.forEach {
|
||||
// it.
|
||||
// }
|
||||
}
|
||||
|
||||
@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`"
|
||||
}
|
||||
fun getBuildRoot(dir: String) = buildRoots[dir]
|
||||
|
||||
tree[prefix] = value
|
||||
values = tree.values
|
||||
@Synchronized
|
||||
fun findNearestRoot(path: String): GradleBuildRoot? {
|
||||
var max: Pair<String, GradleBuildRoot>? = null
|
||||
buildRoots.entries.forEach {
|
||||
if (path.startsWith(it.key) && (max == null || it.key.length > max!!.first.length)) {
|
||||
max = it.key to it.value
|
||||
}
|
||||
}
|
||||
return max?.second
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun remove(prefix: String) = tree.remove(prefix)
|
||||
operator fun set(prefix: String, value: GradleBuildRoot) {
|
||||
val old = buildRoots.put(prefix, value)
|
||||
rebuildProjectRoots()
|
||||
log.info("{}: {} -> {}", prefix, old, value)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun remove(prefix: String) = buildRoots.remove(prefix)?.also {
|
||||
rebuildProjectRoots()
|
||||
log.info("{}: removed", prefix)
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.scripting.gradle
|
||||
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationLoadingTest
|
||||
import org.jetbrains.kotlin.idea.scripting.gradle.legacy.GradleLegacyScriptConfigurationLoaderForOutOfProjectScripts
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
@@ -34,7 +35,9 @@ class GradleScriptOutOfProjectTest : AbstractScriptConfigurationLoadingTest() {
|
||||
}
|
||||
|
||||
private val loaderForOutOfProjectScripts by lazy {
|
||||
GradleScriptConfigurationLoaderForOutOfProjectScripts(project)
|
||||
GradleLegacyScriptConfigurationLoaderForOutOfProjectScripts(
|
||||
project
|
||||
)
|
||||
}
|
||||
|
||||
fun testManualLoadingForUpToDate() {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import kotlin.test.assertEquals
|
||||
class KotlinDslScriptModelsTest {
|
||||
@Test
|
||||
fun write() {
|
||||
val data = ConfigurationData(
|
||||
val data = GradleImportedBuildRootData(
|
||||
listOf("a", "b", "c"),
|
||||
listOf(
|
||||
KotlinDslScriptModel(
|
||||
|
||||
@@ -18,16 +18,16 @@ class RootsIndexTest {
|
||||
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"))
|
||||
assertEquals(1, roots.findNearestRoot("a/b/c/x"))
|
||||
assertEquals(1, roots.findNearestRoot("a/b/c"))
|
||||
assertEquals(3, roots.findNearestRoot("a/c/x"))
|
||||
assertEquals(3, roots.findNearestRoot("a/c"))
|
||||
assertEquals(4, roots.findNearestRoot("d"))
|
||||
assertEquals(4, roots.findNearestRoot("d/x"))
|
||||
assertEquals(null, roots.findNearestRoot("e"))
|
||||
assertEquals(null, roots.findNearestRoot("e/f"))
|
||||
|
||||
roots["d"] = 5
|
||||
assertEquals(5, roots.findRoot("d"))
|
||||
assertEquals(5, roots.findNearestRoot("d"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user