diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/ExternalJavaConfigurationProvider.kt b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/ExternalJavaConfigurationProvider.kt index 427d0d2b4cee..2288d3cc95e8 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/ExternalJavaConfigurationProvider.kt +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/ExternalJavaConfigurationProvider.kt @@ -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 { public val EP_NAME: ExtensionPointName> = 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 { */ 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? } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/SdkmanrcConfigurationProvider.kt b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/SdkmanrcConfigurationProvider.kt index 6f04c4054ff9..ef2ee74cb6da 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/SdkmanrcConfigurationProvider.kt +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/SdkmanrcConfigurationProvider.kt @@ -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 { - 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 { - 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}" + } } \ No newline at end of file