mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[eel][sdk] IJPL-214464 Resolve SDKs via environment‑scoped lookup interface
Introduce `EnvironmentScopedProjectJdkLookup` interface for environment‑aware SDK resolution and make `ProjectJdkTableImpl` implement it. Add `findJdk(String, InternalEnvironmentName)` and `findJdk(String, String, InternalEnvironmentName)` methods that delegate to `SdkTableImplementationDelegate#findSdkByName(String, InternalEnvironmentName)`. Update `ProjectJdkTableProjectView.findJdk(...)` (both overloads) to use the interface methods with environment from the project descriptor. This enables per‑environment SDK separation, reduces unnecessary cross‑environment lookups, and improves correctness without changing external behavior. (cherry picked from commit 73fefa0c54c2156e824da9f081f70efea262b933) IJ-CR-180956 GitOrigin-RevId: 160cfcffeea6209e974d137a0cc144d52170c62b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
21a271d2a1
commit
be70b2c8c7
@@ -58,6 +58,7 @@ jvm_library(
|
||||
"//platform/xdebugger-testFramework:debugger-testFramework",
|
||||
"//xml/xml-psi-api:psi",
|
||||
"//java/java-syntax:syntax",
|
||||
"//platform/eel",
|
||||
],
|
||||
exports = [
|
||||
"//java/testFramework/shared",
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.debugger.testFramework" />
|
||||
<orderEntry type="module" module-name="intellij.xml.psi" />
|
||||
<orderEntry type="module" module-name="intellij.java.syntax" />
|
||||
<orderEntry type="module" module-name="intellij.platform.eel" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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.projectRoots.Sdk
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
/**
|
||||
* Provides environment-aware SDK lookup operations for optimized SDK resolution across isolated environments.
|
||||
*
|
||||
* This interface enables efficient SDK lookups that are scoped to specific environments (such as local, WSL,
|
||||
* Docker containers, etc.) without requiring retrieval and filtering of all available SDKs. Implementations
|
||||
* should leverage environment-specific SDK storage to avoid unnecessary cross-environment operations.
|
||||
*
|
||||
* The primary benefit over using [com.intellij.openapi.projectRoots.ProjectJdkTable.getAllJdks] and manual
|
||||
* filtering is performance optimization: instead of retrieving all SDKs from all environments and then
|
||||
* filtering by environment, this interface allows direct lookup within the target environment's SDK
|
||||
* namespace.
|
||||
*
|
||||
* @see com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
* @see EelDescriptor
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
interface EnvironmentScopedProjectJdkLookup {
|
||||
fun findJdk(name: String, eelDescriptor: EelDescriptor): Sdk?
|
||||
|
||||
fun findJdk(name: String, type: String, eelDescriptor: EelDescriptor): Sdk?
|
||||
}
|
||||
@@ -16,17 +16,21 @@ import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.projectRoots.SdkType
|
||||
import com.intellij.openapi.projectRoots.SdkTypeId
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.workspace.jps.serialization.impl.JpsGlobalEntitiesSerializers
|
||||
import com.intellij.platform.workspace.storage.InternalEnvironmentName
|
||||
import com.intellij.serviceContainer.ComponentManagerImpl
|
||||
import com.intellij.workspaceModel.ide.impl.getInternalEnvironmentName
|
||||
import com.intellij.workspaceModel.ide.impl.legacyBridge.sdk.SdkTableBridgeImpl
|
||||
import com.intellij.workspaceModel.ide.legacyBridge.sdk.SdkTableImplementationDelegate
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
// This annotation is needed only for support of the "export settings" action
|
||||
@State(name = "ProjectJdkTable", storages = [Storage(value = JpsGlobalEntitiesSerializers.SDK_FILE_NAME + DEFAULT_EXT)], presentableName = ProjectJdkTableImpl.PresentableNameGetter::class)
|
||||
open class ProjectJdkTableImpl: ProjectJdkTable() {
|
||||
open class ProjectJdkTableImpl: ProjectJdkTable(), EnvironmentScopedProjectJdkLookup {
|
||||
|
||||
private val delegate: SdkTableImplementationDelegate
|
||||
|
||||
@@ -52,24 +56,44 @@ open class ProjectJdkTableImpl: ProjectJdkTable() {
|
||||
override fun findJdk(name: String): Sdk? = delegate.findSdkByName(name)
|
||||
|
||||
override fun findJdk(name: String, type: String): Sdk? {
|
||||
var sdk = findJdk(name)
|
||||
val sdk = findJdk(name)
|
||||
if (sdk != null) return sdk
|
||||
return getCachedJdkOrTryCreateJdkUsingSystemProperty(name, type, InternalEnvironmentName.Local)
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
override fun findJdk(name: String, eelDescriptor: EelDescriptor): Sdk? {
|
||||
return delegate.findSdkByName(name, environmentName = eelDescriptor.machine.getInternalEnvironmentName())
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
override fun findJdk(name: String, type: String, eelDescriptor: EelDescriptor): Sdk? {
|
||||
val environmentName = eelDescriptor.machine.getInternalEnvironmentName()
|
||||
val sdk = delegate.findSdkByName(name, environmentName)
|
||||
if (sdk != null) return sdk
|
||||
return getCachedJdkOrTryCreateJdkUsingSystemProperty(name, type, environmentName)
|
||||
}
|
||||
|
||||
private fun getCachedJdkOrTryCreateJdkUsingSystemProperty(name: String, type: String, environmentName: InternalEnvironmentName): Sdk? {
|
||||
val uniqueName = "$type.$name"
|
||||
sdk = cachedProjectJdks[uniqueName]
|
||||
val sdk = cachedProjectJdks[uniqueName]
|
||||
if (sdk != null) return sdk
|
||||
return when (environmentName) {
|
||||
InternalEnvironmentName.Local -> {
|
||||
val sdkPath = System.getProperty("jdk.$name")
|
||||
if (sdkPath == null) return null
|
||||
|
||||
val sdkPath = System.getProperty("jdk.$name")
|
||||
if (sdkPath == null) return null
|
||||
|
||||
val sdkType = SdkType.findByName(type)
|
||||
if (sdkType != null && sdkType.isValidSdkHome(sdkPath)) {
|
||||
val createdSdk = delegate.createSdk(name, sdkType, sdkPath)
|
||||
sdkType.setupSdkPaths(createdSdk)
|
||||
cachedProjectJdks[uniqueName] = createdSdk
|
||||
return createdSdk
|
||||
val sdkType = SdkType.findByName(type)
|
||||
if (sdkType != null && sdkType.isValidSdkHome(sdkPath)) {
|
||||
val createdSdk = delegate.createSdk(name, sdkType, sdkPath)
|
||||
sdkType.setupSdkPaths(createdSdk)
|
||||
cachedProjectJdks[uniqueName] = createdSdk
|
||||
return createdSdk
|
||||
}
|
||||
return null
|
||||
}
|
||||
is InternalEnvironmentName.Custom -> null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getAllJdks(): Array<Sdk> = delegate.getAllSdks().toTypedArray()
|
||||
|
||||
@@ -51,12 +51,18 @@ private class SdkTableProjectViewProviderImpl(project: Project) : SdkTableProjec
|
||||
|
||||
private class ProjectJdkTableProjectView(val descriptor: EelDescriptor, val delegate: ProjectJdkTable) : ProjectJdkTable() {
|
||||
override fun findJdk(name: String): Sdk? {
|
||||
if (delegate is EnvironmentScopedProjectJdkLookup) {
|
||||
return delegate.findJdk(name, descriptor)
|
||||
}
|
||||
return delegate.allJdks.find {
|
||||
it.name == name && validateDescriptor(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun findJdk(name: String, type: String): Sdk? {
|
||||
if (delegate is EnvironmentScopedProjectJdkLookup) {
|
||||
return delegate.findJdk(name, type, descriptor)
|
||||
}
|
||||
// sometimes delegate.findJdk can do mutating operations, like in the case of ProjectJdkTableImpl
|
||||
return delegate.allJdks.find { it.name == name && it.sdkType.name == type && validateDescriptor(it) } ?: delegate.findJdk(name, type)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.intellij.platform.workspace.jps.entities.SdkEntity
|
||||
import com.intellij.platform.workspace.jps.entities.SdkRoot
|
||||
import com.intellij.platform.workspace.jps.entities.SdkRootTypeId
|
||||
import com.intellij.platform.workspace.jps.entities.modifySdkEntity
|
||||
import com.intellij.platform.workspace.storage.InternalEnvironmentName
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap
|
||||
import com.intellij.workspaceModel.ide.JpsGlobalModelSynchronizer
|
||||
import com.intellij.workspaceModel.ide.impl.GlobalWorkspaceModel
|
||||
@@ -48,6 +49,14 @@ class SdkTableBridgeImpl: SdkTableImplementationDelegate {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun findSdkByName(name: String, environmentName: InternalEnvironmentName): Sdk? {
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstanceByEnvironmentName(environmentName)
|
||||
val currentSnapshot = globalWorkspaceModel.currentSnapshot
|
||||
val sdkEntity = currentSnapshot.entities(SdkEntity::class.java)
|
||||
.firstOrNull { Comparing.strEqual(name, it.name) } ?: return null
|
||||
return currentSnapshot.sdkMap.getDataByEntity(sdkEntity)
|
||||
}
|
||||
|
||||
override fun getAllSdks(): List<Sdk> {
|
||||
val globalWorkspaceModels = GlobalWorkspaceModel.getInstancesBlocking()
|
||||
return globalWorkspaceModels.flatMap {
|
||||
|
||||
@@ -79,7 +79,7 @@ internal class GlobalWorkspaceModelCacheImpl(coroutineScope: CoroutineScope) : G
|
||||
|
||||
private suspend fun doCacheSaving() {
|
||||
cacheFiles.entries.forEachConcurrent { (id, cacheFile) ->
|
||||
val storage = GlobalWorkspaceModel.getInstanceByEnvironmentName(InternalEnvironmentName.of(id)).currentSnapshot
|
||||
val storage = GlobalWorkspaceModel.getInstanceByEnvironmentNameAsync(InternalEnvironmentName.of(id)).currentSnapshot
|
||||
if (!storage.isConsistent) {
|
||||
invalidateCaches()
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ open class JpsGlobalModelSynchronizerImpl(private val coroutineScope: CoroutineS
|
||||
|
||||
@VisibleForTesting
|
||||
protected open suspend fun delayLoadGlobalWorkspaceModel(environmentName: InternalEnvironmentName) {
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstanceByEnvironmentName(environmentName)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstanceByEnvironmentNameAsync(environmentName)
|
||||
if (loadedFromDisk[environmentName] == true || !globalWorkspaceModel.loadedFromCache) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.projectRoots.SdkTypeId
|
||||
import com.intellij.platform.workspace.storage.InternalEnvironmentName
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
@@ -19,6 +20,7 @@ interface SdkTableImplementationDelegate {
|
||||
fun getAllSdks(): List<Sdk>
|
||||
|
||||
fun findSdkByName(name: String): Sdk?
|
||||
fun findSdkByName(name: String, environmentName: InternalEnvironmentName): Sdk?
|
||||
|
||||
@TestOnly
|
||||
fun saveOnDisk()
|
||||
|
||||
@@ -362,7 +362,11 @@ class GlobalWorkspaceModel internal constructor(
|
||||
return ApplicationManager.getApplication().serviceAsync<GlobalWorkspaceModelRegistry>().getGlobalModel(eelMachine)
|
||||
}
|
||||
|
||||
suspend fun getInstanceByEnvironmentName(environmentName: InternalEnvironmentName): GlobalWorkspaceModel {
|
||||
fun getInstanceByEnvironmentName(environmentName: InternalEnvironmentName): GlobalWorkspaceModel {
|
||||
return ApplicationManager.getApplication().service<GlobalWorkspaceModelRegistry>().getGlobalModelByEnvironmentName(environmentName)
|
||||
}
|
||||
|
||||
suspend fun getInstanceByEnvironmentNameAsync(environmentName: InternalEnvironmentName): GlobalWorkspaceModel {
|
||||
return ApplicationManager.getApplication().serviceAsync<GlobalWorkspaceModelRegistry>().getGlobalModelByEnvironmentName(environmentName)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user