Store processed metadata artifacts in .gradle/ rather than build/
This allows the files to survive Gradle's `clean` task that deletes the `build/` directory with all its contents, which leads to the IDE losing dependencies until next re-import. The `.gradle` directory is chosen because Gradle creates it in every project and it is normally included in .gitignore (or otherwise ignored in VCS). Related to issue #KT-39568
This commit is contained in:
+17
-4
@@ -103,6 +103,14 @@ class HierarchicalMppIT : BaseGradleIT() {
|
||||
assertTrue("$it") { it.newVisibleSourceSets == emptySet<String>() }
|
||||
}
|
||||
}
|
||||
|
||||
// ALso check that the files produced by dependency transformations survive a clean build:
|
||||
val existingFilesFromReports = reports.flatMap { it.useFiles }.filter { it.isFile }
|
||||
assertTrue { existingFilesFromReports.isNotEmpty() }
|
||||
build("clean") {
|
||||
assertSuccessful()
|
||||
existingFilesFromReports.forEach { assertTrue("Expected that $it exists after clean build.") { it.isFile } }
|
||||
}
|
||||
}
|
||||
|
||||
// --- Move the dependency from jvmAndJsMain to commonMain, expect that it is now propagated to commonTest:
|
||||
@@ -582,7 +590,8 @@ class HierarchicalMppIT : BaseGradleIT() {
|
||||
scope,
|
||||
it.groupId + ":" + it.moduleName,
|
||||
it.allVisibleSourceSets.joinToString(","),
|
||||
it.useFilesForSourceSets.keys.joinToString(",")
|
||||
it.useFilesForSourceSets.keys.joinToString(","),
|
||||
it.useFilesForSourceSets.values.flatten().joinToString(",")
|
||||
)
|
||||
|
||||
println(" " + line.joinToString(" :: "))
|
||||
@@ -613,7 +622,8 @@ class HierarchicalMppIT : BaseGradleIT() {
|
||||
val scope: String,
|
||||
val groupAndModule: String,
|
||||
val allVisibleSourceSets: Set<String>,
|
||||
val newVisibleSourceSets: Set<String> // those which the dependsOn parents don't see
|
||||
val newVisibleSourceSets: Set<String>, // those which the dependsOn parents don't see
|
||||
val useFiles: List<File>
|
||||
) {
|
||||
val isExcluded: Boolean get() = allVisibleSourceSets.isEmpty()
|
||||
|
||||
@@ -622,14 +632,17 @@ class HierarchicalMppIT : BaseGradleIT() {
|
||||
const val TEST_OUTPUT_COMPONENT_SEPARATOR = " :: "
|
||||
const val TEST_OUTPUT_ITEMS_SEPARATOR = ","
|
||||
|
||||
private operator fun <T> List<T>.component6() = this[5]
|
||||
|
||||
fun parseTestOutputLine(line: String): DependencyTransformationReport {
|
||||
val tail = line.substringAfter(TEST_OUTPUT_MARKER + TEST_OUTPUT_COMPONENT_SEPARATOR)
|
||||
val (sourceSetName, scope, groupAndModule, allVisibleSourceSets, newVisibleSourceSets) =
|
||||
val (sourceSetName, scope, groupAndModule, allVisibleSourceSets, newVisibleSourceSets, useFiles) =
|
||||
tail.split(TEST_OUTPUT_COMPONENT_SEPARATOR)
|
||||
return DependencyTransformationReport(
|
||||
sourceSetName, scope, groupAndModule,
|
||||
allVisibleSourceSets.split(TEST_OUTPUT_ITEMS_SEPARATOR).filter { it.isNotEmpty() }.toSet(),
|
||||
newVisibleSourceSets.split(TEST_OUTPUT_ITEMS_SEPARATOR).filter { it.isNotEmpty() }.toSet()
|
||||
newVisibleSourceSets.split(TEST_OUTPUT_ITEMS_SEPARATOR).filter { it.isNotEmpty() }.toSet(),
|
||||
useFiles.split(TEST_OUTPUT_ITEMS_SEPARATOR).map { File(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -29,18 +29,16 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companion.sourceSetFreeCompilerArgsPropertyName
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.checkSourceSetVisibilityRequirements
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||
import org.jetbrains.kotlin.gradle.tasks.locateTask
|
||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget.*
|
||||
@@ -111,6 +109,12 @@ class KotlinMultiplatformPlugin(
|
||||
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
|
||||
|
||||
exportProjectStructureMetadataForOtherBuilds(project)
|
||||
|
||||
SingleActionPerBuild.run(project.rootProject, "cleanup-processed-metadata") {
|
||||
project.gradle.buildFinished {
|
||||
SourceSetMetadataStorageForIde.cleanupStaleEntries(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportProjectStructureMetadataForOtherBuilds(
|
||||
|
||||
+2
-1
@@ -155,7 +155,8 @@ class DefaultKotlinSourceSet(
|
||||
?.associateBy { ModuleIds.fromComponent(project, it.dependency) }
|
||||
?: emptyMap()
|
||||
|
||||
val baseDir = project.buildDir.resolve("tmp/kotlinMetadata/$name/${scope.scopeName}")
|
||||
val baseDir = SourceSetMetadataStorageForIde.sourceSetStorage(project, this@DefaultKotlinSourceSet.name)
|
||||
|
||||
if (metadataDependencyResolutionByModule.values.any { it is MetadataDependencyResolution.ChooseVisibleSourceSets }) {
|
||||
if (baseDir.isDirectory) {
|
||||
baseDir.deleteRecursively()
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.plugin.sources
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import java.io.File
|
||||
|
||||
object SourceSetMetadataStorageForIde {
|
||||
fun cleanupStaleEntries(project: Project) {
|
||||
val projectStorageDirectories = project.rootProject.allprojects.associateBy { projectStorage(it) }
|
||||
getStorageRoot(project).listFiles().orEmpty().filter { it.isDirectory }.forEach { directory ->
|
||||
// If no project corresponds to the directory, remove the directory
|
||||
if (directory !in projectStorageDirectories) {
|
||||
directory.deleteRecursively()
|
||||
} else {
|
||||
// Under the project's directory, delete subdirectories that don't correspond to any source set:
|
||||
val sourceSets = projectStorageDirectories.getValue(directory)?.project?.multiplatformExtensionOrNull?.sourceSets.orEmpty()
|
||||
val sourceSetNames = sourceSets.map { it.name }
|
||||
directory.listFiles().orEmpty().filter { it.isDirectory }.forEach { subdirectory ->
|
||||
if (subdirectory.name !in sourceSetNames)
|
||||
subdirectory.deleteRecursively()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStorageRoot(project: Project): File = project.rootDir.resolve(".gradle/kotlin/sourceSetMetadata")
|
||||
|
||||
private fun projectStorage(project: Project): File {
|
||||
val projectPathSegments = generateSequence(project) { it.parent }.map { it.name }
|
||||
return getStorageRoot(project).resolve(
|
||||
// Escape dots in project names to avoid ambiguous paths.
|
||||
projectPathSegments.joinToString(".") { it.replace(".", "_.") }
|
||||
)
|
||||
}
|
||||
|
||||
fun sourceSetStorage(project: Project, sourceSetName: String) = projectStorage(project).resolve(sourceSetName)
|
||||
}
|
||||
Reference in New Issue
Block a user