diff --git a/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt b/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt index b17d935ce66..6836b9b8e44 100644 --- a/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt @@ -27,30 +27,32 @@ class CodeConformanceTest : TestCase() { private val JAVA_FILE_PATTERN = Pattern.compile(".+\\.java") private val SOURCES_FILE_PATTERN = Pattern.compile("(.+\\.java|.+\\.kt|.+\\.js)") private val EXCLUDED_FILES_AND_DIRS = listOf( - "android.tests.dependencies", - "buildSrc", - "core/reflection.jvm/src/kotlin/reflect/jvm/internal/pcollections", - "js/js.tests/.gradle", - "js/js.translator/testData/node_modules", - "libraries/kotlin.test/js/it/.gradle", - "libraries/kotlin.test/js/it/node_modules", - "libraries/stdlib/js/.gradle", - "libraries/stdlib/js/build", - "libraries/reflect/build", - "libraries/reflect/api/src/java9/java/kotlin/reflect/jvm/internal/impl", - "libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools", - "dependencies", - "js/js.translator/qunit/qunit.js", - "libraries/tools/kotlin-js-tests/src/test/web/qunit.js", - "out", - "dist", - "libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build/tmp", - "libraries/tools/kotlin-maven-plugin/target", - "libraries/tools/kotlinp/src", - "compiler/testData/psi/kdoc", - "compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt", - "compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java", - "dependencies/protobuf/protobuf-relocated/build" + "android.tests.dependencies", + "buildSrc", + "core/reflection.jvm/src/kotlin/reflect/jvm/internal/pcollections", + "js/js.tests/.gradle", + "js/js.translator/testData/node_modules", + "libraries/kotlin.test/js/it/.gradle", + "libraries/kotlin.test/js/it/node_modules", + "libraries/stdlib/js/.gradle", + "libraries/stdlib/js/build", + "libraries/reflect/build", + "libraries/reflect/api/src/java9/java/kotlin/reflect/jvm/internal/impl", + "libraries/tools/binary-compatibility-validator/src/main/kotlin/org.jetbrains.kotlin.tools", + "dependencies", + "js/js.translator/qunit/qunit.js", + "libraries/tools/kotlin-js-tests/src/test/web/qunit.js", + "out", + "dist", + "libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build/tmp", + "libraries/tools/kotlin-maven-plugin/target", + "libraries/tools/kotlinp/src", + "libraries/tools/kotlin-test-nodejs-runner/node_modules", + "libraries/tools/kotlin-test-nodejs-runner/.gradle", + "compiler/testData/psi/kdoc", + "compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt", + "compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java", + "dependencies/protobuf/protobuf-relocated/build" ).map(::File) private val COPYRIGHT_EXCLUDED_FILES_AND_DIRS = listOf( @@ -72,6 +74,8 @@ class CodeConformanceTest : TestCase() { "libraries/stdlib/js/node_modules", "libraries/tools/kotlin-maven-plugin-test/target", "libraries/tools/kotlin-gradle-plugin-integration-tests/build", + "libraries/tools/kotlin-test-nodejs-runner/node_modules", + "libraries/tools/kotlin-test-nodejs-runner/.gradle", "buildSrc/prepare-deps/build" ) } @@ -95,49 +99,49 @@ class CodeConformanceTest : TestCase() { val atAuthorPattern = Pattern.compile("/\\*.+@author.+\\*/", Pattern.DOTALL) val tests = listOf( - TestData( - "%d source files contain @author javadoc tag.\nPlease remove them or exclude in this test:\n%s", - { source -> - // substring check is an optimization - "@author" in source && atAuthorPattern.matcher(source).find() && - "ASM: a very small and fast Java bytecode manipulation framework" !in source - } - ), - TestData( - "%d source files use something from com.beust.jcommander.internal package.\n" + + TestData( + "%d source files contain @author javadoc tag.\nPlease remove them or exclude in this test:\n%s", + { source -> + // substring check is an optimization + "@author" in source && atAuthorPattern.matcher(source).find() && + "ASM: a very small and fast Java bytecode manipulation framework" !in source + } + ), + TestData( + "%d source files use something from com.beust.jcommander.internal package.\n" + "This code won't work when there's no TestNG in the classpath of our IDEA plugin, " + "because there's only an optional dependency on testng.jar.\n" + "Most probably you meant to use Guava's Lists, Maps or Sets instead. " + "Please change references in these files to com.google.common.collect:\n%s", - { source -> - "com.beust.jcommander.internal" in source - } - ), - TestData( - "%d source files contain references to package org.jetbrains.jet.\n" + + { source -> + "com.beust.jcommander.internal" in source + } + ), + TestData( + "%d source files contain references to package org.jetbrains.jet.\n" + "Package org.jetbrains.jet is deprecated now in favor of org.jetbrains.kotlin. " + "Please consider changing the package in these files:\n%s", - { source -> - "org.jetbrains.jet" in source - } - ), - TestData( - "%d source files contain references to package kotlin.reflect.jvm.internal.impl.\n" + + { source -> + "org.jetbrains.jet" in source + } + ), + TestData( + "%d source files contain references to package kotlin.reflect.jvm.internal.impl.\n" + "This package contains internal reflection implementation and is a result of a " + "post-processing of kotlin-reflect.jar by jarjar.\n" + "Most probably you meant to use classes from org.jetbrains.kotlin.**.\n" + "Please change references in these files or exclude them in this test:\n%s", - { source -> - "kotlin.reflect.jvm.internal.impl" in source - } - ), - TestData( - "%d source files contain references to package org.objectweb.asm.\n" + + { source -> + "kotlin.reflect.jvm.internal.impl" in source + } + ), + TestData( + "%d source files contain references to package org.objectweb.asm.\n" + "Package org.jetbrains.org.objectweb.asm should be used instead to avoid troubles with different asm versions in classpath. " + "Please consider changing the package in these files:\n%s", - { source -> - " org.objectweb.asm" in source - }) + { source -> + " org.objectweb.asm" in source + }) ) for (sourceFile in FileUtil.findFilesByMask(SOURCES_FILE_PATTERN, File("."))) { @@ -170,7 +174,7 @@ class CodeConformanceTest : TestCase() { for (sourceFile in FileUtil.findFilesByMask(SOURCES_FILE_PATTERN, root)) { val relativePath = FileUtil.toSystemIndependentName(sourceFile.toRelativeString(root)) if (COPYRIGHT_EXCLUDED_FILES_AND_DIRS.any { relativePath.startsWith(it) } || - knownThirdPartyCode.any { relativePath.startsWith(it) }) continue + knownThirdPartyCode.any { relativePath.startsWith(it)}) continue sourceFile.useLines { lineSequence -> for (line in lineSequence) { @@ -181,23 +185,21 @@ class CodeConformanceTest : TestCase() { } } if (filesWithUnlistedCopyrights.isNotEmpty()) { - fail( - "The following files contain third-party copyrights and no license information. " + - "Please update license/README.md accordingly:\n${filesWithUnlistedCopyrights.joinToString("\n")}" - ) + fail("The following files contain third-party copyrights and no license information. " + + "Please update license/README.md accordingly:\n${filesWithUnlistedCopyrights.joinToString("\n")}") } } private fun loadKnownThirdPartyCodeList(): List { File("license/README.md").useLines { lineSequence -> return lineSequence - .filter { it.startsWith(" - Path: ") } - .map { it.removePrefix(" - Path: ").trim().ensureFileOrEndsWithSlash() } - .toList() + .filter { it.startsWith(" - Path: ") } + .map { it.removePrefix(" - Path: ").trim().ensureFileOrEndsWithSlash() } + .toList() } } } private fun String.ensureFileOrEndsWithSlash() = - if (endsWith("/") || "." in substringAfterLast('/')) this else this + "/" + if (endsWith("/") || "." in substringAfterLast('/')) this else this + "/" 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 2d802b52678..222374fe705 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 @@ -379,6 +379,8 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { assertTrue { "kotlin-stdlib-js$kotlinVersionruntime" in pomText } assertFileExists(moduleDir + "kotlin-js-plugin-1.0-sources.jar") + + assertTestResults("testProject/kotlin-js-plugin-project/tests.xml", "test") } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt index ae00024774f..32dde204240 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt @@ -297,7 +297,7 @@ class MultiplatformGradleIT : BaseGradleIT() { } @Test - fun testMppNodeJsTestRun() = with(Project("new-mpp-js-tests", GradleVersionRequired.AtLeast("4.10.2"))) { + fun testMppNodeJsTestRun() = with(Project("new-mpp-js-tests", GradleVersionRequired.AtLeast("5.0"))) { setupWorkingDir() gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl) gradleSettingsScript().modify(::transformBuildScriptWithPluginsDsl) @@ -307,12 +307,12 @@ class MultiplatformGradleIT : BaseGradleIT() { assertSuccessful() assertTasksRegisteredAndNotRealized( - ":clientKotlinJsNodeModules", - ":clientKotlinJsNodeModulesTestRuntime", + ":kotlinNodeJsTestRuntimeExtract", + + ":clientTestNodeModules", ":clientTest", - ":serverKotlinJsNodeModules", - ":serverKotlinJsNodeModulesTestRuntime", + ":serverTestNodeModules", ":serverTest" ) } @@ -321,12 +321,12 @@ class MultiplatformGradleIT : BaseGradleIT() { assertSuccessful() assertTasksExecuted( - ":clientKotlinJsNodeModules", - ":clientKotlinJsNodeModulesTestRuntime", + ":kotlinNodeJsTestRuntimeExtract", + + ":clientTestNodeModules", ":clientTest", - ":serverKotlinJsNodeModules", - ":serverKotlinJsNodeModulesTestRuntime", + ":serverTestNodeModules", ":serverTest" ) @@ -339,12 +339,12 @@ class MultiplatformGradleIT : BaseGradleIT() { assertSuccessful() assertTasksUpToDate( - ":clientKotlinJsNodeModules", - ":clientKotlinJsNodeModulesTestRuntime", + ":kotlinNodeJsTestRuntimeExtract", + + ":clientTestNodeModules", ":clientTest", - ":serverKotlinJsNodeModules", - ":serverKotlinJsNodeModulesTestRuntime", + ":serverTestNodeModules", ":serverTest" ) } @@ -356,15 +356,14 @@ class MultiplatformGradleIT : BaseGradleIT() { assertSuccessful() assertTasksUpToDate( - ":clientKotlinJsNodeModulesTestRuntime", - ":serverKotlinJsNodeModulesTestRuntime" + ":kotlinNodeJsTestRuntimeExtract" ) assertTasksExecuted( - ":clientKotlinJsNodeModules", + ":clientTestNodeModules", ":clientTest", - ":serverKotlinJsNodeModules", + ":serverTestNodeModules", ":serverTest" ) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-plugin-project/src/main/kotlin/Main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-plugin-project/src/main/kotlin/Main.kt index 7c18f20be13..785fd4322e7 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-plugin-project/src/main/kotlin/Main.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-plugin-project/src/main/kotlin/Main.kt @@ -1,15 +1,23 @@ package com.example -import kotlinx.html.dom.create -import kotlinx.html.js.div -import kotlinx.html.p -import kotlin.browser.document +import kotlinx.html.a +import kotlinx.html.body +import kotlinx.html.div +import kotlinx.html.html +import kotlinx.html.stream.appendHTML fun hello() = "hello" fun main() { - document.create.div { - p { hello() } - } - console.log(hello()) + println( + StringBuilder().appendHTML().html { + body { + div { + a("https://kotlinlang.org") { + hello() + } + } + } + } + ) } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-plugin-project/tests.xml b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-plugin-project/tests.xml new file mode 100644 index 00000000000..e1319f50928 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-plugin-project/tests.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt index dd11ed76f69..f39219344c8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/TaskProviderHolder.kt @@ -16,13 +16,13 @@ package org.jetbrains.kotlin.gradle.plugin -import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.tasks.TaskProvider -class TaskProviderHolder(project: Project, private val name: String, type: Class, configureAction: (T) -> (Unit)) : - TaskHolder { - private val provider: TaskProvider = project.tasks.register(name, type, configureAction) +class TaskProviderHolder( + private val name: String, + private val provider: TaskProvider +) : TaskHolder { override fun getTaskOrProvider(): Any = provider diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt index ecc8554773e..74cdf6b667e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsCompilationTestsConfigurator.kt @@ -1,44 +1,52 @@ package org.jetbrains.kotlin.gradle.targets.js import org.gradle.api.Project +import org.gradle.api.file.FileCollection import org.gradle.api.internal.plugins.DslObject import org.gradle.api.plugins.JavaBasePlugin import org.gradle.testing.base.plugins.TestingBasePlugin import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsSetupTask -import org.jetbrains.kotlin.gradle.targets.js.tasks.KotlinJsNodeModulesTask -import org.jetbrains.kotlin.gradle.targets.js.tasks.KotlinNodeJsTestRuntimeToNodeModulesTask -import org.jetbrains.kotlin.gradle.targets.js.tasks.KotlinNodeJsTestTask +import org.jetbrains.kotlin.gradle.targets.js.tasks.* import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile import org.jetbrains.kotlin.gradle.tasks.registerTask +import org.jetbrains.kotlin.utils.addIfNotNull import java.io.File internal class KotlinJsCompilationTestsConfigurator( - val compilation: KotlinCompilationToRunnableFiles<*> + val compilation: KotlinCompilationToRunnableFiles<*> ) { private val target get() = compilation.target + private val disambiguationClassifier get() = target.disambiguationClassifier private val project get() = target.project private val compileTestKotlin2Js get() = compilation.compileKotlinTask as Kotlin2JsCompile - private val isSinglePlatformProject get() = target is KotlinWithJavaTarget<*> - private val testTaskName: String - get() = if (isSinglePlatformProject) "testJs" else camelCaseTargetName("test") - private fun camelCaseTargetName(prefix: String): String { - return if (isSinglePlatformProject) prefix - else target.name + prefix.capitalize() + private fun disambiguate(name: String, includeCompilation: Boolean = false): MutableList { + val components = mutableListOf() + + components.addIfNotNull(disambiguationClassifier) + if (includeCompilation) components.add(compilation.name) + components.add(name) + return components + } + + private fun disambiguateCamelCased(name: String, includeCompilation: Boolean): String { + val components = disambiguate(name, includeCompilation) + + return components.first() + components.drop(1).joinToString("") { it.capitalize() } } @Suppress("SameParameterValue") - private fun underscoredCompilationName(prefix: String): String { - return if (isSinglePlatformProject) prefix - else "${target.name}_${compilation.name}_$prefix" - } + private fun disambiguateUnderscored(name: String, includeCompilation: Boolean) = + disambiguate(name, includeCompilation).joinToString("_") + + private val testTaskName: String + get() = disambiguateCamelCased("test", false) private val nodeModulesDir - get() = project.buildDir.resolve(underscoredCompilationName("node_modules")) + get() = project.buildDir.resolve(disambiguateUnderscored("node_modules", true)) @Suppress("UnstableApiUsage") private val Project.testResults: File @@ -56,41 +64,46 @@ internal class KotlinJsCompilationTestsConfigurator( fun configure() { val nodeModulesTask = registerTask( - project, - camelCaseTargetName("kotlinJsNodeModules"), - KotlinJsNodeModulesTask::class.java + project, + disambiguateCamelCased("nodeModules", true), + KotlinJsNodeModulesTask::class.java ) { it.dependsOn(compileTestKotlin2Js) + it.onlyIf { + compileTestKotlin2Js.outputFile.exists() + } + it.nodeModulesDir = nodeModulesDir it.classpath = compileTask.jsRuntimeClasspath } - val nodeModulesTestRuntimeTask = registerTask( - project, - camelCaseTargetName("kotlinJsNodeModulesTestRuntime"), - KotlinNodeJsTestRuntimeToNodeModulesTask::class.java - ) { - it.nodeModulesDir = nodeModulesDir - } - val projectWithNodeJsPlugin = NodeJsPlugin.ensureAppliedInHierarchy(target.project) + val kotlinJsExtractTestRunnerTask = project.kotlinNodeJsTestRuntimeExtractTask val testTask = registerTask(project, testTaskName, KotlinNodeJsTestTask::class.java) { testJs -> testJs.group = "verification" testJs.dependsOn( - nodeModulesTask.getTaskOrProvider(), - nodeModulesTestRuntimeTask.getTaskOrProvider() + nodeModulesTask.getTaskOrProvider(), + kotlinJsExtractTestRunnerTask.getTaskOrProvider() ) - if (!isSinglePlatformProject) { - testJs.targetName = target.name + testJs.onlyIf { + // run only if there is org.jetbrains.kotlin:kotlin-test-js in classpath + // (kotlin-test-nodejs-runner.js requires kotlin-test.js) + nodeModulesDir.resolve("kotlin-test.js").exists() + compileTestKotlin2Js.outputFile.exists() + } + + if (disambiguationClassifier != null) { + testJs.targetName = disambiguationClassifier } testJs.nodeJsProcessOptions.workingDir = project.projectDir testJs.nodeModulesDir = nodeModulesDir + testJs.testRuntimeNodeModule = project.extractedKotlinTestNodeJsRunner testJs.nodeModulesToLoad = setOf(compileTestKotlin2Js.outputFile.name) val htmlReport = DslObject(testJs.reports.html) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetConfigurator.kt index 4cbfc278876..c7e5bd579e1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetConfigurator.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.targets.js import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider class KotlinJsTargetConfigurator(kotlinPluginVersion: String) : @@ -19,13 +18,24 @@ class KotlinJsTargetConfigurator(kotlinPluginVersion: String) : return Kotlin2JsSourceSetProcessor(compilation.target.project, tasksProvider, compilation, kotlinPluginVersion) } + override fun configureCompilations(platformTarget: KotlinOnlyTarget) { + super.configureCompilations(platformTarget) + + platformTarget.compilations.all { + it.compileKotlinTask.kotlinOptions.moduleKind = "umd" + } + } + override fun configureTest(target: KotlinOnlyTarget) { target.compilations.all { - it.compileKotlinTask.kotlinOptions.moduleKind = "umd" - - if (it.name == KotlinCompilation.TEST_COMPILATION_NAME) { + if (isTestCompilation(it)) { KotlinJsCompilationTestsConfigurator(it).configure() } } } + + companion object { + internal fun isTestCompilation(it: KotlinJsCompilation) = + it.name == KotlinCompilation.TEST_COMPILATION_NAME + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetPreset.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetPreset.kt index aa870e6feb0..59e1b01db4b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetPreset.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargetPreset.kt @@ -7,12 +7,8 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project -import org.jetbrains.kotlin.gradle.plugin.Kotlin2JsSourceSetProcessor import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetProcessor -import org.jetbrains.kotlin.gradle.plugin.KotlinTargetConfigurator import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTargetConfigurator -import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider open class KotlinJsTargetPreset( project: Project, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt index 9a9c0fec74d..5c32e72670c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt @@ -35,10 +35,15 @@ open class NodeJsSetupTask : DefaultTask() { val repo = project.repositories.ivy { repo -> repo.name = "Node Distributions at ${settings.distBaseUrl}" repo.url = URI(settings.distBaseUrl) - repo.layout("pattern") { layout -> - layout as IvyPatternRepositoryLayout - layout.artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") - layout.ivy("v[revision]/ivy.xml") + + if (isGradleVersionAtLeast(5, 0)) { + repo.patternLayout { layout -> + configureNodeJsIvyPatternLayout(layout) + } + } else { + repo.layout("pattern") { layout -> + configureNodeJsIvyPatternLayout(layout as IvyPatternRepositoryLayout) + } } repo.metadataSources { it.artifact() } @@ -62,6 +67,11 @@ open class NodeJsSetupTask : DefaultTask() { } } + private fun configureNodeJsIvyPatternLayout(layout: IvyPatternRepositoryLayout) { + layout.artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") + layout.ivy("v[revision]/ivy.xml") + } + private fun unpackNodeArchive(archive: File, destination: File) { project.logger.kotlinInfo("Unpacking $archive to $destination") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinJsNodeModulesTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinJsNodeModulesTask.kt index ee40faa172e..e425dc262d4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinJsNodeModulesTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinJsNodeModulesTask.kt @@ -22,27 +22,27 @@ open class KotlinJsNodeModulesTask : DefaultTask() { @TaskAction fun copyFromRuntimeClasspath() { - project.copy { copy -> - copy.includeEmptyDirs = false + project.sync { sync -> + sync.includeEmptyDirs = false classpath.forEach { - if (it.isZip) copy.from(project.zipTree(it)) - else copy.from(it) + if (it.isZip) sync.from(project.zipTree(it)) + else sync.from(it) } - copy.include { fileTreeElement -> + sync.include { fileTreeElement -> isKotlinJsRuntimeFile(fileTreeElement.file) } - copy.into(nodeModulesDir) + sync.into(nodeModulesDir) } } } -val File.isZip +private val File.isZip get() = isFile && name.endsWith(".jar") -fun isKotlinJsRuntimeFile(file: File): Boolean { +internal fun isKotlinJsRuntimeFile(file: File): Boolean { if (!file.isFile) return false val name = file.name return (name.endsWith(".js") && !name.endsWith(".meta.js")) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestRuntime.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestRuntime.kt deleted file mode 100644 index a4ce1042c22..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestRuntime.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2010-2019 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.targets.js.tasks - -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.* -import java.io.File -import java.nio.file.Files -import java.nio.file.StandardCopyOption - -const val kotlinNodeJsTestRuntimeBin: String = "kotlin-js-test" - -open class KotlinNodeJsTestRuntimeToNodeModulesTask : DefaultTask() { - @Input - public var resourceName: String = "/kotlin-js-test.js" - - @OutputDirectory - @SkipWhenEmpty - public lateinit var nodeModulesDir: File - - @TaskAction - fun copyRuntime() { - val testsRuntime = javaClass.getResourceAsStream(resourceName) ?: error("Cannot find `$resourceName` in resources") - val bin = nodeModulesDir.resolve(".bin").resolve(kotlinNodeJsTestRuntimeBin) - bin.parentFile.mkdirs() - Files.copy( - testsRuntime, - bin.toPath(), - StandardCopyOption.REPLACE_EXISTING - ) - } -} - -data class KotlinNodeJsTestRunnerCliArgs( - val moduleNames: List, - val include: Collection = listOf(), - val exclude: Collection = listOf(), - val ignoredTestSuites: IgnoredTestSuitesReporting = IgnoredTestSuitesReporting.reportAllInnerTestsAsIgnored -) { - fun toList(): List = mutableListOf().also { args -> - if (include.isNotEmpty()) { - args.add("--include") - args.add(include.joinToString(",")) - } - - if (exclude.isNotEmpty()) { - args.add("--exclude") - args.add(exclude.joinToString(",")) - } - - if (ignoredTestSuites !== IgnoredTestSuitesReporting.reportAllInnerTestsAsIgnored) { - args.add("--ignoredTestSuites") - args.add(ignoredTestSuites.name) - } - - args.addAll(moduleNames) - } - - @Suppress("EnumEntryName") - enum class IgnoredTestSuitesReporting { - skip, reportAsIgnoredTest, reportAllInnerTestsAsIgnored - } -} - diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestRuntimeExtractTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestRuntimeExtractTask.kt new file mode 100644 index 00000000000..f3d0f80dc85 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestRuntimeExtractTask.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2019 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.targets.js.tasks + +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.SkipWhenEmpty +import org.gradle.api.tasks.TaskAction +import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask +import java.io.File +import java.nio.file.Files +import java.nio.file.StandardCopyOption + +const val kotlinTestNodeJsRunnerJs = "kotlin-test-nodejs-runner.js" + +internal val Project.extractedKotlinTestNodeJsRunner: File + get() = project.buildDir.resolve("kotlin/$kotlinTestNodeJsRunnerJs") + +internal val Project.kotlinNodeJsTestRuntimeExtractTask + get() = project.locateOrRegisterTask( + "kotlinNodeJsTestRuntimeExtract" + ) { task -> + task.destination = extractedKotlinTestNodeJsRunner + } + +open class KotlinNodeJsTestRuntimeExtractTask : DefaultTask() { + @Input + public var resourceName: String = "/$kotlinTestNodeJsRunnerJs" + + @OutputFile + @SkipWhenEmpty + public lateinit var destination: File + + @TaskAction + fun copyRuntime() { + val testsRuntime = javaClass.getResourceAsStream(resourceName) + ?: error("Cannot find `$resourceName` in resources") + + check(destination.parentFile.exists() || destination.parentFile.mkdirs()) { + "Cannot create directory ${destination.parentFile}" + } + + Files.copy( + testsRuntime, + destination.toPath(), + StandardCopyOption.REPLACE_EXISTING + ) + } +} + diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestTask.kt index 41383717e4b..cfb9c5740d7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/tasks/KotlinNodeJsTestTask.kt @@ -45,8 +45,7 @@ open class KotlinNodeJsTestTask : AbstractTestTask() { var nodeModulesToLoad: Set = setOf() @InputFile - @Optional - var testRuntimeNodeModule: File? = null + lateinit var testRuntimeNodeModule: File @Suppress("UnstableApiUsage") private val filterExt: DefaultTestFilter @@ -99,7 +98,7 @@ open class KotlinNodeJsTestTask : AbstractTestTask() { return TCServiceMessagesTestExecutionSpec( extendedForkOptions, - listOf(finalTestRuntimeNodeModule.absolutePath) + cliArgs.toList(), + listOf(testRuntimeNodeModule.absolutePath) + cliArgs.toList(), clientSettings ) } @@ -108,16 +107,43 @@ open class KotlinNodeJsTestTask : AbstractTestTask() { open val execHandleFactory: ExecHandleFactory get() = injected - private val finalTestRuntimeNodeModule: File - get() = testRuntimeNodeModule - ?: nodeModulesDir!!.resolve(".bin").resolve(kotlinNodeJsTestRuntimeBin) - override fun createTestExecuter() = TCServiceMessagesTestExecutor( execHandleFactory, buildOperationExecutor ) } +data class KotlinNodeJsTestRunnerCliArgs( + val moduleNames: List, + val include: Collection = listOf(), + val exclude: Collection = listOf(), + val ignoredTestSuites: IgnoredTestSuitesReporting = IgnoredTestSuitesReporting.reportAllInnerTestsAsIgnored +) { + fun toList(): List = mutableListOf().also { args -> + if (include.isNotEmpty()) { + args.add("--include") + args.add(include.joinToString(",")) + } + + if (exclude.isNotEmpty()) { + args.add("--exclude") + args.add(exclude.joinToString(",")) + } + + if (ignoredTestSuites !== IgnoredTestSuitesReporting.reportAllInnerTestsAsIgnored) { + args.add("--ignoredTestSuites") + args.add(ignoredTestSuites.name) + } + + args.addAll(moduleNames) + } + + @Suppress("EnumEntryName") + enum class IgnoredTestSuitesReporting { + skip, reportAsIgnoredTest, reportAllInnerTestsAsIgnored + } +} + private fun MutableMap.addPath(key: String, path: String) { val prev = get(key) if (prev == null) set(key, path) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt index 66ddc4fcee5..cdb3834b6e5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt @@ -18,20 +18,22 @@ package org.jetbrains.kotlin.gradle.tasks import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.UnknownTaskException import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask internal val useLazyTaskConfiguration = org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast(4, 9) +internal val canLocateTask = org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast(5, 0) /** - * Registers the task with name @param name and type @param type and initialization script @param body - * If gradle with version <4.9 is used the task will be created + * Registers the task with [name] and [type] and initialization script [body] + * If Gradle with version <4.9 is used the task will be created */ internal fun registerTask(project: Project, name: String, type: Class, body: (T) -> (Unit)): TaskHolder { return if (useLazyTaskConfiguration) { - TaskProviderHolder(project, name, type) { with(it, body) } + TaskProviderHolder(name, project.tasks.register(name, type) { with(it, body) }) } else { val result = LegacyTaskHolder(project.tasks.create(name, type)) with(result.doGetTask(), body) @@ -39,6 +41,33 @@ internal fun registerTask(project: Project, name: String, type: Class } } +/** + * Locates a task by [name] and [type], without triggering its creation or configuration. + */ +internal fun locateTask(project: Project, name: String, type: Class): TaskHolder? = + if (canLocateTask) { + try { + TaskProviderHolder(name, project.tasks.named(name, type)) + } catch (e: UnknownTaskException) { + null + } + } else { + project.tasks.findByName(name)?.let { + check(type.isInstance(it)) + + @Suppress("UNCHECKED_CAST") + LegacyTaskHolder(it as T) + } + } + +/** + * Locates a task by [name] and [type], without triggering its creation or configuration or registers new task + * with [name], type [T] and initialization script [body] + */ +internal inline fun Project.locateOrRegisterTask(name: String, noinline body: (T) -> (Unit)): TaskHolder { + return locateTask(project, name, T::class.java) ?: registerTask(project, name, T::class.java, body) +} + internal open class KotlinTasksProvider(val targetName: String) { open fun registerKotlinJVMTask( project: Project, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/injected.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/injected.kt index c23f4b9ec02..484d3f6f162 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/injected.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/injected.kt @@ -8,4 +8,4 @@ package org.jetbrains.kotlin.gradle.utils /** * Utility for functions annotated with @Inject */ -val injected: Nothing get() = error("Should be injected"); +internal val injected: Nothing get() = error("Should be injected"); diff --git a/libraries/tools/kotlin-test-nodejs-runner/build.gradle.kts b/libraries/tools/kotlin-test-nodejs-runner/build.gradle.kts index 22dcb85571b..c716c3ec0a7 100644 --- a/libraries/tools/kotlin-test-nodejs-runner/build.gradle.kts +++ b/libraries/tools/kotlin-test-nodejs-runner/build.gradle.kts @@ -26,7 +26,7 @@ tasks { args = listOf("build") inputs.dir(projectDir.resolve("src")) - outputs.file(projectDir.resolve("lib/kotlin-js-test.js")) + outputs.file(projectDir.resolve("lib/kotlin-test-nodejs-runner.js")) } create("cleanYarn") { @@ -43,7 +43,7 @@ tasks { } artifacts { - add("archives", projectDir.resolve("lib/kotlin-js-test.js")) { + add("archives", projectDir.resolve("lib/kotlin-test-nodejs-runner.js")) { builtBy("yarnBuild") } } \ No newline at end of file diff --git a/libraries/tools/kotlin-test-nodejs-runner/rollup.config.js b/libraries/tools/kotlin-test-nodejs-runner/rollup.config.js index 559b32e320d..ddd95b6df22 100644 --- a/libraries/tools/kotlin-test-nodejs-runner/rollup.config.js +++ b/libraries/tools/kotlin-test-nodejs-runner/rollup.config.js @@ -9,7 +9,7 @@ export default [ { input: './cli.ts', output: { - file: 'lib/kotlin-js-test.js', + file: 'lib/kotlin-test-nodejs-runner.js', format: 'cjs', banner: '#!/usr/bin/env node' },