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 721f99574bc..9bd0a9444ec 100644 --- 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 @@ -24,6 +24,9 @@ import com.android.build.gradle.BasePlugin import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.api.ApkVariant import com.android.build.gradle.api.TestVariant +import com.android.build.gradle.internal.variant.BaseVariantData +import com.android.build.gradle.internal.variant.BaseVariantOutputData +import com.android.builder.core.VariantType import org.gradle.api.plugins.JavaPlugin import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.artifacts.ConfigurationContainer @@ -35,6 +38,7 @@ import org.gradle.api.file.SourceDirectorySet import kotlin.properties.Delegates import org.gradle.api.tasks.Delete import groovy.lang.Closure +import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import java.util.ServiceLoader import org.gradle.api.logging.* @@ -288,121 +292,89 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val t project afterEvaluate { project -> if (project != null) { - val testVariants = AndroidGradleWrapper.getTestVariants(ext) - processVariants(testVariants, project, ext) - if (ext is AppExtension) { - val appVariants = ext.getApplicationVariants()!! - processVariants(appVariants, project, ext) - } + val plugin = (project.getPlugins().findPlugin("android") + ?: project.getPlugins().findPlugin("android-library")) as BasePlugin - if (ext is LibraryExtension) { - val libVariants = ext.getLibraryVariants()!! - processVariants(libVariants, project, ext) - } + processVariantData(plugin.getVariantManager().getVariantDataList(), project, ext, plugin) } } project.getExtensions().add(DEFAULT_ANNOTATIONS, GradleUtils(scriptHandler, project).resolveKotlinPluginDependency("kotlin-android-sdk-annotations")) } - private fun processVariants(variants: DefaultDomainObjectSet, project: Project, androidExt: BaseExtension): Unit { + private fun processVariantData( + variantDataList: List>, + project: Project, + androidExt: BaseExtension, + androidPlugin: BasePlugin + ) { val logger = project.getLogger() val kotlinOptions = getExtension(androidExt, "kotlinOptions") - val sourceSets = androidExt.getSourceSets() - //TODO: change to BuilderConstants.MAIN - it was relocated in 0.11 plugin - val mainSourceSet = sourceSets.getByName("main") - val testSourceSet = try { - sourceSets.getByName("instrumentTest") - } catch (e: UnknownDomainObjectException) { - sourceSets.getByName("androidTest") - } val subpluginEnvironment = loadSubplugins(project, logger) - for (variant in variants) { - if (variant is LibraryVariant || variant is ApkVariant) { - val buildTypeSourceSetName = AndroidGradleWrapper.getVariantName(variant) + for (variantData in variantDataList) { + val variantDataName = variantData.getName() + logger.debug("Process variant [$variantDataName]") - logger.debug("Variant build type is [$buildTypeSourceSetName]") - val buildTypeSourceSet = sourceSets.findByName(buildTypeSourceSetName) + val javaTask = variantData.javaCompileTask - val javaTask = variant.getJavaCompile()!! - val variantName = variant.getName() + val kotlinTaskName = "compile${variantDataName.capitalize()}Kotlin" + val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName) + if (kotlinOptions != null) { + kotlinTask.setProperty("kotlinOptions", kotlinOptions) + } - val kotlinTaskName = "compile${variantName.capitalize()}Kotlin" - val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName) - if (kotlinOptions != null) { - kotlinTask.setProperty("kotlinOptions", kotlinOptions) + // store kotlin classes in separate directory. They will serve as class-path to java compiler + val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantDataName}") + kotlinTask.setProperty("kotlinDestinationDir", kotlinOutputDir) + kotlinTask.setDestinationDir(javaTask.getDestinationDir()) + kotlinTask.setDescription("Compiles the ${variantDataName} kotlin.") + kotlinTask.setClasspath(javaTask.getClasspath()) + kotlinTask.setDependsOn(javaTask.getDependsOn()) + + fun SourceDirectorySet.addSourceDirectories(additionalSourceFiles: Collection) { + for (dir in additionalSourceFiles) { + this.srcDir(dir) + logger.debug("Source directory ${dir.getAbsolutePath()} was added to kotlin source for $kotlinTaskName") } + } - // store kotlin classes in separate directory. They will serve as class-path to java compiler - val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantName}") - kotlinTask.setProperty("kotlinDestinationDir", kotlinOutputDir) - kotlinTask.setDestinationDir(javaTask.getDestinationDir()) - kotlinTask.setDescription("Compiles the ${variantName} kotlin.") - kotlinTask.setClasspath(javaTask.getClasspath()) - kotlinTask.setDependsOn(javaTask.getDependsOn()) + fun configureDefaultSourceSet() { + val defaultSourceSet = variantData.getVariantConfiguration().getDefaultSourceSet() + val kotlinSourceDirectorySet = getExtension(defaultSourceSet, "kotlin").getKotlin() + // getJavaSources should return the Java sources used for compilation + // We want to collect only generated files, like R-class output dir + // Actual java sources will be collected later + val additionalSourceFiles = variantData.getJavaSources().filterIsInstance(javaClass()) + kotlinSourceDirectorySet.addSourceDirectories(additionalSourceFiles) + } - fun processSourceSet(javaSourceSet: AndroidSourceSet): SourceDirectorySet { - val javaSrcDirs = AndroidGradleWrapper.getJavaSrcDirs(javaSourceSet) - val kotlinSourceSet = getExtension(javaSourceSet, "kotlin") - val kotlinSDS = kotlinSourceSet.getKotlin() - for (dir in javaSrcDirs) { - kotlinSDS.srcDir(dir) - } - kotlinTask.source(kotlinSDS) - return kotlinSDS - } + configureDefaultSourceSet() - if (variant is TestVariant) { - processSourceSet(testSourceSet) - } else { - processSourceSet(mainSourceSet) - } + // getSortedSourceProviders should return only actual java sources, generated sources should be collected earlier + val providers = variantData.getVariantConfiguration().getSortedSourceProviders() + for (provider in providers) { + val javaSrcDirs = AndroidGradleWrapper.getJavaSrcDirs(provider as AndroidSourceSet) + val kotlinSourceSet = getExtension(provider, "kotlin") + val kotlinSourceDirectorySet = kotlinSourceSet.getKotlin() + kotlinTask.source(kotlinSourceDirectorySet) - if (buildTypeSourceSet != null) { - val variantSourceDirectorySet = processSourceSet(buildTypeSourceSet) - for (resourceFolder in AndroidGradleWrapper.getRClassFolder(variant)) { - variantSourceDirectorySet.srcDir(resourceFolder) - } - variantSourceDirectorySet.srcDir(variant.getGenerateBuildConfig()?.getSourceOutputDir()) - variantSourceDirectorySet.srcDir(variant.getAidlCompile().getSourceOutputDir()) - variantSourceDirectorySet.srcDir(variant.getRenderscriptCompile().getSourceOutputDir()) - } + kotlinSourceDirectorySet.addSourceDirectories(javaSrcDirs) + } - if (variant is ApkVariant) { - for (flavourName in AndroidGradleWrapper.getProductFlavorsNames(variant)) { - val defaultFlavourSourceSetName = flavourName + buildTypeSourceSetName.capitalize() - val defaultFlavourSourceSet = sourceSets.findByName(defaultFlavourSourceSetName) - if (defaultFlavourSourceSet != null) { - processSourceSet(defaultFlavourSourceSet) - } + subpluginEnvironment.addSubpluginArguments(project, kotlinTask) - val flavourSourceSet = sourceSets.findByName(flavourName) - if (flavourSourceSet != null) { - processSourceSet(flavourSourceSet) - } - } - } + kotlinTask doFirst { + val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt)) + val fullClasspath = (javaTask.getClasspath() + androidRT) - project.files(kotlinTask.property("kotlinDestinationDir")) + (it as AbstractCompile).setClasspath(fullClasspath) + } - subpluginEnvironment.addSubpluginArguments(project, kotlinTask) + javaTask.dependsOn(kotlinTaskName) - kotlinTask doFirst { - var plugin = project.getPlugins().findPlugin("android") - if (null == plugin) { - plugin = project.getPlugins().findPlugin("android-library") - } - val basePlugin: BasePlugin = plugin as BasePlugin - val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(basePlugin, androidExt)) - val fullClasspath = (javaTask.getClasspath() + androidRT) - project.files(kotlinTask.property("kotlinDestinationDir")) - (it as AbstractCompile).setClasspath(fullClasspath) - } - - javaTask.dependsOn(kotlinTaskName) - - javaTask doFirst { - javaTask.setClasspath(javaTask.getClasspath() + project.files(kotlinTask.property("kotlinDestinationDir"))) - } + javaTask doFirst { + javaTask.setClasspath(javaTask.getClasspath() + project.files(kotlinTask.property("kotlinDestinationDir"))) } } }