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