disconnect wrapper from core, delegate API calls using Gradle dynamic objects

This commit is contained in:
Nikita Skvortsov
2014-12-25 20:01:38 +03:00
committed by Natalia Ukhorskaya
parent 4e99a61aea
commit f8c65e8a62
5 changed files with 82 additions and 55 deletions
@@ -188,17 +188,22 @@ public open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArgumen
addLibraryFiles(*strs) addLibraryFiles(*strs)
} }
fun outputFile(): String? = kotlinOptions.outputFile public val outputFile: String?
get() = kotlinOptions.outputFile
public fun sourceMapDestinationDir(): File = File(outputFile()).directory public val sourceMapDestinationDir: File
get() = File(outputFile).directory
public val sourceMap: Boolean
get() = kotlinOptions.sourceMap
{ {
getOutputs().file(MethodClosure(this, "outputFile")) getOutputs().file(MethodClosure(this, "getOutputFile"))
} }
override fun populateTargetSpecificArgs(args: K2JSCompilerArguments) { override fun populateTargetSpecificArgs(args: K2JSCompilerArguments) {
args.noStdlib = true args.noStdlib = true
args.outputFile = outputFile() args.outputFile = outputFile
args.outputPrefix = kotlinOptions.outputPrefix args.outputPrefix = kotlinOptions.outputPrefix
args.outputPostfix = kotlinOptions.outputPostfix args.outputPostfix = kotlinOptions.outputPostfix
+2 -6
View File
@@ -25,11 +25,13 @@
<artifactId>kotlin-stdlib</artifactId> <artifactId>kotlin-stdlib</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<!--
<dependency> <dependency>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId> <artifactId>kotlin-js-library</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
-->
<dependency> <dependency>
<groupId>com.android.tools.build</groupId> <groupId>com.android.tools.build</groupId>
<artifactId>gradle</artifactId> <artifactId>gradle</artifactId>
@@ -42,12 +44,6 @@
<version>1.6</version> <version>1.6</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-gradle-plugin-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-gradle-plugin-test</artifactId> <artifactId>kotlin-gradle-plugin-test</artifactId>
@@ -9,8 +9,6 @@ import org.jetbrains.kotlin.gradle.internal.KotlinSourceSetImpl
import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.internal.HasConvention import org.gradle.api.internal.HasConvention
import org.jetbrains.kotlin.gradle.internal.KotlinSourceSet import org.jetbrains.kotlin.gradle.internal.KotlinSourceSet
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KDoc
import java.io.File import java.io.File
import org.gradle.api.Action import org.gradle.api.Action
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
@@ -22,7 +20,6 @@ import org.gradle.api.internal.DefaultDomainObjectSet
import com.android.build.gradle.api.BaseVariant import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.api.AndroidSourceSet import com.android.build.gradle.api.AndroidSourceSet
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.jetbrains.jet.cli.common.arguments.K2JVMCompilerArguments
import java.util.ArrayList import java.util.ArrayList
import com.android.build.gradle.BasePlugin import com.android.build.gradle.BasePlugin
import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.api.LibraryVariant
@@ -35,11 +32,11 @@ import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.initialization.dsl.ScriptHandler import org.gradle.api.initialization.dsl.ScriptHandler
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
import javax.inject.Inject import javax.inject.Inject
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
import org.gradle.api.file.SourceDirectorySet import org.gradle.api.file.SourceDirectorySet
import kotlin.properties.Delegates import kotlin.properties.Delegates
import org.gradle.api.tasks.Delete import org.gradle.api.tasks.Delete
import groovy.lang.Closure import groovy.lang.Closure
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
val DEFAULT_ANNOTATIONS = "org.jebrains.kotlin.gradle.defaultAnnotations" val DEFAULT_ANNOTATIONS = "org.jebrains.kotlin.gradle.defaultAnnotations"
@@ -115,24 +112,26 @@ class Kotlin2JvmSourceSetProcessor(
project: ProjectInternal, project: ProjectInternal,
javaBasePlugin: JavaBasePlugin, javaBasePlugin: JavaBasePlugin,
sourceSet: SourceSet, sourceSet: SourceSet,
val scriptHandler: ScriptHandler val scriptHandler: ScriptHandler,
) : KotlinSourceSetProcessor<KotlinCompile>( val tasksProvider: KotlinTasksProvider
) : KotlinSourceSetProcessor<AbstractCompile>(
project, javaBasePlugin, sourceSet, project, javaBasePlugin, sourceSet,
pluginName = "kotlin", pluginName = "kotlin",
compileTaskNameSuffix = "kotlin", compileTaskNameSuffix = "kotlin",
taskDescription = "Compiles the $sourceSet.kotlin.", taskDescription = "Compiles the $sourceSet.kotlin.",
compilerClass = javaClass() compilerClass = tasksProvider.kotlinJVMCompileTaskClass
) { ) {
override fun doTargetSpecificProcessing() { override fun doTargetSpecificProcessing() {
// store kotlin classes in separate directory. They will serve as class-path to java compiler // store kotlin classes in separate directory. They will serve as class-path to java compiler
kotlinTask.kotlinDestinationDir = File(project.getBuildDir(), "kotlin-classes/${sourceSetName}") val kotlinDestinationDir = File(project.getBuildDir(), "kotlin-classes/${sourceSetName}")
kotlinTask.setProperty("kotlinDestinationDir", kotlinDestinationDir)
val javaTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile? val javaTask = project.getTasks().findByName(sourceSet.getCompileJavaTaskName()) as AbstractCompile?
if (javaTask != null) { if (javaTask != null) {
javaTask.dependsOn(kotlinTaskName) javaTask.dependsOn(kotlinTaskName)
val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir); val javacClassPath = javaTask.getClasspath() + project.files(kotlinDestinationDir);
javaTask.setClasspath(javacClassPath) javaTask.setClasspath(javacClassPath)
} }
} }
@@ -142,13 +141,14 @@ class Kotlin2JsSourceSetProcessor(
project: ProjectInternal, project: ProjectInternal,
javaBasePlugin: JavaBasePlugin, javaBasePlugin: JavaBasePlugin,
sourceSet: SourceSet, sourceSet: SourceSet,
val scriptHandler: ScriptHandler val scriptHandler: ScriptHandler,
) : KotlinSourceSetProcessor<Kotlin2JsCompile>( val tasksProvider: KotlinTasksProvider
) : KotlinSourceSetProcessor<AbstractCompile>(
project, javaBasePlugin, sourceSet, project, javaBasePlugin, sourceSet,
pluginName = "kotlin2js", pluginName = "kotlin2js",
taskDescription = "Compiles the kotlin sources in $sourceSet to JavaScript.", taskDescription = "Compiles the kotlin sources in $sourceSet to JavaScript.",
compileTaskNameSuffix = "kotlin2Js", compileTaskNameSuffix = "kotlin2Js",
compilerClass = javaClass<Kotlin2JsCompile>() compilerClass = tasksProvider.kotlinJSCompileTaskClass
) { ) {
val copyKotlinJsTaskName = sourceSet.getTaskName("copy", "kotlinJs") val copyKotlinJsTaskName = sourceSet.getTaskName("copy", "kotlinJs")
@@ -156,18 +156,18 @@ class Kotlin2JsSourceSetProcessor(
val build = project.getTasks().findByName("build") val build = project.getTasks().findByName("build")
val defaultKotlinDestinationDir = File(project.getBuildDir(), "kotlin2js/${sourceSetName}") val defaultKotlinDestinationDir = File(project.getBuildDir(), "kotlin2js/${sourceSetName}")
private fun kotlinTaskDestinationDir(): File? = kotlinTask.kotlinDestinationDir private fun kotlinTaskDestinationDir(): File? = kotlinTask.property("kotlinDestinationDir") as File?
private fun kotlinJsDestinationDir(): File? = kotlinTask.outputFile()?.let { File(it).directory } private fun kotlinJsDestinationDir(): File? = (kotlinTask.property("outputFile") as String).let { File(it).directory }
private fun kotlinSourcePathsForSourceMap() = sourceSet.getAllSource() private fun kotlinSourcePathsForSourceMap() = sourceSet.getAllSource()
.map { it.path } .map { it.path }
.filter { it.endsWith(".kt") } .filter { it.endsWith(".kt") }
.map { it.replace(absoluteSourceRootDir, kotlinTask.sourceMapDestinationDir().getPath()) } .map { it.replace(absoluteSourceRootDir, (kotlinTask.property("sourceMapDestinationDir") as File).getPath()) }
private fun shouldGenerateSourceMap() = kotlinTask.kotlinOptions.sourceMap private fun shouldGenerateSourceMap() = kotlinTask.property("sourceMap")
override fun doTargetSpecificProcessing() { override fun doTargetSpecificProcessing() {
kotlinTask.kotlinDestinationDir = defaultKotlinDestinationDir kotlinTask.setProperty("kotlinDestinationDir", defaultKotlinDestinationDir)
build?.dependsOn(kotlinTaskName) build?.dependsOn(kotlinTaskName)
clean?.dependsOn("clean" + kotlinTaskName.capitalize()) clean?.dependsOn("clean" + kotlinTaskName.capitalize())
@@ -177,16 +177,16 @@ class Kotlin2JsSourceSetProcessor(
private fun createCleanSourceMapTask() { private fun createCleanSourceMapTask() {
val taskName = sourceSet.getTaskName("clean", "sourceMap") val taskName = sourceSet.getTaskName("clean", "sourceMap")
val task = project.getTasks().create(taskName, javaClass<Delete>()) val task = project.getTasks().create(taskName, javaClass<Delete>())
task.onlyIf { kotlinTask.kotlinOptions.sourceMap } task.onlyIf { kotlinTask.property("sourceMap") as Boolean }
task.delete(object : Closure<String>(this) { task.delete(object : Closure<String>(this) {
override fun call(): String? = kotlinTask.outputFile() + ".map" override fun call(): String? = (kotlinTask.property("outputFile") as String) + ".map"
}) })
clean?.dependsOn(taskName) clean?.dependsOn(taskName)
} }
} }
abstract class AbstractKotlinPlugin [Inject] (val scriptHandler: ScriptHandler) : Plugin<Project> { abstract class AbstractKotlinPlugin [Inject] (val scriptHandler: ScriptHandler, val tasksProvider: KotlinTasksProvider) : Plugin<Project> {
abstract fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet): KotlinSourceSetProcessor<*> abstract fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet): KotlinSourceSetProcessor<*>
public override fun apply(project: Project) { public override fun apply(project: Project) {
@@ -216,33 +216,34 @@ abstract class AbstractKotlinPlugin [Inject] (val scriptHandler: ScriptHandler)
val mainSourceSet = javaPluginConvention.getSourceSets()?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) as HasConvention? val mainSourceSet = javaPluginConvention.getSourceSets()?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) as HasConvention?
if (mainSourceSet != null) { if (mainSourceSet != null) {
val kdoc = project.getTasks().create(KDOC_TASK_NAME, javaClass<KDoc>())!!
val kdoc = tasksProvider.createKDocTask(project, KDOC_TASK_NAME)
kdoc.setDescription("Generates KDoc API documentation for the main source code.") kdoc.setDescription("Generates KDoc API documentation for the main source code.")
kdoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP) kdoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP)
kdoc.setSource(mainSourceSet.getConvention().getExtensionsAsDynamicObject().getProperty("kotlin")) kdoc.setSource(mainSourceSet.getConvention().getExtensionsAsDynamicObject().getProperty("kotlin"))
} }
project.getTasks().withType(javaClass<KDoc>()) { it!!.destinationDir = File(javaPluginConvention.getDocsDir(), "kdoc") } project.getTasks().withType(tasksProvider.kDocTaskClass) { it!!.setProperty("destinationDir", File(javaPluginConvention.getDocsDir(), "kdoc")) }
} }
public val KDOC_TASK_NAME: String = "kdoc" public val KDOC_TASK_NAME: String = "kdoc"
} }
open class KotlinPlugin [Inject] (scriptHandler: ScriptHandler) : AbstractKotlinPlugin(scriptHandler) { open class KotlinPlugin [Inject] (scriptHandler: ScriptHandler, tasksProvider: KotlinTasksProvider) : AbstractKotlinPlugin(scriptHandler, tasksProvider) {
override fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet) = override fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet) =
Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, scriptHandler) Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, scriptHandler, tasksProvider)
} }
open class Kotlin2JsPlugin [Inject] (scriptHandler: ScriptHandler) : AbstractKotlinPlugin(scriptHandler) { open class Kotlin2JsPlugin [Inject] (scriptHandler: ScriptHandler, tasksProvider: KotlinTasksProvider) : AbstractKotlinPlugin(scriptHandler, tasksProvider) {
override fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet) = override fun buildSourceSetProcessor(project: ProjectInternal, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet) =
Kotlin2JsSourceSetProcessor(project, javaBasePlugin, sourceSet, scriptHandler) Kotlin2JsSourceSetProcessor(project, javaBasePlugin, sourceSet, scriptHandler, tasksProvider)
} }
open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler) : Plugin<Project> { open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler, val tasksProvider: KotlinTasksProvider) : Plugin<Project> {
val log = Logging.getLogger(this.javaClass) val log = Logging.getLogger(this.javaClass)
@@ -272,8 +273,6 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler) : Plu
} }
}) })
(ext as ExtensionAware).getExtensions().add("kotlinOptions", K2JVMCompilerArguments())
project afterEvaluate { project -> project afterEvaluate { project ->
if (project != null) { if (project != null) {
val testVariants = ext.getTestVariants()!! val testVariants = ext.getTestVariants()!!
@@ -295,7 +294,7 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler) : Plu
private fun processVariants(variants: DefaultDomainObjectSet<out BaseVariant>, project: Project, androidExt: BaseExtension): Unit { private fun processVariants(variants: DefaultDomainObjectSet<out BaseVariant>, project: Project, androidExt: BaseExtension): Unit {
val logger = project.getLogger() val logger = project.getLogger()
val kotlinOptions = getExtention<K2JVMCompilerArguments>(androidExt, "kotlinOptions") val kotlinOptions = getExtention<Any>(androidExt, "kotlinOptions")
val sourceSets = androidExt.getSourceSets() val sourceSets = androidExt.getSourceSets()
//TODO: change to BuilderConstants.MAIN - it was relocated in 0.11 plugin //TODO: change to BuilderConstants.MAIN - it was relocated in 0.11 plugin
val mainSourceSet = sourceSets.getByName("main") val mainSourceSet = sourceSets.getByName("main")
@@ -316,13 +315,13 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler) : Plu
val variantName = variant.getName() val variantName = variant.getName()
val kotlinTaskName = "compile${variantName.capitalize()}Kotlin" val kotlinTaskName = "compile${variantName.capitalize()}Kotlin"
val kotlinTask = project.getTasks().create(kotlinTaskName, javaClass<KotlinCompile>()) val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName)
kotlinTask.kotlinOptions = kotlinOptions kotlinTask.setProperty("kotlinOptions", kotlinOptions)
// store kotlin classes in separate directory. They will serve as class-path to java compiler // store kotlin classes in separate directory. They will serve as class-path to java compiler
val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantName}") val kotlinOutputDir = File(project.getBuildDir(), "tmp/kotlin-classes/${variantName}")
kotlinTask.kotlinDestinationDir = kotlinOutputDir kotlinTask.setProperty("kotlinDestinationDir", kotlinOutputDir)
kotlinTask.setDestinationDir(javaTask.getDestinationDir()) kotlinTask.setDestinationDir(javaTask.getDestinationDir())
kotlinTask.setDescription("Compiles the ${variantName} kotlin.") kotlinTask.setDescription("Compiles the ${variantName} kotlin.")
kotlinTask.setClasspath(javaTask.getClasspath()) kotlinTask.setClasspath(javaTask.getClasspath())
@@ -377,12 +376,12 @@ open class KotlinAndroidPlugin [Inject] (val scriptHandler: ScriptHandler) : Plu
val basePlugin: BasePlugin = plugin as BasePlugin val basePlugin: BasePlugin = plugin as BasePlugin
val javaSources = project.files(javaSourceList) val javaSources = project.files(javaSourceList)
val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(basePlugin)) val androidRT = project.files(AndroidGradleWrapper.getRuntimeJars(basePlugin))
val fullClasspath = (javaTask.getClasspath() + (javaSources + androidRT)) - project.files(kotlinTask.kotlinDestinationDir) val fullClasspath = (javaTask.getClasspath() + (javaSources + androidRT)) - project.files(kotlinTask.property("kotlinDestinationDir"))
(it as AbstractCompile).setClasspath(fullClasspath) (it as AbstractCompile).setClasspath(fullClasspath)
} }
javaTask.dependsOn(kotlinTaskName) javaTask.dependsOn(kotlinTaskName)
val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.kotlinDestinationDir) val javacClassPath = javaTask.getClasspath() + project.files(kotlinTask.property("kotlinDestinationDir"))
javaTask.setClasspath(javacClassPath) javaTask.setClasspath(javacClassPath)
} }
} }
@@ -0,0 +1,37 @@
package org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.Task
import org.gradle.api.Project
import org.gradle.api.tasks.SourceTask
import java.net.URLClassLoader
/**
* Tasks provider to be used wrapper
* Created by Nikita.Skvortsov
* date: 17.12.2014.
*/
public open class KotlinTasksProvider(val tasksLoader: ClassLoader) {
val kotlinJVMCompileTaskClass: Class<AbstractCompile> =
tasksLoader.loadClass("org.jetbrains.kotlin.gradle.tasks.KotlinCompile") as Class<AbstractCompile>
val kotlinJSCompileTaskClass: Class<AbstractCompile> =
tasksLoader.loadClass("org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile") as Class<AbstractCompile>
val kDocTaskClass: Class<SourceTask> =
tasksLoader.loadClass("org.jetbrains.kotlin.gradle.tasks.KDoc") as Class<SourceTask>
public fun createKotlinJVMTask(project: Project, name: String): AbstractCompile {
return project.getTasks().create(name, kotlinJVMCompileTaskClass)
}
public fun createKotlinJSTask(project: Project, name: String): AbstractCompile {
return project.getTasks().create(name, kotlinJSCompileTaskClass)
}
public fun createKDocTask(project: Project, name: String): SourceTask {
return project.getTasks().create(name, kDocTaskClass)
}
}
@@ -1,16 +1,6 @@
package org.jetbrains.kotlin.gradle package org.jetbrains.kotlin.gradle
import com.google.common.io.Files
import com.intellij.openapi.util.SystemInfo
import java.io.File
import java.util.Arrays
import java.util.Scanner
import org.junit.Before
import org.junit.After
import org.junit.Test import org.junit.Test
import kotlin.test.assertTrue
import kotlin.test.assertEquals
import kotlin.test.fail
import org.jetbrains.kotlin.gradle.BaseGradleIT.Project import org.jetbrains.kotlin.gradle.BaseGradleIT.Project
class BasicKotlinGradleIT: BaseGradleIT() { class BasicKotlinGradleIT: BaseGradleIT() {