From 9e1afe71f299b9222ed95cc5e014f80883c85bf9 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Fri, 10 Feb 2017 16:00:53 +0300 Subject: [PATCH] Fixed Kotlin2Js output not being the output of the compileKotlin2Js tasks. Therefore, fixed Kotlin2Js output not present in JAR. Reworked the clean behavior in regard to compileKotlin2Js tasks. Fixed duplicate source roots passed to the compiler. Issues: - #KT-15829 Fixed - #KT-16267 Fixed - #KT-15902 Fixed --- .../kotlin/gradle/ExecutionStrategyIT.kt | 4 +- .../kotlin/gradle/Kotlin2JsGradlePluginIT.kt | 43 +++++++++++++++++-- .../build.gradle | 7 +++ .../kotlin/gradle/plugin/KotlinPlugin.kt | 33 ++++++++++---- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 7 --- 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ExecutionStrategyIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ExecutionStrategyIT.kt index ee948eb9568..240d6a5048a 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ExecutionStrategyIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/ExecutionStrategyIT.kt @@ -9,11 +9,11 @@ class ExecutionStrategyJsIT : ExecutionStrategyIT() { project.setupWorkingDir() val buildGradle = project.projectDir.getFileByName("build.gradle") buildGradle.modify { it.replace("apply plugin: \"kotlin\"", "apply plugin: \"kotlin2js\"") + - "\ncompileKotlin2Js.kotlinOptions.outputFile = \"out.js\"" } + "\ncompileKotlin2Js.kotlinOptions.outputFile = \"web/js/out.js\"" } } override fun CompiledProject.checkOutput() { - assertFileExists("out.js") + assertFileExists("web/js/out.js") } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt index d7ec1d4c7e3..210c53d9142 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt @@ -4,6 +4,8 @@ import org.jetbrains.kotlin.gradle.util.getFileByName import org.jetbrains.kotlin.gradle.util.modify import org.junit.Test import java.io.File +import java.util.zip.ZipFile +import kotlin.test.assertEquals class Kotlin2JsGradlePluginIT : BaseGradleIT() { @Test @@ -38,8 +40,6 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { project.build("clean") { assertSuccessful() assertReportExists() - assertContains(":mainProject:cleanCompileKotlin2Js\n") - assertNoSuchFile("mainProject/web/js/app.js") // Test that we don't accidentally remove the containing directory // This would fail if we used the default clean task of the copy task @@ -52,7 +52,38 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { project.build("clean") { assertSuccessful() assertReportExists() - assertContains(":mainProject:cleanCompileKotlin2Js UP-TO-DATE") + } + } + + @Test + fun testJarIncludesJsDefaultOutput() { + val project = Project("kotlin2JsNoOutputFileProject", "2.10") + + project.build("jar") { + assertSuccessful() + + assertContains(":compileKotlin2Js") + val jarPath = "build/libs/kotlin2JsNoOutputFileProject.jar" + assertFileExists(jarPath) + val jar = ZipFile(fileInWorkingDir(jarPath)) + assertEquals(1, jar.entries().asSequence().count { it.name == "kotlin2JsNoOutputFileProject_main.js" }, + "The jar should contain an entry `kotlin2JsNoOutputFileProject_main.js` with no duplicates") + } + } + + @Test + fun testJarIncludesJsOutputSetExplicitly() { + val project = Project("kotlin2JsModuleKind", "2.10") + + project.build(":jar") { + assertSuccessful() + + assertContains(":compileKotlin2Js") + val jarPath = "build/libs/kotlin2JsModuleKind.jar" + assertFileExists(jarPath) + val jar = ZipFile(fileInWorkingDir(jarPath)) + assertEquals(1, jar.entries().asSequence().count { it.name == "app.js" }, + "The jar should contain an entry `app.js` with no duplicates") } } @@ -107,6 +138,12 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { assertFileExists("build/kotlin2js/main/module.js") assertFileExists("build/kotlin2js/integrationTest/module-inttests.js") + + val jarPath = "build/libs/kotlin2JsProjectWithCustomSourceset-inttests.jar" + assertFileExists(jarPath) + val jar = ZipFile(fileInWorkingDir(jarPath)) + assertEquals(1, jar.entries().asSequence().count { it.name == "module-inttests.js" }, + "The jar should contain an entry `module-inttests.js` with no duplicates") } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsProjectWithCustomSourceset/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsProjectWithCustomSourceset/build.gradle index 2d57f0c95aa..33a301d9be6 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsProjectWithCustomSourceset/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsProjectWithCustomSourceset/build.gradle @@ -33,6 +33,13 @@ dependencies { integrationTestCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version" } +task integrationTestJar(type: Jar) { + from sourceSets.integrationTest.output + classifier = 'inttests' +} + +build.dependsOn integrationTestJar + task jarSources(type: Jar) { from sourceSets.main.allSource classifier = 'source' 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 bde7f14954c..d33f1496ed8 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 @@ -7,6 +7,7 @@ import com.android.build.gradle.internal.variant.BaseVariantData import com.android.build.gradle.internal.variant.BaseVariantOutputData import com.android.builder.model.SourceProvider import groovy.lang.Closure +import org.gradle.api.InvalidUserDataException import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.Configuration @@ -20,16 +21,18 @@ import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.bundling.Zip import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile +import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl -import org.jetbrains.kotlin.gradle.internal.* +import org.jetbrains.kotlin.gradle.internal.AnnotationProcessingManager +import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin +import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin.Companion.getKaptClasssesDir +import org.jetbrains.kotlin.gradle.internal.initKapt import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.plugin.android.KotlinJillTask import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProviderAndroidWrapper -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.io.File import java.net.URL import java.util.* @@ -186,18 +189,30 @@ internal class Kotlin2JsSourceSetProcessor( taskDescription = "Compiles the kotlin sources in $sourceSet to JavaScript.", compileTaskNameSuffix = "kotlin2Js" ) { - private val clean = project.tasks.findByName("clean") - private val build = project.tasks.findByName("build") override fun doCreateTask(project: Project, taskName: String): Kotlin2JsCompile = tasksProvider.createKotlinJSTask(project, taskName, sourceSet.name) override fun doTargetSpecificProcessing() { - val taskName = kotlinTask.name - build?.dependsOn(taskName) - clean?.dependsOn("clean" + taskName.capitalize()) + project.tasks.findByName(sourceSet.classesTaskName).dependsOn(kotlinTask) kotlinTask.source(kotlinSourceSet.kotlin) createCleanSourceMapTask() + + // outputFile can be set later during the configuration phase, get it only after the phase: + project.afterEvaluate { + kotlinTask.kotlinOptions.outputFile = File(kotlinTask.outputFile).absolutePath + val outputDir = File(kotlinTask.outputFile).parentFile + + if (FileUtil.isAncestor(outputDir, project.rootDir, false)) + throw InvalidUserDataException( + "The output directory '$outputDir' (defined by outputFile of $kotlinTask) contains or " + + "matches the project root directory '${project.rootDir}'.\n" + + "Gradle will not be able to build the project because of the root directory lock.\n" + + "To fix this, consider using the default outputFile location instead of providing it explicitly.") + + sourceSet.output.setClassesDir(outputDir) + kotlinTask.destinationDir = outputDir + } } private fun createCleanSourceMapTask() { @@ -207,7 +222,7 @@ internal class Kotlin2JsSourceSetProcessor( task.delete(object : Closure(this) { override fun call(): String? = (kotlinTask.property("outputFile") as String) + ".map" }) - clean?.dependsOn(taskName) + project.tasks.findByName("clean")?.dependsOn(taskName) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 4e68237d9a0..c5015a77104 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.gradle.tasks -import org.codehaus.groovy.runtime.MethodClosure import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.logging.Logger @@ -44,7 +43,6 @@ import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider import org.jetbrains.kotlin.utils.LibraryUtils import java.io.File -import java.rmi.Remote import java.util.* import kotlin.properties.Delegates @@ -322,10 +320,6 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile(), val outputFile: String get() = kotlinOptions.outputFile ?: defaultOutputFile.canonicalPath - init { - @Suppress("LeakingThis") - outputs.file(MethodClosure(this, "getOutputFile")) - } override fun findKotlinCompilerJar(project: Project): File? = findKotlinJsCompilerJar(project) @@ -348,7 +342,6 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile(), logger.debug("Calling compiler") destinationDir.mkdirs() - args.freeArgs = args.freeArgs + sourceRoots.kotlinSourceFiles.map { it.absolutePath } val friendDependency = friendTaskName ?.let { project.getTasksByName(it, false).singleOrNull() as? Kotlin2JsCompile }