[jdk] Extend ExternalJavaConfigurationProvider API

IDEA-364749

GitOrigin-RevId: 75c92b3a7cc724a8d7d17419996690d998dcae92
This commit is contained in:
Louis Vignier
2025-08-29 14:42:24 +00:00
committed by intellij-monorepo-bot
parent 0ffd59361c
commit 604fdbacda
3 changed files with 61 additions and 9 deletions
@@ -1,9 +1,10 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.projectRoots.impl
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.util.TextRange
import java.io.File
/**
@@ -18,11 +19,21 @@ public interface ExternalJavaConfigurationProvider<T> {
public val EP_NAME: ExtensionPointName<ExternalJavaConfigurationProvider<*>> = ExtensionPointName.create("com.intellij.openapi.projectRoots.externalJavaConfigurationProvider")
}
/**
* @return true if the file with given [fileName] is supported by the configuration provider.
*/
public fun isConfigurationFile(fileName: String): Boolean
/**
* @return the configuration file supported by this provider.
*/
public fun getConfigurationFile(project: Project): File
/**
* @return range of the release data in the configuration file.
*/
public fun getReleaseDataOffset(text: String): TextRange?
/**
* @return the release data [T] corresponding to the [text] content of the configuration file.
*/
@@ -38,4 +49,9 @@ public interface ExternalJavaConfigurationProvider<T> {
*/
public fun matchAgainstPath(releaseData: T, path: String): Boolean
/**
* @return the command to be executed in the terminal to download the release data JDK,
* null if downloads are not supported.
*/
public fun getDownloadCommandFor(releaseData: T): String?
}
@@ -1,10 +1,11 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.projectRoots.impl
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.util.TextRange
import org.jetbrains.jps.model.java.JdkVersionDetector
import java.io.File
import java.util.*
@@ -16,10 +17,10 @@ public data class SdkmanReleaseData(val target: String,
val flavour: String? = null,
val vendor: String? = null) {
public companion object {
private val regex: Regex = Regex("(\\d+(?:\\.\\d+)*)(?:\\.([^-]+))?-?(.*)?")
private val regex: Regex = Regex("(\\d+(?:\\.\\d+)*)(?:\\.([^-]+))?-?(\\S*)?")
public fun parse(text: String): SdkmanReleaseData? {
val matchResult = regex.find(text) ?: return null
val matchResult = regex.matchEntire(text) ?: return null
return SdkmanReleaseData(
text,
matchResult.groups[1]?.value ?: return null,
@@ -56,20 +57,33 @@ public data class SdkmanReleaseData(val target: String,
// Check vendor
val variantName = variant.displayName
return variantName != null && versionString.contains(variantName)
return versionString.contains(variantName)
}
}
private const val SDKMANRC = ".sdkmanrc"
public class SdkmanrcConfigurationProvider: ExternalJavaConfigurationProvider<SdkmanReleaseData> {
override fun getConfigurationFile(project: Project): File = File(project.basePath, ".sdkmanrc")
override fun isConfigurationFile(fileName: String): Boolean = fileName == SDKMANRC
override fun getConfigurationFile(project: Project): File = File(project.basePath, SDKMANRC)
override fun getReleaseData(text: String): SdkmanReleaseData? {
val properties = Properties().apply {
load(text.byteInputStream())
}
val java = properties.getProperty("java") ?: return null
return SdkmanReleaseData.parse(java)
return SdkmanReleaseData.parse(java.trim())
}
override fun getReleaseDataOffset(text: String): TextRange? {
val releaseData = getReleaseData(text) ?: return null
val range = Regex("^java=(.*)$", RegexOption.MULTILINE)
.findAll(text)
.firstOrNull { it.groupValues.getOrNull(1)?.contains(releaseData.target) == true }
?.range ?: return null
return TextRange(range.first, range.last)
}
override fun matchAgainstSdk(releaseData: SdkmanReleaseData, sdk: Sdk): Boolean {
@@ -81,4 +95,8 @@ public class SdkmanrcConfigurationProvider: ExternalJavaConfigurationProvider<Sd
val info = SdkVersionUtil.getJdkVersionInfo(path) ?: return false
return releaseData.matchVersionString(info.displayVersionString())
}
override fun getDownloadCommandFor(releaseData: SdkmanReleaseData): String {
return "sdk install java ${releaseData.target}"
}
}
@@ -5,6 +5,7 @@ import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.util.TextRange
import org.jetbrains.jps.model.java.JdkVersionDetector
import java.io.File
@@ -53,12 +54,16 @@ public data class AsdfReleaseData(val name: String, val vendor: String, val vers
// Check vendor
val variantName = variant.displayName
return variantName != null && versionString.contains(variantName)
return versionString.contains(variantName)
}
}
private const val TOOL_VERSIONS = ".tool-versions"
public class ToolVersionsConfigurationProvider : ExternalJavaConfigurationProvider<AsdfReleaseData> {
override fun getConfigurationFile(project: Project): File = File(project.basePath, ".tool-versions")
override fun isConfigurationFile(fileName: String): Boolean = fileName == TOOL_VERSIONS
override fun getConfigurationFile(project: Project): File = File(project.basePath, TOOL_VERSIONS)
override fun getReleaseData(text: String): AsdfReleaseData? {
val releaseDataText = text.lines()
@@ -67,6 +72,15 @@ public class ToolVersionsConfigurationProvider : ExternalJavaConfigurationProvid
return AsdfReleaseData.parse(releaseDataText.trim())
}
override fun getReleaseDataOffset(text: String): TextRange? {
val releaseData = getReleaseData(text) ?: return null
val range = Regex("^java (.*)$", RegexOption.MULTILINE)
.findAll(text)
.firstOrNull { it.groupValues.getOrNull(1)?.contains(releaseData.name) == true }
?.range ?: return null
return TextRange(range.first, range.last)
}
override fun matchAgainstSdk(releaseData: AsdfReleaseData, sdk: Sdk): Boolean {
val sdkVersion = sdk.versionString ?: return false
return releaseData.matchVersionString(sdkVersion)
@@ -76,4 +90,8 @@ public class ToolVersionsConfigurationProvider : ExternalJavaConfigurationProvid
val info = SdkVersionUtil.getJdkVersionInfo(path) ?: return false
return releaseData.matchVersionString(info.displayVersionString())
}
override fun getDownloadCommandFor(releaseData: AsdfReleaseData): String {
return "asdf install java ${releaseData.name}"
}
}