[Gradle, JS] Move incremental test into non-ir js tests and add module name into 2js plugin

[Gradle, JS] Fix tests for incremental compilation of IR klib dir

[Gradle, JS] Add hack of outputFile into kotlin2js plugin

[Gradle, JS] Remove producing klib-dir

[Gradle, JS] Try to fix outputFileOrNull in JS compile

Because on clean run, file is not yet created, isFile check is incorrect
This commit is contained in:
Ilya Goncharov
2021-01-27 13:29:05 +03:00
parent 7e6abffb62
commit c13949d322
4 changed files with 86 additions and 64 deletions
@@ -127,6 +127,47 @@ class Kotlin2JsGradlePluginIT : AbstractKotlin2JsGradlePluginIT(false) {
return super.defaultBuildOptions().copy(warningMode = WarningMode.Summary) return super.defaultBuildOptions().copy(warningMode = WarningMode.Summary)
} }
@Test
fun testIncrementalCompilation() = Project("kotlin2JsICProject").run {
setupWorkingDir()
val modules = listOf("app", "lib")
val mainFiles = modules.flatMapTo(LinkedHashSet()) {
projectDir.resolve("$it/src/main").allKotlinFiles()
}
build("build") {
assertSuccessful()
checkIrCompilationMessage()
assertContains(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)
if (irBackend) {
assertCompiledKotlinSources(project.relativize(mainFiles))
} else {
assertCompiledKotlinSources(project.relativize(allKotlinFiles))
}
}
build("build") {
assertSuccessful()
assertCompiledKotlinSources(emptyList())
}
projectFile("A.kt").modify {
it.replace("val x = 0", "val x = \"a\"")
}
build("build") {
assertSuccessful()
checkIrCompilationMessage()
assertContains(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)
val affectedFiles = project.projectDir.getFilesByNames("A.kt", "useAInLibMain.kt", "useAInAppMain.kt", "useAInAppTest.kt")
if (irBackend) {
// only klib ic is supported for now, so tests are generated non-incrementally with ir backend
assertCompiledKotlinSources(project.relativize(affectedFiles.filter { it in mainFiles }))
} else {
assertCompiledKotlinSources(project.relativize(affectedFiles))
}
}
}
@Test @Test
fun testKotlinJsBuiltins() { fun testKotlinJsBuiltins() {
val project = Project("kotlinBuiltins") val project = Project("kotlinBuiltins")
@@ -257,7 +298,7 @@ class Kotlin2JsGradlePluginIT : AbstractKotlin2JsGradlePluginIT(false) {
} }
} }
abstract class AbstractKotlin2JsGradlePluginIT(private val irBackend: Boolean) : BaseGradleIT() { abstract class AbstractKotlin2JsGradlePluginIT(val irBackend: Boolean) : BaseGradleIT() {
override fun defaultBuildOptions(): BuildOptions = override fun defaultBuildOptions(): BuildOptions =
super.defaultBuildOptions().copy( super.defaultBuildOptions().copy(
jsIrBackend = irBackend, jsIrBackend = irBackend,
@@ -284,10 +325,12 @@ abstract class AbstractKotlin2JsGradlePluginIT(private val irBackend: Boolean) :
val jarPath = "build/libs/kotlin2JsNoOutputFileProject.jar" val jarPath = "build/libs/kotlin2JsNoOutputFileProject.jar"
assertFileExists(jarPath) assertFileExists(jarPath)
val jar = ZipFile(fileInWorkingDir(jarPath)) val jar = ZipFile(fileInWorkingDir(jarPath))
assertEquals( if (!irBackend) {
1, jar.entries().asSequence().count { it.name == "kotlin2JsNoOutputFileProject.js" }, assertEquals(
"The jar should contain an entry `kotlin2JsNoOutputFileProject.js` with no duplicates" 1, jar.entries().asSequence().count { it.name == "kotlin2JsNoOutputFileProject.js" },
) "The jar should contain an entry `kotlin2JsNoOutputFileProject.js` with no duplicates"
)
}
} }
} }
@@ -327,9 +370,7 @@ abstract class AbstractKotlin2JsGradlePluginIT(private val irBackend: Boolean) :
project.build("build") { project.build("build") {
assertSuccessful() assertSuccessful()
checkIrCompilationMessage() checkIrCompilationMessage()
if (irBackend) { if (!irBackend) {
assertFileExists(kotlinClassesDir() + "default/manifest")
} else {
assertFileExists(kotlinClassesDir() + "kotlin2JsNoOutputFileProject.js") assertFileExists(kotlinClassesDir() + "kotlin2JsNoOutputFileProject.js")
} }
assertFileExists(kotlinClassesDir(sourceSet = "test") + "kotlin2JsNoOutputFileProject_test.js") assertFileExists(kotlinClassesDir(sourceSet = "test") + "kotlin2JsNoOutputFileProject_test.js")
@@ -445,47 +486,6 @@ abstract class AbstractKotlin2JsGradlePluginIT(private val irBackend: Boolean) :
} }
} }
@Test
fun testIncrementalCompilation() = Project("kotlin2JsICProject").run {
setupWorkingDir()
val modules = listOf("app", "lib")
val mainFiles = modules.flatMapTo(LinkedHashSet()) {
projectDir.resolve("$it/src/main").allKotlinFiles()
}
build("build") {
assertSuccessful()
checkIrCompilationMessage()
assertContains(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)
if (irBackend) {
assertCompiledKotlinSources(project.relativize(mainFiles))
} else {
assertCompiledKotlinSources(project.relativize(allKotlinFiles))
}
}
build("build") {
assertSuccessful()
assertCompiledKotlinSources(emptyList())
}
projectFile("A.kt").modify {
it.replace("val x = 0", "val x = \"a\"")
}
build("build") {
assertSuccessful()
checkIrCompilationMessage()
assertContains(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)
val affectedFiles = project.projectDir.getFilesByNames("A.kt", "useAInLibMain.kt", "useAInAppMain.kt", "useAInAppTest.kt")
if (irBackend) {
// only klib ic is supported for now, so tests are generated non-incrementally with ir backend
assertCompiledKotlinSources(project.relativize(affectedFiles.filter { it in mainFiles }))
} else {
assertCompiledKotlinSources(project.relativize(affectedFiles))
}
}
}
@Test @Test
fun testIncrementalCompilationDisabled() = Project("kotlin2JsICProject").run { fun testIncrementalCompilationDisabled() = Project("kotlin2JsICProject").run {
val options = defaultBuildOptions().run { val options = defaultBuildOptions().run {
@@ -20,6 +20,6 @@ dependencies {
} }
if (project.findProperty("kotlin.js.useIrBackend")?.toBoolean() == true) { if (project.findProperty("kotlin.js.useIrBackend")?.toBoolean() == true) {
compileKotlin2Js.kotlinOptions.freeCompilerArgs += ["-Xir-produce-klib-dir", "-Xir-produce-js", "-Xir-only"] compileKotlin2Js.kotlinOptions.freeCompilerArgs += ["-Xir-produce-klib-dir", "-Xir-only"]
compileTestKotlin2Js.kotlinOptions.freeCompilerArgs += ["-Xir-produce-js"] compileTestKotlin2Js.kotlinOptions.freeCompilerArgs += ["-Xir-produce-js"]
} }
@@ -262,8 +262,13 @@ internal class Kotlin2JsSourceSetProcessor(
// outputFile can be set later during the configuration phase, get it only after the phase: // outputFile can be set later during the configuration phase, get it only after the phase:
project.whenEvaluated { project.whenEvaluated {
kotlinTask.configure { kotlinTaskInstance -> kotlinTask.configure { kotlinTaskInstance ->
kotlinTaskInstance.kotlinOptions.outputFile = kotlinTaskInstance.outputFile.absolutePath val kotlinOptions = kotlinTaskInstance.kotlinOptions
val outputDir = kotlinTaskInstance.outputFile.parentFile val outputDir: File = kotlinTaskInstance.outputFile.parentFile
kotlinOptions.outputFile = if (!kotlinOptions.isProduceUnzippedKlib()) {
kotlinTaskInstance.outputFile.absolutePath
} else {
kotlinTaskInstance.outputFile.parentFile.absolutePath
}
if (outputDir.isParentOf(project.rootDir)) if (outputDir.isParentOf(project.rootDir))
throw InvalidUserDataException( throw InvalidUserDataException(
"The output directory '$outputDir' (defined by outputFile of $kotlinTaskInstance) contains or " + "The output directory '$outputDir' (defined by outputFile of $kotlinTaskInstance) contains or " +
@@ -272,6 +277,20 @@ internal class Kotlin2JsSourceSetProcessor(
"To fix this, consider using the default outputFile location instead of providing it explicitly." "To fix this, consider using the default outputFile location instead of providing it explicitly."
) )
kotlinTaskInstance.destinationDir = outputDir kotlinTaskInstance.destinationDir = outputDir
if (
kotlinOptions.freeCompilerArgs.contains(PRODUCE_JS) ||
kotlinOptions.freeCompilerArgs.contains(PRODUCE_UNZIPPED_KLIB) ||
kotlinOptions.freeCompilerArgs.contains(PRODUCE_ZIPPED_KLIB)
) {
// Configure FQ module name to avoid cyclic dependencies in klib manifests (see KT-36721).
val baseName = if (kotlinCompilation.isMain()) {
project.name
} else {
"${project.name}_${kotlinCompilation.name}"
}
kotlinTaskInstance.kotlinOptions.freeCompilerArgs += "$MODULE_NAME=${project.klibModuleName(baseName)}"
}
} }
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion) val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project, kotlinPluginVersion)
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName
import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.report.ReportingSettings
import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib
import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.library.impl.isKotlinLibrary import org.jetbrains.kotlin.library.impl.isKotlinLibrary
@@ -276,7 +277,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
// Input is needed to force rebuild even if source files are not changed // Input is needed to force rebuild even if source files are not changed
@get:Input @get:Input
internal val coroutinesStr: Provider<String> = project.provider {coroutines.get().name} internal val coroutinesStr: Provider<String> = project.provider { coroutines.get().name }
@get:Input @get:Input
internal val coroutines: Provider<Coroutines> = project.provider { internal val coroutines: Provider<Coroutines> = project.provider {
@@ -397,7 +398,11 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
internal val isMultiplatform: Boolean by lazy { project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper } } internal val isMultiplatform: Boolean by lazy { project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper } }
@get:Internal @get:Internal
internal val abstractKotlinCompileArgumentsContributor by lazy { AbstractKotlinCompileArgumentsContributor(KotlinCompileArgumentsProvider(this)) } internal val abstractKotlinCompileArgumentsContributor by lazy {
AbstractKotlinCompileArgumentsContributor(
KotlinCompileArgumentsProvider(this)
)
}
override fun setupCompilerArgs(args: T, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) { override fun setupCompilerArgs(args: T, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
abstractKotlinCompileArgumentsContributor.contributeArguments( abstractKotlinCompileArgumentsContributor.contributeArguments(
@@ -496,10 +501,12 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
K2JVMCompilerArguments() K2JVMCompilerArguments()
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) { override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
compilerArgumentsContributor.contributeArguments(args, compilerArgumentsConfigurationFlags( compilerArgumentsContributor.contributeArguments(
defaultsOnly, args, compilerArgumentsConfigurationFlags(
ignoreClasspathResolutionErrors defaultsOnly,
)) ignoreClasspathResolutionErrors
)
)
} }
@get:Internal @get:Internal
@@ -635,23 +642,19 @@ open class Kotlin2JsCompile : AbstractKotlinCompile<K2JSCompilerArguments>(), Ko
@get:Internal @get:Internal
val outputFile: File val outputFile: File
get() = outputFilePath?.let(::File) ?: defaultOutputFile get() = kotlinOptions.outputFile?.let(::File) ?: defaultOutputFile
@get:OutputFile @get:OutputFile
@get:Optional @get:Optional
val outputFileOrNull: File? val outputFileOrNull: File?
get() = outputFile.let { file -> get() = outputFile.let { file ->
if (file.isFile) { if (!kotlinOptions.isProduceUnzippedKlib()) {
file file
} else { } else {
null null
} }
} }
@get:Input
val outputFilePath: String?
get() = kotlinOptions.outputFile
override fun findKotlinCompilerClasspath(project: Project): List<File> = override fun findKotlinCompilerClasspath(project: Project): List<File> =
findKotlinJsCompilerClasspath(project) findKotlinJsCompilerClasspath(project)