Implement support for non-kts scripts in gradle
#KT-26784 fixed
This commit is contained in:
+2
@@ -39,4 +39,6 @@ interface KotlinSourceSet : Named, HasKotlinDependencies {
|
||||
const val COMMON_MAIN_SOURCE_SET_NAME = "commonMain"
|
||||
const val COMMON_TEST_SOURCE_SET_NAME = "commonTest"
|
||||
}
|
||||
|
||||
val customSourceFilesExtensions: Iterable<String> // lazy iterable expected
|
||||
}
|
||||
@@ -45,6 +45,7 @@ dependencies {
|
||||
compileOnly project(':kotlin-compiler-runner')
|
||||
compileOnly project(':kotlin-annotation-processing')
|
||||
compileOnly project(':kotlin-annotation-processing-gradle')
|
||||
compileOnly project(':kotlin-scripting-compiler')
|
||||
|
||||
compileOnly 'com.android.tools.build:gradle:2.0.0'
|
||||
compileOnly 'org.codehaus.groovy:groovy-all:2.4.12'
|
||||
@@ -62,6 +63,7 @@ dependencies {
|
||||
runtime project(path: ':kotlin-annotation-processing-gradle', configuration: "runtimeJar")
|
||||
runtime project(path: ':kotlin-android-extensions', configuration: 'runtimeJar')
|
||||
runtime project(path: ':kotlin-compiler-runner', configuration: 'runtimeJar')
|
||||
runtime project(path: ':kotlin-scripting-compiler-embeddable', configuration: 'runtimeJar')
|
||||
runtime project(':kotlin-reflect')
|
||||
|
||||
// com.android.tools.build:gradle has ~50 unneeded transitive dependencies
|
||||
|
||||
+1
@@ -162,6 +162,7 @@ internal class Kotlin2JvmSourceSetProcessor(
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
Kapt3KotlinGradleSubplugin.createAptConfigurationIfNeeded(project, kotlinCompilation.compilationName)
|
||||
ScriptingGradleSubplugin.createDiscoveryConfigurationIfNeeded(project, kotlinCompilation.compilationName)
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile }
|
||||
|
||||
+6
-4
@@ -70,10 +70,12 @@ abstract class AbstractKotlinCompilation(
|
||||
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||
|
||||
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||
val compileTask = target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>
|
||||
compileTask.source(sourceSet.kotlin)
|
||||
if (addAsCommonSources) {
|
||||
compileTask.commonSourceSet += sourceSet.kotlin
|
||||
(target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).apply {
|
||||
source(sourceSet.kotlin)
|
||||
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||
if (addAsCommonSources) {
|
||||
commonSourceSet += sourceSet.kotlin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-1
@@ -12,6 +12,7 @@ import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.internal.file.DefaultSourceDirectorySet
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||
@@ -53,7 +54,9 @@ class DefaultKotlinSourceSet(
|
||||
get() = lowerCamelCaseName(runtimeOnlyConfigurationName, METADATA_CONFIGURATION_NAME_SUFFIX)
|
||||
|
||||
override val kotlin: SourceDirectorySet = createDefaultSourceDirectorySet(name + " Kotlin source", fileResolver).apply {
|
||||
filter.include("**/*.java", "**/*.kt", "**/*.kts")
|
||||
filter.include("**/*.java")
|
||||
filter.include("**/*.kt")
|
||||
filter.include("**/*.kts")
|
||||
}
|
||||
|
||||
override val languageSettings: LanguageSettingsBuilder = DefaultLanguageSettingsBuilder()
|
||||
@@ -89,6 +92,16 @@ class DefaultKotlinSourceSet(
|
||||
get() = dependsOnSourceSetsImpl
|
||||
|
||||
override fun toString(): String = "source set $name"
|
||||
|
||||
override val customSourceFilesExtensions: Iterable<String>
|
||||
get() = Iterable {
|
||||
kotlin.filter.includes.mapNotNull { pattern ->
|
||||
pattern.substringAfterLast('.').takeUnless { extension ->
|
||||
DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS.any { extension.equals(it, ignoreCase = true) }
|
||||
|| extension.any { it == '\\' || it == '/' }
|
||||
}
|
||||
}.iterator()
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinSourceSet.checkForCircularDependencies(): Unit {
|
||||
|
||||
+87
-1
@@ -5,18 +5,104 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.scripting.internal
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension
|
||||
import org.jetbrains.kotlin.gradle.tasks.GradleMessageCollector
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptDefinitionsFromClasspathDiscoverySource
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class ScriptingGradleSubplugin : Plugin<Project> {
|
||||
companion object {
|
||||
fun isEnabled(project: Project) = project.plugins.findPlugin(ScriptingGradleSubplugin::class.java) != null
|
||||
|
||||
val MAIN_CONFIGURATION_NAME = "kotlinScriptDef"
|
||||
|
||||
fun getConfigurationName(sourceSetName: String): String = when (sourceSetName) {
|
||||
"main" -> MAIN_CONFIGURATION_NAME
|
||||
else -> "$sourceSetName${MAIN_CONFIGURATION_NAME.capitalize()}"
|
||||
}
|
||||
|
||||
fun createDiscoveryConfigurationIfNeeded(project: Project, sourceSetName: String) {
|
||||
project.configurations.maybeCreate(getConfigurationName(sourceSetName))
|
||||
}
|
||||
}
|
||||
|
||||
override fun apply(project: Project) {}
|
||||
override fun apply(project: Project) {
|
||||
|
||||
project.afterEvaluate {
|
||||
|
||||
val javaPluginConvention = project.convention.findPlugin(JavaPluginConvention::class.java)
|
||||
if (javaPluginConvention?.sourceSets?.isEmpty() == false) {
|
||||
|
||||
project.tasks.all { task ->
|
||||
if (task is KotlinCompile) {
|
||||
val configuration = project.configurations.findByName(getConfigurationName(task.sourceSetName))
|
||||
if (configuration?.isEmpty == false) {
|
||||
javaPluginConvention.sourceSets.findByName(task.sourceSetName)?.let { sourceSet ->
|
||||
val extensionsTask =
|
||||
project.tasks.create(
|
||||
"discover${task.sourceSetName.capitalize()}ScriptsExtensions",
|
||||
DiscoverScriptExtensionsTask::class.java
|
||||
)
|
||||
extensionsTask.sourceSet = sourceSet
|
||||
extensionsTask.discoveryClasspathConfiguration = configuration
|
||||
extensionsTask.kotlinCompile = task
|
||||
task.dependsOn.add(extensionsTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
project.logger.warn("kotlin scripting plugin: applied to a non-JVM project $project")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class DiscoverScriptExtensionsTask : DefaultTask() {
|
||||
|
||||
@get:Internal
|
||||
internal var sourceSet: SourceSet by Delegates.notNull()
|
||||
|
||||
@get:Internal
|
||||
internal var discoveryClasspathConfiguration: Configuration by Delegates.notNull()
|
||||
|
||||
@get:Internal
|
||||
internal var kotlinCompile: KotlinCompile by Delegates.notNull()
|
||||
|
||||
override fun getDependsOn(): MutableSet<Any> = kotlinCompile.dependsOn
|
||||
|
||||
@TaskAction
|
||||
@Suppress("unused")
|
||||
fun findKnownScriptExtensions() {
|
||||
val scriptingClasspath = discoveryClasspathConfiguration.files.takeIf { it.isNotEmpty() } ?: return
|
||||
|
||||
val definitions =
|
||||
ScriptDefinitionsFromClasspathDiscoverySource(
|
||||
scriptingClasspath.toList(), emptyMap(),
|
||||
GradleMessageCollector(project.logger)
|
||||
).definitions
|
||||
val extensions = definitions.mapTo(arrayListOf(), KotlinScriptDefinition::fileExtension)
|
||||
val kotlinSourceSet = sourceSet.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet
|
||||
if (kotlinSourceSet == null) {
|
||||
project.logger.warn("kotlin scripting plugin: kotlin source set not found: $project.$sourceSet")
|
||||
} else if (extensions.isNotEmpty()) {
|
||||
project.logger.info("kotlin scripting plugin: Add new extensions to the sourceset $project.$sourceSet: $extensions")
|
||||
kotlinSourceSet.kotlin.filter.include(extensions.map { "**/*.$it" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ScriptingKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ internal open class KotlinCompileCommon : AbstractKotlinCompile<K2MetadataCompil
|
||||
K2MetadataCompilerArguments()
|
||||
|
||||
override fun getSourceRoots(): SourceRoots =
|
||||
SourceRoots.KotlinOnly.create(getSource())
|
||||
SourceRoots.KotlinOnly.create(getSource(), sourceFilesExtensions)
|
||||
|
||||
override fun findKotlinCompilerClasspath(project: Project): List<File> =
|
||||
findKotlinMetadataCompilerClasspath(project)
|
||||
|
||||
+4
-3
@@ -22,8 +22,8 @@ internal sealed class SourceRoots(val kotlinSourceFiles: List<File>) {
|
||||
|
||||
class ForJvm(kotlinSourceFiles: List<File>, val javaSourceRoots: Set<File>) : SourceRoots(kotlinSourceFiles) {
|
||||
companion object {
|
||||
fun create(taskSource: FileTree, sourceRoots: FilteringSourceRootsContainer): ForJvm {
|
||||
val kotlinSourceFiles = (taskSource as Iterable<File>).filter(File::isKotlinFile)
|
||||
fun create(taskSource: FileTree, sourceRoots: FilteringSourceRootsContainer, sourceFilesExtensions: List<String>): ForJvm {
|
||||
val kotlinSourceFiles = (taskSource as Iterable<File>).filter { it.isKotlinFile(sourceFilesExtensions) }
|
||||
val javaSourceRoots = findRootsForSources(
|
||||
sourceRoots.sourceRoots, taskSource.filter(File::isJavaFile))
|
||||
return ForJvm(kotlinSourceFiles, javaSourceRoots)
|
||||
@@ -53,7 +53,8 @@ internal sealed class SourceRoots(val kotlinSourceFiles: List<File>) {
|
||||
|
||||
class KotlinOnly(kotlinSourceFiles: List<File>) : SourceRoots(kotlinSourceFiles) {
|
||||
companion object {
|
||||
fun create(taskSource: FileTree) = KotlinOnly((taskSource as Iterable<File>).filter(File::isKotlinFile))
|
||||
fun create(taskSource: FileTree, sourceFilesExtensions: List<String>) =
|
||||
KotlinOnly((taskSource as Iterable<File>).filter { it.isKotlinFile(sourceFilesExtensions) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -15,6 +15,7 @@ import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||
@@ -153,6 +154,16 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
get() = (classpath + additionalClasspath)
|
||||
.filterTo(LinkedHashSet(), File::exists)
|
||||
|
||||
private val sourceFilesExtensionsSources: MutableList<Iterable<String>> = mutableListOf()
|
||||
|
||||
@get:Input
|
||||
val sourceFilesExtensions: List<String>
|
||||
get() = DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS + sourceFilesExtensionsSources.flatten()
|
||||
|
||||
internal fun sourceFilesExtensions(extensions: Iterable<String>) {
|
||||
sourceFilesExtensionsSources.add(extensions)
|
||||
}
|
||||
|
||||
private val kotlinExt: KotlinProjectExtension
|
||||
get() = project.extensions.findByType(KotlinProjectExtension::class.java)!!
|
||||
|
||||
@@ -360,7 +371,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
}
|
||||
|
||||
@Internal
|
||||
override fun getSourceRoots() = SourceRoots.ForJvm.create(getSource(), sourceRootsContainer)
|
||||
override fun getSourceRoots() = SourceRoots.ForJvm.create(getSource(), sourceRootsContainer, sourceFilesExtensions)
|
||||
|
||||
override fun callCompiler(args: K2JVMCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) {
|
||||
sourceRoots as SourceRoots.ForJvm
|
||||
@@ -487,7 +498,7 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>(),
|
||||
kotlinOptionsImpl.updateArguments(args)
|
||||
}
|
||||
|
||||
override fun getSourceRoots() = SourceRoots.KotlinOnly.create(getSource())
|
||||
override fun getSourceRoots() = SourceRoots.KotlinOnly.create(getSource(), sourceFilesExtensions)
|
||||
|
||||
@get:InputFiles
|
||||
@get:Optional
|
||||
|
||||
+2
-5
@@ -13,11 +13,8 @@ import java.util.*
|
||||
internal fun File.isJavaFile() =
|
||||
extension.equals("java", ignoreCase = true)
|
||||
|
||||
internal fun File.isKotlinFile(): Boolean =
|
||||
extension.let {
|
||||
"kt".equals(it, ignoreCase = true) ||
|
||||
"kts".equals(it, ignoreCase = true)
|
||||
}
|
||||
internal fun File.isKotlinFile(sourceFilesExtensions: List<String>): Boolean =
|
||||
!isJavaFile() && sourceFilesExtensions.any { it.equals(extension, ignoreCase = true) }
|
||||
|
||||
internal fun File.isClassFile(): Boolean =
|
||||
extension.equals("class", ignoreCase = true)
|
||||
|
||||
Reference in New Issue
Block a user