diff --git a/idea/src/org/jetbrains/kotlin/idea/script/BridgeDefinitionsContributor.kt b/idea/src/org/jetbrains/kotlin/idea/script/BridgeDefinitionsContributor.kt index b69e5efbccf..37375a6cb2d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/script/BridgeDefinitionsContributor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/script/BridgeDefinitionsContributor.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor import org.jetbrains.kotlin.idea.core.script.loadDefinitionsFromTemplates import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource +import org.jetbrains.kotlin.scripting.definitions.reporter import kotlin.script.experimental.intellij.ScriptDefinitionsProvider class BridgeScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionContributor { @@ -34,7 +35,7 @@ class BridgeScriptDefinitionsContributor(private val project: Project) : ScriptD else ScriptDefinitionsFromClasspathDiscoverySource( classPath, emptyMap(), - messageCollector + messageCollector.reporter ).definitions explicitDefinitions + discoveredDefinitions } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt index d69910b24bc..29a694b7718 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/scripting/internal/ScriptingGradleSubplugin.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.useLazyTaskConfiguration import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource +import org.jetbrains.kotlin.scripting.definitions.reporter import java.io.File private const val MIN_SUPPORTED_GRADLE_MAJOR_VERSION = 5 @@ -166,7 +167,7 @@ internal class DiscoverScriptExtensionsTransform : ArtifactTransform() { val definitions = ScriptDefinitionsFromClasspathDiscoverySource( listOf(input), emptyMap(), - PrintingMessageCollector(System.out, MessageRenderer.WITHOUT_PATHS, false) + PrintingMessageCollector(System.out, MessageRenderer.WITHOUT_PATHS, false).reporter ).definitions val extensions = definitions.mapTo(arrayListOf()) { it.fileExtension } return if (extensions.isNotEmpty()) { diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/configuration/configuration.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/configuration/configuration.kt index 2f2a0a40e7a..ce0bcdb8c21 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/configuration/configuration.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/configuration/configuration.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.scripting.definitions.loadScriptTemplatesFromClasspath +import org.jetbrains.kotlin.scripting.definitions.reporter const val KOTLIN_SCRIPTING_PLUGIN_ID = "kotlin.scripting" @@ -21,7 +22,7 @@ fun configureScriptDefinitions( ) { // TODO: consider using escaping to allow kotlin escaped names in class names val templatesFromClasspath = loadScriptTemplatesFromClasspath( - scriptTemplates, configuration.jvmClasspathRoots, emptyList(), baseClassloader, scriptResolverEnv, messageCollector + scriptTemplates, configuration.jvmClasspathRoots, emptyList(), baseClassloader, scriptResolverEnv, messageCollector.reporter ) configuration.addAll(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, templatesFromClasspath.toList()) } diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/LazyScriptDefinitionFromDiscoveredClass.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/LazyScriptDefinitionFromDiscoveredClass.kt index 32c7f8732e6..67865e8c1a1 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/LazyScriptDefinitionFromDiscoveredClass.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/LazyScriptDefinitionFromDiscoveredClass.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.scripting.definitions import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.MessageCollector import java.io.File import kotlin.script.experimental.annotations.KotlinScript import kotlin.script.experimental.api.KotlinType @@ -22,15 +21,15 @@ class LazyScriptDefinitionFromDiscoveredClass internal constructor( private val annotationsFromAsm: ArrayList, private val className: String, private val classpath: List, - private val messageCollector: MessageCollector + private val messageReporter: MessageReporter ) : KotlinScriptDefinitionAdapterFromNewAPIBase() { constructor( classBytes: ByteArray, className: String, classpath: List, - messageCollector: MessageCollector - ) : this(loadAnnotationsFromClass(classBytes), className, classpath, messageCollector) + messageReporter: MessageReporter + ) : this(loadAnnotationsFromClass(classBytes), className, classpath, messageReporter) override val hostConfiguration: ScriptingHostConfiguration by lazy(LazyThreadSafetyMode.PUBLICATION) { ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) { @@ -39,7 +38,7 @@ class LazyScriptDefinitionFromDiscoveredClass internal constructor( } override val scriptCompilationConfiguration: ScriptCompilationConfiguration by lazy(LazyThreadSafetyMode.PUBLICATION) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.LOGGING, "Configure scripting: loading script definition class $className using classpath $classpath\n. ${Thread.currentThread().stackTrace}" ) @@ -50,10 +49,10 @@ class LazyScriptDefinitionFromDiscoveredClass internal constructor( LazyScriptDefinitionFromDiscoveredClass::class ) } catch (ex: ClassNotFoundException) { - messageCollector.report(CompilerMessageSeverity.ERROR, "Cannot find script definition class $className") + messageReporter(CompilerMessageSeverity.ERROR, "Cannot find script definition class $className") InvalidScriptDefinition } catch (ex: Exception) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.ERROR, "Error processing script definition class $className: ${ex.message}\nclasspath:\n${classpath.joinToString("\n", " ")}" ) diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptiDefinitionsFromClasspathDiscoverySource.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptiDefinitionsFromClasspathDiscoverySource.kt index ed2dff544a7..346fb1a66de 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptiDefinitionsFromClasspathDiscoverySource.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/ScriptiDefinitionsFromClasspathDiscoverySource.kt @@ -23,10 +23,17 @@ import kotlin.script.templates.ScriptTemplateDefinition const val SCRIPT_DEFINITION_MARKERS_PATH = "META-INF/kotlin/script/templates/" const val SCRIPT_DEFINITION_MARKERS_EXTENSION_WITH_DOT = ".classname" +typealias MessageReporter = (CompilerMessageSeverity, String) -> Unit + +val MessageCollector.reporter: MessageReporter + get() = { severity, message -> + this.report(severity, message) + } + class ScriptDefinitionsFromClasspathDiscoverySource( private val classpath: List, private val scriptResolverEnv: Map, - private val messageCollector: MessageCollector + private val messageReporter: MessageReporter ) : ScriptDefinitionsSource { override val definitions: Sequence = run { @@ -34,7 +41,7 @@ class ScriptDefinitionsFromClasspathDiscoverySource( classpath, this::class.java.classLoader, scriptResolverEnv, - messageCollector + messageReporter ) } } @@ -44,7 +51,7 @@ private const val MANIFEST_RESOURCE_NAME = "/META-INF/MANIFEST.MF" fun discoverScriptTemplatesInClassLoader( classLoader: ClassLoader, scriptResolverEnv: Map, - messageCollector: MessageCollector + messageReporter: MessageReporter ): Sequence { val classpath = classLoader.getResources(MANIFEST_RESOURCE_NAME).asSequence().mapNotNull { try { @@ -54,25 +61,25 @@ fun discoverScriptTemplatesInClassLoader( } } val classpathWithLoader = SimpleClasspathWithClassLoader(classpath.toList(), classLoader) - return scriptTemplatesDiscoverySequence(classpathWithLoader, scriptResolverEnv, messageCollector) + return scriptTemplatesDiscoverySequence(classpathWithLoader, scriptResolverEnv, messageReporter) } fun discoverScriptTemplatesInClasspath( classpath: List, baseClassLoader: ClassLoader?, scriptResolverEnv: Map, - messageCollector: MessageCollector + messageReporter: MessageReporter ): Sequence { // TODO: try to find a way to reduce classpath (and classloader) to minimal one needed to load script definition and its dependencies val classpathWithLoader = LazyClasspathWithClassLoader(baseClassLoader) { classpath } - return scriptTemplatesDiscoverySequence(classpathWithLoader, scriptResolverEnv, messageCollector) + return scriptTemplatesDiscoverySequence(classpathWithLoader, scriptResolverEnv, messageReporter) } private fun scriptTemplatesDiscoverySequence( classpathWithLoader: ClasspathWithClassLoader, scriptResolverEnv: Map, - messageCollector: MessageCollector + messageReporter: MessageReporter ): Sequence { return sequence { // for jar files the definition class is expected in the same jar as the discovery file @@ -96,10 +103,10 @@ private fun scriptTemplatesDiscoverySequence( jar, classpathWithLoader, scriptResolverEnv, - messageCollector + messageReporter ) if (notFoundClasses.isNotEmpty()) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "Configure scripting: unable to find script definitions [${notFoundClasses.joinToString(", ")}]" ) @@ -115,7 +122,7 @@ private fun scriptTemplatesDiscoverySequence( val discoveryMarkers = File(dep, SCRIPT_DEFINITION_MARKERS_PATH).listFiles() if (discoveryMarkers?.isEmpty() == false) { val (foundDefinitionClasses, notFoundDefinitions) = discoveryMarkers.map { it.name } - .partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageCollector) + .partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageReporter) foundDefinitionClasses.forEach { yield(it) } @@ -124,11 +131,11 @@ private fun scriptTemplatesDiscoverySequence( } else -> { // assuming that invalid classpath entries will be reported elsewhere anyway, so do not spam user with additional warnings here - messageCollector.report(CompilerMessageSeverity.LOGGING, "Configure scripting: Unknown classpath entry $dep") + messageReporter(CompilerMessageSeverity.LOGGING, "Configure scripting: Unknown classpath entry $dep") } } } catch (e: IOException) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "Configure scripting: unable to process classpath entry $dep: $e" ) } @@ -138,19 +145,19 @@ private fun scriptTemplatesDiscoverySequence( if (remainingDefinitionCandidates.isEmpty()) break try { val (foundDefinitionClasses, notFoundDefinitions) = - remainingDefinitionCandidates.partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageCollector) + remainingDefinitionCandidates.partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageReporter) foundDefinitionClasses.forEach { yield(it) } remainingDefinitionCandidates = notFoundDefinitions } catch (e: IOException) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "Configure scripting: unable to process classpath entry $dep: $e" ) } } if (remainingDefinitionCandidates.isNotEmpty()) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "The following script definitions are not found in the classpath: [${remainingDefinitionCandidates.joinToString()}]" ) @@ -164,7 +171,7 @@ fun loadScriptTemplatesFromClasspath( dependenciesClasspath: List, baseClassLoader: ClassLoader, scriptResolverEnv: Map, - messageCollector: MessageCollector + messageReporter: MessageReporter ): Sequence = if (scriptTemplates.isEmpty()) emptySequence() else sequence { @@ -174,7 +181,7 @@ fun loadScriptTemplatesFromClasspath( baseClassLoader, it, scriptResolverEnv, - messageCollector + messageReporter ) } initialLoadedDefinitions.forEach { @@ -192,15 +199,15 @@ fun loadScriptTemplatesFromClasspath( val (loadedDefinitions, notFoundTemplates) = when { dep.isFile && dep.extension == "jar" -> { // checking for extension is the compiler current behaviour, so the same logic is implemented here JarFile(dep).use { jar -> - remainingTemplates.partitionLoadJarDefinitions(jar, classpathWithLoader, scriptResolverEnv, messageCollector) + remainingTemplates.partitionLoadJarDefinitions(jar, classpathWithLoader, scriptResolverEnv, messageReporter) } } dep.isDirectory -> { - remainingTemplates.partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageCollector) + remainingTemplates.partitionLoadDirDefinitions(dep, classpathWithLoader, scriptResolverEnv, messageReporter) } else -> { // assuming that invalid classpath entries will be reported elsewhere anyway, so do not spam user with additional warnings here - messageCollector.report(CompilerMessageSeverity.LOGGING, "Configure scripting: Unknown classpath entry $dep") + messageReporter(CompilerMessageSeverity.LOGGING, "Configure scripting: Unknown classpath entry $dep") DefinitionsLoadPartitionResult( listOf(), remainingTemplates @@ -214,7 +221,7 @@ fun loadScriptTemplatesFromClasspath( remainingTemplates = notFoundTemplates } } catch (e: IOException) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "Configure scripting: unable to process classpath entry $dep: $e" ) @@ -222,7 +229,7 @@ fun loadScriptTemplatesFromClasspath( } if (remainingTemplates.isNotEmpty()) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "Configure scripting: unable to find script definition classes: ${remainingTemplates.joinToString(", ")}" ) @@ -237,7 +244,7 @@ private data class DefinitionsLoadPartitionResult( private inline fun List.partitionLoadDefinitions( classpathWithLoader: ClasspathWithClassLoader, scriptResolverEnv: Map, - messageCollector: MessageCollector, + noinline messageReporter: MessageReporter, getBytes: (String) -> ByteArray? ): DefinitionsLoadPartitionResult { val loaded = ArrayList() @@ -250,7 +257,7 @@ private inline fun List.partitionLoadDefinitions( definitionName, classpathWithLoader, scriptResolverEnv, - messageCollector + messageReporter ) } when { @@ -267,8 +274,8 @@ private fun List.partitionLoadJarDefinitions( jar: JarFile, classpathWithLoader: ClasspathWithClassLoader, scriptResolverEnv: Map, - messageCollector: MessageCollector -): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, scriptResolverEnv, messageCollector) { definitionName -> + messageReporter: MessageReporter +): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, scriptResolverEnv, messageReporter) { definitionName -> jar.getJarEntry("${definitionName.replace('.', '/')}.class")?.let { jar.getInputStream(it).readBytes() } } @@ -276,8 +283,8 @@ private fun List.partitionLoadDirDefinitions( dir: File, classpathWithLoader: ClasspathWithClassLoader, scriptResolverEnv: Map, - messageCollector: MessageCollector -): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, scriptResolverEnv, messageCollector) { definitionName -> + messageReporter: MessageReporter +): DefinitionsLoadPartitionResult = partitionLoadDefinitions(classpathWithLoader, scriptResolverEnv, messageReporter) { definitionName -> File(dir, "${definitionName.replace('.', '/')}.class").takeIf { it.exists() && it.isFile }?.readBytes() } @@ -286,7 +293,7 @@ private fun loadScriptDefinition( templateClassName: String, classpathWithLoader: ClasspathWithClassLoader, scriptResolverEnv: Map, - messageCollector: MessageCollector + messageReporter: MessageReporter ): KotlinScriptDefinition? { val anns = loadAnnotationsFromClass(templateClassBytes) for (ann in anns) { @@ -296,21 +303,21 @@ private fun loadScriptDefinition( anns, templateClassName, classpathWithLoader.classpath, - messageCollector + messageReporter ) } else if (ann.name == ScriptTemplateDefinition::class.simpleName) { val templateClass = classpathWithLoader.classLoader.loadClass(templateClassName).kotlin def = KotlinScriptDefinitionFromAnnotatedTemplate(templateClass, scriptResolverEnv, classpathWithLoader.classpath) } if (def != null) { - messageCollector.report( + messageReporter( CompilerMessageSeverity.LOGGING, "Configure scripting: Added template $templateClassName from ${classpathWithLoader.classpath}" ) return def } } - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "Configure scripting: $templateClassName is not marked with any known kotlin script annotation" ) @@ -321,7 +328,7 @@ private fun loadScriptDefinition( classLoader: ClassLoader, template: String, scriptResolverEnv: Map, - messageCollector: MessageCollector + messageReporter: MessageReporter ): KotlinScriptDefinition? { try { val cls = classLoader.loadClass(template) @@ -339,7 +346,7 @@ private fun loadScriptDefinition( } else { KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, scriptResolverEnv) } - messageCollector.report( + messageReporter( CompilerMessageSeverity.INFO, "Added script definition $template to configuration: name = ${def.name}, " + "resolver = ${def.dependencyResolver.javaClass.name}" @@ -349,7 +356,7 @@ private fun loadScriptDefinition( // not found - not an error, return null } catch (ex: Exception) { // other exceptions - might be an error - messageCollector.report( + messageReporter( CompilerMessageSeverity.STRONG_WARNING, "Error on loading script definition $template: ${ex.message}" ) diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingCompilerConfigurationExtension.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingCompilerConfigurationExtension.kt index 03181f2b487..ec8be9821dd 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingCompilerConfigurationExtension.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingCompilerConfigurationExtension.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.scripting.configuration.configureScriptDefinitions import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionsFromClasspathDiscoverySource import org.jetbrains.kotlin.scripting.definitions.StandardScriptDefinition +import org.jetbrains.kotlin.scripting.definitions.reporter import java.io.File class ScriptingCompilerConfigurationExtension(val project: MockProject) : CompilerConfigurationExtension { @@ -66,7 +67,7 @@ class ScriptingCompilerConfigurationExtension(val project: MockProject) : Compil ScriptDefinitionsFromClasspathDiscoverySource( configuration.jvmClasspathRoots, configuration.get(ScriptingConfigurationKeys.LEGACY_SCRIPT_RESOLVER_ENVIRONMENT_OPTION) ?: emptyMap(), - messageCollector + messageCollector.reporter ) ) }