mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[eel] RUBY-34864 Keep WSL remote interpreters for local projects when per-environment separation is OFF
- Honor `ide.workspace.model.per.environment.model.separation` being OFF by attributing SDK entities to the local environment (`LocalEelDescriptor`) and by not filtering out SDK bridge events across environments. - `getEffectiveWorkspaceEelDescriptorOfHomePath(...)`: returns `LocalEelDescriptor` when the separation flag is disabled; falls back to local on invalid paths. - `SdkEntity.getAssociatedEffectiveWorkspaceEelDescriptor()`: mirrors the same OFF-mode behavior so SDKs aren’t partitioned away from RubyMine’s shared global model. - `GlobalSdkBridgesLoader`: initializes bridges and processes SDK changes even when entities originate from different environments if separation is OFF; only filters by environment when the flag is ON. (cherry picked from commit 7d2f82e4f3a64a8b6bbcad1d59037ccfbbe0449f) IJ-MR-182760 GitOrigin-RevId: 3cfc15a689e2a69d1c7815da62009e12369eee90
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3173ef4fdd
commit
5e937826db
+1
-1
@@ -71,7 +71,7 @@ private class ProjectJdkTableProjectView(val descriptor: EelDescriptor, val dele
|
||||
}
|
||||
|
||||
private fun validateDescriptor(sdk: Sdk): Boolean {
|
||||
val sdkDescriptor = sdk.homePath?.let { getEelDescriptorOfHomePath(it) }
|
||||
val sdkDescriptor = sdk.homePath?.let { getEffectiveWorkspaceEelDescriptorOfHomePath(it) }
|
||||
return if (sdkDescriptor == null) {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package com.intellij.openapi.projectRoots.impl
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.projectRoots.SdkTypeId
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
@@ -23,13 +24,46 @@ fun findClashingSdk(sdkName: String, sdk: Sdk): SdkEntity? {
|
||||
return relevantSnapshot.entities(SdkEntity::class.java).find { it.name == sdkName }
|
||||
}
|
||||
|
||||
fun getEelDescriptorOfHomePath(homePath: String): EelDescriptor =
|
||||
try {
|
||||
/**
|
||||
* Returns the [EelDescriptor] that the Workspace Model should use for SDK entities
|
||||
* associated with the given `homePath`.
|
||||
*
|
||||
* This helper abstracts the current "per-environment" separation of the global
|
||||
* workspace model by EEL descriptors:
|
||||
*
|
||||
* - If the registry key `ide.workspace.model.per.environment.model.separation` is ON,
|
||||
* the descriptor is inferred from `homePath` via `Path.getEelDescriptor()` and thus
|
||||
* points to the machine that actually owns the path (e.g., local OS, a specific WSL
|
||||
* distribution, a remote/container environment).
|
||||
* - If the registry key is OFF, the local machine descriptor ([LocalEelDescriptor]) is
|
||||
* always returned so that SDKs from different environments are kept together in a
|
||||
* single, shared model. This escape hatch is required by IDEs that expect certain
|
||||
* remote interpreters (e.g., WSL) to be visible from both local and remote projects,
|
||||
* where strict separation would otherwise break discovery or reuse.
|
||||
* - If `homePath` cannot be parsed into a valid [Path], the method falls back to
|
||||
* [LocalEelDescriptor].
|
||||
*
|
||||
* The returned descriptor determines which instance of [GlobalWorkspaceModel] will hold
|
||||
* the corresponding [SdkEntity] records, preventing cross-environment linkage issues
|
||||
* when separation is enabled, while preserving legacy behavior when it is disabled.
|
||||
*
|
||||
* @param homePath a string path used solely to infer the owning environment; it does not
|
||||
* need to exist locally and is not validated beyond basic path parsing
|
||||
* @return the effective environment ([EelDescriptor]) to use for workspace model operations
|
||||
* @see com.intellij.workspaceModel.ide.impl.GlobalWorkspaceModel
|
||||
* @see com.intellij.platform.eel.provider.getEelDescriptor
|
||||
*/
|
||||
fun getEffectiveWorkspaceEelDescriptorOfHomePath(homePath: String): EelDescriptor {
|
||||
if (!Registry.`is`("ide.workspace.model.per.environment.model.separation")) {
|
||||
return LocalEelDescriptor
|
||||
}
|
||||
return try {
|
||||
Path.of(homePath).getEelDescriptor()
|
||||
}
|
||||
catch (_: InvalidPathException) {
|
||||
LocalEelDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SDK in the [GlobalWorkspaceModel] that matches the eek environment inferred
|
||||
@@ -61,7 +95,7 @@ fun ProjectJdkTable.createSdkForEnvironment(
|
||||
homePathForEnvironmentDetection: String,
|
||||
): Sdk =
|
||||
if (this is EnvironmentScopedSdkTableOps) {
|
||||
val eelDescriptor = getEelDescriptorOfHomePath(homePathForEnvironmentDetection)
|
||||
val eelDescriptor = getEffectiveWorkspaceEelDescriptorOfHomePath(homePathForEnvironmentDetection)
|
||||
createSdk(name, sdkType, eelDescriptor)
|
||||
}
|
||||
else {
|
||||
|
||||
+31
-5
@@ -26,13 +26,39 @@ import com.intellij.workspaceModel.ide.toPath
|
||||
import java.nio.file.InvalidPathException
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
private fun SdkEntity.getAssociatedEelDescriptor(): EelDescriptor =
|
||||
try {
|
||||
/**
|
||||
* Resolves the effective [EelDescriptor] (environment) that the Global Workspace Model
|
||||
* should associate with this [SdkEntity].
|
||||
*
|
||||
* Behavior depends on the per-environment model separation flag
|
||||
* (`ide.workspace.model.per.environment.model.separation`):
|
||||
*
|
||||
* - When separation is ON, the environment is inferred from `homePath`, so the SDK is attributed
|
||||
* to the machine that actually owns the path (e.g., local OS, a particular WSL distribution,
|
||||
* or a remote/container environment).
|
||||
* - When separation is OFF, [LocalEelDescriptor] is always returned so SDKs from different
|
||||
* environments are kept together in a single, shared global model (compatibility mode for IDEs
|
||||
* that expect cross-environment SDK visibility).
|
||||
* - If `homePath` is `null`, cannot be converted to a path, or throws [InvalidPathException],
|
||||
* the method falls back to [LocalEelDescriptor].
|
||||
*
|
||||
* The resolved descriptor is used to:
|
||||
* - decide which [com.intellij.workspaceModel.ide.impl.GlobalWorkspaceModel] instance
|
||||
* (per environment) should store the SDK entity;
|
||||
* - filter which per-environment bridges should create/load SDK bridges, preventing unrelated
|
||||
* environments from processing changes.
|
||||
*/
|
||||
private fun SdkEntity.getAssociatedEffectiveWorkspaceEelDescriptor(): EelDescriptor {
|
||||
if (!Registry.`is`("ide.workspace.model.per.environment.model.separation")) {
|
||||
return LocalEelDescriptor
|
||||
}
|
||||
return try {
|
||||
homePath?.toPath()?.getEelDescriptor() ?: LocalEelDescriptor
|
||||
}
|
||||
catch (_: InvalidPathException) {
|
||||
LocalEelDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
private class GlobalSdkBridgeInitializer : BridgeInitializer {
|
||||
override fun isEnabled(): Boolean = true
|
||||
@@ -45,7 +71,7 @@ private class GlobalSdkBridgeInitializer : BridgeInitializer {
|
||||
val environmentName = projectEelDescriptor.machine.getInternalEnvironmentName()
|
||||
|
||||
for (addChange in addChanges) {
|
||||
if (addChange.newEntity.getAssociatedEelDescriptor() != projectEelDescriptor) continue
|
||||
if (addChange.newEntity.getAssociatedEffectiveWorkspaceEelDescriptor() != projectEelDescriptor) continue
|
||||
// Will initialize the bridge if missing
|
||||
builder.mutableSdkMap.getOrPutDataByEntity(addChange.newEntity) {
|
||||
val sdkEntityCopy = SdkBridgeImpl.createEmptySdkEntity("", "", environmentName = environmentName)
|
||||
@@ -63,7 +89,7 @@ private class GlobalSdkBridgesLoader(private val eelMachine: EelMachine) : Globa
|
||||
val sdks = mutableStorage
|
||||
.entities(SdkEntity::class.java)
|
||||
.filter { mutableStorage.sdkMap.getDataByEntity(it) == null }
|
||||
.filter { it.getAssociatedEelDescriptor().machine == eelMachine }
|
||||
.filter { it.getAssociatedEffectiveWorkspaceEelDescriptor().machine == eelMachine }
|
||||
.map { sdkEntity ->
|
||||
val sdkEntityBuilder = sdkEntity.createEntityTreeCopy(false) as SdkEntityBuilder
|
||||
sdkEntity to ProjectJdkImpl(SdkBridgeImpl(sdkEntityBuilder, environmentName))
|
||||
@@ -85,7 +111,7 @@ private class GlobalSdkBridgesLoader(private val eelMachine: EelMachine) : Globa
|
||||
val environmentName = eelMachine.getInternalEnvironmentName()
|
||||
|
||||
for (addChange in addChanges) {
|
||||
if (addChange.newEntity.getAssociatedEelDescriptor().machine != eelMachine) continue
|
||||
if (addChange.newEntity.getAssociatedEffectiveWorkspaceEelDescriptor().machine != eelMachine) continue
|
||||
// Will initialize the bridge if missing
|
||||
builder.mutableSdkMap.getOrPutDataByEntity(addChange.newEntity) {
|
||||
val sdkEntityCopy = SdkBridgeImpl.createEmptySdkEntity("", "", environmentName = environmentName)
|
||||
|
||||
Reference in New Issue
Block a user