Skip to content

Commit

Permalink
[Gradle|Daemon|JVM] new: implement mechanism to migrate existing proj…
Browse files Browse the repository at this point in the history
…ects to Daemon JVM criteria

closes #2882

Issues: IDEA-358562

GitOrigin-RevId: d8e66f12ba4496ab53ccf5eac3461636aab6566f
  • Loading branch information
vmadalin authored and intellij-monorepo-bot committed Jan 8, 2025
1 parent 363222f commit 6fbc227
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ fun Module.getTopLevelBuildScriptSettingsPsiFile(): PsiFile? {
?.getPsiFile(project)
}

fun Project.getTopLevelBuildScriptSettingsPsiFile(): PsiFile? {
val projectDir = this.guessProjectDir() ?: return null
return findBuildGradleFile(projectDir.path, SETTINGS_FILE_NAME, KOTLIN_SETTINGS_SCRIPT_NAME)
?.getPsiFile(this)
}

private fun Module.getBuildScriptFile(vararg fileNames: String): Path? {
moduleNioFile.parent?.let { moduleDir ->
findBuildGradleFile(moduleDir.pathString, *fileNames)?.let {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.toolchain

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.components.Service
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil.USE_PROJECT_JDK
import com.intellij.openapi.externalSystem.task.TaskCallback
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import org.jetbrains.jps.model.java.JdkVersionDetector
import org.jetbrains.kotlin.idea.gradle.extensions.nameSupportedByFoojayPlugin
import org.jetbrains.kotlin.idea.gradleCodeInsightCommon.GradleBuildScriptSupport
import org.jetbrains.kotlin.idea.gradleCodeInsightCommon.getTopLevelBuildScriptSettingsPsiFile
import org.jetbrains.plugins.gradle.service.GradleInstallationManager
import org.jetbrains.plugins.gradle.service.execution.GradleDaemonJvmCriteria
import org.jetbrains.plugins.gradle.service.execution.GradleDaemonJvmHelper
import org.jetbrains.plugins.gradle.settings.GradleSettings
import org.jetbrains.plugins.gradle.util.GradleBundle

@Service(Service.Level.PROJECT)
class GradleDaemonToolchainMigrationService(private val project: Project) {

fun startMigration(externalProjectPath: String) {
val currentJdkInfo = GradleInstallationManager.getInstance().getGradleJvmPath(project, externalProjectPath)?.let {
JdkVersionDetector.getInstance().detectJdkVersionInfo(it)
}
if (currentJdkInfo?.version == null) {
displayMigrationFailureMessage()
return
}

applyDefaultToolchainResolverPlugin()

GradleDaemonJvmHelper.updateProjectDaemonJvmCriteria(
project,
externalProjectPath,
GradleDaemonJvmCriteria(
version = currentJdkInfo.version.feature.toString(),
vendor = currentJdkInfo.variant.nameSupportedByFoojayPlugin
), object : TaskCallback {
override fun onSuccess() {
overrideGradleJvmReferenceWithDefault(externalProjectPath)
}

override fun onFailure() {
displayMigrationFailureMessage()
}
}
)
}

private fun applyDefaultToolchainResolverPlugin() {
CommandProcessor.getInstance().executeCommand(project, {
ApplicationManager.getApplication().runWriteAction {
project.getTopLevelBuildScriptSettingsPsiFile()?.let {
val buildScriptSupport = GradleBuildScriptSupport.getManipulator(it)
buildScriptSupport.addFoojayPlugin(it)
}
}
}, GradleBundle.message("gradle.notifications.daemon.toolchain.migration.apply.plugin.command.name"), null)
}

private fun overrideGradleJvmReferenceWithDefault(externalProjectPath: String) {
val projectSettings = GradleSettings.getInstance(project).getLinkedProjectSettings(externalProjectPath)
projectSettings?.gradleJvm = USE_PROJECT_JDK
}

private fun displayMigrationFailureMessage() {
ApplicationManager.getApplication().invokeLater {
Messages.showErrorDialog(
project,
GradleBundle.message("gradle.notifications.daemon.toolchain.migration.error.message", project.name),
GradleBundle.message("gradle.notifications.daemon.toolchain.migration.error.title")
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.toolchain.gradle

import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.readAction
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil.JAVA_HOME
import com.intellij.openapi.roots.ui.configuration.SdkTestCase.Companion.withRegisteredSdks
import kotlinx.coroutines.runBlocking
import org.jetbrains.jps.model.java.JdkVersionDetector
import org.jetbrains.kotlin.idea.gradle.extensions.nameSupportedByFoojayPlugin
import org.jetbrains.kotlin.idea.gradleCodeInsightCommon.getTopLevelBuildScriptSettingsPsiFile
import org.jetbrains.kotlin.idea.gradleJava.toolchain.GradleDaemonToolchainMigrationService
import org.jetbrains.plugins.gradle.importing.GradleProjectSdkResolverTestCase
import org.jetbrains.plugins.gradle.properties.GradleDaemonJvmPropertiesFile
import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions
import org.junit.Test
import kotlin.io.path.Path

class GradleDaemonToolchainMigrationServiceTest: GradleProjectSdkResolverTestCase() {

@Test
@TargetVersions("8.8+")
fun `test Given project When migrate to Daemon toolchain Then criteria is maintained`() = runBlocking {
val jdk = resolveRealTestSdk()
val jdkInfo = JdkVersionDetector.getInstance().detectJdkVersionInfo(jdk.homePath!!)
check(jdkInfo != null)
createGradleSubProject()

environment.withVariables(JAVA_HOME to jdk.homePath) {
withRegisteredSdks(jdk) {
loadProject()
check(GradleDaemonJvmPropertiesFile.getProperties(Path(projectPath)) == null)

invokeAndWaitIfNeeded {
GradleDaemonToolchainMigrationService(project).startMigration(projectPath)
}
assertFoojayPluginIsApplied()
assertDaemonJvmProperties(jdkInfo.version.feature, jdkInfo.variant.nameSupportedByFoojayPlugin)
}
}
}

private suspend fun assertFoojayPluginIsApplied() {
readAction {
project.getTopLevelBuildScriptSettingsPsiFile()!!.text.contains("org.gradle.toolchains.foojay-resolver-convention")
}
}

private fun assertDaemonJvmProperties(expectedVersion: Int, expectedVendor: String?) {
GradleDaemonJvmPropertiesFile.getProperties(Path(projectPath))!!.run {
assertEquals(expectedVersion.toString(), version?.value)
assertEquals(expectedVendor, vendor?.value)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradle.extensions

import org.jetbrains.jps.model.java.JdkVersionDetector.Variant

/**
* Transform [Variant.name] into expected vendors name by [foojay-plugin](https://github.com/gradle/foojay-toolchains) being the default
* [plugin resolver](https://docs.gradle.org/current/userguide/toolchain_plugins.html) applied to projects when Gradle
* toolchains are configured
*/
val Variant.nameSupportedByFoojayPlugin: String?
get() = when(this) {
Variant.AdoptOpenJdk_HS -> "AOJ"
Variant.AdoptOpenJdk_J9 -> "AOJ OpenJ9"
Variant.JBR -> "JetBrains"
Variant.IBM -> Variant.Semeru.name
Variant.Unknown, Variant.GraalVMCE, Variant.Homebrew -> null
else -> name
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,8 @@
<orderEntry type="module" module-name="kotlin.completion.tests.shared" scope="TEST" />
<orderEntry type="module" module-name="kotlin.completion.tests.k1" scope="TEST" />
<orderEntry type="library" scope="TEST" name="TestNG" level="project" />
<orderEntry type="library" scope="TEST" name="mockito" level="project" />
<orderEntry type="library" scope="TEST" name="mockito-kotlin" level="project" />
<orderEntry type="module" module-name="intellij.platform.testFramework.junit5" scope="TEST" />
</component>
</module>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradle.externsions

import com.intellij.testFramework.junit5.TestApplication
import org.jetbrains.jps.model.java.JdkVersionDetector.Variant
import org.jetbrains.kotlin.idea.gradle.extensions.nameSupportedByFoojayPlugin
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

@TestApplication
class VariantExtensionsTest {

@Test
fun testVariantNameSupportedByFoojayPlugin() {
Variant.entries.forEach { variant ->
assertEquals(variant.expectedNameSupportedByFoojayPlugin, variant.nameSupportedByFoojayPlugin)
}
}

private val Variant.expectedNameSupportedByFoojayPlugin: String?
get() = when (this) {
Variant.AdoptOpenJdk_HS -> "AOJ"
Variant.AdoptOpenJdk_J9 -> "AOJ OpenJ9"
Variant.IBM, Variant.Semeru -> "Semeru"
Variant.JBR -> "JetBrains"
Variant.BiSheng -> "BiSheng"
Variant.Corretto -> "Corretto"
Variant.Dragonwell -> "Dragonwell"
Variant.GraalVM -> "GraalVM"
Variant.Kona -> "Kona"
Variant.Liberica -> "Liberica"
Variant.Microsoft -> "Microsoft"
Variant.Oracle -> "Oracle"
Variant.SapMachine -> "SapMachine"
Variant.Temurin -> "Temurin"
Variant.Zulu -> "Zulu"
Variant.Unknown, Variant.GraalVMCE, Variant.Homebrew -> null
}
}

0 comments on commit 6fbc227

Please sign in to comment.