Fix cooperative development setup for kt-master

This commit is contained in:
Ilya Kirillov
2022-03-01 15:54:00 +01:00
parent 8576265108
commit 7fbfb1bd95
10 changed files with 154 additions and 106 deletions
@@ -6,6 +6,7 @@ plugins {
dependencies {
implementation(kotlinStdlib("jdk8"))
implementation(jpsModel())
implementation("com.jetbrains.intellij.platform:util-text-matching:$intellijVersion")
implementation(jpsModelImpl())
implementation(jpsModelSerialization())
implementation(commonDependency("com.google.code.gson:gson"))
@@ -5,42 +5,11 @@
package org.jetbrains.kotlin.generators.imltogradle
open class GradleDependencyNotation(val dependencyNotation: String, val dependencyConfiguration: String? = null) {
sealed class GradleDependencyNotation(val dependencyNotation: String) {
init {
require(dependencyNotation.isNotEmpty())
require(dependencyConfiguration?.isNotEmpty() ?: true)
}
companion object {
private const val artifactNameSubregex = """([a-zA-Z\-\._1-9]*?)"""
private val libPathToGradleNotationRegex = """^lib\/$artifactNameSubregex\.jar$""".toRegex()
private val pluginsPathToGradleNotationRegex = """^plugins\/$artifactNameSubregex\/.*?$""".toRegex()
private val jarToGradleNotationRegex = """^$artifactNameSubregex\.jar$""".toRegex()
fun fromJarPath(jarPath: String): GradleDependencyNotation? {
if (jarPath == "lib/cds/classesLogAgent.jar") {
return null // TODO remove hack?
}
if (jarPath.contains("intellij-core.jar")) {
return IntellijCoreGradleDependencyNotation
}
fun Regex.firstGroup() = matchEntire(jarPath)?.groupValues?.get(1)
return pluginsPathToGradleNotationRegex.firstGroup()?.let { IntellijPluginDepGradleDependencyNotation(it) }
?: libPathToGradleNotationRegex.firstGroup()?.let { IntellijDepGradleDependencyNotation(it) }
?: jarToGradleNotationRegex.firstGroup()?.let { IntellijDepGradleDependencyNotation(it) }
?: error("Path $jarPath matches none of the regexes")
}
}
object IntellijCoreGradleDependencyNotation : GradleDependencyNotation("intellijCoreDep()", null)
data class IntellijPluginDepGradleDependencyNotation(val pluginName: String) :
GradleDependencyNotation("intellijPluginDep(\"$pluginName\", forIde = true)")
data class IntellijDepGradleDependencyNotation(val jarName: String) :
GradleDependencyNotation("intellijDep(forIde = true)", "{ includeJars(\"$jarName\") }")
data class IntellijMavenDepGradleDependencyNotation(val groupId: String, val artifactId: String) :
GradleDependencyNotation("""intellijMavenDep("$groupId", "$artifactId")""")
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.generators.imltogradle
import com.google.gson.JsonParser
import org.jetbrains.jps.model.JpsSimpleElement
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JavaSourceRootType
@@ -14,11 +13,8 @@ import org.jetbrains.jps.model.library.JpsLibrary
import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor
import org.jetbrains.jps.model.library.JpsOrderRootType
import org.jetbrains.jps.model.module.*
import org.jetbrains.kotlin.generators.imltogradle.GradleDependencyNotation.IntellijDepGradleDependencyNotation
import java.io.File
private lateinit var intellijModuleNameToGradleDependencyNotationsMapping: Map<String, List<GradleDependencyNotation>>
private val KOTLIN_REPO_ROOT = File(".").canonicalFile
val DEFAULT_KOTLIN_SNAPSHOT_VERSION = KOTLIN_REPO_ROOT.resolve("gradle.properties")
.readProperty("defaultSnapshotVersion")
@@ -26,11 +22,6 @@ val DEFAULT_KOTLIN_SNAPSHOT_VERSION = KOTLIN_REPO_ROOT.resolve("gradle.propertie
private val INTELLIJ_REPO_ROOT = KOTLIN_REPO_ROOT.resolve("intellij").resolve("community").takeIf { it.exists() }
?: KOTLIN_REPO_ROOT.resolve("intellij")
private val intellijModuleNameToGradleDependencyNotationsMappingManual: List<Pair<String, GradleDependencyNotation>> = listOf(
"intellij.platform.jps.build" to GradleDependencyNotation("jpsBuildTest()"),
"intellij.platform.structuralSearch" to IntellijDepGradleDependencyNotation("structuralsearch") // for some reason it's absent in json mapping
)
// These modules are used in Kotlin plugin and IDEA doesn't publish artifact of these modules
private val intellijModulesForWhichGenerateBuildGradle = listOf(
"intellij.platform.debugger.testFramework",
@@ -41,13 +32,20 @@ private val intellijModulesForWhichGenerateBuildGradle = listOf(
"intellij.java.compiler.tests",
"intellij.gradle.toolingExtension.tests",
"intellij.maven",
"intellij.gradle.java",
"intellij.gradle.jps",
"intellij.relaxng",
"intellij.jvm.analysis.kotlin.tests",
"intellij.jvm.analysis.testFramework",
"intellij.platform.configurationStore.tests",
"intellij.statsCollector.tests",
"intellij.groovy.uast.tests",
)
val jsonUrlPrefixes = mapOf(
"202" to "https://buildserver.labs.intellij.net/guestAuth/repository/download/ijplatform_IjPlatform202_IntellijArtifactMappings/113235432:id",
"203" to "https://buildserver.labs.intellij.net/guestAuth/repository/download/ijplatform_IjPlatform203_IntellijArtifactMappings/117989041:id",
"211" to "https://buildserver.labs.intellij.net/guestAuth/repository/download/ijplatform_IjPlatform211_IntellijArtifactMappings/121258191:id",
"212" to "https://buildserver.labs.intellij.net/guestAuth/repository/download/ijplatform_IjPlatform211_IntellijArtifactMappings/131509697:id",
private val intellijModulesToIgnore = listOf(
"kotlin.util.compiler-dependencies",
"intellij.gradle.java.tests",
"intellij.grazie.tests",
)
fun main() {
@@ -64,35 +62,6 @@ fun main() {
}
.toList()
val ideaMajorVersion = KOTLIN_REPO_ROOT.resolve("local.properties").readProperty("attachedIntellijVersion")
intellijModuleNameToGradleDependencyNotationsMapping = fetchJsonsFromBuildserver(ideaMajorVersion)
.flatMap { jsonStr ->
JsonParser.parseString(jsonStr).asJsonArray.mapNotNull { jsonElement ->
val jsonObject = jsonElement.asJsonObject
val moduleName = jsonObject.get("moduleName")?.asString ?: return@mapNotNull null
val jarPath = jsonObject.get("path")?.asString ?: return@mapNotNull null
moduleName to jarPath
}
}
.filter { (_, jarPath) -> !jarPath.contains("DatabaseTools") && !jarPath.contains("lib/openapi.jar") }
.groupBy(
keySelector = { (_, jarPath) -> jarPath },
valueTransform = { (moduleName, _) -> moduleName }
)
.filter { (_, moduleNames) ->
moduleNames.all { it in ijCommunityModuleNameToJpsModuleMapping } // filter out ultimate jars
}
.flatMap { (jarPath, moduleNames) -> moduleNames.map { it to jarPath } }
.mapNotNull { (moduleName, jarPath) ->
moduleName to (GradleDependencyNotation.fromJarPath(jarPath) ?: return@mapNotNull null)
}
.plus(intellijModuleNameToGradleDependencyNotationsMappingManual)
.groupBy(
keySelector = { (moduleName, _) -> moduleName },
valueTransform = { (_, dependencyNotation) -> dependencyNotation }
)
val imlsInSameDirectory: List<List<File>> = imlFiles.groupBy { it.parentFile }.filter { it.value.size > 1 }.map { it.value }
if (imlsInSameDirectory.isNotEmpty()) {
val report = imlsInSameDirectory.joinToString("\n") { "In same directory: " + it.joinToString() }
@@ -103,7 +72,7 @@ fun main() {
.mapNotNull { imlFile ->
ijCommunityModuleNameToJpsModuleMapping[imlFile.nameWithoutExtension]?.let { imlFile to it }
}
.filter { (_, jpsModule) -> jpsModule.name != "kotlin.util.compiler-dependencies" }
.filter { (_, jpsModule) -> jpsModule.name !in intellijModulesToIgnore }
.forEach { (imlFile, jpsModule) ->
println("Processing iml ${imlFile}")
imlFile.parentFile.resolve("build.gradle.kts").writeText(convertJpsModule(imlFile, jpsModule))
@@ -168,14 +137,22 @@ fun convertJpsLibrary(lib: JpsLibrary, scope: JpsJavaDependencyScope, exported:
fun convertIntellijDependencyNotFollowingTransitive(dep: JpsDependencyDescriptor, exported: Boolean): List<JpsLikeDependency> {
return when (val moduleOrLibrary = dep.moduleOrLibrary) {
is Either.First -> {
val moduleName = moduleOrLibrary.value.name
if (moduleName in intellijModulesForWhichGenerateBuildGradle) {
listOf(JpsLikeModuleDependency(":kotlin-ide.$moduleName", dep.scope, exported))
} else {
intellijModuleNameToGradleDependencyNotationsMapping[moduleName]
.also { if (it == null) println("WARNING: Cannot find GradleDependencyNotation for $moduleName") }
?.map { JpsLikeJarDependency(it.dependencyNotation, dep.scope, it.dependencyConfiguration, exported) }
?: emptyList()
when (val moduleName = moduleOrLibrary.value.name) {
in intellijModulesForWhichGenerateBuildGradle -> {
listOf(JpsLikeModuleDependency(":kotlin-ide.$moduleName", dep.scope, exported))
}
in intellijModulesToIgnore -> emptyList()
else -> {
val (groupId, artifactId) = MavenArtifactsBuilder.generateMavenCoordinates(moduleName)
listOf(
JpsLikeJarDependency(
GradleDependencyNotation.IntellijMavenDepGradleDependencyNotation(groupId, artifactId).dependencyNotation,
dep.scope,
dependencyConfiguration = null,
exported
)
)
}
}
}
is Either.Second -> convertJpsLibrary(moduleOrLibrary.value, dep.scope, exported)
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2022 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.generators.imltogradle
import com.intellij.util.text.NameUtilCore
import java.util.*
// Copied from intellij build scripts
object MavenArtifactsBuilder {
fun generateMavenCoordinates(moduleName: String): MavenArtifact {
val names = moduleName.split(".")
if (names.size < 2) {
error("Cannot generate Maven artifacts: incorrect module name '${moduleName}'")
}
val groupId = names.take(2).joinToString(separator = ".")
val firstMeaningful = if (names.size > 2 && COMMON_GROUP_NAMES.contains(names[1])) 2 else 1
val artifactId = names.drop(firstMeaningful).flatMap {
splitByCamelHumpsMergingNumbers(it).map { it.lowercase(Locale.US) }
}.joinToString(separator = "-")
return MavenArtifact(groupId, artifactId)
}
private fun splitByCamelHumpsMergingNumbers(s: String): List<String> {
val words: List<String> = NameUtilCore.splitNameIntoWords(s).toList()
val result = ArrayList<String>()
var i = 0
while (i < words.size) {
val next: String
if (i < words.size - 1 && Character.isDigit(words[i + 1][0])) {
next = words[i] + words[i + 1]
i++
} else {
next = words[i]
}
result += next
i++
}
return result
}
private val COMMON_GROUP_NAMES = setOf("platform", "vcs", "tools", "clouds")
}
data class MavenArtifact(
val groupId: String,
val artifactId: String
)
@@ -83,22 +83,6 @@ inline fun <T> T?.orElse(block: () -> T): T = this ?: block()
val JpsModule.dependencies: List<JpsDependencyElement>
get() = dependenciesList.dependencies.filter { it is JpsModuleDependency || it is JpsLibraryDependency }
fun fetchJsonsFromBuildserver(ideaMajorVersion: String): List<String> {
require(ideaMajorVersion.length == 3 && ideaMajorVersion.all { it.isDigit() }) {
"attachedIntellijVersion='$ideaMajorVersion' must be 3 length all digit string"
}
val urlPrefix = jsonUrlPrefixes[ideaMajorVersion] ?: error("'$ideaMajorVersion' platform is absent in mapping")
return listOf(
"$urlPrefix/ideaIU-project-structure-mapping.json",
"$urlPrefix/intellij-core-project-structure-mapping.json"
).map { url ->
try {
URL(url).readText()
} catch (ex: Throwable) {
error("Can't access $url. Is VPN on?")
}
}
}
fun File.readProperty(propertyName: String): String {
return inputStream().use { Properties().apply { load(it) }.getProperty(propertyName) }