[Pill] Use the multi-platform kotlin-test library (see KT-61969)

Pill import broke after the 'kotlin-test' build refactoring
(now it's a proper KMP project). This change adapts source set handling
in Pill, providing support both for Java and Kotlin KMP source sets.
This commit is contained in:
Yan Zhulanow
2023-12-14 18:03:10 +09:00
committed by Space Team
parent e2a06c66cc
commit e67042118a
2 changed files with 124 additions and 45 deletions
@@ -6,11 +6,8 @@
package org.jetbrains.kotlin.pill package org.jetbrains.kotlin.pill
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.plugins.BasePluginExtension
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSet
import org.gradle.kotlin.dsl.extra import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.getByType
import org.jdom2.Element import org.jdom2.Element
import org.jdom2.Verifier import org.jdom2.Verifier
import org.jdom2.input.SAXBuilder import org.jdom2.input.SAXBuilder
@@ -37,8 +34,7 @@ class JpsCompatiblePluginTasks(
":kotlin-stdlib-jdk7", ":kotlin-stdlib-jdk7",
":kotlin-stdlib-jdk8", ":kotlin-stdlib-jdk8",
":kotlin-reflect", ":kotlin-reflect",
":kotlin-test:kotlin-test-jvm", ":kotlin-test",
":kotlin-test:kotlin-test-junit",
":kotlin-script-runtime" ":kotlin-script-runtime"
) )
@@ -287,18 +283,28 @@ class JpsCompatiblePluginTasks(
for (path in DIST_LIBRARIES) { for (path in DIST_LIBRARIES) {
val project = rootProject.findProject(path) ?: error("Project '$path' not found") val project = rootProject.findProject(path) ?: error("Project '$path' not found")
val archiveName = project.extensions.getByType<BasePluginExtension>().archivesName.get()
val classesJars = listOf(File(distLibDir, "$archiveName.jar")).filterExisting()
val sourcesJars = listOf(File(distLibDir, "$archiveName-sources.jar")).filterExisting()
val sourceSets = project.extensions.getByType<JavaPluginExtension>().sourceSets
val applicableSourceSets = listOfNotNull( for (sourceSet in computeAllSourceSets(project)) {
sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME), if (sourceSet.isTest) {
sourceSets.findByName("java9") continue
) }
val optLibrary = Optional.of(PLibrary(archiveName, classesJars, sourcesJars, originalName = path)) val jarTask = sourceSet.findJarTask(project) ?: continue
applicableSourceSets.forEach { ss -> result["$path/${ss.name}"] = optLibrary }
val archiveName = listOfNotNull(jarTask.archiveBaseName.get(), jarTask.archiveAppendix.orNull).joinToString("-")
val classesJars = listOf(File(distLibDir, "$archiveName.jar")).filterExisting()
val sourcesJars = listOf(File(distLibDir, "$archiveName-sources.jar")).filterExisting()
val optLibrary = Optional.of(PLibrary(archiveName, classesJars, sourcesJars, originalName = path))
result[path + "/" + sourceSet.name] = optLibrary
val java9SourceSetName = when (val sourceSetBaseName = sourceSet.baseName) {
SourceSet.MAIN_SOURCE_SET_NAME -> "java9"
else -> sourceSetBaseName + "Java9"
}
result["$path/$java9SourceSetName"] = optLibrary
}
} }
for (path in IGNORED_LIBRARIES) { for (path in IGNORED_LIBRARIES) {
+103 -30
View File
@@ -7,6 +7,8 @@
package org.jetbrains.kotlin.pill package org.jetbrains.kotlin.pill
import org.gradle.api.Named
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Configuration
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
@@ -51,25 +53,17 @@ class ModelParser(private val modulePrefix: String, private val globalExcludedDi
val additionalOutputs = HashMap<OutputDir, List<OutputDir>>() val additionalOutputs = HashMap<OutputDir, List<OutputDir>>()
for (project in rootProject.allprojects) { for (project in rootProject.allprojects) {
val sourceSets = project.sourceSets?.toList() ?: emptyList() for (sourceSet in computeAllSourceSets(project)) {
for (sourceSet in sourceSets) {
val path = makePath(project, sourceSet.name) val path = makePath(project, sourceSet.name)
for (output in sourceSet.output.toList()) { if (sourceSet is SourceSetWrapper.JavaSourceSet) {
artifacts[output.absolutePath] = listOf(path) for (output in sourceSet.gradleSourceSet.output.toList()) {
} artifacts[output.absolutePath] = listOf(path)
val jarTaskNameCandidates = buildList {
add(sourceSet.jarTaskName)
when (sourceSet.name) {
SourceSet.MAIN_SOURCE_SET_NAME -> add("jvmJar")
SourceSet.TEST_SOURCE_SET_NAME -> add("jvmJarForTests")
} }
} }
val jarTask = jarTaskNameCandidates.firstNotNullOfOrNull { project.tasks.findByName(it) } as? Jar ?: continue val jarTask = sourceSet.findJarTask(project)
val embeddedTask = findEmbeddableTask(project, sourceSet) val embeddedTask = sourceSet.findEmbeddedTask(project)
for (task in listOfNotNull(jarTask, embeddedTask)) { for (task in listOfNotNull(jarTask, embeddedTask)) {
val archiveFile = task.archiveFile.get().asFile val archiveFile = task.archiveFile.get().asFile
@@ -102,14 +96,6 @@ class ModelParser(private val modulePrefix: String, private val globalExcludedDi
return artifacts return artifacts
} }
private fun findEmbeddableTask(project: Project, sourceSet: SourceSet): Jar? {
val jarName = sourceSet.jarTaskName
val embeddable = "embeddable"
val embeddedName = if (jarName == "jar") embeddable else jarName.dropLast("jar".length) +
embeddable.replaceFirstChar { it.uppercase() }
return project.tasks.findByName(embeddedName) as? Jar
}
private fun makePath(project: Project, sourceSetName: String): GradleProjectPath { private fun makePath(project: Project, sourceSetName: String): GradleProjectPath {
return project.path + "/" + sourceSetName return project.path + "/" + sourceSetName
} }
@@ -234,7 +220,7 @@ class ModelParser(private val modulePrefix: String, private val globalExcludedDi
sourceSets += PSourceSet( sourceSets += PSourceSet(
name = sourceSet.name, name = sourceSet.name,
forTests = sourceSet.isTestSourceSet, forTests = SourceSetWrapper.JavaSourceSet(sourceSet).isTest,
sourceDirectories = sourceDirectories, sourceDirectories = sourceDirectories,
resourceDirectories = resourceDirectories, resourceDirectories = resourceDirectories,
kotlinOptions = kotlinCompileTask?.let { getKotlinOptions(it, project) }, kotlinOptions = kotlinCompileTask?.let { getKotlinOptions(it, project) },
@@ -352,12 +338,99 @@ class ModelParser(private val modulePrefix: String, private val globalExcludedDi
} }
} }
private val SourceSet.isTestSourceSet: Boolean /**
get() = name == SourceSet.TEST_SOURCE_SET_NAME * Returns both Java and Kotlin source sets, including multiplatform ones.
|| name == "testFixtures" */
|| name.endsWith("Test") internal fun computeAllSourceSets(project: Project): List<SourceSetWrapper> {
|| name.endsWith("Tests") return buildList {
|| (extra.has("jpsKind") && extra.get("jpsKind") == SourceSet.TEST_SOURCE_SET_NAME) val existingNames = HashSet<String>()
for (javaSourceSet in project.sourceSets.orEmpty()) {
if (existingNames.add(javaSourceSet.name)) {
add(SourceSetWrapper.JavaSourceSet(javaSourceSet))
}
}
val kotlinExtension = project.extensions.findByName("kotlin")
if (kotlinExtension != null) {
// Calls 'KotlinSourceSetContainer.getSourceSets()'
val kotlinSourceSets = kotlinExtension.javaClass.getMethod("getSourceSets").invoke(kotlinExtension)
if (kotlinSourceSets is NamedDomainObjectContainer<*>) {
for (kotlinSourceSet in kotlinSourceSets) {
val name = (kotlinSourceSet as Named).name
if (existingNames.add(name)) {
add(SourceSetWrapper.KotlinSourceSet(kotlinSourceSet))
}
}
}
}
}
}
sealed class SourceSetWrapper(val name: String) {
class KotlinSourceSet(private val sourceSet: Named) : SourceSetWrapper(sourceSet.name) {
override val jarTaskCandidates: List<String>
get() {
// Production source sets (such as 'jvmMain') have a task without the 'Main' suffix, e.g. 'jvmJar'
return listOf("${baseName}Jar")
}
override fun findEmbeddedTask(project: Project): Jar? {
return null
}
}
class JavaSourceSet(val gradleSourceSet: SourceSet) : SourceSetWrapper(gradleSourceSet.name) {
override val jarTaskCandidates: List<String>
get() = buildList {
add(gradleSourceSet.jarTaskName)
when (gradleSourceSet.name) {
SourceSet.MAIN_SOURCE_SET_NAME -> add("jvmJar")
SourceSet.TEST_SOURCE_SET_NAME -> add("jvmJarForTests")
}
}
override val isTest: Boolean
get() {
if (gradleSourceSet.extra.has("jpsKind") && gradleSourceSet.extra.get("jpsKind") == SourceSet.TEST_SOURCE_SET_NAME) {
return true
}
return super.isTest
}
override fun findEmbeddedTask(project: Project): Jar? {
val jarName = gradleSourceSet.jarTaskName
val embeddable = "embeddable"
val embeddedName = if (jarName == "jar") embeddable else jarName.dropLast("jar".length) +
embeddable.replaceFirstChar { it.uppercase() }
return project.tasks.findByName(embeddedName) as? Jar
}
}
val baseName: String
get() = name.removeSuffix("Main")
open val isTest: Boolean
get() {
return name == SourceSet.TEST_SOURCE_SET_NAME
|| name == "testFixtures"
|| name.endsWith("Test")
|| name.endsWith("Tests")
}
protected abstract val jarTaskCandidates: List<String>
fun findJarTask(project: Project): Jar? {
return jarTaskCandidates.firstNotNullOfOrNull { project.tasks.findByName(it) } as? Jar
}
abstract fun findEmbeddedTask(project: Project): Jar?
override fun toString(): String {
return name
}
}
private fun Any.invokeInternal(name: String, instance: Any = this): Any? { private fun Any.invokeInternal(name: String, instance: Any = this): Any? {
val method = javaClass.methods.single { it.name.startsWith(name) && it.parameterTypes.isEmpty() } val method = javaClass.methods.single { it.name.startsWith(name) && it.parameterTypes.isEmpty() }
@@ -368,7 +441,7 @@ private fun Any.invokeInternal(name: String, instance: Any = this): Any? {
val Project.pillModuleName: String val Project.pillModuleName: String
get() = path.removePrefix(":").replace(':', '.') get() = path.removePrefix(":").replace(':', '.')
val Project.sourceSets: SourceSetContainer? private val Project.sourceSets: SourceSetContainer?
get() { get() {
val javaExtension = project.extensions.findByType<JavaPluginExtension>() ?: return null val javaExtension = project.extensions.findByType<JavaPluginExtension>() ?: return null
return javaExtension.sourceSets return javaExtension.sourceSets