From 25eb93b136372d8d2707bdbb2d9b4101195133c5 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Fri, 13 Jul 2018 12:10:35 +0300 Subject: [PATCH] (partial) Replace the KotlinSourceSet implementation and its factory (Note: this commit leaves the repository in a non-compilable state as it leaves some of the old API usages unchanged; they are replaced with new implementations in further commits where more appropriate) The new implementation covers the wider interface, and the factory should now be used not on its own but in a named domain object container (the API for creating a source set is now provided through the source sets container rather than the factory, so that source sets are also properly registered). --- .../gradle/dsl/KotlinProjectExtension.kt | 10 ++- .../internal/KotlinSourceSetProviderImpl.kt | 71 ---------------- .../model/builder/KotlinModelBuilder.kt | 2 +- .../kotlin/gradle/plugin/KotlinPlugin.kt | 10 ++- .../gradle/plugin/KotlinPluginWrapper.kt | 14 ++- .../gradle/plugin/KotlinSourceSetProvider.kt | 21 ----- .../plugin/sources/DefaultKotlinSourceSet.kt | 85 +++++++++++++++++++ .../plugin/sources/KotlinSourceSetFactory.kt | 55 ++++++++++++ 8 files changed, 169 insertions(+), 99 deletions(-) delete mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSetProviderImpl.kt delete mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinSourceSetProvider.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt index 3d9b20c1dfe..ad092e79571 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt @@ -25,9 +25,17 @@ internal fun Project.createKotlinExtension(extensionClass: KClass + @Suppress("UNCHECKED_CAST") + get() = DslObject(this).extensions.getByName("sourceSets") as NamedDomainObjectContainer + internal set(value) { DslObject(this).extensions.add("sourceSets", value) } } open class KotlinJvmProjectExtension : KotlinProjectExtension() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSetProviderImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSetProviderImpl.kt deleted file mode 100644 index ac0e5cd4d4e..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSetProviderImpl.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.gradle.internal - -import groovy.lang.Closure -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.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetProvider -import java.lang.reflect.Constructor - -internal class KotlinSourceSetProviderImpl constructor(private val fileResolver: FileResolver) : KotlinSourceSetProvider { - override fun create(displayName: String): KotlinSourceSet = - KotlinSourceSetImpl(displayName, fileResolver) -} - -private class KotlinSourceSetImpl(displayName: String, resolver: FileResolver) : KotlinSourceSet { - override val kotlin: SourceDirectorySet = - createDefaultSourceDirectorySet(displayName + " Kotlin source", resolver) - - init { - kotlin.filter?.include("**/*.java", "**/*.kt", "**/*.kts") - } - - override fun kotlin(configureClosure: Closure?): KotlinSourceSet { - ConfigureUtil.configure(configureClosure, kotlin) - return this - } -} - -private val createDefaultSourceDirectorySet: (name: String?, resolver: FileResolver?) -> SourceDirectorySet = run { - val klass = DefaultSourceDirectorySet::class.java - val defaultConstructor = klass.constructorOrNull(String::class.java, FileResolver::class.java) - - if (defaultConstructor != null && defaultConstructor.getAnnotation(java.lang.Deprecated::class.java) == null) { - // TODO: drop when gradle < 2.12 are obsolete - { name, resolver -> defaultConstructor.newInstance(name, resolver) } - } - else { - val directoryFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DirectoryFileTreeFactory") - val alternativeConstructor = klass.getConstructor(String::class.java, FileResolver::class.java, directoryFileTreeFactoryClass) - - val defaultFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DefaultDirectoryFileTreeFactory") - val defaultFileTreeFactory = defaultFileTreeFactoryClass.getConstructor().newInstance() - return@run { name, resolver -> alternativeConstructor.newInstance(name, resolver, defaultFileTreeFactory) } - } -} - -private fun Class.constructorOrNull(vararg parameterTypes: Class<*>): Constructor? = - try { - getConstructor(*parameterTypes) - } - catch (e: NoSuchMethodException) { - null - } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinModelBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinModelBuilder.kt index 9d0c6c84979..98430f9dc02 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinModelBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/model/builder/KotlinModelBuilder.kt @@ -20,8 +20,8 @@ import org.jetbrains.kotlin.gradle.model.impl.KotlinProjectImpl import org.jetbrains.kotlin.gradle.model.impl.SourceSetImpl import org.jetbrains.kotlin.gradle.plugin.KOTLIN_DSL_NAME import org.jetbrains.kotlin.gradle.plugin.KOTLIN_JS_DSL_NAME -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.getConvention +import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile /** diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 7152809ce66..a7870c74c82 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -511,9 +511,13 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT val aptConfigurations = hashMapOf() ext.sourceSets.all { sourceSet -> - logger.kotlinDebug("Creating KotlinSourceSet for source set $sourceSet") - val kotlinSourceSet = kotlinConfigurationTools.kotlinSourceSetProvider.create(sourceSet.name) - kotlinSourceSet.kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin"))) + logger.kotlinDebug("Creating KotlinBaseSourceSet for source set $sourceSet") + val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate( + lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, sourceSet.name) + ).apply { + kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin"))) + kotlin.srcDirs(sourceSet.java.srcDirs) + } sourceSet.addConvention(KOTLIN_DSL_NAME, kotlinSourceSet) Kapt3KotlinGradleSubplugin.createAptConfigurationIfNeeded(project, sourceSet.name) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index be22f74ee5f..e59c891838c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -37,6 +37,11 @@ abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver) private val log = Logging.getLogger(this.javaClass) val kotlinPluginVersion = loadKotlinVersionFromResource(log) + open val projectExtensionClass: KClass get() = KotlinProjectExtension::class + + internal open fun kotlinSourceSetFactory(project: Project): KotlinSourceSetFactory = + DefaultKotlinSourceSetFactory(project, fileResolver) + override fun apply(project: Project) { project.configurations.maybeCreate(COMPILER_CLASSPATH_CONFIGURATION_NAME).defaultDependencies { it.add(project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_COMPILER_EMBEDDABLE:$kotlinPluginVersion")) @@ -50,9 +55,14 @@ abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver) System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true") val kotlinGradleBuildServices = KotlinGradleBuildServices.getInstance(project.gradle) - project.createKotlinExtension(projectExtensionClass) + project.createKotlinExtension(projectExtensionClass).apply { + fun kotlinSourceSetContainer(factory: KotlinSourceSetFactory) = + project.container(factory.itemClass, factory) - val plugin = getPlugin(kotlinGradleBuildServices) + project.kotlinExtension.sourceSets = kotlinSourceSetContainer(kotlinSourceSetFactory(project)) + } + + val plugin = getPlugin(project, kotlinGradleBuildServices) plugin.apply(project) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinSourceSetProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinSourceSetProvider.kt deleted file mode 100644 index f1c39edc90d..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinSourceSetProvider.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.gradle.plugin - -internal interface KotlinSourceSetProvider { - fun create(displayName: String): KotlinSourceSet -} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt new file mode 100644 index 00000000000..c1ee934083f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.plugin.sources + +import groovy.lang.Closure +import org.gradle.api.Project +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.gradle.plugin.KotlinDependencyHandler +import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler +import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSetWithResources +import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName +import java.lang.reflect.Constructor + +class DefaultKotlinSourceSet( + private val project: Project, + val displayName: String, + fileResolver: FileResolver +) : KotlinSourceSetWithResources { + + override val apiConfigurationName: String + get() = disambiguateName("api") + + override val implementationConfigurationName: String + get() = disambiguateName("implementation") + + override val compileOnlyConfigurationName: String + get() = disambiguateName("compileOnly") + + override val runtimeOnlyConfigurationName: String + get() = disambiguateName("runtimeOnly") + + override val kotlin: SourceDirectorySet = createDefaultSourceDirectorySet(name + " Kotlin source", fileResolver).apply { + filter.include("**/*.java", "**/*.kt", "**/*.kts") + } + + override val resources: SourceDirectorySet = createDefaultSourceDirectorySet(displayName + " resources", fileResolver) + + override fun kotlin(configureClosure: Closure): SourceDirectorySet = kotlin.apply { ConfigureUtil.configure(configureClosure, this) } + + override fun getName(): String = displayName + + override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit = + DefaultKotlinDependencyHandler(this, project).run(configure) + + override fun dependencies(configureClosure: Closure) = + dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) } + + override fun toString(): String = "source set $name" +} + +internal fun KotlinSourceSet.disambiguateName(simpleName: String): String { + val nameParts = listOfNotNull(this.name.takeIf { it != "main" }, simpleName) + return lowerCamelCaseName(*nameParts.toTypedArray()) +} + +private val createDefaultSourceDirectorySet: (name: String?, resolver: FileResolver?) -> SourceDirectorySet = run { + val klass = DefaultSourceDirectorySet::class.java + val defaultConstructor = klass.constructorOrNull(String::class.java, FileResolver::class.java) + + if (defaultConstructor != null && defaultConstructor.getAnnotation(java.lang.Deprecated::class.java) == null) { + // TODO: drop when gradle < 2.12 are obsolete + { name, resolver -> defaultConstructor.newInstance(name, resolver) } + } else { + val directoryFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DirectoryFileTreeFactory") + val alternativeConstructor = klass.getConstructor(String::class.java, FileResolver::class.java, directoryFileTreeFactoryClass) + + val defaultFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DefaultDirectoryFileTreeFactory") + val defaultFileTreeFactory = defaultFileTreeFactoryClass.getConstructor().newInstance() + return@run { name, resolver -> alternativeConstructor.newInstance(name, resolver, defaultFileTreeFactory) } + } +} + +private fun Class.constructorOrNull(vararg parameterTypes: Class<*>): Constructor? = + try { + getConstructor(*parameterTypes) + } catch (e: NoSuchMethodException) { + null + } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt new file mode 100644 index 00000000000..016d6b658fe --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/KotlinSourceSetFactory.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.plugin.sources + +import org.gradle.api.NamedDomainObjectFactory +import org.gradle.api.Project +import org.gradle.api.internal.file.FileResolver +import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet +import java.io.File + +internal abstract class KotlinSourceSetFactory internal constructor( + protected val fileResolver: FileResolver, + protected val project: Project +) : NamedDomainObjectFactory { + + abstract val itemClass: Class + + override fun create(name: String): T { + val result = doCreateSourceSet(name) + setUpSourceSetDefaults(result) + return result + } + + protected open fun defaultSourceLocation(sourceSetName: String): File = + project.file("src/$sourceSetName") + + protected open fun setUpSourceSetDefaults(sourceSet: T) { + with(sourceSet) { + sourceSet.kotlin.srcDir(File(defaultSourceLocation(sourceSet.name), "kotlin")) + } + } + + protected abstract fun doCreateSourceSet(name: String): T +} + +internal class DefaultKotlinSourceSetFactory( + project: Project, + fileResolver: FileResolver +) : KotlinSourceSetFactory(fileResolver, project) { + + override val itemClass: Class + get() = DefaultKotlinSourceSet::class.java + + override fun setUpSourceSetDefaults(sourceSet: DefaultKotlinSourceSet) { + super.setUpSourceSetDefaults(sourceSet) + sourceSet.resources.srcDir(File(defaultSourceLocation(sourceSet.name), "resources")) + } + + override fun doCreateSourceSet(name: String): DefaultKotlinSourceSet { + return DefaultKotlinSourceSet(project, name, fileResolver) + } +} \ No newline at end of file