Refactor configs loading, Add config script definitions reloading on config files changes

This commit is contained in:
Ilya Chernikov
2016-06-01 12:25:53 +02:00
parent 310e8014a8
commit dfc96d216b
3 changed files with 47 additions and 24 deletions
@@ -40,23 +40,21 @@ import java.util.*
val SCRIPT_CONFIG_FILE_EXTENSION = ".ktscfg.xml"
fun loadScriptDefinitionsFromDirectoryWithConfigs(dir: File, kotlinEnvVars: Map<String, List<String>>? = null): List<KotlinConfigurableScriptDefinition> =
dir.walk().filter { it.isFile && it.name.endsWith(SCRIPT_CONFIG_FILE_EXTENSION, ignoreCase = true) }.toList()
.flatMap { loadScriptDefinitionsFromConfig(it, kotlinEnvVars) }
fun isScriptDefinitionConfigFile(it: File) = it.isFile && it.name.endsWith(SCRIPT_CONFIG_FILE_EXTENSION, ignoreCase = true)
fun loadScriptDefinitionsFromConfig(configFile: File, kotlinEnvVars: Map<String, List<String>>? = null): List<KotlinConfigurableScriptDefinition> =
fun loadScriptConfigsFromProjectRoot(projectRoot: File): List<KotlinScriptConfig> =
projectRoot.walk().filter ( ::isScriptDefinitionConfigFile ).toList()
.flatMap { loadScriptConfigs(it) }
fun loadScriptConfigs(configFile: File): List<KotlinScriptConfig> =
JDOMUtil.loadDocument(configFile).rootElement.children.mapNotNull {
XmlSerializer.deserialize(it, KotlinScriptConfig::class.java)?.let {
KotlinConfigurableScriptDefinition(it, kotlinEnvVars)
}
XmlSerializer.deserialize(it, KotlinScriptConfig::class.java)
}
@Suppress("unused") // Used externally
fun loadScriptDefinitionsFromConfig(configStream: InputStream, kotlinEnvVars: Map<String, List<String>>? = null): List<KotlinConfigurableScriptDefinition> =
fun loadScriptConfigs(configStream: InputStream): List<KotlinScriptConfig> =
JDOMUtil.loadDocument(configStream).rootElement.children.mapNotNull {
XmlSerializer.deserialize(it, KotlinScriptConfig::class.java)?.let {
KotlinConfigurableScriptDefinition(it, kotlinEnvVars)
}
XmlSerializer.deserialize(it, KotlinScriptConfig::class.java)
}
@Suppress("unused")
@@ -135,3 +133,4 @@ class KotlinConfigurableScriptDefinition(val config: KotlinScriptConfig, val env
}
}
}
@@ -19,25 +19,34 @@ package org.jetbrains.kotlin.script
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import java.util.*
import kotlin.concurrent.read
import kotlin.concurrent.write
class KotlinScriptDefinitionProvider {
private val definitions: MutableList<KotlinScriptDefinition> = arrayListOf(StandardScriptDefinition)
private val definitionsLock = java.util.concurrent.locks.ReentrantReadWriteLock()
var scriptDefinitions: List<KotlinScriptDefinition>
get() = definitions
get() = definitionsLock.read { definitions } // TODO: remove as unsafe with locking, replace with particular data extractors
set(definitions: List<KotlinScriptDefinition>) {
this.definitions.clear()
this.definitions.addAll(definitions)
definitionsLock.write {
this.definitions.clear()
this.definitions.addAll(definitions)
}
}
fun findScriptDefinition(file: VirtualFile?): KotlinScriptDefinition? = file?.let { file -> definitions.firstOrNull { it.isScript(file) } }
fun findScriptDefinition(file: VirtualFile?): KotlinScriptDefinition? = definitionsLock.read {
file?.let { file -> definitions.firstOrNull { it.isScript(file) } }
}
fun isScript(file: VirtualFile?): Boolean = findScriptDefinition(file) != null
fun addScriptDefinition(scriptDefinition: KotlinScriptDefinition) {
definitions.add(0, scriptDefinition)
definitionsLock.write {
definitions.add(0, scriptDefinition)
}
}
fun removeScriptDefinition(scriptDefinition: KotlinScriptDefinition) {
@@ -18,15 +18,17 @@ package org.jetbrains.kotlin.idea.script
import com.intellij.openapi.components.AbstractProjectComponent
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
import org.jetbrains.kotlin.script.StandardScriptDefinition
import org.jetbrains.kotlin.script.loadScriptDefinitionsFromDirectoryWithConfigs
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.newvfs.BulkFileListener
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import org.jetbrains.kotlin.script.*
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
class KotlinScriptConfigurationManager(project: Project, scriptDefinitionProvider: KotlinScriptDefinitionProvider) : AbstractProjectComponent(project) {
@Suppress("unused") // project component
class KotlinScriptConfigurationManager(private val project: Project, private val scriptDefinitionProvider: KotlinScriptDefinitionProvider) : AbstractProjectComponent(project) {
val kotlinEnvVars: Map<String, List<String>> by lazy {
private val kotlinEnvVars: Map<String, List<String>> by lazy {
val paths = PathUtil.getKotlinPathsForIdeaPlugin()
mapOf("kotlin-runtime" to listOf(paths.runtimePath.canonicalPath),
"project-root" to listOf(project.basePath ?: "."),
@@ -34,9 +36,22 @@ class KotlinScriptConfigurationManager(project: Project, scriptDefinitionProvide
}
init {
loadScriptDefinitionsFromDirectoryWithConfigs(File(project.basePath ?: "."), kotlinEnvVars).let {
reloadScriptDefinitions()
val conn = project.messageBus.connect()
conn.subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener.Adapter() {
override fun after(events: List<VFileEvent>) {
events.firstOrNull { it is VFileEvent && isScriptDefinitionConfigFile(File(it.path)) }?.let {
reloadScriptDefinitions()
}
}
})
}
private fun reloadScriptDefinitions() {
loadScriptConfigsFromProjectRoot(File(project.basePath ?: ".")).let {
if (it.isNotEmpty()) {
scriptDefinitionProvider.scriptDefinitions = it + StandardScriptDefinition
scriptDefinitionProvider.scriptDefinitions =
it.map { KotlinConfigurableScriptDefinition(it, kotlinEnvVars) } + StandardScriptDefinition
}
}
}