diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/annotations.xml new file mode 100644 index 00000000000..a86a23af2a8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/api/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/api/annotations.xml new file mode 100644 index 00000000000..52bd261a149 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/android/build/gradle/api/annotations.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml index dc5cd1bbcbe..d7fbf5637ce 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml @@ -1,18 +1,26 @@ + - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml index c14ebed20ae..0c7f23a66ff 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml @@ -1,15 +1,17 @@ + - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml index 5859b33807e..fb08bfa4358 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml @@ -1,22 +1,27 @@ + - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 9b609f0d3ee..efda0897cbe 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -4,18 +4,11 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPluginConvention -import org.gradle.api.plugins.JavaPlugin -import groovy.lang.Closure import org.gradle.api.tasks.SourceSet import org.jetbrains.kotlin.gradle.internal.KotlinSourceSetImpl import org.gradle.api.internal.project.ProjectInternal -import org.gradle.api.internal.IConventionAware import org.gradle.api.internal.HasConvention -import org.gradle.api.internal.file.collections.SimpleFileCollection -import org.gradle.api.file.FileTreeElement import org.jetbrains.kotlin.gradle.internal.KotlinSourceSet -import org.gradle.api.file.SourceDirectorySet -import org.codehaus.groovy.runtime.MethodClosure import org.gradle.api.specs.Spec import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KDoc @@ -23,14 +16,22 @@ import java.io.File import java.util.concurrent.Callable import org.gradle.api.Action import org.gradle.api.tasks.compile.AbstractCompile -import java.util.Arrays import org.gradle.api.logging.Logging import com.android.build.gradle.BaseExtension import com.android.build.gradle.AppExtension import com.android.build.gradle.LibraryExtension import org.gradle.api.internal.DefaultDomainObjectSet import com.android.build.gradle.api.BaseVariant -import org.gradle.api.tasks.compile.JavaCompile +import com.android.build.gradle.api.AndroidSourceSet +import org.gradle.api.plugins.ExtensionAware +import org.jetbrains.jet.cli.jvm.K2JVMCompilerArguments +import java.util.ArrayList +import com.android.build.gradle.BasePlugin +import com.android.build.gradle.api.LibraryVariant +import com.android.build.gradle.api.ApkVariant +import com.android.builder.model.BuildType +import com.android.builder.BuilderConstants +import com.android.build.gradle.api.TestVariant open class KotlinPlugin: Plugin { @@ -50,17 +51,15 @@ open class KotlinPlugin: Plugin { javaPluginConvention: JavaPluginConvention) { javaPluginConvention.getSourceSets()?.all(object : Action { override fun execute(sourceSet: SourceSet?) { - if (sourceSet is HasConvention) { + if (sourceSet is ExtensionAware) { val sourceSetName = sourceSet.getName() - val kotlinSourceSet = KotlinSourceSetImpl(sourceSetName, project.getFileResolver()) + val kotlinSourceSet = sourceSet.getExtensions().create("kotlin", javaClass(), sourceSetName, project.getFileResolver())!! val kotlinDirSet = kotlinSourceSet.getKotlin() kotlinDirSet.srcDir(project.file("src/${sourceSetName}/kotlin")) sourceSet.getAllJava()?.source(kotlinDirSet) sourceSet.getAllSource()?.source(kotlinDirSet) - sourceSet.getConvention().getPlugins().put("kotlin", kotlinSourceSet) - sourceSet.getResources()?.getFilter()?.exclude(KSpec({ elem -> kotlinDirSet.contains(elem.getFile()) })) @@ -116,61 +115,150 @@ open class KotlinPlugin: Plugin { open class KotlinAndroidPlugin: Plugin { - val log = Logging.getLogger(getClass())!! + val log = Logging.getLogger(getClass()) + + public override fun apply(p0: Project) { + + val project = p0 as ProjectInternal + val ext = project.getExtensions().getByName("android") as BaseExtension + + ext.getSourceSets()?.all(object : Action { + override fun execute(sourceSet: AndroidSourceSet?) { + if (sourceSet is ExtensionAware) { + val sourceSetName = sourceSet.getName() + val kotlinSourceSet = sourceSet.getExtensions().create("kotlin", javaClass(), sourceSetName, project.getFileResolver())!! + val kotlinDirSet = kotlinSourceSet.getKotlin() + kotlinDirSet.srcDir(project.file("src/${sourceSetName}/kotlin")) + + sourceSet.getAllJava().source(kotlinDirSet) + sourceSet.getAllSource().source(kotlinDirSet) + sourceSet.getResources()?.getFilter()?.exclude(KSpec({ elem -> + kotlinDirSet.contains(elem.getFile()) + })) + project.getLogger().debug("Created kotlin sourceDirectorySet at ${kotlinDirSet.getSrcDirs()}") + } + } + }) + + (ext as ExtensionAware).getExtensions().add("kotlinOptions", K2JVMCompilerArguments()) - public override fun apply(project: Project) { project.afterEvaluate( { (project: Project?): Unit -> if (project != null) { - val extension = project.getExtensions()!!.getByName("android") as BaseExtension - - val testVariants = extension.getTestVariants()!! - processVariants(testVariants, project) - if (extension is AppExtension) { - val appVariants = extension.getApplicationVariants()!! - processVariants(appVariants, project) - + val testVariants = ext.getTestVariants()!! + processVariants(testVariants, project, ext) + if (ext is AppExtension) { + val appVariants = ext.getApplicationVariants()!! + processVariants(appVariants, project, ext) } - if (extension is LibraryExtension) { - val libVariants = extension.getLibraryVariants()!!; - processVariants(libVariants, project) + if (ext is LibraryExtension) { + val libVariants = ext.getLibraryVariants()!!; + processVariants(libVariants, project, ext) } } }) } - private fun processVariants(variants: DefaultDomainObjectSet, project: Project): Unit { + private fun processVariants(variants: DefaultDomainObjectSet, project: Project, androidExt: BaseExtension): Unit { + val logger = project.getLogger() + logger.debug("Kotlin plugin processing variants") + val kotlinOptions = (androidExt as ExtensionAware).getExtensions().getByName("kotlinOptions") as K2JVMCompilerArguments + val sourceSets = androidExt.getSourceSets() + val mainSourceSet = sourceSets.getByName(BuilderConstants.MAIN) + val testSourceSet = sourceSets.getByName(BuilderConstants.INSTRUMENT_TEST) + logger.debug("Loaded ${BuilderConstants.MAIN} and ${BuilderConstants.INSTRUMENT_TEST} source sets") + for (variant in variants) { - val javaTask = variant.getJavaCompile()!! - val destinationDir = javaTask.getDestinationDir() - val classPath = javaTask.getClasspath() + logger.debug("Processing variant [${variant}]") + + if (variant is LibraryVariant || variant is ApkVariant) { + val buildType: BuildType = if (variant is LibraryVariant) { + variant.getBuildType() + } else { + (variant as ApkVariant).getBuildType() + } + + val buildTypeSourceSetName = buildType.getName() + logger.debug("Variant build type is [$buildTypeSourceSetName]") + val buildTypeSourceSet : AndroidSourceSet? = sourceSets.findByName(buildTypeSourceSetName) + + val javaTask = variant.getJavaCompile()!! + val variantName = variant.getName() + + val kotlinTaskName = "compile${variantName}Kotlin" + val kotlinTask: KotlinCompile = project.getTasks()!!.add(kotlinTaskName, javaClass())!! + kotlinTask.kotlinOptions = kotlinOptions - val variantName = variant.getName() - val kotlinTaskName = "compile${variantName}Kotlin" - val kotlinTask: KotlinCompile = project.getTasks()!!.add(kotlinTaskName, javaClass())!! - // store kotlin classes in separate directory. They will serve as class-path to java compiler - val kotlinOutputDir = File(project.getBuildDir(), "kotlin-classes/${variantName}") - kotlinTask.kotlinDestinationDir = kotlinOutputDir; - kotlinTask.setDestinationDir(destinationDir) - kotlinTask.setDescription("Compiles the ${variantName} kotlin.") + // store kotlin classes in separate directory. They will serve as class-path to java compiler + val kotlinOutputDir = File(project.getBuildDir(), "kotlin-classes/${variantName}") + kotlinTask.kotlinDestinationDir = kotlinOutputDir; + kotlinTask.setDestinationDir(javaTask.getDestinationDir()) + kotlinTask.setDescription("Compiles the ${variantName} kotlin.") + kotlinTask.setClasspath(javaTask.getClasspath()) + kotlinTask.setDependsOn(javaTask.getDependsOn()) - kotlinTask.source("src/main/kotlin") - kotlinTask.source(javaTask.getSource()) // for cross compilation + val javaSourceList = ArrayList() - kotlinTask.setClasspath(javaTask.getClasspath()) - kotlinTask.setDependsOn(javaTask.getDependsOn()) + if (variant is TestVariant) { + javaSourceList.addAll(testSourceSet.getJava()!!.getSrcDirs()!!) + val testKotlinSource = (testSourceSet as ExtensionAware).getExtensions().getByName("kotlin") as KotlinSourceSet + logger.debug("Attaching ${testKotlinSource.getKotlin().getSrcDirs()} to variant ${variantName}") + kotlinTask.source(testKotlinSource.getKotlin()) + } else { + javaSourceList.addAll(mainSourceSet.getJava()!!.getSrcDirs()!!) + val mainKotlinSource = (mainSourceSet as ExtensionAware).getExtensions().getByName("kotlin") as KotlinSourceSet + logger.debug("Attaching ${mainKotlinSource.getKotlin().getSrcDirs()} to variant ${variantName}") + kotlinTask.source(mainKotlinSource.getKotlin()) + } - javaTask.dependsOn(kotlinTaskName) - val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir); - javaTask.setClasspath(javacClassPath) + if (null != buildTypeSourceSet) { + javaSourceList.add(buildTypeSourceSet.getJava()!!.getSrcDirs()!!) + kotlinTask.source(((buildTypeSourceSet as ExtensionAware).getExtensions().getByName("kotlin") as KotlinSourceSet).getKotlin()) + } + javaSourceList.add(callable{ variant.getProcessResources()!!.getSourceOutputDir()!! }) + javaSourceList.add(callable{ variant.getGenerateBuildConfig()!!.getSourceOutputDir()!! }) + javaSourceList.add(callable{ variant.getAidlCompile()!!.getSourceOutputDir()!! }) + javaSourceList.add(callable{ variant.getRenderscriptCompile()!!.getSourceOutputDir()!! }) + + if (variant is ApkVariant) { + for (flavour in variant.getProductFlavors().iterator()) { + val flavourSourceSetName = buildTypeSourceSetName + flavour.getName() + val flavourSourceSet : AndroidSourceSet? = sourceSets.findByName(flavourSourceSetName) + if (flavourSourceSet != null) { + javaSourceList.add(flavourSourceSet.getJava()) + kotlinTask.source((buildTypeSourceSet as ExtensionAware).getExtensions().getByName("kotlin")) + } + } + } + + logger.debug("Kotlin Source list for [${variantName}]") + kotlinTask.getSource().forEach { f -> logger.debug(f.getPath()) } + logger.debug("Kotlin Source list end") + + val basePlugin : BasePlugin = project.getPlugins().getPlugin("android") as BasePlugin + + kotlinTask.doFirst({ task -> + val javaSources = project.files(javaSourceList) + logger.debug("Java Source list for [${variantName}]") + javaSources?.forEach { f -> logger.debug(f.getPath()) } + logger.debug("Java Source list end") + + val cp = javaTask.getClasspath() + javaSources + val cpWithRt = project.files(basePlugin.getRuntimeJarList())!! + cp + (task as AbstractCompile).setClasspath(cpWithRt) + logger.debug("Final Classpath for variant [${variantName}]") + cpWithRt?.forEach { f -> logger.debug(f.getPath()) } + logger.debug("Final Classpath end") + }) + + javaTask.dependsOn(kotlinTaskName) + val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir); + javaTask.setClasspath(javacClassPath) + } } } - - private fun configureKotlinCompileTask(javaCompile : JavaCompile) : Unit { - - } } open class KSpec(val predicate: (T) -> Boolean): Spec { diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 3ac44255d81..4d9c02f3420 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -31,7 +31,7 @@ public open class KotlinCompile(): AbstractCompile() { val compiler = K2JVMCompiler() val logger = Logging.getLogger(getClass()) - public val kotlinOptions: K2JVMCompilerArguments = K2JVMCompilerArguments(); + public var kotlinOptions: K2JVMCompilerArguments = K2JVMCompilerArguments(); public var kotlinDestinationDir : File? = getDestinationDir()