[Gradle] Restore writing errors into <project_dir>/.gradle directory
This is required for compatibility with older IDEA releases where it expects errors only in <project_dir>/.gradle/kotlin/errors directory. It is possible to disable such behaviour via "kotlin.project.persistent.dir.gradle.disableWrite" property. ^KT-58223 Fixed
This commit is contained in:
committed by
Space Team
parent
070de9cc85
commit
656b61b945
+77
-16
@@ -277,7 +277,10 @@ class BuildReportsIT : KGPBaseTest() {
|
||||
) {
|
||||
|
||||
val lookupsTab = projectPath.resolve("build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab")
|
||||
val kotlinErrorPath = projectPersistentCache.resolve("errors")
|
||||
val kotlinErrorPaths = setOf(
|
||||
projectPersistentCache.resolve("errors"),
|
||||
projectPath.resolve(".gradle/kotlin/errors")
|
||||
)
|
||||
|
||||
buildGradle.appendText(
|
||||
"""
|
||||
@@ -290,26 +293,29 @@ class BuildReportsIT : KGPBaseTest() {
|
||||
)
|
||||
|
||||
build("compileKotlin") {
|
||||
assertTrue { kotlinErrorPath.listDirectoryEntries().isEmpty() }
|
||||
for (kotlinErrorPath in kotlinErrorPaths) {
|
||||
assertDirectoryDoesNotExist(kotlinErrorPath)
|
||||
}
|
||||
assertOutputDoesNotContain("errors were stored into file")
|
||||
}
|
||||
val kotlinFile = kotlinSourcesDir().resolve("helloWorld.kt")
|
||||
kotlinFile.modify { it.replace("ArrayList", "skjfghsjk") }
|
||||
buildAndFail("compileKotlin", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
|
||||
assertOutputContains("errors were stored into file")
|
||||
val files = kotlinErrorPath.listDirectoryEntries()
|
||||
assertTrue { files.first().exists() }
|
||||
files.first().bufferedReader().use { reader ->
|
||||
val kotlinVersion = reader.readLine()
|
||||
assertTrue("kotlin version should be in the error file") {
|
||||
kotlinVersion != null && kotlinVersion.trim().equals("kotlin version: ${buildOptions.kotlinVersion}")
|
||||
}
|
||||
val errorMessage = reader.readLine()
|
||||
assertTrue("Error message should start with 'error message: ' to parse it on IDEA side") {
|
||||
errorMessage != null && errorMessage.trim().startsWith("error message:")
|
||||
kotlinErrorPaths.forEach { kotlinErrorPath ->
|
||||
val files = kotlinErrorPath.listDirectoryEntries()
|
||||
assertFileExists(files.single())
|
||||
files.single().bufferedReader().use { reader ->
|
||||
val kotlinVersion = reader.readLine()
|
||||
assertTrue("kotlin version should be in the error file") {
|
||||
kotlinVersion != null && kotlinVersion.trim().equals("kotlin version: ${buildOptions.kotlinVersion}")
|
||||
}
|
||||
val errorMessage = reader.readLine()
|
||||
assertTrue("Error message should start with 'error message: ' to parse it on IDEA side") {
|
||||
errorMessage != null && errorMessage.trim().startsWith("error message:")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,17 +332,72 @@ class BuildReportsIT : KGPBaseTest() {
|
||||
projectName = "simpleProject",
|
||||
gradleVersion = gradleVersion,
|
||||
) {
|
||||
val kotlinErrorPath = projectPersistentCache.resolve("errors")
|
||||
val kotlinErrorPaths = setOf(
|
||||
projectPersistentCache.resolve("errors"),
|
||||
projectPath.resolve(".gradle/kotlin/errors")
|
||||
)
|
||||
|
||||
build("compileKotlin", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
|
||||
assertOutputDoesNotContain("errors were stored into file")
|
||||
assertTrue { kotlinErrorPath.listDirectoryEntries().isEmpty() }
|
||||
for (kotlinErrorPath in kotlinErrorPaths) {
|
||||
assertDirectoryDoesNotExist(kotlinErrorPath)
|
||||
}
|
||||
}
|
||||
val kotlinFile = kotlinSourcesDir().resolve("helloWorld.kt")
|
||||
kotlinFile.modify { it.replace("ArrayList", "skjfghsjk") }
|
||||
buildAndFail("compileKotlin", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
|
||||
assertOutputDoesNotContain("errors were stored into file")
|
||||
assertTrue { kotlinErrorPath.listDirectoryEntries().isEmpty() }
|
||||
for (kotlinErrorPath in kotlinErrorPaths) {
|
||||
assertDirectoryDoesNotExist(kotlinErrorPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("Error file is not written into .gradle/kotlin/errors")
|
||||
@GradleTest
|
||||
fun testDisableWritingErrorsIntoGradleProjectDir(
|
||||
gradleVersion: GradleVersion,
|
||||
) {
|
||||
project(
|
||||
projectName = "simpleProject",
|
||||
gradleVersion = gradleVersion,
|
||||
) {
|
||||
val kotlinErrorPath = projectPersistentCache.resolve("errors")
|
||||
val gradleErrorPath = projectPath.resolve(".gradle/kotlin/errors")
|
||||
gradleProperties.appendText(
|
||||
"""
|
||||
|
|
||||
|kotlin.project.persistent.dir.gradle.disableWrite=true
|
||||
""".trimMargin()
|
||||
)
|
||||
|
||||
val lookupsTab = projectPath.resolve("build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab")
|
||||
buildGradle.appendText(
|
||||
//language=groovy
|
||||
"""
|
||||
|tasks.named("compileKotlin") {
|
||||
| doLast {
|
||||
| new File("${lookupsTab.toUri().path}").write("Invalid contents")
|
||||
| }
|
||||
|}
|
||||
""".trimMargin()
|
||||
)
|
||||
|
||||
build("compileKotlin") {
|
||||
assertDirectoryDoesNotExist(kotlinErrorPath.toAbsolutePath())
|
||||
assertDirectoryDoesNotExist(gradleErrorPath.toAbsolutePath())
|
||||
}
|
||||
|
||||
val kotlinFile = kotlinSourcesDir().resolve("helloWorld.kt")
|
||||
kotlinFile.modify { it.replace("ArrayList", "skjfghsjk") }
|
||||
buildAndFail("compileKotlin", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
|
||||
assertOutputContains("errors were stored into file")
|
||||
assertDirectoryExists(kotlinErrorPath.toAbsolutePath())
|
||||
val errorFiles = kotlinErrorPath.listDirectoryEntries()
|
||||
assertFileExists(errorFiles.single())
|
||||
|
||||
assertDirectoryDoesNotExist(gradleErrorPath.toAbsolutePath())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -110,7 +110,7 @@ internal open class GradleCompilerRunner(
|
||||
internal val sessionDirProvider = taskProvider.sessionsDir.get()
|
||||
internal val projectNameProvider = taskProvider.projectName.get()
|
||||
internal val incrementalModuleInfoProvider = taskProvider.buildModulesInfo
|
||||
internal val errorsFile = taskProvider.errorsFile.get()
|
||||
internal val errorsFiles = taskProvider.errorsFiles.get()
|
||||
|
||||
/**
|
||||
* Compiler might be executed asynchronously. Do not do anything requiring end of compilation after this function is called.
|
||||
@@ -231,7 +231,7 @@ internal open class GradleCompilerRunner(
|
||||
kotlinScriptExtensions = environment.kotlinScriptExtensions,
|
||||
allWarningsAsErrors = compilerArgs.allWarningsAsErrors,
|
||||
compilerExecutionSettings = compilerExecutionSettings,
|
||||
errorsFile = errorsFile,
|
||||
errorsFiles = errorsFiles,
|
||||
kotlinPluginVersion = getKotlinPluginVersion(loggerProvider),
|
||||
//no need to log warnings in MessageCollector hear it will be logged by compiler
|
||||
kotlinLanguageVersion = parseLanguageVersion(compilerArgs.languageVersion, compilerArgs.useK2)
|
||||
|
||||
+5
-3
@@ -74,7 +74,7 @@ internal class GradleKotlinCompilerWorkArguments(
|
||||
val kotlinScriptExtensions: Array<String>,
|
||||
val allWarningsAsErrors: Boolean,
|
||||
val compilerExecutionSettings: CompilerExecutionSettings,
|
||||
val errorsFile: File?,
|
||||
val errorsFiles: Set<File>?,
|
||||
val kotlinPluginVersion: String,
|
||||
val kotlinLanguageVersion: KotlinVersion,
|
||||
) : Serializable {
|
||||
@@ -112,7 +112,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
||||
private val metrics = if (reportingSettings.buildReportOutputs.isNotEmpty()) BuildMetricsReporterImpl() else DoNothingBuildMetricsReporter
|
||||
private var icLogLines: List<String> = emptyList()
|
||||
private val compilerExecutionSettings = config.compilerExecutionSettings
|
||||
private val errorsFile = config.errorsFile
|
||||
private val errorsFiles = config.errorsFiles
|
||||
private val kotlinPluginVersion = config.kotlinPluginVersion
|
||||
private val kotlinLanguageVersion = config.kotlinLanguageVersion
|
||||
|
||||
@@ -131,7 +131,9 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
||||
if (incrementalCompilationEnvironment?.disableMultiModuleIC == true) {
|
||||
incrementalCompilationEnvironment.multiModuleICSettings.buildHistoryFile.delete()
|
||||
}
|
||||
errorsFile?.also { gradleMessageCollector.flush(it) }
|
||||
errorsFiles?.let {
|
||||
gradleMessageCollector.flush(it)
|
||||
}
|
||||
|
||||
throwExceptionIfCompilationFailed(exitCode, executionStrategy)
|
||||
} finally {
|
||||
|
||||
+11
-8
@@ -52,19 +52,22 @@ class GradleErrorMessageCollector(
|
||||
return errors.isNotEmpty()
|
||||
}
|
||||
|
||||
fun flush(file: File) {
|
||||
fun flush(files: Set<File>) {
|
||||
if (!hasErrors()) {
|
||||
return
|
||||
}
|
||||
file.createNewFile()
|
||||
FileWriter(file).use {
|
||||
kotlinPluginVersion?.also { version -> it.append("kotlin version: $version\n") }
|
||||
for (error in errors) {
|
||||
it.append("error message: $error\n\n")
|
||||
for (file in files) {
|
||||
file.parentFile.mkdirs()
|
||||
file.createNewFile()
|
||||
FileWriter(file).use {
|
||||
kotlinPluginVersion?.also { version -> it.append("kotlin version: $version\n") }
|
||||
for (error in errors) {
|
||||
it.append("error message: $error\n\n")
|
||||
}
|
||||
it.flush()
|
||||
}
|
||||
it.flush()
|
||||
logger.debug("${errors.count()} errors were stored into file ${file.absolutePath}")
|
||||
}
|
||||
logger.debug("${errors.count()} errors were stored into file ${file.absolutePath}")
|
||||
clear()
|
||||
}
|
||||
}
|
||||
+7
@@ -554,6 +554,12 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
val kotlinProjectPersistentDir: String?
|
||||
get() = get(PropertyNames.KOTLIN_PROJECT_PERSISTENT_DIR)
|
||||
|
||||
/**
|
||||
* Disable writing into `<project_dir>/.gradle` directory.
|
||||
*/
|
||||
val kotlinProjectPersistentDirGradleDisableWrite: Boolean
|
||||
get() = booleanProperty(PropertyNames.KOTLIN_PROJECT_PERSISTENT_DIR_GRADLE_DISABLE_WRITE) ?: false
|
||||
|
||||
/**
|
||||
* Retrieves a comma-separated list of browsers to use when running karma tests for [target]
|
||||
* @see KOTLIN_JS_KARMA_BROWSERS
|
||||
@@ -646,6 +652,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
||||
property("kotlin.internal.suppress.buildToolsApiVersionConsistencyChecks")
|
||||
val KOTLIN_USER_HOME_DIR = property("kotlin.user.home")
|
||||
val KOTLIN_PROJECT_PERSISTENT_DIR = property("kotlin.project.persistent.dir")
|
||||
val KOTLIN_PROJECT_PERSISTENT_DIR_GRADLE_DISABLE_WRITE = property("kotlin.project.persistent.dir.gradle.disableWrite")
|
||||
|
||||
/**
|
||||
* Internal properties: builds get big non-suppressible warning when such properties are used
|
||||
|
||||
+19
-6
@@ -12,12 +12,15 @@ import org.gradle.api.file.ProjectLayout
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.Companion.normalizeForFlagFile
|
||||
import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.gradle.utils.kotlinErrorsDir
|
||||
import org.jetbrains.kotlin.gradle.utils.property
|
||||
import org.jetbrains.kotlin.gradle.utils.kotlinSessionsDir
|
||||
import org.jetbrains.kotlin.gradle.utils.property
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -55,9 +58,19 @@ abstract class GradleCompileTaskProvider @Inject constructor(
|
||||
.property(incrementalModuleInfoProvider)
|
||||
|
||||
@get:Internal
|
||||
val errorsFile: Provider<File> = objectFactory
|
||||
.property(
|
||||
project.kotlinErrorsDir.also { it.mkdirs() }
|
||||
.resolve("errors-${System.currentTimeMillis()}.log")
|
||||
val errorsFiles: SetProperty<File> = objectFactory
|
||||
.setPropertyWithValue<File>(
|
||||
setOfNotNull(
|
||||
project.kotlinErrorsDir
|
||||
.errorFile,
|
||||
if (!project.kotlinPropertiesProvider.kotlinProjectPersistentDirGradleDisableWrite) {
|
||||
project.rootDir
|
||||
.resolve(".gradle/kotlin/errors/")
|
||||
.errorFile
|
||||
} else null,
|
||||
)
|
||||
)
|
||||
}
|
||||
.chainedDisallowChanges()
|
||||
}
|
||||
|
||||
private val File.errorFile get() = resolve("errors-${System.currentTimeMillis()}.log")
|
||||
+1
-1
@@ -348,7 +348,7 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
||||
environment,
|
||||
taskOutputsBackup
|
||||
)
|
||||
compilerRunner.errorsFile?.also { gradleMessageCollector.flush(it) }
|
||||
compilerRunner.errorsFiles?.let { gradleMessageCollector.flush(it) }
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -350,7 +350,7 @@ abstract class KotlinCompile @Inject constructor(
|
||||
defaultKotlinJavaToolchain.get().buildJvm.get().javaHome,
|
||||
taskOutputsBackup
|
||||
)
|
||||
compilerRunner.errorsFile?.also { gradleMessageCollector.flush(it) }
|
||||
compilerRunner.errorsFiles?.let { gradleMessageCollector.flush(it) }
|
||||
}
|
||||
|
||||
private fun validateKotlinAndJavaHasSameTargetCompatibility(
|
||||
|
||||
+1
-1
@@ -144,6 +144,6 @@ abstract class KotlinCompileCommon @Inject constructor(
|
||||
outputFiles = allOutputFiles()
|
||||
)
|
||||
compilerRunner.runMetadataCompilerAsync(args, environment)
|
||||
compilerRunner.errorsFile?.also { gradleMessageCollector.flush(it) }
|
||||
compilerRunner.errorsFiles?.let { gradleMessageCollector.flush(it) }
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -48,6 +48,10 @@ internal inline fun <reified T : Any?> ObjectFactory.setPropertyWithValue(
|
||||
initialValue: Provider<Iterable<T>>
|
||||
) = setProperty<T>().value(initialValue)
|
||||
|
||||
internal inline fun <reified T : Any?> ObjectFactory.setPropertyWithValue(
|
||||
initialValue: Iterable<T>
|
||||
) = setProperty<T>().value(initialValue)
|
||||
|
||||
internal inline fun <reified T : Any?> ObjectFactory.setPropertyWithLazyValue(
|
||||
noinline lazyValue: () -> Iterable<T>
|
||||
) = setPropertyWithValue(providerWithLazyConvention(lazyValue))
|
||||
@@ -97,6 +101,12 @@ internal fun <PropType : Any?, T : Property<PropType>> T.chainedDisallowChanges(
|
||||
disallowChanges()
|
||||
}
|
||||
|
||||
internal fun <PropType : Any?, T : SetProperty<PropType>> T.chainedDisallowChanges(): T =
|
||||
apply {
|
||||
disallowChanges()
|
||||
}
|
||||
|
||||
|
||||
// Before 5.0 fileProperty is created via ProjectLayout
|
||||
// https://docs.gradle.org/current/javadoc/org/gradle/api/model/ObjectFactory.html#fileProperty--
|
||||
internal fun Project.newFileProperty(initialize: (() -> File)? = null): RegularFileProperty {
|
||||
|
||||
Reference in New Issue
Block a user