Provide a method to update script definitions after loading into IDE

also documenting ScriptDefinitionsProvider
This commit is contained in:
Ilya Chernikov
2020-05-14 14:51:54 +02:00
parent 4b032a14af
commit d92e4d28f5
3 changed files with 62 additions and 14 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource
import kotlin.script.experimental.api.ScriptDiagnostic
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
import kotlin.script.experimental.intellij.ScriptDefinitionsProvider
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
@@ -25,19 +26,28 @@ class BridgeScriptDefinitionsContributor(private val project: Project) : ScriptD
return extensions.asSequence().flatMap { provider ->
val explicitClasses = provider.getDefinitionClasses().toList()
val classPath = provider.getDefinitionsClassPath().toList()
val hostConfiguration = defaultJvmScriptingHostConfiguration
val baseHostConfiguration = defaultJvmScriptingHostConfiguration
// TODO: rewrite load and discovery to return kotlin.script.experimental.host.ScriptDefinition to avoid unnecessary conversions
val explicitDefinitions =
if (explicitClasses.isEmpty()) emptySequence()
else loadDefinitionsFromTemplates(explicitClasses, classPath, hostConfiguration).asSequence()
else loadDefinitionsFromTemplates(explicitClasses, classPath, baseHostConfiguration).asSequence()
val discoveredDefinitions =
if (provider.useDiscovery())
ScriptDefinitionsFromClasspathDiscoverySource(
classPath,
hostConfiguration,
baseHostConfiguration,
::loggingReporter
).definitions
else emptySequence()
explicitDefinitions + discoveredDefinitions
val loadedDefinitions = (explicitDefinitions + discoveredDefinitions).map {
kotlin.script.experimental.host.ScriptDefinition(
it.compilationConfiguration,
it.evaluationConfiguration ?: ScriptEvaluationConfiguration.Default
)
}.toList()
provider.provideDefinitions(baseHostConfiguration, loadedDefinitions).map {
ScriptDefinition.FromNewDefinition(baseHostConfiguration, it)
}.asSequence()
}
}
}
@@ -6,22 +6,55 @@
package kotlin.script.experimental.intellij
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.project.Project
import java.io.File
import kotlin.script.experimental.host.ScriptDefinition
import kotlin.script.experimental.host.ScriptingHostConfiguration
/**
* IntelliJ extension point for providing script definitions
*
* The scripting infrastructure will load this extension point on project instantiation, and then collect all definitions
* provided by the extension point, combining 3 ways, depending on the data returned from the interface members:
* - for all FQNs of classes returned from the [getDefinitionClasses] function, it will load the class with the classpath from
* the [getDefinitionsClassPath] and create it's definition from the KotlinScript annotation
* - if [useDiscovery] method returns true, the classpath returned by [getDefinitionsClassPath] will be scanned for the discovery
* markers, and found script definitions will be loaded and created the same way as ones returned from [getDefinitionClasses]
* After collecting all definitions will be passed to the [provideDefinitions] for possible modifications. The implementation
* may also remove or add new definitions at this point.
* Processed definitions are provided to the scripting support infrastructure.
*/
interface ScriptDefinitionsProvider {
/**
* A display name used to identify particular providers
*/
val id: String
/**
* Should return a list of the FQNs of the script definition template classes to load explicitly, if any
*/
fun getDefinitionClasses(): Iterable<String>
/**
* Should return a classpath required for loading script definition template classes
*/
fun getDefinitionsClassPath(): Iterable<File>
/**
* if returns true, the IntelliJ will scan the classpath from [getDefinitionClasses] to discover script definition templates
* using definition markers in the "META-INF/kotlin/script/templates/" folder
*/
fun useDiscovery(): Boolean
/**
* The callback to update/add/remove script definitions after loading, if needed
*/
fun provideDefinitions(
baseHostConfiguration: ScriptingHostConfiguration,
loadedScriptDefinitions: List<ScriptDefinition>
): Iterable<ScriptDefinition> = loadedScriptDefinitions
companion object {
val EP_NAME: ExtensionPointName<ScriptDefinitionsProvider> =
ExtensionPointName.create<ScriptDefinitionsProvider>("org.jetbrains.kotlin.scriptDefinitionsProvider")
ExtensionPointName.create("org.jetbrains.kotlin.scriptDefinitionsProvider")
}
}
@@ -178,14 +178,10 @@ abstract class ScriptDefinition : UserDataHolderBase() {
override val evaluationConfiguration: ScriptEvaluationConfiguration?
) : FromConfigurationsBase()
open class FromTemplate(
open class FromNewDefinition(
private val baseHostConfiguration: ScriptingHostConfiguration,
template: KClass<*>,
contextClass: KClass<*> = ScriptCompilationConfiguration::class
private val definition: kotlin.script.experimental.host.ScriptDefinition
) : FromConfigurationsBase() {
private val definition = createScriptDefinitionFromTemplate(KotlinType(template), baseHostConfiguration, contextClass)
override val hostConfiguration: ScriptingHostConfiguration
get() = definition.compilationConfiguration[ScriptCompilationConfiguration.hostConfiguration] ?: baseHostConfiguration
@@ -193,6 +189,15 @@ abstract class ScriptDefinition : UserDataHolderBase() {
override val evaluationConfiguration: ScriptEvaluationConfiguration get() = definition.evaluationConfiguration
}
open class FromTemplate(
baseHostConfiguration: ScriptingHostConfiguration,
template: KClass<*>,
contextClass: KClass<*> = ScriptCompilationConfiguration::class
) : FromNewDefinition(
baseHostConfiguration,
createScriptDefinitionFromTemplate(KotlinType(template), baseHostConfiguration, contextClass)
)
companion object {
fun getDefault(hostConfiguration: ScriptingHostConfiguration) =
object : FromLegacy(hostConfiguration, StandardScriptDefinition) {