Clear outputs before compiling with in-process/out-of-process execution mode
Issue #KT-30492 Fixed
This commit is contained in:
+32
-8
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.jetbrains.kotlin.gradle.util.checkedReplace
|
||||
import org.jetbrains.kotlin.gradle.util.getFileByName
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.junit.Test
|
||||
@@ -18,9 +19,29 @@ class ExecutionStrategyJsIT : ExecutionStrategyIT() {
|
||||
override fun CompiledProject.checkOutput() {
|
||||
assertFileExists("web/js/out.js")
|
||||
}
|
||||
|
||||
override fun CompiledProject.checkOutputAfterChange() {
|
||||
assertFileExists("web/js/out.js")
|
||||
}
|
||||
}
|
||||
|
||||
open class ExecutionStrategyIT : BaseGradleIT() {
|
||||
class ExecutionStrategyJvmIT : ExecutionStrategyIT() {
|
||||
override fun CompiledProject.checkOutput() {
|
||||
val classesDir = kotlinClassesDir(subproject = "app") + "foo/"
|
||||
assertFileExists("${classesDir}MainKt.class")
|
||||
assertFileExists("${classesDir}A.class")
|
||||
assertFileExists("${classesDir}B.class")
|
||||
}
|
||||
|
||||
override fun CompiledProject.checkOutputAfterChange() {
|
||||
val classesDir = kotlinClassesDir(subproject = "app") + "foo/"
|
||||
assertFileExists("${classesDir}MainKt.class")
|
||||
assertFileExists("${classesDir}A.class")
|
||||
assertNoSuchFile("${classesDir}B.class")
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ExecutionStrategyIT : BaseGradleIT() {
|
||||
@Test
|
||||
fun testDaemon() {
|
||||
doTestExecutionStrategy("daemon")
|
||||
@@ -48,14 +69,18 @@ open class ExecutionStrategyIT : BaseGradleIT() {
|
||||
assertContains(finishMessage)
|
||||
checkOutput()
|
||||
assertNoWarnings()
|
||||
assertFileExists(kotlinClassesDir(subproject = "app") + "foo/B.class")
|
||||
}
|
||||
|
||||
val fKt = project.projectDir.getFileByName("f.kt")
|
||||
fKt.delete()
|
||||
val classesKt = project.projectDir.getFileByName("classes.kt")
|
||||
classesKt.modify {
|
||||
it.checkedReplace("class B", "//class B")
|
||||
}
|
||||
project.build("build", strategyCLIArg) {
|
||||
assertFailed()
|
||||
assertSuccessful()
|
||||
assertContains(finishMessage)
|
||||
assert(output.contains("Unresolved reference: f", ignoreCase = true))
|
||||
checkOutputAfterChange()
|
||||
assertNoWarnings()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +91,6 @@ open class ExecutionStrategyIT : BaseGradleIT() {
|
||||
)
|
||||
}
|
||||
|
||||
protected open fun CompiledProject.checkOutput() {
|
||||
assertFileExists(kotlinClassesDir(subproject = "app") + "foo/MainKt.class")
|
||||
}
|
||||
protected abstract fun CompiledProject.checkOutput()
|
||||
protected abstract fun CompiledProject.checkOutputAfterChange()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package foo
|
||||
|
||||
class A
|
||||
|
||||
class B
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
package foo
|
||||
|
||||
@Suppress("unused_parameter")
|
||||
fun f(fn: (x: Int)->Unit) { }
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
package foo
|
||||
|
||||
fun main() {
|
||||
f { it * 2 }
|
||||
A()
|
||||
}
|
||||
+10
-4
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
||||
import org.jetbrains.kotlin.gradle.report.BuildReportMode
|
||||
import org.jetbrains.kotlin.gradle.report.TaskExecutionResult
|
||||
import org.jetbrains.kotlin.gradle.tasks.clearLocalState
|
||||
import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError
|
||||
import org.jetbrains.kotlin.gradle.utils.stackTraceAsString
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
@@ -292,8 +293,10 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun compileOutOfProcess(): ExitCode =
|
||||
try {
|
||||
private fun compileOutOfProcess(): ExitCode {
|
||||
clearLocalState(outputFiles, log, reason = "out-of-process execution strategy is non-incremental")
|
||||
|
||||
return try {
|
||||
runToolInSeparateProcess(compilerArgs, compilerClassName, compilerFullClasspath, log)
|
||||
} finally {
|
||||
reportExecutionResultIfNeeded {
|
||||
@@ -303,17 +306,20 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileInProcess(messageCollector: MessageCollector): ExitCode {
|
||||
clearLocalState(outputFiles, log, reason = "in-process execution strategy is non-incremental")
|
||||
|
||||
// in-process compiler should always be run in a different thread
|
||||
// to avoid leaking thread locals from compiler (see KT-28037)
|
||||
val threadPool = Executors.newSingleThreadExecutor()
|
||||
val bufferingMessageCollector = GradleBufferingMessageCollector()
|
||||
try {
|
||||
return try {
|
||||
val future = threadPool.submit(Callable {
|
||||
compileInProcessImpl(bufferingMessageCollector)
|
||||
})
|
||||
return future.get()
|
||||
future.get()
|
||||
} finally {
|
||||
bufferingMessageCollector.flush(messageCollector)
|
||||
threadPool.shutdown()
|
||||
|
||||
+6
-1
@@ -2,10 +2,12 @@ package org.jetbrains.kotlin.gradle.tasks
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinLogger
|
||||
import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||
import java.io.File
|
||||
|
||||
fun throwGradleExceptionIfError(exitCode: ExitCode) {
|
||||
when (exitCode) {
|
||||
@@ -20,13 +22,16 @@ fun throwGradleExceptionIfError(exitCode: ExitCode) {
|
||||
|
||||
internal fun TaskWithLocalState.clearLocalState(reason: String? = null) {
|
||||
val log = GradleKotlinLogger(logger)
|
||||
clearLocalState(allOutputFiles(), log, reason)
|
||||
}
|
||||
|
||||
internal fun clearLocalState(outputFiles: Iterable<File>, log: KotlinLogger, reason: String? = null) {
|
||||
log.kotlinDebug {
|
||||
val suffix = reason?.let { " ($it)" }.orEmpty()
|
||||
"Clearing output$suffix:"
|
||||
}
|
||||
|
||||
for (file in allOutputFiles()) {
|
||||
for (file in outputFiles) {
|
||||
if (!file.exists()) continue
|
||||
when {
|
||||
file.isDirectory -> {
|
||||
|
||||
Reference in New Issue
Block a user