From 834372a3b39378057c99698dc49ae420d3b0bc4e Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Fri, 10 Jun 2016 15:07:50 +0200 Subject: [PATCH] Implement extension point for providing script templates --- .../scriptTemplateProviderExtensionPoint.kt | 64 +++++++++++++++++++ .../script/tmpConfigBasedScriptSupport.kt | 17 +++-- .../KotlinScriptConfigurationManager.kt | 7 +- .../script/gradleScriptTemplateProvider.kt | 33 ++++++++++ idea/src/META-INF/extensions/common.xml | 2 + idea/src/META-INF/extensions/ide.xml | 2 + 6 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt create mode 100644 idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt new file mode 100644 index 00000000000..4b36c79850a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTemplateProviderExtensionPoint.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.script + +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.extensions.Extensions +import java.io.File +import java.net.URLClassLoader + +interface ScriptTemplateProvider { + + // for resolving ambiguities + val id: String + val version: Int + + val isValid: Boolean + + val templateClass: String + + val dependenciesClasspath: Iterable + + val context: Any? + + companion object { + val EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.scriptTemplateProvider") + } +} + +fun makeScriptDefsFromTemplateProviderExtesions(errorsHandler: ((ScriptTemplateProvider, Exception) -> Unit) = fun (ep, ex) = println(ex)): List = + makeScriptDefsFromTemplateProviders(Extensions.getExtensions(ScriptTemplateProvider.EP_NAME).asIterable(), + errorsHandler) + +fun makeScriptDefsFromTemplateProviders(providers: Iterable, + errorsHandler: ((ScriptTemplateProvider, Exception) -> Unit) = fun (ep, ex) = println(ex) +): List { + val idToVersion = hashMapOf() + return providers.filter { it.isValid }.sortedByDescending { it.version }.mapNotNull { + try { + idToVersion.get(it.id)?.let { ver -> errorsHandler(it, RuntimeException("Conflicting scriptTemplateProvider ${it.id}, using one with version $ver")) } + val loader = URLClassLoader(it.dependenciesClasspath.map { File(it).toURI().toURL() }.toTypedArray()) + val cl = loader.loadClass(it.templateClass) + idToVersion.put(it.id, it.version) + KotlinScriptDefinitionFromTemplate(cl.kotlin, it.context) + } + catch (ex: Exception) { + errorsHandler(it, ex) + null + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/tmpConfigBasedScriptSupport.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/tmpConfigBasedScriptSupport.kt index 7a8241e71ae..5a9f6270792 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/tmpConfigBasedScriptSupport.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/tmpConfigBasedScriptSupport.kt @@ -39,11 +39,18 @@ fun loadScriptDefConfigs(configFile: File): List = XmlSerializer.deserialize(it, KotlinScripDeftConfig::class.java) } -fun makeScriptDefsFromConfigs(configs: List): List = - configs.map { - val loader = URLClassLoader(it.classpath.map { File(it).toURI().toURL() }.toTypedArray()) - val cl = loader.loadClass(it.def) - KotlinScriptDefinitionFromTemplate(cl.kotlin, null) +fun makeScriptDefsFromConfigs(configs: List, + errorsHandler: ((KotlinScripDeftConfig, Exception) -> Unit) = fun (ep, ex) = println(ex)): List = + configs.mapNotNull { + try { + val loader = URLClassLoader(it.classpath.map { File(it).toURI().toURL() }.toTypedArray()) + val cl = loader.loadClass(it.def) + KotlinScriptDefinitionFromTemplate(cl.kotlin, null) + } + catch (ex: Exception) { + errorsHandler(it, ex) + null + } } @Tag("scriptDef") diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptConfigurationManager.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptConfigurationManager.kt index 4df18de8933..b434e1a23b4 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptConfigurationManager.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptConfigurationManager.kt @@ -83,10 +83,11 @@ class KotlinScriptConfigurationManager( } private fun reloadScriptDefinitions() { - loadScriptConfigsFromProjectRoot(File(project.basePath ?: "")).let { + (makeScriptDefsFromTemplateProviderExtesions(/* TODO: add logging here */) + + loadScriptConfigsFromProjectRoot(File(project.basePath ?: "")).map { KotlinConfigurableScriptDefinition(it, kotlinEnvVars) } + + makeScriptDefsFromConfigs(loadScriptDefConfigsFromProjectRoot(File(project.basePath ?: "")))).let { if (it.isNotEmpty()) { - scriptDefinitionProvider.setScriptDefinitions( - it.map { KotlinConfigurableScriptDefinition(it, kotlinEnvVars) } + StandardScriptDefinition) + scriptDefinitionProvider.setScriptDefinitions(it + StandardScriptDefinition) } } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt new file mode 100644 index 00000000000..da67ab51642 --- /dev/null +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.core.script + +import org.jetbrains.kotlin.script.ScriptTemplateProvider +import java.io.File + +class GradleScriptTemplateProvider: ScriptTemplateProvider { + + private val gradleHome = System.getProperty("idea.gradle.home")?.let { File(it) }?.let { if (it.exists()) it else null } + + override val id: String = "Gradle" + override val version: Int = 1 + override val isValid: Boolean = gradleHome != null + + override val templateClass: String = "org.gradle.script.lang.kotlin.KotlinBuildScript" + override val dependenciesClasspath: Iterable = listOf(File(gradleHome, "gradle_all.jar").absolutePath) + override val context: Any? = gradleHome +} diff --git a/idea/src/META-INF/extensions/common.xml b/idea/src/META-INF/extensions/common.xml index 378acfe3fda..ba2484ae380 100644 --- a/idea/src/META-INF/extensions/common.xml +++ b/idea/src/META-INF/extensions/common.xml @@ -34,5 +34,7 @@ + diff --git a/idea/src/META-INF/extensions/ide.xml b/idea/src/META-INF/extensions/ide.xml index 7971c60231c..f0a1013199d 100644 --- a/idea/src/META-INF/extensions/ide.xml +++ b/idea/src/META-INF/extensions/ide.xml @@ -10,5 +10,7 @@ + +