diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt index 78426681cdd..7eca96abd2d 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.cli.jvm.compiler +import com.intellij.ide.highlighter.JavaClassFileType +import com.intellij.ide.highlighter.JavaFileType import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.StandardFileSystems @@ -19,9 +21,11 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfigurationKey import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.extensions.CompilerConfigurationExtension import org.jetbrains.kotlin.extensions.PreprocessedFileCreator import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.modules.Module +import org.jetbrains.kotlin.parsing.KotlinParserDefinition import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource import java.io.File @@ -43,6 +47,8 @@ inline fun List.forAllFiles( val virtualFileCreator = PreprocessedFileCreator(project) + var pluginsConfigured = false + for ((sourceRootPath, isCommon) in this) { val sourceRoot = File(sourceRootPath) val vFile = localFileSystem.findFileByPath(sourceRoot.normalize().path) @@ -59,9 +65,15 @@ inline fun List.forAllFiles( continue } - if (!vFile.isDirectory && vFile.extension != KotlinFileType.EXTENSION && vFile.fileType != KotlinFileType.INSTANCE) { - configuration.report(CompilerMessageSeverity.ERROR, "Source entry is not a Kotlin file: $sourceRootPath", reportLocation) - continue + if (!vFile.isDirectory && vFile.extension != KotlinFileType.EXTENSION) { + if (!pluginsConfigured) { + vFile.registerPluginsSuppliedExtensionsIfNeeded(project) + pluginsConfigured = true + } + if (vFile.fileType != KotlinFileType.INSTANCE) { + configuration.report(CompilerMessageSeverity.ERROR, "Source entry is not a Kotlin file: $sourceRootPath", reportLocation) + continue + } } for (file in sourceRoot.walkTopDown()) { @@ -69,12 +81,29 @@ inline fun List.forAllFiles( val virtualFile = localFileSystem.findFileByPath(file.absoluteFile.normalize().path)?.let(virtualFileCreator::create) if (virtualFile != null && processedFiles.add(virtualFile)) { + if (!pluginsConfigured) { + virtualFile.registerPluginsSuppliedExtensionsIfNeeded(project) + pluginsConfigured = true + } body(virtualFile, isCommon) } } } } +fun VirtualFile.registerPluginsSuppliedExtensionsIfNeeded(project: Project) { + if ( + extension == null || + extension == KotlinFileType.EXTENSION || + extension == JavaFileType.INSTANCE.defaultExtension || + extension == JavaClassFileType.INSTANCE.defaultExtension || + fileType == KotlinFileType.INSTANCE + ) return + for (extension in CompilerConfigurationExtension.getInstances(project)) { + extension.updateFileRegistry() + } +} + fun createSourceFilesFromSourceRoots( configuration: CompilerConfiguration, project: Project, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/CompilerConfigurationExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/CompilerConfigurationExtension.kt index 14b9ebe74b4..60563230c82 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/extensions/CompilerConfigurationExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/CompilerConfigurationExtension.kt @@ -15,4 +15,6 @@ interface CompilerConfigurationExtension { ) fun updateConfiguration(configuration: CompilerConfiguration) + + fun updateFileRegistry() {} } diff --git a/compiler/testData/integration/ant/js/verbose/build.log.expected b/compiler/testData/integration/ant/js/verbose/build.log.expected index 3547c07936c..47e94efe601 100644 --- a/compiler/testData/integration/ant/js/verbose/build.log.expected +++ b/compiler/testData/integration/ant/js/verbose/build.log.expected @@ -5,7 +5,6 @@ build: [kotlin2js] Compiling [[TestData]/root1] => [[Temp]/out.js] [kotlin2js] logging: using Kotlin home directory [KotlinProjectHome]/dist/kotlinc [kotlin2js] logging: exception on loading scripting plugin: java.lang.ClassNotFoundException: org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar -[kotlin2js] logging: configure scripting: Added template org.jetbrains.kotlin.mainKts.MainKtsScript from [[CompilerLib]/kotlin-main-kts.jar, [CompilerLib]/kotlin-reflect.jar, [CompilerLib]/kotlin-script-runtime.jar, [CompilerLib]/kotlin-stdlib.jar] [kotlin2js] logging: compiling source files: [TestData]/root1/foo.kt BUILD SUCCESSFUL diff --git a/compiler/testData/integration/ant/jvm/verbose/build.log.expected b/compiler/testData/integration/ant/jvm/verbose/build.log.expected index 01b50dabf9d..8b9e0dea68c 100644 --- a/compiler/testData/integration/ant/jvm/verbose/build.log.expected +++ b/compiler/testData/integration/ant/jvm/verbose/build.log.expected @@ -7,7 +7,6 @@ build: [kotlinc] logging: exception on loading scripting plugin: java.lang.ClassNotFoundException: org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar [kotlinc] logging: using JVM IR backend [kotlinc] logging: configuring the compilation environment - [kotlinc] logging: configure scripting: Added template org.jetbrains.kotlin.mainKts.MainKtsScript from [[CompilerLib]/kotlin-main-kts.jar, [CompilerLib]/kotlin-reflect.jar, [CompilerLib]/kotlin-script-runtime.jar, [CompilerLib]/kotlin-stdlib.jar] BUILD SUCCESSFUL Total time: [time] diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scripting/script-template/src/main/kotlin/GreetScriptTemplate.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scripting/script-template/src/main/kotlin/GreetScriptTemplate.kt index 07d650b799e..dc13db8922a 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scripting/script-template/src/main/kotlin/GreetScriptTemplate.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scripting/script-template/src/main/kotlin/GreetScriptTemplate.kt @@ -6,10 +6,18 @@ package org.jetbrains.kotlin.test import kotlin.script.experimental.annotations.* +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.isStandalone -@KotlinScript(fileExtension = "greet.kts") +@KotlinScript(fileExtension = "greet.kts", compilationConfiguration = GreetScriptDefinition::class) abstract class GreetScriptTemplate { fun greet(subject: String) { println("Hello, $subject!") } -} \ No newline at end of file +} + +object GreetScriptDefinition : ScriptCompilationConfiguration( + { + isStandalone(false) + } +) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scriptingCustomExtension/script-template/src/main/kotlin/GreetScriptTemplate.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scriptingCustomExtension/script-template/src/main/kotlin/GreetScriptTemplate.kt index 2283cc1d8e8..2d77bd5db10 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scriptingCustomExtension/script-template/src/main/kotlin/GreetScriptTemplate.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scriptingCustomExtension/script-template/src/main/kotlin/GreetScriptTemplate.kt @@ -5,11 +5,19 @@ package org.jetbrains.kotlin.test -import kotlin.script.experimental.annotations.* +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.isStandalone -@KotlinScript(fileExtension = "greet") +@KotlinScript(fileExtension = "greet", compilationConfiguration = GreetScriptDefinition::class) abstract class GreetScriptTemplate { fun greet(subject: String) { println("Hello, $subject!") } -} \ No newline at end of file +} + +object GreetScriptDefinition : ScriptCompilationConfiguration( + { + isStandalone(false) + } +) 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 10135840370..92e8d81296f 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 @@ -39,6 +39,7 @@ class ScriptDefinitionsFromClasspathDiscoverySource( private const val MANIFEST_RESOURCE_NAME = "/META-INF/MANIFEST.MF" +@Suppress("unused") // TODO: remove if really unused fun discoverScriptTemplatesInClassLoader( classLoader: ClassLoader, hostConfiguration: ScriptingHostConfiguration, diff --git a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt index 42c7c39ca9a..b581ea9c2ff 100644 --- a/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt +++ b/plugins/scripting/scripting-compiler-impl/src/org/jetbrains/kotlin/scripting/definitions/definitions.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.scripting.definitions import com.intellij.ide.highlighter.JavaClassFileType +import com.intellij.ide.highlighter.JavaFileType import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.fileTypes.FileTypeRegistry import com.intellij.openapi.project.Project @@ -56,6 +57,7 @@ fun findScriptDefinition(project: Project, script: SourceCode): ScriptDefinition fun VirtualFile.isNonScript(): Boolean = isDirectory || extension == KotlinFileType.EXTENSION || + extension == JavaFileType.INSTANCE.defaultExtension || extension == JavaClassFileType.INSTANCE.defaultExtension || !this.isKotlinFileType() 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 8729826f22f..065445699cb 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 @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.scripting.compiler.plugin.impl.reporter import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys import org.jetbrains.kotlin.scripting.definitions.* import java.io.File +import java.util.concurrent.atomic.AtomicBoolean import kotlin.script.experimental.host.ScriptingHostConfiguration class ScriptingCompilerConfigurationExtension( @@ -88,15 +89,20 @@ class ScriptingCompilerConfigurationExtension( if (scriptDefinitionProvider != null) { scriptDefinitionProvider.setScriptDefinitionsSources(configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS_SOURCES)) scriptDefinitionProvider.setScriptDefinitions(configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS)) + } + } + } - // Register new file extensions - val fileTypeRegistry = FileTypeRegistry.getInstance() as CoreFileTypeRegistry + override fun updateFileRegistry() { + val scriptDefinitionProvider = ScriptDefinitionProvider.getInstance(project) as? CliScriptDefinitionProvider + if (scriptDefinitionProvider != null) { + // Register new file extensions + val fileTypeRegistry = FileTypeRegistry.getInstance() as CoreFileTypeRegistry - scriptDefinitionProvider.getKnownFilenameExtensions().filter { - fileTypeRegistry.getFileTypeByExtension(it) != KotlinFileType.INSTANCE - }.forEach { - fileTypeRegistry.registerFileType(KotlinFileType.INSTANCE, it) - } + scriptDefinitionProvider.getKnownFilenameExtensions().filter { + fileTypeRegistry.getFileTypeByExtension(it) != KotlinFileType.INSTANCE + }.forEach { + fileTypeRegistry.registerFileType(KotlinFileType.INSTANCE, it) } } } diff --git a/plugins/scripting/scripting-compiler/testData/compiler/mixedCompilation/nonScript.kt b/plugins/scripting/scripting-compiler/testData/compiler/mixedCompilation/nonScript.kt new file mode 100644 index 00000000000..fb57e4d5807 --- /dev/null +++ b/plugins/scripting/scripting-compiler/testData/compiler/mixedCompilation/nonScript.kt @@ -0,0 +1,4 @@ + +fun main() { + println("OK") +} diff --git a/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingWithCliCompilerTest.kt b/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingWithCliCompilerTest.kt index 3b7e086a365..d2a6be121c2 100644 --- a/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingWithCliCompilerTest.kt +++ b/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/plugin/ScriptingWithCliCompilerTest.kt @@ -240,6 +240,33 @@ class ScriptingWithCliCompilerTest { } } + @Test + fun testScriptMainKtsDiscovery() { + withTempDir { tmpdir -> + + fun compileSuccessfullyGetStdErr(fileArg: String): List { + val (_, err, ret) = captureOutErrRet { + CLITool.doMainNoExit( + K2JVMCompiler(), + arrayOf( + "-P", "plugin:kotlin.scripting:disable-script-definitions-autoloading=true", + "-cp", getMainKtsClassPath().joinToString(File.pathSeparator), "-d", tmpdir.path, "-verbose", fileArg) + ) + } + Assert.assertEquals(0, ret.code) + return err.linesSplitTrim() + } + + val loadMainKtsMessage = "logging: configure scripting: loading script definition class org.jetbrains.kotlin.mainKts.MainKtsScript using classpath" + + val res1 = compileSuccessfullyGetStdErr("$TEST_DATA_DIR/compiler/mixedCompilation/nonScript.kt") + Assert.assertTrue(res1.none { it.startsWith(loadMainKtsMessage) }) + + val res2 = compileSuccessfullyGetStdErr("$TEST_DATA_DIR/compiler/mixedCompilation/simpleScript.main.kts") + Assert.assertTrue(res2.any { it.startsWith(loadMainKtsMessage) }) + } + } + private fun getMainKtsClassPath(): List { return listOf( File("dist/kotlinc/lib/kotlin-main-kts.jar").also {