From 0af52f2fa6da18d519f57202339cff0d6a5e8092 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Mon, 22 Jul 2019 14:14:32 +0200 Subject: [PATCH] Implement composable refinement handlers... for compilation and evaluation configurations. Add utilities to apply refinements uniformly. Also fix one invoke for list values - it was not consistent with other builders --- .../experimental/api/scriptCompilation.kt | 68 +++++++-- .../script/experimental/api/scriptData.kt | 4 +- .../experimental/api/scriptEvaluation.kt | 12 +- .../experimental/util/propertiesCollection.kt | 2 +- .../jvmhost/test/ConfigurationDslTest.kt | 134 ++++++++++++++++++ .../jvmhost/jvmScriptCompilation.kt | 25 ++-- .../jvm/BasicJvmScriptEvaluator.kt | 15 +- .../jvm/impl/BridgeDependenciesResolver.kt | 13 +- ...KotlinScriptDefinitionAdapterFromNewAPI.kt | 12 +- .../resolve/refineCompilationConfiguration.kt | 21 ++- 10 files changed, 240 insertions(+), 66 deletions(-) create mode 100644 libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ConfigurationDslTest.kt diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt index 0fe613b7ba8..2a75f9e6f71 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptCompilation.kt @@ -130,17 +130,17 @@ val ScriptCompilationConfigurationKeys.compilerOptions by PropertiesCollection.k /** * The callback that will be called on the script compilation before parsing the script */ -val ScriptCompilationConfigurationKeys.refineConfigurationBeforeParsing by PropertiesCollection.key() +val ScriptCompilationConfigurationKeys.refineConfigurationBeforeParsing by PropertiesCollection.key>() /** * The callback that will be called on the script compilation after parsing script file annotations */ -val ScriptCompilationConfigurationKeys.refineConfigurationOnAnnotations by PropertiesCollection.key() +val ScriptCompilationConfigurationKeys.refineConfigurationOnAnnotations by PropertiesCollection.key>() /** * The callback that will be called on the script compilation immediately before starting the compilation */ -val ScriptCompilationConfigurationKeys.refineConfigurationBeforeCompiling by PropertiesCollection.key() +val ScriptCompilationConfigurationKeys.refineConfigurationBeforeCompiling by PropertiesCollection.key>() /** * The list of script fragments that should be compiled intead of the whole text @@ -166,7 +166,7 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() { * @param handler the callback that will be called */ fun beforeParsing(handler: RefineScriptCompilationConfigurationHandler) { - set(ScriptCompilationConfiguration.refineConfigurationBeforeParsing, RefineConfigurationUnconditionallyData(handler)) + ScriptCompilationConfiguration.refineConfigurationBeforeParsing.append(RefineConfigurationUnconditionallyData(handler)) } /** @@ -176,7 +176,7 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() { */ fun onAnnotations(annotations: List, handler: RefineScriptCompilationConfigurationHandler) { // TODO: implement handlers composition - set(ScriptCompilationConfiguration.refineConfigurationOnAnnotations, RefineConfigurationOnAnnotationsData(annotations, handler)) + ScriptCompilationConfiguration.refineConfigurationOnAnnotations.append(RefineConfigurationOnAnnotationsData(annotations, handler)) } /** @@ -220,7 +220,7 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() { * @param handler the callback that will be called */ fun beforeCompiling(handler: RefineScriptCompilationConfigurationHandler) { - set(ScriptCompilationConfiguration.refineConfigurationBeforeCompiling, RefineConfigurationUnconditionallyData(handler)) + ScriptCompilationConfiguration.refineConfigurationBeforeCompiling.append(RefineConfigurationUnconditionallyData(handler)) } } @@ -230,20 +230,72 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() { typealias RefineScriptCompilationConfigurationHandler = (ScriptConfigurationRefinementContext) -> ResultWithDiagnostics +/** + * The refinement callback function signature for simple handlers (without diagnostics or errors) + */ +typealias SimpleRefineScriptCompilationConfigurationHandler = + (ScriptConfigurationRefinementContext) -> ScriptCompilationConfiguration + data class RefineConfigurationUnconditionallyData( val handler: RefineScriptCompilationConfigurationHandler ) : Serializable { - companion object { private const val serialVersionUID: Long = 1L } + companion object { + private const val serialVersionUID: Long = 1L + } } data class RefineConfigurationOnAnnotationsData( val annotations: List, val handler: RefineScriptCompilationConfigurationHandler ) : Serializable { - companion object { private const val serialVersionUID: Long = 1L } + companion object { + private const val serialVersionUID: Long = 1L + } } +fun ScriptCompilationConfiguration.refineBeforeParsing( + script: SourceCode, + collectedData: ScriptCollectedData? = null +): ResultWithDiagnostics = + simpleRefineImpl(ScriptCompilationConfiguration.refineConfigurationBeforeParsing) { config, refineData -> + refineData.handler.invoke(ScriptConfigurationRefinementContext(script, config, collectedData)) + } + +fun ScriptCompilationConfiguration.refineOnAnnotations( + script: SourceCode, + collectedData: ScriptCollectedData +): ResultWithDiagnostics { + val foundAnnotationNames = collectedData[ScriptCollectedData.foundAnnotations]?.mapTo(HashSet()) { it.annotationClass.java.name } + if (foundAnnotationNames.isNullOrEmpty()) return this.asSuccess() + + val refinedConfig = this[ScriptCompilationConfiguration.refineConfigurationOnAnnotations] + ?.fold(this) { config, (annotations, handler) -> + // checking that the collected data contains expected annotations + if (annotations.none { foundAnnotationNames.contains(it.typeName) }) config + else handler.invoke(ScriptConfigurationRefinementContext(script, config, collectedData)).valueOr { return it } + } + return (refinedConfig ?: this).asSuccess() +} + +fun ScriptCompilationConfiguration.refineBeforeCompiling( + script: SourceCode, + collectedData: ScriptCollectedData? = null +): ResultWithDiagnostics = + simpleRefineImpl(ScriptCompilationConfiguration.refineConfigurationBeforeCompiling) { config, refineData -> + refineData.handler.invoke(ScriptConfigurationRefinementContext(script, config, collectedData)) + } + +internal inline fun Configuration.simpleRefineImpl( + key: PropertiesCollection.Key>, + refineFn: (Configuration, RefineData) -> ResultWithDiagnostics +): ResultWithDiagnostics = ( + this[key] + ?.fold(this) { config, refineData -> + refineFn(config, refineData).valueOr { return it } + } ?: this + ).asSuccess() + /** * The functional interface to the script compiler */ diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt index 2e619bcebb1..4f8df8b6329 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptData.kt @@ -94,7 +94,7 @@ val ScriptCollectedDataKeys.foundAnnotations by PropertiesCollection.key, A /** * The facade to the script data for evaluation configuration refinement callbacks */ -class ScriptEvaluationConfigurationRefinementContext( +data class ScriptEvaluationConfigurationRefinementContext( val compiledScript: CompiledScript<*>, val evaluationConfiguration: ScriptEvaluationConfiguration, val contextData: ScriptEvaluationContextData? = null diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt index 7f7c6220c44..15bf93c9f0e 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt @@ -88,7 +88,7 @@ val ScriptEvaluationConfigurationKeys.hostConfiguration by PropertiesCollection. /** * The callback that will be called on the script compilation immediately before starting the compilation */ -val ScriptEvaluationConfigurationKeys.refineConfigurationBeforeEvaluate by PropertiesCollection.key() +val ScriptEvaluationConfigurationKeys.refineConfigurationBeforeEvaluate by PropertiesCollection.key>() /** * A helper to enable scriptsInstancesSharingMap with default implementation @@ -103,7 +103,7 @@ fun ScriptEvaluationConfiguration.Builder.enableScriptsInstancesSharing() { * A helper to enable passing lambda directly to the refinement "keyword" */ fun ScriptEvaluationConfiguration.Builder.refineConfigurationBeforeEvaluate(handler: RefineScriptEvaluationConfigurationHandler) { - set(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate, RefineEvaluationConfigurationData(handler)) + ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate.append(RefineEvaluationConfigurationData(handler)) } /** @@ -118,6 +118,14 @@ data class RefineEvaluationConfigurationData( companion object { private const val serialVersionUID: Long = 1L } } +fun ScriptEvaluationConfiguration.refineBeforeEvaluation( + script: CompiledScript<*>, + contextData: ScriptEvaluationContextData? = null +): ResultWithDiagnostics = + simpleRefineImpl(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate) { config, refineData -> + refineData.handler.invoke(ScriptEvaluationConfigurationRefinementContext(script, config, contextData)) + } + /** * The script evaluation result value */ diff --git a/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt b/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt index e946009ae94..61d2a8d96f0 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/util/propertiesCollection.kt @@ -111,7 +111,7 @@ open class PropertiesCollection(private val properties: Map, Any?> = empt // generic for lists operator fun PropertiesCollection.Key>.invoke(vararg vals: T) { - data[this] = vals.toList() + append(vals.asIterable()) } // generic for maps: diff --git a/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ConfigurationDslTest.kt b/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ConfigurationDslTest.kt new file mode 100644 index 00000000000..9a816184d96 --- /dev/null +++ b/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ConfigurationDslTest.kt @@ -0,0 +1,134 @@ +/* + * 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 kotlin.script.experimental.jvmhost.test + +import junit.framework.TestCase +import kotlinx.coroutines.runBlocking +import org.junit.Assert +import org.junit.Test +import kotlin.script.experimental.api.* +import kotlin.script.experimental.host.toScriptSource +import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator +import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration +import kotlin.script.experimental.jvm.dependenciesFromCurrentContext +import kotlin.script.experimental.jvm.jvm +import kotlin.script.experimental.jvmhost.JvmScriptCompiler +import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate +import kotlin.script.experimental.jvmhost.createJvmEvaluationConfigurationFromTemplate + +class ConfigurationDslTest : TestCase() { + + @Test + fun testComposableRefinementHandlers() { + val baseConfig = createJvmCompilationConfigurationFromTemplate { + jvm { + dependenciesFromCurrentContext(wholeClasspath = true) + } + defaultImports(MyTestAnnotation1::class, MyTestAnnotation2::class) + refineConfiguration { + beforeParsing { (_, config, _) -> + config.with { + implicitReceivers(Int::class) + }.asSuccess() + } + onAnnotations { (_, config, _) -> + config.with { + providedProperties("ann1" to String::class) + }.asSuccess() + } + onAnnotations(MyTestAnnotation1::class, MyTestAnnotation2::class) { (_, config, _) -> + config.with { + providedProperties("ann12" to Int::class) + }.asSuccess() + } + onAnnotations { (_, config, _) -> + config.with { + providedProperties("ann2" to String::class) + }.asSuccess() + } + beforeCompiling { (_, config, _) -> + config.with { + compilerOptions("-version") + }.asSuccess() + } + beforeCompiling { (_, config, _) -> + config.with { + implicitReceivers(Float::class) + }.asSuccess() + } + } + } + + Assert.assertNull(baseConfig[ScriptCompilationConfiguration.implicitReceivers]) + Assert.assertNull(baseConfig[ScriptCompilationConfiguration.providedProperties]) + Assert.assertNull(baseConfig[ScriptCompilationConfiguration.compilerOptions]) + + val script = "@file:MyTestAnnotation1\nann1+ann12".toScriptSource() + + val compiledScript = runBlocking { + JvmScriptCompiler(defaultJvmScriptingHostConfiguration).invoke(script, baseConfig).valueOrThrow() + } + val finalConfig = compiledScript.compilationConfiguration + + Assert.assertEquals( + listOf(KotlinType(Int::class), KotlinType(Float::class)), + finalConfig[ScriptCompilationConfiguration.implicitReceivers] + ) + Assert.assertEquals( + mapOf("ann1" to KotlinType(String::class), "ann12" to KotlinType(Int::class)), + finalConfig[ScriptCompilationConfiguration.providedProperties] + ) + Assert.assertEquals( + listOf("-version"), + finalConfig[ScriptCompilationConfiguration.compilerOptions] + ) + + val implicitReceiver1 = 10 + val implicitReceiver2 = 2.0f + val propAnn1 = "a1" + val propAnn12 = 12 + + val baseEvalConfig = createJvmEvaluationConfigurationFromTemplate { + refineConfigurationBeforeEvaluate { (_, config, _) -> + config.with { + implicitReceivers(implicitReceiver1) + providedProperties("ann1" to propAnn1) + }.asSuccess() + } + refineConfigurationBeforeEvaluate { (_, config, _) -> + config.with { + implicitReceivers(implicitReceiver2) + providedProperties("ann12" to propAnn12) + }.asSuccess() + } + } + + Assert.assertNull(baseEvalConfig[ScriptCompilationConfiguration.implicitReceivers]) + Assert.assertNull(baseEvalConfig[ScriptCompilationConfiguration.providedProperties]) + + val evalRes = runBlocking { + BasicJvmScriptEvaluator().invoke(compiledScript, baseEvalConfig).valueOrThrow() + } + val finalEvalConfig = evalRes.configuration!! + + Assert.assertEquals( + listOf(implicitReceiver1, implicitReceiver2), + finalEvalConfig[ScriptEvaluationConfiguration.implicitReceivers] + ) + Assert.assertEquals( + mapOf("ann1" to propAnn1, "ann12" to propAnn12), + finalEvalConfig[ScriptEvaluationConfiguration.providedProperties] + ) + + Assert.assertEquals(propAnn1 + propAnn12, (evalRes.returnValue as ResultValue.Value).value) + } +} + +@Target(AnnotationTarget.FILE) +annotation class MyTestAnnotation1 + +@Target(AnnotationTarget.FILE) +annotation class MyTestAnnotation2 diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt index 2a785c73041..e3967fe09bf 100644 --- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt +++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptCompilation.kt @@ -39,24 +39,17 @@ open class JvmScriptCompiler( override suspend operator fun invoke( script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration - ): ResultWithDiagnostics> { - val refineConfigurationFn = scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationBeforeParsing] - val refinedConfiguration = - refineConfigurationFn?.handler?.invoke(ScriptConfigurationRefinementContext(script, scriptCompilationConfiguration))?.let { - when (it) { - is ResultWithDiagnostics.Failure -> return it - is ResultWithDiagnostics.Success -> it.value + ): ResultWithDiagnostics> = + scriptCompilationConfiguration.refineBeforeParsing(script).onSuccess { refinedConfiguration -> + val cached = cache.get(script, refinedConfiguration) + + if (cached != null) return cached.asSuccess() + + compilerProxy.compile(script, refinedConfiguration).also { + if (it is ResultWithDiagnostics.Success) { + cache.store(it.value, script, refinedConfiguration) } - } ?: scriptCompilationConfiguration - val cached = cache.get(script, refinedConfiguration) - - if (cached != null) return cached.asSuccess() - - return compilerProxy.compile(script, refinedConfiguration).also { - if (it is ResultWithDiagnostics.Success) { - cache.store(it.value, script, refinedConfiguration) } } - } } diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/BasicJvmScriptEvaluator.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/BasicJvmScriptEvaluator.kt index 95752935941..7fb3936d3af 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/BasicJvmScriptEvaluator.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/BasicJvmScriptEvaluator.kt @@ -31,18 +31,9 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator { }.onSuccess { importedScriptsEvalResults -> val refinedEvalConfiguration = - configuration[ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate] - ?.handler?.invoke( - ScriptEvaluationConfigurationRefinementContext( - compiledScript, - configuration - ) - ) - ?.onFailure { - return@invoke ResultWithDiagnostics.Failure(it.reports) - } - ?.valueOrNull() - ?: configuration + configuration.refineBeforeEvaluation(compiledScript).valueOr { + return@invoke ResultWithDiagnostics.Failure(it.reports) + } val resultValue = try { val instance = diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt index 1956ab9fc1d..dfef4e81a6e 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/impl/BridgeDependenciesResolver.kt @@ -43,15 +43,10 @@ class BridgeDependenciesResolver( val script = getScriptSource(scriptContents) ?: scriptContents.toScriptSource() - val refineResults = scriptCompilationConfiguration.refineWith( - scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.handler, - processedScriptData, script - ).onSuccess { - it.refineWith( - scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationBeforeCompiling]?.handler, - processedScriptData, script - ) - } + val refineResults = + scriptCompilationConfiguration.refineOnAnnotations(script, processedScriptData).onSuccess { + it.refineBeforeCompiling(script, processedScriptData) + } val refinedConfiguration = when (refineResults) { is ResultWithDiagnostics.Failure -> diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/KotlinScriptDefinitionAdapterFromNewAPI.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/KotlinScriptDefinitionAdapterFromNewAPI.kt index f804e3b7532..c86c3b74a33 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/KotlinScriptDefinitionAdapterFromNewAPI.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/KotlinScriptDefinitionAdapterFromNewAPI.kt @@ -56,12 +56,14 @@ abstract class KotlinScriptDefinitionAdapterFromNewAPIBase : KotlinScriptDefinit } override val acceptedAnnotations: List> by lazy(LazyThreadSafetyMode.PUBLICATION) { - scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.annotations - .orEmpty() - .map { - @Suppress("UNCHECKED_CAST") - getScriptingClass(it) as KClass + scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations] + ?.flatMap { + it.annotations.map { ann -> + @Suppress("UNCHECKED_CAST") + getScriptingClass(ann) as KClass + } } + .orEmpty() } override val implicitReceivers: List by lazy(LazyThreadSafetyMode.PUBLICATION) { diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/refineCompilationConfiguration.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/refineCompilationConfiguration.kt index 917a19bb4dc..8d45a256af3 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/refineCompilationConfiguration.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/resolve/refineCompilationConfiguration.kt @@ -227,15 +227,12 @@ fun refineScriptCompilationConfiguration( val collectedData = getScriptCollectedData(ktFileSource.ktFile, compilationConfiguration, project, definition.contextClassLoader) - return compilationConfiguration.refineWith( - compilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.handler, collectedData, script - ).onSuccess { - it.refineWith( - compilationConfiguration[ScriptCompilationConfiguration.refineConfigurationBeforeCompiling]?.handler, collectedData, script - ) - }.onSuccess { - ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(ktFileSource, it).asSuccess() - } + return compilationConfiguration.refineOnAnnotations(script, collectedData) + .onSuccess { + it.refineBeforeCompiling(script, collectedData) + }.onSuccess { + ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(ktFileSource, it).asSuccess() + } } else { val file = script.getVirtualFile(definition) val scriptContents = @@ -335,8 +332,10 @@ fun getScriptCollectedData( val jvmGetScriptingClass = (getScriptingClass as? JvmGetScriptingClass) ?: throw IllegalArgumentException("Expecting JvmGetScriptingClass in the hostConfiguration[getScriptingClass], got $getScriptingClass") val acceptedAnnotations = - compilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.annotations?.mapNotNull { - jvmGetScriptingClass(it, contextClassLoader, hostConfiguration) as? KClass // TODO errors + compilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.flatMap { + it.annotations.mapNotNull { ann -> + jvmGetScriptingClass(ann, contextClassLoader, hostConfiguration) as? KClass // TODO errors + } }.orEmpty() val annotations = scriptFile.annotationEntries.construct(contextClassLoader, acceptedAnnotations, project) return ScriptCollectedData(