mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
[eel][wsl] IJPL-196973 Compile error open target not source in wsl
- Split EelDescriptor in to EelDescriptor and the EelMachine - Add EelPathBoundDescriptor GitOrigin-RevId: e0b7e5d5f3532682498466642b034e1892ef3cda
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cc05795d91
commit
2fa1af099c
@@ -33,7 +33,7 @@ import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.platform.eel.EelDescriptor;
|
||||
import com.intellij.platform.eel.EelMachine;
|
||||
import com.intellij.platform.eel.provider.EelProviderUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SystemProperties;
|
||||
@@ -676,7 +676,7 @@ public final class JarRepositoryManager {
|
||||
final List<OrderRoot> result = new ArrayList<>();
|
||||
final VirtualFileManager manager = VirtualFileManager.getInstance();
|
||||
String repositoryPath = getJPSLocalMavenRepositoryForIdeaProject(project).toString();
|
||||
EelDescriptor targetRepositoryDescriptor = EelProviderUtil.getEelDescriptor(Path.of(repositoryPath));
|
||||
final EelMachine targetRepositoryMachine = EelProviderUtil.getEelDescriptor(Path.of(repositoryPath)).getMachine();
|
||||
for (Artifact each : artifacts) {
|
||||
long ms = System.currentTimeMillis();
|
||||
try {
|
||||
@@ -688,7 +688,7 @@ public final class JarRepositoryManager {
|
||||
FileUtil.copy(repoFile, toFile);
|
||||
}
|
||||
}
|
||||
else if (!targetRepositoryDescriptor.equals(EelProviderUtil.getEelDescriptor(Path.of(each.getFile().getPath())))) {
|
||||
else if (!targetRepositoryMachine.equals(EelProviderUtil.getEelDescriptor(Path.of(each.getFile().getPath())).getMachine())) {
|
||||
// if .m2 is located remotely, then we need to copy the files to the remote location
|
||||
String suffix = repoFile.getAbsolutePath().substring(repositoryPath.length());
|
||||
String actualPath = repositoryPath + suffix;
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.diagnostic.trace
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelPathBoundDescriptor
|
||||
import com.intellij.platform.eel.annotations.MultiRoutingFileSystemPath
|
||||
import com.intellij.platform.eel.isPosix
|
||||
import com.intellij.platform.eel.path.EelPath
|
||||
@@ -27,110 +28,45 @@ import java.nio.file.Path
|
||||
*
|
||||
* @throws IllegalArgumentException if the Eel API for [this] does not have a corresponding [java.nio.file.FileSystem]
|
||||
*/
|
||||
@Throws(IllegalArgumentException::class)
|
||||
@ApiStatus.Internal
|
||||
fun EelPath.asNioPath(): @MultiRoutingFileSystemPath Path =
|
||||
asNioPath(null)
|
||||
|
||||
/**
|
||||
* Converts [EelPath], which is likely a path from a remote machine, to a [Path] for the local machine.
|
||||
*
|
||||
* The [project] is important for targets like WSL: paths like `\\wsl.localhost\Ubuntu` and `\\wsl$\Ubuntu` are equivalent,
|
||||
* but they have different string representation, and some functionality is confused when `wsl.localhost` and `wsl$` are confused.
|
||||
* This function helps to choose the proper root according to the base path of the project.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* val eelPath = EelPath.parse("/home/user", getWslDescriptorSomewhere())
|
||||
*
|
||||
* eelPath.asNioPath(getProject1()) ==
|
||||
* Path.of("""\\wsl.localhost\Ubuntu\home\user""")
|
||||
*
|
||||
* eelPath.asNioPath(getProject2()) ==
|
||||
* Path.of("""\\wsl$\Ubuntu\home\user""")
|
||||
* ```
|
||||
*/
|
||||
@Throws(IllegalArgumentException::class)
|
||||
@ApiStatus.Internal
|
||||
fun EelPath.asNioPath(project: Project?): @MultiRoutingFileSystemPath Path {
|
||||
return asNioPathOrNull(project)
|
||||
fun EelPath.asNioPath(): @MultiRoutingFileSystemPath Path {
|
||||
return asNioPathOrNull()
|
||||
?: throw IllegalArgumentException("Could not convert $this to NIO path, descriptor is $descriptor")
|
||||
}
|
||||
|
||||
private val EelDescriptor.rootsInternal: List<Path>?
|
||||
get() = EelProvider.EP_NAME.extensionList
|
||||
.firstNotNullOfOrNull { eelProvider -> eelProvider.getCustomRoots(this) }
|
||||
?.takeIf { it.isNotEmpty() }
|
||||
?.map(Path::of)
|
||||
|
||||
@get:ApiStatus.Internal
|
||||
val EelDescriptor.roots: List<Path> get() = rootsInternal ?: error("No roots for $this")
|
||||
@Throws(IllegalArgumentException::class)
|
||||
@ApiStatus.Internal
|
||||
@Deprecated("Use asNioPath() instead", replaceWith = ReplaceWith("asNioPath()"))
|
||||
fun EelPath.asNioPath(project: Project?): @MultiRoutingFileSystemPath Path {
|
||||
return asNioPath()
|
||||
}
|
||||
|
||||
/** See docs for [asNioPath] */
|
||||
@Deprecated("It never returns null anymore")
|
||||
@ApiStatus.Internal
|
||||
fun EelPath.asNioPathOrNull(): @MultiRoutingFileSystemPath Path? =
|
||||
asNioPathOrNull(null)
|
||||
|
||||
/** See docs for [asNioPath] */
|
||||
@Deprecated("It never returns null anymore")
|
||||
@ApiStatus.Internal
|
||||
fun EelPath.asNioPathOrNull(project: Project?): @MultiRoutingFileSystemPath Path? {
|
||||
fun EelPath.asNioPathOrNull(): @MultiRoutingFileSystemPath Path? {
|
||||
if (descriptor === LocalEelDescriptor) {
|
||||
return Path.of(toString())
|
||||
}
|
||||
val eelRoots = descriptor.rootsInternal
|
||||
|
||||
// Comparing strings because `Path.of("\\wsl.localhost\distro\").equals(Path.of("\\wsl$\distro\")) == true`
|
||||
// If the project works with `wsl$` paths, this function must return `wsl$` paths, and the same for `wsl.localhost`.
|
||||
val projectBasePathNio = project?.basePath?.let(Path::of)
|
||||
val root = (descriptor as? EelPathBoundDescriptor)?.rootPath ?: return null
|
||||
|
||||
LOG.trace {
|
||||
"asNioPathOrNull():" +
|
||||
" path=$this" +
|
||||
" project=$project" +
|
||||
" descriptor=$descriptor" +
|
||||
" eelRoots=${eelRoots?.joinToString(prefix = "[", postfix = "]", separator = ", ") { path -> "$path (${path.javaClass.name})" }}" +
|
||||
" projectBasePathNio=$projectBasePathNio"
|
||||
" rootPath=$root"
|
||||
}
|
||||
|
||||
if (eelRoots == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val eelRoot: Path = asNioPathOrNullImpl(projectBasePathNio, eelRoots, this)
|
||||
|
||||
@MultiRoutingFileSystemPath
|
||||
val result = parts.fold(eelRoot, Path::resolve)
|
||||
val result = parts.fold(root, Path::resolve)
|
||||
LOG.trace {
|
||||
"asNioPathOrNull(): path=$this project=$project result=$result"
|
||||
"asNioPathOrNull(): path=$this basePath=$root result=$result"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Choosing between not only paths belonging to the project, but also paths with the same root, e.g., mount drive on Windows.
|
||||
* It's possible that some code in the project tries to access the file outside the project, f.i., accessing `~/.m2`.
|
||||
*
|
||||
* This function also tries to preserve the case in case-insensitive file systems, because some other parts of the IDE
|
||||
* may compare paths as plain string despite the incorrectness of that approach.
|
||||
*/
|
||||
private fun asNioPathOrNullImpl(basePath: Path?, eelRoots: Collection<Path>, sourcePath: EelPath): Path {
|
||||
if (basePath != null) {
|
||||
for (eelRoot in eelRoots) {
|
||||
if (basePath.startsWith(eelRoot)) {
|
||||
var resultPath = basePath.root
|
||||
if (eelRoot.nameCount > 0) {
|
||||
resultPath = resultPath.resolve(basePath.subpath(0, eelRoot.nameCount))
|
||||
}
|
||||
return resultPath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eelRoots.first()
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a path generated by the default NIO filesystem to [EelPath].
|
||||
*
|
||||
@@ -154,18 +90,10 @@ fun Path.asEelPath(): EelPath {
|
||||
if (fileSystem != FileSystems.getDefault()) {
|
||||
throw IllegalArgumentException("Could not convert $this to EelPath: the path does not belong to the default NIO FileSystem")
|
||||
}
|
||||
val (descriptor, eelProvider) =
|
||||
EelProvider.EP_NAME.extensionList
|
||||
.firstNotNullOfOrNull { eelProvider ->
|
||||
eelProvider.getEelDescriptor(this)?.to(eelProvider)
|
||||
}
|
||||
?: return EelPath.parse(toString(), LocalEelDescriptor)
|
||||
val descriptor = EelProvider.EP_NAME.extensionList.firstNotNullOfOrNull { eelProvider -> eelProvider.getEelDescriptor(this) }
|
||||
?: return EelPath.parse(toString(), LocalEelDescriptor)
|
||||
|
||||
val root =
|
||||
eelProvider.getCustomRoots(descriptor)
|
||||
?.map { rootStr -> Path.of(rootStr) }
|
||||
?.firstOrNull { rootCandidate -> startsWith(rootCandidate) }
|
||||
?: throw NoSuchElementException("No roots for $descriptor match $this: ${eelProvider.getCustomRoots(descriptor)}")
|
||||
val root = (descriptor as? EelPathBoundDescriptor)?.rootPath ?: throw NoSuchElementException("Cannot find a root for $this")
|
||||
|
||||
val relative = root.relativize(this)
|
||||
if (descriptor.osFamily.isPosix) {
|
||||
|
||||
@@ -90,31 +90,35 @@ val localEel: LocalEelApi by lazy {
|
||||
@ApiStatus.Internal
|
||||
fun EelDescriptor.upgradeBlocking(): EelApi = toEelApiBlocking()
|
||||
|
||||
fun EelMachine.toEelApiBlocking(): EelApi = runBlockingMaybeCancellable { toEelApi() }
|
||||
|
||||
@ApiStatus.Experimental
|
||||
fun EelDescriptor.toEelApiBlocking(): EelApi {
|
||||
if (this === LocalEelDescriptor) return localEel
|
||||
return runBlockingMaybeCancellable { toEelApi() }
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
data object LocalEelDescriptor : EelDescriptor {
|
||||
data object LocalEelMachine : EelMachine {
|
||||
private val LOG = logger<LocalEelDescriptor>()
|
||||
override val userReadableDescription: @NonNls String = "Local: ${System.getProperty("os.name")}"
|
||||
override val name: @NonNls String = "Local: ${System.getProperty("os.name")}"
|
||||
|
||||
override val osFamily: EelOsFamily by lazy {
|
||||
when {
|
||||
SystemInfo.isWindows -> EelOsFamily.Windows
|
||||
SystemInfo.isMac || SystemInfo.isLinux || SystemInfo.isFreeBSD -> EelOsFamily.Posix
|
||||
else -> {
|
||||
LOG.info("Eel is not supported on current platform")
|
||||
LocalEelMachine.LOG.info("Eel is not supported on current platform")
|
||||
EelOsFamily.Posix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun toEelApi(): EelApi {
|
||||
return localEel
|
||||
}
|
||||
override suspend fun toEelApi(): EelApi = localEel
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
data object LocalEelDescriptor : EelDescriptor {
|
||||
override val machine: EelMachine = LocalEelMachine
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@@ -146,10 +150,10 @@ interface EelProvider {
|
||||
|
||||
// TODO Better name.
|
||||
// TODO Move it into the EelDescriptor?
|
||||
fun getInternalName(eelDescriptor: EelDescriptor): String?
|
||||
fun getInternalName(eelMachine: EelMachine): String?
|
||||
|
||||
// TODO Better name.
|
||||
fun getEelDescriptorByInternalName(internalName: String): EelDescriptor?
|
||||
fun getEelMachineByInternalName(internalName: String): EelMachine?
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.intellij.platform.eel
|
||||
import com.intellij.platform.eel.path.EelPath.OS
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* A marker interface that indicates an environment where native file chooser dialogs should be disabled.
|
||||
@@ -21,33 +22,92 @@ import org.jetbrains.annotations.NonNls
|
||||
interface EelDescriptorWithoutNativeFileChooserSupport : EelDescriptor
|
||||
|
||||
/**
|
||||
* A descriptor of an environment where [EelApi] may exist.
|
||||
* Identifies a specific machine — such as a Docker container, WSL distribution, or SSH host.
|
||||
*
|
||||
* Multiple [EelDescriptor]s may map to the same machine.
|
||||
* This interface is useful when caching, deduplicating, or sharing resources across descriptor instances.
|
||||
*
|
||||
* ## Examples
|
||||
* 1. There is a singleton [LocalEelDescriptor] which always exists, and it denotes the environment where the IDE runs
|
||||
* 2. On Windows, there can be [EelDescriptor] that corresponds to a WSL distribution.
|
||||
* Each distribution gives rise to a unique [EelDescriptor]
|
||||
* 3. Each separate Docker container has its own [EelDescriptor]
|
||||
* 4. Each SSH host has its own [EelDescriptor]
|
||||
* - For WSL: all descriptors with base paths like `\\wsl$\Ubuntu` and `\\wsl.localhost\Ubuntu` point to the same [EelMachine].
|
||||
* - For Docker: descriptors with `/docker-<id>/...` paths share the same container machine.
|
||||
*
|
||||
* ## Purpose
|
||||
* [EelDescriptor] is a marker of an environment, that is
|
||||
* - **Lightweight**: it is opposed to [EelApi], which is a heavy object that takes considerable amount of resources to initialize.
|
||||
* While it is not free to obtain [EelDescriptor] (i.e., you may need to interact with WSL services and Docker daemon), it is much cheaper than
|
||||
* preparing an environment for deep interaction (i.e., running a WSL Distribution or a Docker container).
|
||||
* - **Durable**: There is no guarantee that an instance of [EelApi] would be alive for a long time.
|
||||
* For example, an SSH connection can be interrupted, and a Docker container can be restarted. These events do not affect the lifetime of [EelDescriptor].
|
||||
* Use this when caching or pooling long-lived data that’s stable across paths.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
interface EelMachine {
|
||||
/**
|
||||
* The platform of an environment corresponding to this [EelMachine].
|
||||
*/
|
||||
@get:ApiStatus.Experimental
|
||||
val osFamily: EelOsFamily
|
||||
|
||||
/**
|
||||
* Describes machine in a user-readable manner, i.e: "Docker: <container_name>" or "Wsl: <distro name>".
|
||||
* Format is *not* specified but guaranteed to be user-readable.
|
||||
*/
|
||||
@get:ApiStatus.Experimental
|
||||
val name: @NonNls String
|
||||
|
||||
/**
|
||||
* Converts this machine into a [EelApi] — starts or reuses a running environment.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
suspend fun toEelApi(): EelApi
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization of [EelDescriptor] that resolves to a path-based environment.
|
||||
*
|
||||
* These descriptors are tied to a concrete filesystem root (e.g. `\\wsl$\Ubuntu` or `/docker-xyz`).
|
||||
* Different paths to the same logical environment yield different descriptors — even if they point to the same [EelMachine].
|
||||
*
|
||||
* This allows tools to distinguish between environments even if the underlying host is the same.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
interface EelPathBoundDescriptor : EelDescriptor {
|
||||
/**
|
||||
* A platform-specific base path representing the environment's root.
|
||||
*
|
||||
* Examples:
|
||||
* - `\\wsl$\Ubuntu` for a WSL distribution
|
||||
* - `/docker-12345/` for Docker containers
|
||||
*/
|
||||
val rootPath: Path
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an abstract description of an environment where [EelApi] may exist.
|
||||
*
|
||||
* ## Concepts
|
||||
* - [EelDescriptor] describes a *specific path-based access* to an environment.
|
||||
* - [EelMachine] describes the *physical or logical host* (e.g., WSL distribution, Docker container).
|
||||
*
|
||||
* For example, two descriptors like `\\wsl$\Ubuntu` and `\\wsl.localhost\Ubuntu` may point to the same [EelMachine],
|
||||
* but they should be treated as distinct [EelDescriptor]s since tooling behavior or caching may differ per path.
|
||||
*
|
||||
* ## Use cases
|
||||
* - If you're caching data that is *machine-wide*, prefer using [machine] as a cache key instead of [EelDescriptor].
|
||||
* - If you're accessing a specific path (e.g., resolving symbolic links or permissions), use [EelDescriptor].
|
||||
*
|
||||
* ## Examples
|
||||
* - [LocalEelDescriptor] refers to the machine where the IDE runs (same machine and descriptor).
|
||||
* - WSL: Each distribution is a machine. Paths like `\\wsl$\Ubuntu` and `\\wsl.localhost\Ubuntu` are different descriptors pointing to the same machine.
|
||||
* - Docker: Each container is a machine. Paths like `/docker-abc123/...` are descriptors.
|
||||
* - SSH: Each remote host is a machine. A descriptor may correspond to a specific session or path.
|
||||
*
|
||||
* ## Lifecycle
|
||||
* [EelDescriptor] is:
|
||||
* - **Lightweight**: Unlike [EelApi], it does not represent a running environment.
|
||||
* - **Durable**: It can persist even when [EelApi] becomes unavailable (e.g., Docker stopped).
|
||||
*
|
||||
* ## Access
|
||||
* Use `getEelDescriptor()` to resolve a descriptor from a [Path] or [Project].
|
||||
*
|
||||
* ## Usage
|
||||
* The intended way to obtain [EelDescriptor] is with the use of `getEelDescriptor`:
|
||||
* ```kotlin
|
||||
* Path.of("\\\\wsl.localhost\\Ubuntu\\home\\Jacob\\projects").getEelDescriptor()
|
||||
* project.getEelDescriptor()
|
||||
* val descriptor = Path.of("\\\\wsl.localhost\\Ubuntu\\home\\me").getEelDescriptor()
|
||||
* val machine = descriptor.machine // Shared between paths pointing to the same distro/container
|
||||
* val api = descriptor.toEelApi() // Starts or connects to the actual environment
|
||||
* ```
|
||||
*
|
||||
* You are free to compare and store [EelDescriptor].
|
||||
* TODO: In the future, [EelDescriptor] may also be serializable.
|
||||
* If you need to access the remote environment, you can use the method [toEelApi], which can suspend for some time before returning a working instance of [EelApi]
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
interface EelDescriptor {
|
||||
@@ -60,20 +120,24 @@ interface EelDescriptor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes Eel in a user-readable manner, i.e: "Docker: <container_name>" or "Wsl: <distro name>".
|
||||
* Format is *not* specified, but guaranteed to be user-readable.
|
||||
* Returns the machine this descriptor belongs to.
|
||||
*
|
||||
* Multiple descriptors may resolve to the same [EelMachine], e.g.:
|
||||
* - Docker paths with different mount points
|
||||
* - WSL descriptors using `wsl$` vs `wsl.localhost`
|
||||
*/
|
||||
@get:ApiStatus.Internal
|
||||
val userReadableDescription: @NonNls String
|
||||
val machine: EelMachine
|
||||
|
||||
/**
|
||||
* The platform of an environment corresponding to this [EelDescriptor].
|
||||
*/
|
||||
@get:ApiStatus.Experimental
|
||||
val osFamily: EelOsFamily
|
||||
val osFamily: EelOsFamily get() = machine.osFamily
|
||||
|
||||
@ApiStatus.Experimental
|
||||
suspend fun toEelApi(): EelApi
|
||||
suspend fun toEelApi(): EelApi {
|
||||
return machine.toEelApi()
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an instance of [EelApi] corresponding to this [EelDescriptor].
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.platform.eel.path
|
||||
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.EelOsFamily
|
||||
import io.kotest.matchers.shouldBe
|
||||
import org.junit.jupiter.api.Assertions
|
||||
@@ -70,10 +71,12 @@ class EelAbsolutePathTest {
|
||||
}
|
||||
|
||||
class DummyEelDescriptor(override val osFamily: EelOsFamily) : EelDescriptor {
|
||||
override val userReadableDescription: String = "mock"
|
||||
|
||||
override suspend fun toEelApi(): EelApi {
|
||||
return Assertions.fail<Nothing>()
|
||||
override val machine: EelMachine = object : EelMachine {
|
||||
override val name: String = "mock"
|
||||
override val osFamily: EelOsFamily = this@DummyEelDescriptor.osFamily
|
||||
override suspend fun toEelApi(): EelApi {
|
||||
return Assertions.fail<Nothing>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,8 @@ import com.intellij.execution.target.local.LocalTargetEnvironmentRequest;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.JarUtil;
|
||||
import com.intellij.platform.eel.EelDescriptor;
|
||||
import com.intellij.platform.eel.EelOsFamily;
|
||||
import com.intellij.platform.eel.provider.EelProviderUtil;
|
||||
import com.intellij.util.lang.JavaVersion;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -137,7 +134,7 @@ public final class JdkUtil {
|
||||
* @return if the JDK can be run on this machine.
|
||||
*/
|
||||
public static boolean isCompatible(@NotNull Path jdkHomePath, @NotNull Project project) {
|
||||
return EelProviderUtil.getEelDescriptor(jdkHomePath).equals(EelProviderUtil.getEelDescriptor(project));
|
||||
return EelProviderUtil.getEelDescriptor(jdkHomePath).getMachine().equals(EelProviderUtil.getEelDescriptor(project).getMachine());
|
||||
}
|
||||
|
||||
public static boolean checkForJre(@NotNull String homePath) {
|
||||
|
||||
@@ -6,6 +6,7 @@ package com.intellij.openapi.projectRoots.impl
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.workspace.jps.entities.SdkEntity
|
||||
import com.intellij.workspaceModel.ide.impl.GlobalWorkspaceModel
|
||||
@@ -13,7 +14,7 @@ import org.jetbrains.annotations.ApiStatus
|
||||
import java.nio.file.Path
|
||||
|
||||
fun findClashingSdk(sdkName: String, sdk: Sdk): SdkEntity? {
|
||||
val descriptor = sdk.homePath?.let { Path.of(it) }?.getEelDescriptor() ?: LocalEelDescriptor
|
||||
val relevantSnapshot = GlobalWorkspaceModel.getInstance(descriptor).currentSnapshot
|
||||
val machine = sdk.homePath?.let { Path.of(it) }?.getEelDescriptor()?.machine ?: LocalEelMachine
|
||||
val relevantSnapshot = GlobalWorkspaceModel.getInstance(machine).currentSnapshot
|
||||
return relevantSnapshot.entities(SdkEntity::class.java).find { it.name == sdkName }
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public class ProjectSdksModel implements SdkModel {
|
||||
if (sdkHomePath != null) {
|
||||
try {
|
||||
Path path = Path.of(sdkHomePath);
|
||||
if (getEelDescriptor(path).equals(eelDescriptor)) {
|
||||
if (getEelDescriptor(path).getMachine().equals(eelDescriptor.getMachine())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ private class ModuleBridgeLoaderService : InitProjectActivity {
|
||||
workspaceModel = workspaceModel,
|
||||
)
|
||||
}
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstanceAsync(project.getEelDescriptor())
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstanceAsync(project.getEelDescriptor().machine)
|
||||
backgroundWriteAction {
|
||||
globalWorkspaceModel.applyStateToProject(project)
|
||||
}
|
||||
@@ -108,7 +108,7 @@ private class ModuleBridgeLoaderService : InitProjectActivity {
|
||||
}
|
||||
|
||||
// Set the project synchronization job on the global synchronizer to prevent race conditions
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstanceAsync(project.getEelDescriptor())
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstanceAsync(project.getEelDescriptor().machine)
|
||||
JpsGlobalModelSynchronizer.getInstance().setProjectSynchronizationJob(projectSyncJob)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.platform.backend.workspace.BridgeInitializer
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.workspace.jps.entities.SdkEntity
|
||||
import com.intellij.platform.workspace.storage.*
|
||||
@@ -40,7 +40,7 @@ private class GlobalSdkBridgeInitializer : BridgeInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
private class GlobalSdkBridgesLoader(private val descriptor: EelDescriptor) : GlobalSdkTableBridge {
|
||||
private class GlobalSdkBridgesLoader(private val eelMachine: EelMachine) : GlobalSdkTableBridge {
|
||||
override fun initializeBridgesAfterLoading(mutableStorage: MutableEntityStorage,
|
||||
initialEntityStorage: VersionedEntityStorage): () -> Unit {
|
||||
val sdks = mutableStorage
|
||||
@@ -132,18 +132,18 @@ private class GlobalSdkBridgesLoader(private val descriptor: EelDescriptor) : Gl
|
||||
if (!Registry.`is`("ide.workspace.model.per.environment.model.separation")) {
|
||||
return false
|
||||
}
|
||||
return entity.homePath?.toPath()?.getEelDescriptor() != descriptor
|
||||
return entity.homePath?.toPath()?.getEelDescriptor()?.machine != eelMachine
|
||||
}
|
||||
}
|
||||
|
||||
private val LOG = logger<GlobalSdkBridgesLoader>()
|
||||
|
||||
private class GlobalSdkTableBridgeRegistryImpl : GlobalSdkTableBridgeRegistry {
|
||||
private val registry = ConcurrentHashMap<EelDescriptor, GlobalSdkTableBridge>()
|
||||
private val registry = ConcurrentHashMap<EelMachine, GlobalSdkTableBridge>()
|
||||
|
||||
override fun getTableBridge(eelDescriptor: EelDescriptor): GlobalSdkTableBridge {
|
||||
return registry.computeIfAbsent(eelDescriptor) {
|
||||
GlobalSdkBridgesLoader(eelDescriptor)
|
||||
override fun getTableBridge(eelMachine: EelMachine): GlobalSdkTableBridge {
|
||||
return registry.computeIfAbsent(eelMachine) {
|
||||
GlobalSdkBridgesLoader(eelMachine)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ class SdkTableBridgeImpl: SdkTableImplementationDelegate {
|
||||
override fun addNewSdk(sdk: Sdk) {
|
||||
val delegateSdk = (sdk as ProjectJdkImpl).delegate as SdkBridgeImpl
|
||||
val descriptor = delegateSdk.homeDirectory?.toNioPath()?.getEelDescriptor() ?: LocalEelDescriptor
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(descriptor)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(descriptor.machine)
|
||||
val existingSdkEntity = globalWorkspaceModel.currentSnapshot.sdkMap.getFirstEntity(sdk)
|
||||
|
||||
if (existingSdkEntity != null) {
|
||||
@@ -93,7 +93,7 @@ class SdkTableBridgeImpl: SdkTableImplementationDelegate {
|
||||
|
||||
override fun removeSdk(sdk: Sdk) {
|
||||
val descriptor = sdk.homeDirectory?.toNioPath()?.getEelDescriptor() ?: LocalEelDescriptor
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(descriptor)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(descriptor.machine)
|
||||
|
||||
// It's absolutely OK if we try to remove what does not yet exist in `ProjectJdkTable` SDK
|
||||
// E.g. org.jetbrains.idea.maven.actions.AddMavenDependencyQuickFixTest
|
||||
@@ -107,7 +107,7 @@ class SdkTableBridgeImpl: SdkTableImplementationDelegate {
|
||||
modifiedSdk as ProjectJdkImpl
|
||||
originalSdk as ProjectJdkImpl
|
||||
val descriptor = modifiedSdk.homeDirectory?.toNioPath()?.getEelDescriptor() ?: LocalEelDescriptor
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(descriptor)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(descriptor.machine)
|
||||
val sdkEntity = (globalWorkspaceModel.currentSnapshot.entities(SdkEntity::class.java)
|
||||
.firstOrNull { it.name == originalSdk.name && it.type == originalSdk.sdkType.name }
|
||||
?: error("SDK entity for bridge `${originalSdk.name}` `${originalSdk.sdkType.name}` doesn't exist"))
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.intellij.platform.ide.impl.wsl
|
||||
import com.intellij.execution.eel.MultiRoutingFileSystemUtils
|
||||
import com.intellij.execution.ijent.nio.IjentEphemeralRootAwareFileSystemProvider
|
||||
import com.intellij.execution.wsl.*
|
||||
import com.intellij.execution.wsl.WSLDistribution
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
@@ -12,7 +13,9 @@ import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.platform.core.nio.fs.MultiRoutingFileSystemProvider
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.EelOsFamily
|
||||
import com.intellij.platform.eel.EelPathBoundDescriptor
|
||||
import com.intellij.platform.eel.annotations.MultiRoutingFileSystemPath
|
||||
import com.intellij.platform.eel.impl.fs.EelEarlyAccessChecker
|
||||
import com.intellij.platform.eel.provider.EelProvider
|
||||
@@ -60,34 +63,7 @@ class EelWslMrfsBackend(private val coroutineScope: CoroutineScope) : MultiRouti
|
||||
private val reportedNonExistentWslIds = AtomicReference<List<String>>(listOf())
|
||||
|
||||
override fun compute(localFS: FileSystem, sanitizedPath: String): FileSystem? {
|
||||
@MultiRoutingFileSystemPath
|
||||
val wslRoot: String
|
||||
val distributionId: String
|
||||
|
||||
run {
|
||||
// https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths
|
||||
// Although it's not clearly documented that a root of a UNC share must have a backslash at the end,
|
||||
// it can be deducted by the nature of the root >directory<. Also, the examples from the docs allude to that.
|
||||
// `WslPath.parseWindowsUncPath` and other platform functions parse according to the documentation,
|
||||
// but `sanitizedPath` never has a backslash at the end.
|
||||
|
||||
val serverNameEndIdx = when {
|
||||
sanitizedPath.startsWith("//wsl.localhost/", ignoreCase = true) -> 16
|
||||
sanitizedPath.startsWith("//wsl$/", ignoreCase = true) -> 7
|
||||
else -> return null
|
||||
}
|
||||
|
||||
val shareNameEndIdx = sanitizedPath.indexOf('/', startIndex = serverNameEndIdx)
|
||||
|
||||
if (shareNameEndIdx == -1) {
|
||||
wslRoot = sanitizedPath + "\\"
|
||||
distributionId = sanitizedPath.substring(serverNameEndIdx)
|
||||
}
|
||||
else {
|
||||
wslRoot = sanitizedPath.take(shareNameEndIdx + 1)
|
||||
distributionId = sanitizedPath.substring(serverNameEndIdx, shareNameEndIdx)
|
||||
}
|
||||
}
|
||||
val (wslRoot, distributionId) = WslEelProvider.parsePath(sanitizedPath) ?: return null
|
||||
|
||||
try {
|
||||
if (!WslIjentAvailabilityService.getInstance().useIjentForWslNioFileSystem()) {
|
||||
@@ -107,17 +83,12 @@ class EelWslMrfsBackend(private val coroutineScope: CoroutineScope) : MultiRouti
|
||||
return providersCache.computeIfAbsent(key) {
|
||||
service<EelEarlyAccessChecker>().check(sanitizedPath)
|
||||
|
||||
val descriptor = WslEelDescriptor(WSLDistribution(distributionId))
|
||||
if (LOG.isDebugEnabled) {
|
||||
LOG.debug("Triggered initialization of IJent for $descriptor, the path is $sanitizedPath", Throwable())
|
||||
}
|
||||
|
||||
val ijentUri = URI("ijent", "wsl", "/$distributionId", null, null)
|
||||
|
||||
val ijentFsProvider = TracingFileSystemProvider(IjentNioFileSystemProvider.getInstance())
|
||||
|
||||
try {
|
||||
val ijentFs = IjentFailSafeFileSystemPosixApi(coroutineScope, descriptor)
|
||||
val ijentFs = IjentFailSafeFileSystemPosixApi(coroutineScope, WslEelDescriptor(WSLDistribution(distributionId), wslRoot))
|
||||
val fs = ijentFsProvider.newFileSystem(ijentUri, IjentNioFileSystemProvider.newFileSystemMap(ijentFs))
|
||||
|
||||
coroutineScope.coroutineContext.job.invokeOnCompletion {
|
||||
@@ -212,21 +183,22 @@ class WslEelProvider : EelProvider {
|
||||
|
||||
return WslEelDescriptor(
|
||||
WSLDistribution(wslPath.distributionId),
|
||||
root.toString()
|
||||
)
|
||||
}
|
||||
|
||||
override fun getInternalName(eelDescriptor: EelDescriptor): String? =
|
||||
if (eelDescriptor is WslEelDescriptor)
|
||||
"WSL-" + eelDescriptor.distribution.id
|
||||
override fun getInternalName(eelMachine: EelMachine): String? =
|
||||
if (eelMachine is WslEelMachine)
|
||||
"WSL-" + eelMachine.distribution.id
|
||||
else
|
||||
null
|
||||
|
||||
override fun getCustomRoots(eelDescriptor: EelDescriptor): Collection<@MultiRoutingFileSystemPath String>? =
|
||||
(eelDescriptor as? WslEelDescriptor)?.distribution?.roots
|
||||
|
||||
override fun getEelDescriptorByInternalName(internalName: String): EelDescriptor? =
|
||||
override fun getEelMachineByInternalName(internalName: String): EelMachine? =
|
||||
if (internalName.startsWith("WSL-"))
|
||||
WslEelDescriptor(WSLDistribution(internalName.substring(4)))
|
||||
WslEelMachine(WSLDistribution(internalName.substring(4)))
|
||||
else
|
||||
null
|
||||
|
||||
@@ -262,22 +234,82 @@ class WslEelProvider : EelProvider {
|
||||
|
||||
(getDefault().provider() as MultiRoutingFileSystemProvider).theOnlyFileSystem.getBackend(wslPath.wslRoot + "\\")
|
||||
}
|
||||
|
||||
companion object {
|
||||
// wsl root -> distribution id
|
||||
internal fun parsePath(sanitizedPath: String): Pair<String, String>? {
|
||||
@MultiRoutingFileSystemPath
|
||||
val wslRoot: String
|
||||
val distributionId: String
|
||||
|
||||
val serverNameEndIdx = when {
|
||||
sanitizedPath.startsWith("//wsl.localhost/", ignoreCase = true) -> 16
|
||||
sanitizedPath.startsWith("//wsl$/", ignoreCase = true) -> 7
|
||||
else -> return null
|
||||
}
|
||||
|
||||
val shareNameEndIdx = sanitizedPath.indexOf('/', startIndex = serverNameEndIdx)
|
||||
|
||||
if (shareNameEndIdx == -1) {
|
||||
wslRoot = sanitizedPath + "\\"
|
||||
distributionId = sanitizedPath.substring(serverNameEndIdx)
|
||||
}
|
||||
else {
|
||||
wslRoot = sanitizedPath.take(shareNameEndIdx + 1)
|
||||
distributionId = sanitizedPath.substring(serverNameEndIdx, shareNameEndIdx)
|
||||
}
|
||||
|
||||
return wslRoot to distributionId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class WslEelDescriptor(val distribution: WSLDistribution) : EelDescriptor {
|
||||
class WslEelMachine(val distribution: WSLDistribution) : EelMachine {
|
||||
override val osFamily: EelOsFamily = EelOsFamily.Posix
|
||||
|
||||
override val userReadableDescription: @NonNls String = "WSL: ${distribution.presentableName}"
|
||||
override val name: @NonNls String = "WSL: ${distribution.presentableName}"
|
||||
|
||||
override suspend fun toEelApi(): EelApi {
|
||||
return distribution.getIjent()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is WslEelDescriptor && other.distribution.id == distribution.id
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as WslEelMachine
|
||||
|
||||
if (distribution != other.distribution) return false
|
||||
if (osFamily != other.osFamily) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return distribution.id.hashCode()
|
||||
var result = distribution.hashCode()
|
||||
result = 31 * result + osFamily.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class WslEelDescriptor(val distribution: WSLDistribution, internal val fsRoot: String) : EelPathBoundDescriptor {
|
||||
override val rootPath: Path get() = fsRoot.let(::Path)
|
||||
override val machine: EelMachine = WslEelMachine(distribution)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as WslEelDescriptor
|
||||
|
||||
if (fsRoot != other.fsRoot) return false
|
||||
if (machine != other.machine) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = fsRoot.hashCode()
|
||||
result = 31 * result + machine.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.intellij.execution.wsl.WSLDistribution
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.IntellijInternalApi
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.platform.core.nio.fs.MultiRoutingFileSystem
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.ijent.spi.IjentConnectionStrategy
|
||||
import com.intellij.platform.ijent.spi.IjentDeployingOverShellProcessStrategy
|
||||
@@ -22,7 +23,7 @@ class WslIjentDeployingStrategy(
|
||||
override val ijentLabel: String,
|
||||
private val distribution: WSLDistribution,
|
||||
private val project: Project?,
|
||||
private val wslCommandLineOptionsModifier: (WSLCommandLineOptions) -> Unit = {}
|
||||
private val wslCommandLineOptionsModifier: (WSLCommandLineOptions) -> Unit = {},
|
||||
) : IjentDeployingOverShellProcessStrategy(scope) {
|
||||
override suspend fun mapPath(path: Path): String? =
|
||||
distribution.getWslPath(path)
|
||||
@@ -46,7 +47,10 @@ class WslIjentDeployingStrategy(
|
||||
}
|
||||
|
||||
override suspend fun getTargetDescriptor(): EelDescriptor {
|
||||
return WslEelDescriptor(distribution)
|
||||
val root = project?.basePath?.let {
|
||||
MultiRoutingFileSystem.sanitizeRoot(it)
|
||||
}?.let(WslEelProvider::parsePath)?.first ?: distribution.getUNCRootPath().toString()
|
||||
return WslEelDescriptor(distribution, root)
|
||||
}
|
||||
|
||||
override suspend fun getConnectionStrategy(): IjentConnectionStrategy {
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.intellij.execution.ijent.nio
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.platform.core.nio.fs.DelegatingFileSystemProvider
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.provider.EelProvider
|
||||
import com.intellij.platform.eel.annotations.MultiRoutingFileSystemPath
|
||||
import com.intellij.platform.eel.provider.MultiRoutingFileSystemBackend
|
||||
@@ -92,12 +93,12 @@ fun CoroutineScope.registerIjentNioFs(
|
||||
if (eelDescriptor == ijent.descriptor) listOf(root)
|
||||
else null
|
||||
|
||||
override fun getInternalName(eelDescriptor: EelDescriptor): String? =
|
||||
if (eelDescriptor == ijent.descriptor) eelDescriptor.userReadableDescription
|
||||
override fun getInternalName(eelMachine: EelMachine): String? =
|
||||
if (eelMachine == ijent.descriptor.machine) ijent.descriptor.machine.name
|
||||
else null
|
||||
|
||||
override fun getEelDescriptorByInternalName(internalName: String): EelDescriptor? =
|
||||
if (internalName == ijent.descriptor.userReadableDescription) ijent.descriptor
|
||||
override fun getEelMachineByInternalName(internalName: String): EelMachine? =
|
||||
if (internalName == ijent.descriptor.machine.name) ijent.descriptor.machine
|
||||
else null
|
||||
},
|
||||
disposable,
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.platform.backend.workspace.GlobalWorkspaceModelCache
|
||||
import com.intellij.platform.diagnostic.telemetry.helpers.MillisecondsMeasurer
|
||||
import com.intellij.platform.eel.provider.EelProvider
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.JpsGlobalFileEntitySource
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
import com.intellij.platform.workspace.jps.entities.SdkEntity
|
||||
@@ -289,12 +290,12 @@ open class JpsGlobalModelSynchronizerImpl(private val coroutineScope: CoroutineS
|
||||
initialEntityStorage: VersionedEntityStorage,
|
||||
notifyListeners: Boolean,
|
||||
): () -> Unit {
|
||||
val descriptor =
|
||||
val eelMachine =
|
||||
EelProvider.EP_NAME.extensionList.firstNotNullOfOrNull { eelProvider ->
|
||||
eelProvider.getEelDescriptorByInternalName(environmentName.name)
|
||||
eelProvider.getEelMachineByInternalName(environmentName.name)
|
||||
}
|
||||
?: LocalEelDescriptor
|
||||
val callbacks = GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(descriptor)
|
||||
?: LocalEelMachine
|
||||
val callbacks = GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(eelMachine)
|
||||
.map { it.initializeBridgesAfterLoading(mutableStorage, initialEntityStorage) }
|
||||
return {
|
||||
callbacks.forEach { it.invoke() }
|
||||
|
||||
@@ -389,7 +389,7 @@ class JpsProjectModelSynchronizer(private val project: Project) : Disposable {
|
||||
workspaceModel.entityTracer.printInfoAboutTracedEntity(builder, "JPS files")
|
||||
childActivity = childActivity?.endAndStart("applying entities from global storage")
|
||||
val mutableStorage = MutableEntityStorage.create()
|
||||
GlobalWorkspaceModel.getInstanceAsync(project.getEelDescriptor()).applyStateToProjectBuilder(mutableStorage, workspaceModel)
|
||||
GlobalWorkspaceModel.getInstanceAsync(project.getEelDescriptor().machine).applyStateToProjectBuilder(mutableStorage, workspaceModel)
|
||||
builder.applyChangesFrom(mutableStorage)
|
||||
childActivity = childActivity?.endAndStart("applying loaded changes (in queue)")
|
||||
LoadedProjectEntities(builder, orphanage, unloadedEntitiesBuilder, sourcesToUpdate)
|
||||
|
||||
@@ -522,11 +522,13 @@ private class MockIjentApi(private val adapter: GeneralCommandLine, val rootUser
|
||||
|
||||
override val descriptor: EelDescriptor
|
||||
get() = object : EelDescriptor {
|
||||
override val userReadableDescription: @NonNls String = "mock"
|
||||
override val osFamily: EelOsFamily = this@MockIjentApi.platform.osFamily
|
||||
override val machine: EelMachine = object : EelMachine {
|
||||
override val name: @NonNls String = "mock"
|
||||
override val osFamily: EelOsFamily = this@MockIjentApi.platform.osFamily
|
||||
|
||||
override suspend fun toEelApi(): EelApi {
|
||||
throw UnsupportedOperationException()
|
||||
override suspend fun toEelApi(): EelApi {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.openapi.application.edtWriteAction
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.platform.backend.workspace.workspaceModel
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.JpsGlobalFileEntitySource
|
||||
import com.intellij.platform.workspace.jps.entities.*
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
@@ -93,8 +94,8 @@ class ModuleDependencyIndexTest {
|
||||
fun `test dependency on global library`() = runBlocking {
|
||||
try {
|
||||
edtWriteAction {
|
||||
GlobalWorkspaceModel.getInstance(LocalEelDescriptor).updateModel("Test") {
|
||||
val manager = GlobalWorkspaceModel.getInstance(LocalEelDescriptor).getVirtualFileUrlManager()
|
||||
GlobalWorkspaceModel.getInstance(LocalEelMachine).updateModel("Test") {
|
||||
val manager = GlobalWorkspaceModel.getInstance(LocalEelMachine).getVirtualFileUrlManager()
|
||||
val globalEntitySource = JpsGlobalFileEntitySource(manager.getOrCreateFromUrl("/url"))
|
||||
it addEntity LibraryEntity("GlobalLib", LibraryTableId.GlobalLibraryTableId("application"), emptyList(), globalEntitySource)
|
||||
}
|
||||
@@ -156,8 +157,8 @@ class ModuleDependencyIndexTest {
|
||||
fun `test dependency on global library after rename`() = runBlocking {
|
||||
try {
|
||||
edtWriteAction {
|
||||
GlobalWorkspaceModel.getInstance(LocalEelDescriptor).updateModel("Test") {
|
||||
val manager = GlobalWorkspaceModel.getInstance(LocalEelDescriptor).getVirtualFileUrlManager()
|
||||
GlobalWorkspaceModel.getInstance(LocalEelMachine).updateModel("Test") {
|
||||
val manager = GlobalWorkspaceModel.getInstance(LocalEelMachine).getVirtualFileUrlManager()
|
||||
val globalEntitySource = JpsGlobalFileEntitySource(manager.getOrCreateFromUrl("/url"))
|
||||
it addEntity LibraryEntity("GlobalLib", LibraryTableId.GlobalLibraryTableId("application"), emptyList(), globalEntitySource)
|
||||
}
|
||||
@@ -168,7 +169,7 @@ class ModuleDependencyIndexTest {
|
||||
}
|
||||
|
||||
edtWriteAction {
|
||||
GlobalWorkspaceModel.getInstance(LocalEelDescriptor).updateModel("Test") {
|
||||
GlobalWorkspaceModel.getInstance(LocalEelMachine).updateModel("Test") {
|
||||
val resolved = it.resolve(LibraryId("GlobalLib", LibraryTableId.GlobalLibraryTableId("application")))!!
|
||||
it.modifyLibraryEntity(resolved) {
|
||||
this.name = "NewGlobalName"
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor;
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine;
|
||||
import com.intellij.workspaceModel.ide.legacyBridge.GlobalLibraryTableBridge;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -35,7 +35,7 @@ final class LibraryTablesRegistrarImpl extends LibraryTablesRegistrar implements
|
||||
@Override
|
||||
public @NotNull LibraryTable getLibraryTable() {
|
||||
// todo: IJPL-175225 add possibility to select non-local global library tables
|
||||
return GlobalLibraryTableBridge.Companion.getInstance(LocalEelDescriptor.INSTANCE);
|
||||
return GlobalLibraryTableBridge.Companion.getInstance(LocalEelMachine.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,9 +14,9 @@ import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.platform.backend.workspace.GlobalWorkspaceModelCache
|
||||
import com.intellij.platform.backend.workspace.WorkspaceModel
|
||||
import com.intellij.platform.diagnostic.telemetry.helpers.MillisecondsMeasurer
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.provider.EelProvider
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.workspace.jps.GlobalStorageEntitySource
|
||||
import com.intellij.platform.workspace.jps.JpsGlobalFileEntitySource
|
||||
@@ -57,9 +57,9 @@ class GlobalWorkspaceModel internal constructor(
|
||||
* 1. Prevent entities from one environment from appearing for another one;
|
||||
* 2. Ensure that the namespace of "global" entities (such as SDKs and global libraries) is local to each environment.
|
||||
*/
|
||||
private val eelDescriptor: EelDescriptor,
|
||||
private val eelMachine: EelMachine,
|
||||
private val internalEnvironmentName: GlobalWorkspaceModelCache.InternalEnvironmentName,
|
||||
) {
|
||||
) {
|
||||
|
||||
/**
|
||||
* Store link to the project from which changes came from. It's needed to avoid redundant changes application at [applyStateToProject]
|
||||
@@ -186,7 +186,7 @@ class GlobalWorkspaceModel internal constructor(
|
||||
private fun initializeBridges(change: Map<Class<*>, List<EntityChange<*>>>, builder: MutableEntityStorage) {
|
||||
ThreadingAssertions.assertWriteAccess()
|
||||
|
||||
GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(eelDescriptor).forEach {
|
||||
GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(eelMachine).forEach {
|
||||
logErrorOnEventHandling {
|
||||
it.initializeBridges(change, builder)
|
||||
}
|
||||
@@ -196,19 +196,19 @@ class GlobalWorkspaceModel internal constructor(
|
||||
private fun onBeforeChanged(change: VersionedStorageChange) {
|
||||
ThreadingAssertions.assertWriteAccess()
|
||||
|
||||
GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(eelDescriptor).forEach { it.handleBeforeChangeEvents(change) }
|
||||
GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(eelMachine).forEach { it.handleBeforeChangeEvents(change) }
|
||||
}
|
||||
|
||||
@RequiresWriteLock
|
||||
private fun onChanged(change: VersionedStorageChange) {
|
||||
ThreadingAssertions.assertWriteAccess()
|
||||
|
||||
GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(eelDescriptor).forEach { it.handleChangedEvents(change) }
|
||||
GlobalEntityBridgeAndEventHandler.getAllGlobalEntityHandlers(eelMachine).forEach { it.handleChangedEvents(change) }
|
||||
|
||||
globalWorkspaceModelCache?.scheduleCacheSave()
|
||||
isFromGlobalWorkspaceModel = true
|
||||
for (project in ProjectManager.getInstance().openProjects) {
|
||||
if (project.isDisposed || project.getEelDescriptor() != eelDescriptor) {
|
||||
if (project.isDisposed || project.getEelDescriptor().machine != eelMachine) {
|
||||
continue
|
||||
}
|
||||
applyStateToProject(project)
|
||||
@@ -233,7 +233,7 @@ class GlobalWorkspaceModel internal constructor(
|
||||
|
||||
fun applyStateToProjectBuilder(
|
||||
targetBuilder: MutableEntityStorage,
|
||||
workspaceModel: WorkspaceModelImpl
|
||||
workspaceModel: WorkspaceModelImpl,
|
||||
): Unit = applyStateToProjectBuilderTimeMs.addMeasuredTime {
|
||||
LOG.info("Sync global entities with mutable entity storage")
|
||||
targetBuilder.replaceBySource(
|
||||
@@ -287,7 +287,7 @@ class GlobalWorkspaceModel internal constructor(
|
||||
val entitySourceCopy = (libraryEntity.entitySource as? JpsGlobalFileEntitySource)?.copy(vfuManager) ?: libraryEntity.entitySource
|
||||
val excludedRootsCopy = libraryEntity.excludedRoots.map { it.copy(entitySourceCopy, vfuManager) }
|
||||
val libraryPropertiesCopy = libraryEntity.libraryProperties?.copy(entitySourceCopy)
|
||||
val libraryEntityCopy = mutableEntityStorage addEntity LibraryEntity(libraryEntity.name, libraryEntity.tableId, libraryRootsCopy, entitySourceCopy) {
|
||||
val libraryEntityCopy = mutableEntityStorage addEntity LibraryEntity(libraryEntity.name, libraryEntity.tableId, libraryRootsCopy, entitySourceCopy) {
|
||||
typeId = libraryEntity.typeId
|
||||
excludedRoots = excludedRootsCopy
|
||||
libraryProperties = libraryPropertiesCopy
|
||||
@@ -331,12 +331,12 @@ class GlobalWorkspaceModel internal constructor(
|
||||
|
||||
@RequiresBlockingContext
|
||||
@JvmStatic
|
||||
fun getInstance(descriptor: EelDescriptor): GlobalWorkspaceModel {
|
||||
return ApplicationManager.getApplication().service<GlobalWorkspaceModelRegistry>().getGlobalModel(descriptor)
|
||||
fun getInstance(eelMachine: EelMachine): GlobalWorkspaceModel {
|
||||
return ApplicationManager.getApplication().service<GlobalWorkspaceModelRegistry>().getGlobalModel(eelMachine)
|
||||
}
|
||||
|
||||
suspend fun getInstanceAsync(descriptor: EelDescriptor): GlobalWorkspaceModel {
|
||||
return ApplicationManager.getApplication().serviceAsync<GlobalWorkspaceModelRegistry>().getGlobalModel(descriptor)
|
||||
suspend fun getInstanceAsync(eelMachine: EelMachine): GlobalWorkspaceModel {
|
||||
return ApplicationManager.getApplication().serviceAsync<GlobalWorkspaceModelRegistry>().getGlobalModel(eelMachine)
|
||||
}
|
||||
|
||||
suspend fun getInstanceByInternalName(name: GlobalWorkspaceModelCache.InternalEnvironmentName): GlobalWorkspaceModel {
|
||||
@@ -404,31 +404,31 @@ class GlobalWorkspaceModelRegistry {
|
||||
const val GLOBAL_WORKSPACE_MODEL_LOCAL_CACHE_ID: String = "Local"
|
||||
}
|
||||
|
||||
private val environmentToModel = ConcurrentHashMap<EelDescriptor, GlobalWorkspaceModel>()
|
||||
private val environmentToModel = ConcurrentHashMap<EelMachine, GlobalWorkspaceModel>()
|
||||
|
||||
fun getGlobalModel(descriptor: EelDescriptor): GlobalWorkspaceModel {
|
||||
val protectedDescriptor = if (Registry.`is`("ide.workspace.model.per.environment.model.separation")) descriptor else LocalEelDescriptor
|
||||
val internalName = if (protectedDescriptor is LocalEelDescriptor) {
|
||||
fun getGlobalModel(eelMachine: EelMachine): GlobalWorkspaceModel {
|
||||
val protectedMachine = if (Registry.`is`("ide.workspace.model.per.environment.model.separation")) eelMachine else LocalEelMachine
|
||||
val internalName = if (protectedMachine is LocalEelMachine) {
|
||||
GLOBAL_WORKSPACE_MODEL_LOCAL_CACHE_ID
|
||||
}
|
||||
else {
|
||||
EelProvider.EP_NAME.extensionList.firstNotNullOfOrNull { eelProvider ->
|
||||
eelProvider.getInternalName(protectedDescriptor)
|
||||
eelProvider.getInternalName(protectedMachine)
|
||||
}
|
||||
?: throw IllegalArgumentException("Descriptor $protectedDescriptor must be registered before using in Workspace Model")
|
||||
?: throw IllegalArgumentException("Descriptor $protectedMachine must be registered before using in Workspace Model")
|
||||
}
|
||||
return environmentToModel.computeIfAbsent(protectedDescriptor) { GlobalWorkspaceModel(protectedDescriptor, InternalEnvironmentNameImpl(internalName)) }
|
||||
return environmentToModel.computeIfAbsent(protectedMachine) { GlobalWorkspaceModel(protectedMachine, InternalEnvironmentNameImpl(internalName)) }
|
||||
}
|
||||
|
||||
fun getGlobalModelByDescriptorName(name: GlobalWorkspaceModelCache.InternalEnvironmentName): GlobalWorkspaceModel {
|
||||
val protectedName = if (Registry.`is`("ide.workspace.model.per.environment.model.separation")) name.name else GLOBAL_WORKSPACE_MODEL_LOCAL_CACHE_ID
|
||||
val descriptor = if (protectedName == GLOBAL_WORKSPACE_MODEL_LOCAL_CACHE_ID) {
|
||||
LocalEelDescriptor
|
||||
val machine = if (protectedName == GLOBAL_WORKSPACE_MODEL_LOCAL_CACHE_ID) {
|
||||
LocalEelMachine
|
||||
}
|
||||
else {
|
||||
EelProvider.EP_NAME.extensionList.firstNotNullOf { eelProvider -> eelProvider.getEelDescriptorByInternalName(protectedName) }
|
||||
EelProvider.EP_NAME.extensionList.firstNotNullOf { eelProvider -> eelProvider.getEelMachineByInternalName(protectedName) }
|
||||
}
|
||||
val model = getGlobalModel(descriptor)
|
||||
val model = getGlobalModel(machine)
|
||||
return model
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ class GlobalWorkspaceModelRegistry {
|
||||
environmentToModel.values.toList()
|
||||
}
|
||||
else {
|
||||
listOf(getGlobalModel(LocalEelDescriptor))
|
||||
listOf(getGlobalModel(LocalEelMachine))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import com.intellij.platform.workspace.storage.impl.VersionedStorageChangeIntern
|
||||
|
||||
internal class GlobalWorkspaceModelSynchronizerListener(private val project: Project) : WorkspaceModelChangeListener {
|
||||
override fun changed(event: VersionedStorageChange) {
|
||||
val eelDescriptor = project.getEelDescriptor()
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(eelDescriptor)
|
||||
val eelMachine = project.getEelDescriptor().machine
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(eelMachine)
|
||||
// Avoid handling events if change was made by global workspace model
|
||||
if (globalWorkspaceModel.isFromGlobalWorkspaceModel) return
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablePresentation
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.GlobalStorageEntitySource
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryId
|
||||
@@ -33,7 +33,7 @@ internal class CustomLibraryTableBridgeImpl(private val level: String, private v
|
||||
private var tmpEntityStorage: EntityStorage? = null
|
||||
private val entitySource = LegacyCustomLibraryEntitySource(tableLevel)
|
||||
private val libraryTableId = LibraryTableId.GlobalLibraryTableId(tableLevel)
|
||||
private val libraryTableDelegate = GlobalLibraryTableDelegate(this, getDescriptor(), libraryTableId)
|
||||
private val libraryTableDelegate = GlobalLibraryTableDelegate(this, getMachine(), libraryTableId)
|
||||
|
||||
override fun initializeBridgesAfterLoading(mutableStorage: MutableEntityStorage,
|
||||
initialEntityStorage: VersionedEntityStorage): () -> Unit {
|
||||
@@ -80,7 +80,7 @@ internal class CustomLibraryTableBridgeImpl(private val level: String, private v
|
||||
override fun getPresentation(): LibraryTablePresentation = presentation
|
||||
|
||||
override fun getModifiableModel(): LibraryTable.ModifiableModel {
|
||||
return GlobalOrCustomModifiableLibraryTableBridgeImpl(this, getDescriptor(), entitySource)
|
||||
return GlobalOrCustomModifiableLibraryTableBridgeImpl(this, getMachine(), entitySource)
|
||||
}
|
||||
|
||||
override fun isEditable(): Boolean = false
|
||||
@@ -90,7 +90,7 @@ internal class CustomLibraryTableBridgeImpl(private val level: String, private v
|
||||
Disposer.dispose(libraryTableDelegate)
|
||||
|
||||
val runnable: () -> Unit = {
|
||||
GlobalWorkspaceModel.getInstance(getDescriptor()).updateModel("Cleanup custom libraries after dispose") { storage ->
|
||||
GlobalWorkspaceModel.getInstance(getMachine()).updateModel("Cleanup custom libraries after dispose") { storage ->
|
||||
storage.entities(LibraryEntity::class.java).filter { it.entitySource == entitySource }.forEach {
|
||||
storage.removeEntity(it)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ internal class CustomLibraryTableBridgeImpl(private val level: String, private v
|
||||
|
||||
@OptIn(EntityStorageInstrumentationApi::class)
|
||||
override fun readExternal(libraryTableTag: Element) {
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(getDescriptor())
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(getMachine())
|
||||
val mutableEntityStorage = MutableEntityStorage.create()
|
||||
|
||||
libraryTableTag.getChildren(JpsLibraryTableSerializer.LIBRARY_TAG).forEach { libraryTag ->
|
||||
@@ -138,7 +138,7 @@ internal class CustomLibraryTableBridgeImpl(private val level: String, private v
|
||||
|
||||
val libraryBridge = actualLibraryEntity.findLibraryBridge(entityStorage) ?: LibraryBridgeImpl(
|
||||
libraryTable = this,
|
||||
origin = LibraryOrigin.OfDescriptor(getDescriptor()),
|
||||
origin = LibraryOrigin.OfMachine(getMachine()),
|
||||
initialId = libraryEntity.symbolicId,
|
||||
initialEntityStorage = storageOnBuilder,
|
||||
targetBuilder = null
|
||||
@@ -170,7 +170,7 @@ internal class CustomLibraryTableBridgeImpl(private val level: String, private v
|
||||
}
|
||||
|
||||
override fun writeExternal(element: Element) {
|
||||
GlobalWorkspaceModel.getInstance(LocalEelDescriptor).currentSnapshot.entities(LibraryEntity::class.java)
|
||||
GlobalWorkspaceModel.getInstance(LocalEelMachine).currentSnapshot.entities(LibraryEntity::class.java)
|
||||
.filter { it.tableId == libraryTableId }
|
||||
.sortedBy { it.name }
|
||||
.forEach { libraryEntity ->
|
||||
@@ -189,8 +189,8 @@ internal class CustomLibraryTableBridgeImpl(private val level: String, private v
|
||||
/**
|
||||
* As for now, we permit custom library tables only for local projects. These tables are internal anyway.
|
||||
*/
|
||||
private fun getDescriptor(): EelDescriptor {
|
||||
return LocalEelDescriptor
|
||||
private fun getMachine(): EelMachine {
|
||||
return LocalEelMachine
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
|
||||
@@ -20,8 +20,8 @@ internal class GlobalAndCustomLibraryTableBridgeInitializer : BridgeInitializer
|
||||
override fun initializeBridges(project: Project,
|
||||
changes: Map<Class<*>, List<EntityChange<*>>>,
|
||||
builder: MutableEntityStorage) = GlobalLibraryTableBridgeImpl.initializeLibraryBridgesTimeMs.addMeasuredTime {
|
||||
val descriptor = project.getEelDescriptor()
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(descriptor).entityStorage
|
||||
val machine = project.getEelDescriptor().machine
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(machine).entityStorage
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val libraryChanges = (changes[LibraryEntity::class.java] as? List<EntityChange<LibraryEntity>>) ?: emptyList()
|
||||
@@ -32,7 +32,7 @@ internal class GlobalAndCustomLibraryTableBridgeInitializer : BridgeInitializer
|
||||
builder.mutableLibraryMap.getOrPutDataByEntity(addChange.newEntity) {
|
||||
LibraryBridgeImpl(
|
||||
libraryTable = getGlobalOrCustomLibraryTable(addChange.newEntity.symbolicId.tableId.level),
|
||||
origin = LibraryOrigin.OfDescriptor(descriptor),
|
||||
origin = LibraryOrigin.OfMachine(machine),
|
||||
initialId = addChange.newEntity.symbolicId,
|
||||
initialEntityStorage = entityStorage,
|
||||
targetBuilder = builder
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.intellij.openapi.roots.libraries.LibraryTablePresentation
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.platform.diagnostic.telemetry.helpers.MillisecondsMeasurer
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.workspace.jps.JpsGlobalFileEntitySource
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryTableId
|
||||
import com.intellij.platform.workspace.jps.serialization.impl.JpsGlobalEntitiesSerializers
|
||||
@@ -22,8 +22,8 @@ import io.opentelemetry.api.metrics.Meter
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
class GlobalLibraryTableBridgeImpl(val descriptor: EelDescriptor) : GlobalLibraryTableBridge, Disposable {
|
||||
private val libraryTableDelegate = GlobalLibraryTableDelegate(this, descriptor, LibraryTableId.GlobalLibraryTableId(LibraryTablesRegistrar.APPLICATION_LEVEL))
|
||||
class GlobalLibraryTableBridgeImpl(val eelMachine: EelMachine) : GlobalLibraryTableBridge, Disposable {
|
||||
private val libraryTableDelegate = GlobalLibraryTableDelegate(this, eelMachine, LibraryTableId.GlobalLibraryTableId(LibraryTablesRegistrar.APPLICATION_LEVEL))
|
||||
|
||||
override fun initializeBridges(changes: Map<Class<*>, List<EntityChange<*>>>,
|
||||
builder: MutableEntityStorage) = initializeLibraryBridgesTimeMs.addMeasuredTime {
|
||||
@@ -67,7 +67,7 @@ class GlobalLibraryTableBridgeImpl(val descriptor: EelDescriptor) : GlobalLibrar
|
||||
override fun getPresentation(): LibraryTablePresentation = GLOBAL_LIBRARY_TABLE_PRESENTATION
|
||||
|
||||
override fun getModifiableModel(): LibraryTable.ModifiableModel {
|
||||
return GlobalOrCustomModifiableLibraryTableBridgeImpl(this, descriptor, createEntitySourceForGlobalLibrary())
|
||||
return GlobalOrCustomModifiableLibraryTableBridgeImpl(this, eelMachine, createEntitySourceForGlobalLibrary())
|
||||
}
|
||||
|
||||
override fun dispose(): Unit = Disposer.dispose(libraryTableDelegate)
|
||||
@@ -79,7 +79,7 @@ class GlobalLibraryTableBridgeImpl(val descriptor: EelDescriptor) : GlobalLibrar
|
||||
override fun removeListener(listener: LibraryTable.Listener) = libraryTableDelegate.removeListener(listener)
|
||||
|
||||
private fun createEntitySourceForGlobalLibrary(): EntitySource {
|
||||
val virtualFileUrlManager = GlobalWorkspaceModel.getInstance(descriptor).getVirtualFileUrlManager()
|
||||
val virtualFileUrlManager = GlobalWorkspaceModel.getInstance(eelMachine).getVirtualFileUrlManager()
|
||||
val globalLibrariesFile = virtualFileUrlManager.getOrCreateFromUrl(PathManager.getOptionsFile(JpsGlobalEntitiesSerializers.GLOBAL_LIBRARIES_FILE_NAME).absolutePath)
|
||||
return JpsGlobalFileEntitySource(globalLibrariesFile)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.intellij.openapi.diagnostic.debug
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryId
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryTableId
|
||||
@@ -19,11 +19,11 @@ import com.intellij.workspaceModel.ide.impl.GlobalWorkspaceModel
|
||||
import com.intellij.workspaceModel.ide.impl.legacyBridge.library.ProjectLibraryTableBridgeImpl.Companion.libraryMap
|
||||
import com.intellij.workspaceModel.ide.impl.legacyBridge.library.ProjectLibraryTableBridgeImpl.Companion.mutableLibraryMap
|
||||
|
||||
internal class GlobalLibraryTableDelegate(private val libraryTable: LibraryTable, val descriptor: EelDescriptor, private val libraryTableId: LibraryTableId) : Disposable {
|
||||
internal class GlobalLibraryTableDelegate(private val libraryTable: LibraryTable, val eelMachine: EelMachine, private val libraryTableId: LibraryTableId) : Disposable {
|
||||
private val dispatcher = EventDispatcher.create(LibraryTable.Listener::class.java)
|
||||
|
||||
internal fun initializeLibraryBridges(changes: Map<Class<*>, List<EntityChange<*>>>, builder: MutableEntityStorage) {
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(descriptor).entityStorage
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(eelMachine).entityStorage
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val libraryChanges = (changes[LibraryEntity::class.java] as? List<EntityChange<LibraryEntity>>) ?: emptyList()
|
||||
@@ -34,7 +34,7 @@ internal class GlobalLibraryTableDelegate(private val libraryTable: LibraryTable
|
||||
builder.mutableLibraryMap.getOrPutDataByEntity(addChange.newEntity) {
|
||||
LibraryBridgeImpl(
|
||||
libraryTable = libraryTable,
|
||||
origin = LibraryOrigin.OfDescriptor(descriptor),
|
||||
origin = LibraryOrigin.OfMachine(eelMachine),
|
||||
initialId = addChange.newEntity.symbolicId,
|
||||
initialEntityStorage = entityStorage,
|
||||
targetBuilder = builder
|
||||
@@ -52,7 +52,7 @@ internal class GlobalLibraryTableDelegate(private val libraryTable: LibraryTable
|
||||
.map { libraryEntity ->
|
||||
Pair(libraryEntity, LibraryBridgeImpl(
|
||||
libraryTable = libraryTable,
|
||||
origin = LibraryOrigin.OfDescriptor(descriptor),
|
||||
origin = LibraryOrigin.OfMachine(eelMachine),
|
||||
initialId = libraryEntity.symbolicId,
|
||||
initialEntityStorage = initialEntityStorage,
|
||||
targetBuilder = null
|
||||
@@ -107,7 +107,7 @@ internal class GlobalLibraryTableDelegate(private val libraryTable: LibraryTable
|
||||
val changes = event.getChanges(LibraryEntity::class.java).filterLibraryChanges(libraryTableId)
|
||||
if (changes.isEmpty()) return
|
||||
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(descriptor).entityStorage
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(eelMachine).entityStorage
|
||||
for (change in changes) {
|
||||
LOG.debug { "Process ${libraryTableId.level} library change $change" }
|
||||
when (change) {
|
||||
@@ -174,7 +174,7 @@ internal class GlobalLibraryTableDelegate(private val libraryTable: LibraryTable
|
||||
}
|
||||
|
||||
internal fun getLibraries(): Array<Library> {
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(descriptor).entityStorage
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(eelMachine).entityStorage
|
||||
val storage = entityStorage.current
|
||||
val libraryEntitySequence = storage.entities(LibraryEntity::class.java).filter { it.tableId == libraryTableId }.toList()
|
||||
val libs: Array<Library> = libraryEntitySequence.mapNotNull { storage.libraryMap.getDataByEntity(it) }
|
||||
@@ -183,7 +183,7 @@ internal class GlobalLibraryTableDelegate(private val libraryTable: LibraryTable
|
||||
}
|
||||
|
||||
internal fun getLibraryByName(name: String): Library? {
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(descriptor).entityStorage
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(eelMachine).entityStorage
|
||||
val libraryId = LibraryId(name, libraryTableId)
|
||||
val library = entityStorage.current.resolve(libraryId)?.let { entity ->
|
||||
entityStorage.current.libraryMap.getDataByEntity(entity)
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable
|
||||
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.workspace.jps.entities.*
|
||||
import com.intellij.platform.workspace.storage.EntitySource
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
@@ -19,8 +19,8 @@ import com.intellij.workspaceModel.ide.impl.legacyBridge.library.ProjectLibraryT
|
||||
import com.intellij.workspaceModel.ide.impl.legacyBridge.library.ProjectLibraryTableBridgeImpl.Companion.mutableLibraryMap
|
||||
import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer
|
||||
|
||||
internal class GlobalOrCustomModifiableLibraryTableBridgeImpl(private val libraryTable: LibraryTable, val descriptor: EelDescriptor, private val entitySource: EntitySource) :
|
||||
LegacyBridgeModifiableBase(MutableEntityStorage.from(GlobalWorkspaceModel.getInstance(descriptor).currentSnapshot), true),
|
||||
internal class GlobalOrCustomModifiableLibraryTableBridgeImpl(private val libraryTable: LibraryTable, val machine: EelMachine, private val entitySource: EntitySource) :
|
||||
LegacyBridgeModifiableBase(MutableEntityStorage.from(GlobalWorkspaceModel.getInstance(machine).currentSnapshot), true),
|
||||
LibraryTable.ModifiableModel {
|
||||
|
||||
private val myAddedLibraries = mutableListOf<LibraryBridgeImpl>()
|
||||
@@ -54,7 +54,7 @@ internal class GlobalOrCustomModifiableLibraryTableBridgeImpl(private val librar
|
||||
|
||||
val library = LibraryBridgeImpl(
|
||||
libraryTable = libraryTable,
|
||||
origin = LibraryOrigin.OfDescriptor(descriptor),
|
||||
origin = LibraryOrigin.OfMachine(machine),
|
||||
initialId = LibraryId(name, libraryTableId),
|
||||
initialEntityStorage = entityStorageOnDiff,
|
||||
targetBuilder = this.diff
|
||||
@@ -78,7 +78,7 @@ internal class GlobalOrCustomModifiableLibraryTableBridgeImpl(private val librar
|
||||
}
|
||||
|
||||
override fun commit() {
|
||||
GlobalWorkspaceModel.getInstance(descriptor).updateModel("${libraryTableId.level} library table commit") {
|
||||
GlobalWorkspaceModel.getInstance(machine).updateModel("${libraryTableId.level} library table commit") {
|
||||
it.applyChangesFrom(diff)
|
||||
}
|
||||
libraries.forEach { library -> (library as LibraryBridgeImpl).clearTargetBuilder() }
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.TraceableDisposable
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.backend.workspace.WorkspaceModel
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryId
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryRootTypeId
|
||||
import com.intellij.platform.workspace.jps.serialization.impl.LibraryNameGenerator
|
||||
@@ -49,7 +49,7 @@ interface LibraryBridge : LibraryEx {
|
||||
@ApiStatus.Internal
|
||||
sealed interface LibraryOrigin {
|
||||
class OfProject(val project: Project) : LibraryOrigin
|
||||
class OfDescriptor(val descriptor: EelDescriptor) : LibraryOrigin
|
||||
class OfMachine(val eelMachine: EelMachine) : LibraryOrigin
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@@ -126,7 +126,7 @@ class LibraryBridgeImpl(
|
||||
|
||||
override fun getModifiableModel(builder: MutableEntityStorage): LibraryEx.ModifiableModelEx {
|
||||
val virtualFileUrlManager = when (origin) {
|
||||
is LibraryOrigin.OfDescriptor -> GlobalWorkspaceModel.getInstance(origin.descriptor).getVirtualFileUrlManager()
|
||||
is LibraryOrigin.OfMachine -> GlobalWorkspaceModel.getInstance(origin.eelMachine).getVirtualFileUrlManager()
|
||||
is LibraryOrigin.OfProject -> WorkspaceModel.getInstance(origin.project).getVirtualFileUrlManager()
|
||||
}
|
||||
return LibraryModifiableModelBridgeImpl(this, librarySnapshot, builder, targetBuilder, virtualFileUrlManager, false)
|
||||
@@ -185,7 +185,7 @@ class LibraryBridgeImpl(
|
||||
}
|
||||
val isDisposedGlobally = libraryEntity?.let {
|
||||
val snapshot = when (origin) {
|
||||
is LibraryOrigin.OfDescriptor -> GlobalWorkspaceModel.getInstance(origin.descriptor).currentSnapshot
|
||||
is LibraryOrigin.OfMachine -> GlobalWorkspaceModel.getInstance(origin.eelMachine).currentSnapshot
|
||||
is LibraryOrigin.OfProject -> WorkspaceModel.getInstance(origin.project).currentSnapshot
|
||||
}
|
||||
snapshot.libraryMap.getDataByEntity(it)?.isDisposed
|
||||
@@ -196,7 +196,7 @@ class LibraryBridgeImpl(
|
||||
Entity: ${libraryEntity.run { "$name, $this" }}
|
||||
Is disposed in ${
|
||||
when (origin) {
|
||||
is LibraryOrigin.OfProject -> "project"; is LibraryOrigin.OfDescriptor -> "global (${origin.descriptor})"
|
||||
is LibraryOrigin.OfProject -> "project"; is LibraryOrigin.OfMachine -> "global (${origin.eelMachine})"
|
||||
}
|
||||
} model: ${isDisposedGlobally != false}
|
||||
Stack trace: $stackTrace
|
||||
|
||||
@@ -103,8 +103,8 @@ internal class LibraryModifiableModelBridgeImpl(
|
||||
it.applyChangesFrom(diff)
|
||||
}
|
||||
}
|
||||
is LibraryOrigin.OfDescriptor -> {
|
||||
GlobalWorkspaceModel.getInstance(o.descriptor).updateModel("Library model commit") {
|
||||
is LibraryOrigin.OfMachine -> {
|
||||
GlobalWorkspaceModel.getInstance(o.eelMachine).updateModel("Library model commit") {
|
||||
it.applyChangesFrom(diff)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.backend.workspace.virtualFile
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.JpsGlobalFileEntitySource
|
||||
import com.intellij.platform.workspace.jps.entities.SdkEntity
|
||||
import com.intellij.platform.workspace.jps.entities.SdkRoot
|
||||
@@ -276,6 +276,6 @@ fun SdkEntity.Builder.applyChangesFrom(fromSdk: SdkEntity) {
|
||||
}
|
||||
|
||||
private fun getVirtualFileUrlManager(): VirtualFileUrlManager {
|
||||
// here we can use LocalEelDescriptor, as we simply need to get the virtual file url manager
|
||||
return GlobalWorkspaceModel.getInstance(LocalEelDescriptor).getVirtualFileUrlManager()
|
||||
// here we can use LocalEelMachine, as we simply need to get the virtual file url manager
|
||||
return GlobalWorkspaceModel.getInstance(LocalEelMachine).getVirtualFileUrlManager()
|
||||
}
|
||||
@@ -9,8 +9,8 @@ import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.backend.workspace.virtualFile
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.workspace.jps.entities.*
|
||||
import com.intellij.platform.workspace.jps.serialization.impl.ELEMENT_ADDITIONAL
|
||||
@@ -55,7 +55,7 @@ internal class SdkModificatorBridgeImpl(private val originalEntity: SdkEntity.Bu
|
||||
|
||||
override fun setHomePath(path: String?) {
|
||||
modifiedSdkEntity.homePath = if (path != null) {
|
||||
val descriptor = getDescriptor(path)
|
||||
val descriptor = getMachine(path)
|
||||
val globalInstance = GlobalWorkspaceModel.getInstance(descriptor).getVirtualFileUrlManager()
|
||||
globalInstance.getOrCreateFromUrl(path)
|
||||
} else {
|
||||
@@ -86,7 +86,7 @@ internal class SdkModificatorBridgeImpl(private val originalEntity: SdkEntity.Bu
|
||||
}
|
||||
|
||||
override fun addRoot(root: VirtualFile, rootType: OrderRootType) {
|
||||
val virtualFileUrlManager = GlobalWorkspaceModel.getInstance(LocalEelDescriptor).getVirtualFileUrlManager()
|
||||
val virtualFileUrlManager = GlobalWorkspaceModel.getInstance(LocalEelMachine).getVirtualFileUrlManager()
|
||||
modifiedSdkEntity.roots.add(
|
||||
SdkRoot(virtualFileUrlManager.getOrCreateFromUrl(root.url), rootTypes[rootType.customName]!!)
|
||||
)
|
||||
@@ -111,7 +111,7 @@ internal class SdkModificatorBridgeImpl(private val originalEntity: SdkEntity.Bu
|
||||
ThreadingAssertions.assertWriteAccess()
|
||||
if (isCommitted) error("Modification already completed")
|
||||
|
||||
val descriptor = getDescriptor(modifiedSdkEntity.homePath?.toString())
|
||||
val descriptor = getMachine(modifiedSdkEntity.homePath?.toString())
|
||||
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(descriptor)
|
||||
|
||||
@@ -169,14 +169,14 @@ internal class SdkModificatorBridgeImpl(private val originalEntity: SdkEntity.Bu
|
||||
return "$name Version:$versionString Path:($homePath)"
|
||||
}
|
||||
|
||||
private fun getDescriptor(path: String?): EelDescriptor {
|
||||
path ?: return LocalEelDescriptor
|
||||
private fun getMachine(path: String?): EelMachine {
|
||||
path ?: return LocalEelMachine
|
||||
return try {
|
||||
Path.of(path).getEelDescriptor()
|
||||
Path.of(path).getEelDescriptor().machine
|
||||
}
|
||||
catch (_: InvalidPathException) {
|
||||
// sometimes (in Ruby) the SDK home is set to 'temp:///root/nostubs'
|
||||
LocalEelDescriptor
|
||||
LocalEelMachine
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package com.intellij.workspaceModel.ide.legacyBridge
|
||||
|
||||
import com.intellij.openapi.roots.impl.libraries.CustomLibraryTableImpl
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.workspace.storage.EntityChange
|
||||
import com.intellij.platform.workspace.storage.MutableEntityStorage
|
||||
import com.intellij.platform.workspace.storage.VersionedEntityStorage
|
||||
@@ -18,10 +18,10 @@ interface GlobalEntityBridgeAndEventHandler {
|
||||
fun handleChangedEvents(event: VersionedStorageChange)
|
||||
|
||||
companion object {
|
||||
fun getAllGlobalEntityHandlers(descriptor: EelDescriptor): List<GlobalEntityBridgeAndEventHandler> {
|
||||
fun getAllGlobalEntityHandlers(eelMachine: EelMachine): List<GlobalEntityBridgeAndEventHandler> {
|
||||
val result = mutableListOf<GlobalEntityBridgeAndEventHandler>()
|
||||
result.add(GlobalLibraryTableBridge.getInstance(descriptor))
|
||||
result.add(GlobalSdkTableBridge.getInstance(descriptor))
|
||||
result.add(GlobalLibraryTableBridge.getInstance(eelMachine))
|
||||
result.add(GlobalSdkTableBridge.getInstance(eelMachine))
|
||||
LibraryTablesRegistrar.getInstance().customLibraryTables.forEach { customLibraryTable ->
|
||||
customLibraryTable as CustomLibraryTableImpl
|
||||
result.add(customLibraryTable.getDelegate() as CustomLibraryTableBridge)
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.workspaceModel.ide.impl.legacyBridge.library.GlobalLibraryTableBridgeImpl
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
@@ -16,16 +16,16 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
@ApiStatus.Internal
|
||||
interface GlobalLibraryTableBridge : GlobalEntityBridgeAndEventHandler, LibraryTable {
|
||||
companion object {
|
||||
fun getInstance(descriptor: EelDescriptor): GlobalLibraryTableBridge = ApplicationManager.getApplication().service<GlobalLibraryTableBridgeRegistry>().getTableBridge(descriptor)
|
||||
fun getInstance(eelMachine: EelMachine): GlobalLibraryTableBridge = ApplicationManager.getApplication().service<GlobalLibraryTableBridgeRegistry>().getTableBridge(eelMachine)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
private class GlobalLibraryTableBridgeRegistry {
|
||||
private val registry: MutableMap<EelDescriptor, GlobalLibraryTableBridge> = ConcurrentHashMap()
|
||||
private val registry: MutableMap<EelMachine, GlobalLibraryTableBridge> = ConcurrentHashMap()
|
||||
|
||||
fun getTableBridge(eelDescriptor: EelDescriptor): GlobalLibraryTableBridge {
|
||||
return registry.computeIfAbsent(eelDescriptor) { GlobalLibraryTableBridgeImpl(it) }
|
||||
fun getTableBridge(eelMachine: EelMachine): GlobalLibraryTableBridge {
|
||||
return registry.computeIfAbsent(eelMachine) { GlobalLibraryTableBridgeImpl(it) }
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,17 @@ package com.intellij.workspaceModel.ide.legacyBridge
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
interface GlobalSdkTableBridge: GlobalEntityBridgeAndEventHandler {
|
||||
companion object {
|
||||
fun getInstance(descriptor: EelDescriptor): GlobalSdkTableBridge = ApplicationManager.getApplication().service<GlobalSdkTableBridgeRegistry>().getTableBridge(descriptor)
|
||||
fun getInstance(eelMachine: EelMachine): GlobalSdkTableBridge = ApplicationManager.getApplication().service<GlobalSdkTableBridgeRegistry>().getTableBridge(eelMachine)
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
interface GlobalSdkTableBridgeRegistry {
|
||||
fun getTableBridge(eelDescriptor: EelDescriptor): GlobalSdkTableBridge
|
||||
fun getTableBridge(eelMachine: EelMachine): GlobalSdkTableBridge
|
||||
}
|
||||
@@ -3,24 +3,38 @@ package com.intellij.platform.testFramework.junit5.eel.impl
|
||||
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.EelOsFamily
|
||||
import com.intellij.platform.eel.EelPathBoundDescriptor
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import java.nio.file.Path
|
||||
|
||||
internal class EelTestDescriptor(val id: String, override val osFamily: EelOsFamily, val apiProvider: () -> EelApi) : EelDescriptor {
|
||||
|
||||
override val userReadableDescription: @NonNls String = "mock $id"
|
||||
internal class EelTestDescriptor(override val rootPath: Path, val id: String, override val osFamily: EelOsFamily, val apiProvider: () -> EelApi) : EelPathBoundDescriptor {
|
||||
override val machine: EelMachine = object : EelMachine {
|
||||
override val name: @NonNls String = "mock $id"
|
||||
override val osFamily: EelOsFamily get() = this@EelTestDescriptor.osFamily
|
||||
override suspend fun toEelApi(): EelApi = apiProvider()
|
||||
}
|
||||
|
||||
override suspend fun toEelApi(): EelApi {
|
||||
return apiProvider()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is EelTestDescriptor && other.id == id
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as EelTestDescriptor
|
||||
|
||||
if (rootPath != other.rootPath) return false
|
||||
if (id != other.id) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = id.hashCode()
|
||||
result = 31 * result + apiProvider.hashCode()
|
||||
var result = rootPath.hashCode()
|
||||
result = 31 * result + id.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.platform.core.nio.fs.MultiRoutingFileSystem
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.EelPlatform
|
||||
import com.intellij.platform.eel.annotations.MultiRoutingFileSystemPath
|
||||
import com.intellij.platform.eel.fs.createTemporaryDirectory
|
||||
@@ -25,14 +26,16 @@ import com.intellij.util.io.delete
|
||||
import org.junit.jupiter.api.Assumptions
|
||||
import java.nio.file.*
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.name
|
||||
|
||||
internal const val FAKE_WINDOWS_ROOT = "\\\\dummy-ij-root\\test-eel\\"
|
||||
|
||||
private val EelPlatform.name: String get() = when (this) {
|
||||
is EelPlatform.Posix -> "posix"
|
||||
is EelPlatform.Windows -> "windows"
|
||||
}
|
||||
private val EelPlatform.name: String
|
||||
get() = when (this) {
|
||||
is EelPlatform.Posix -> "posix"
|
||||
is EelPlatform.Windows -> "windows"
|
||||
}
|
||||
|
||||
internal val currentOs: EelPlatform
|
||||
get() = if (SystemInfo.isWindows) {
|
||||
@@ -67,7 +70,7 @@ internal fun eelInitializer(os: EelPlatform): TestFixtureInitializer<IsolatedFil
|
||||
|
||||
val fakeLocalFileSystem = EelUnitTestFileSystem(EelUnitTestFileSystemProvider(defaultProvider), os, directory, fakeRoot)
|
||||
val apiRef = AtomicReference<EelApi>(null)
|
||||
val descriptor = EelTestDescriptor(Ksuid.generate().toString(), os.osFamily, apiRef::get)
|
||||
val descriptor = EelTestDescriptor(Path(fakeRoot), Ksuid.generate().toString(), os.osFamily, apiRef::get)
|
||||
|
||||
val disposable = Disposer.newDisposable()
|
||||
|
||||
@@ -102,12 +105,12 @@ internal fun eelInitializer(os: EelPlatform): TestFixtureInitializer<IsolatedFil
|
||||
if (eelDescriptor == descriptor) listOf(fakeRoot)
|
||||
else null
|
||||
|
||||
override fun getInternalName(eelDescriptor: EelDescriptor): String? =
|
||||
if (eelDescriptor == descriptor) meaningfulDirName
|
||||
override fun getInternalName(eelMachine: EelMachine): String? =
|
||||
if (eelMachine == descriptor.machine) meaningfulDirName
|
||||
else null
|
||||
|
||||
override fun getEelDescriptorByInternalName(internalName: String): EelDescriptor? =
|
||||
if (internalName == meaningfulDirName) descriptor
|
||||
override fun getEelMachineByInternalName(internalName: String): EelMachine? =
|
||||
if (internalName == meaningfulDirName) descriptor.machine
|
||||
else null
|
||||
},
|
||||
disposable,
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.testFramework.projectModel.library.MockCustomLibraryTableDescription
|
||||
import com.intellij.platform.testFramework.projectModel.library.NewMockCustomLibraryTableDescription
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
@@ -57,7 +58,7 @@ class CustomLibraryBridgeTest {
|
||||
}
|
||||
}
|
||||
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
globalWorkspaceModel.currentSnapshot.entities(LibraryEntity::class.java)
|
||||
.onEach { assertEquals(it.tableId, LibraryTableId.GlobalLibraryTableId("Mock")) }
|
||||
.onEach { assertTrue(libraryNames.contains(it.name)) }
|
||||
@@ -175,7 +176,7 @@ class CustomLibraryBridgeTest {
|
||||
}
|
||||
assertEquals(firstLibraryName, customLibraryTable.libraries.single().name)
|
||||
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
assertEquals(1, globalWorkspaceModel.currentSnapshot.entities(LibraryEntity::class.java).toList().size)
|
||||
|
||||
val mockCustomLibraryTableDescription = MockCustomLibraryTableDescription()
|
||||
|
||||
@@ -47,17 +47,17 @@ class GlobalWorkspaceModelEelTest {
|
||||
assumeRegistryValueSet()
|
||||
application.service<GlobalWorkspaceModelRegistry>().dropCaches()
|
||||
|
||||
val globalWorkspaceModelEel = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor())
|
||||
val globalWorkspaceModelEel = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor().machine)
|
||||
|
||||
edtWriteAction {
|
||||
globalWorkspaceModelEel.updateModel("A test update") { mutableStorage ->
|
||||
mutableStorage.addEntity(StringEntity("sample", SampleEntitySource("test eel")))
|
||||
}
|
||||
}
|
||||
val eelEntities = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor()).currentSnapshot.entities(StringEntity::class.java).toList()
|
||||
val eelEntities = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor().machine).currentSnapshot.entities(StringEntity::class.java).toList()
|
||||
Assertions.assertFalse(eelEntities.isEmpty())
|
||||
|
||||
val localEntities = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor()).currentSnapshot.entities(StringEntity::class.java).toList()
|
||||
val localEntities = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor().machine).currentSnapshot.entities(StringEntity::class.java).toList()
|
||||
Assertions.assertTrue(localEntities.isEmpty())
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ class GlobalWorkspaceModelEelTest {
|
||||
assumeRegistryValueSet()
|
||||
application.service<GlobalWorkspaceModelRegistry>().dropCaches()
|
||||
|
||||
val globalWorkspaceModelEel = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor())
|
||||
val globalWorkspaceModelLocal = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor())
|
||||
val globalWorkspaceModelEel = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor().machine)
|
||||
val globalWorkspaceModelLocal = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor().machine)
|
||||
|
||||
|
||||
edtWriteAction {
|
||||
@@ -83,15 +83,15 @@ class GlobalWorkspaceModelEelTest {
|
||||
application.service<GlobalWorkspaceModelCache>().saveCacheNow()
|
||||
application.service<GlobalWorkspaceModelRegistry>().dropCaches()
|
||||
|
||||
val eelModel = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor())
|
||||
val eelModel = GlobalWorkspaceModel.getInstance(eelProject.get().getEelDescriptor().machine)
|
||||
Assertions.assertTrue(eelModel.loadedFromCache)
|
||||
val eelEntities = eelModel.currentSnapshot.entities(StringEntity::class.java).toList()
|
||||
Assertions.assertTrue(eelEntities.find { it.data == "eel sample" } != null)
|
||||
Assertions.assertFalse(eelEntities.find { it.data == "local sample" } != null)
|
||||
|
||||
val localModel = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor())
|
||||
val localModel = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor().machine)
|
||||
Assertions.assertTrue(localModel.loadedFromCache)
|
||||
val localEntities = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor()).currentSnapshot.entities(StringEntity::class.java).toList()
|
||||
val localEntities = GlobalWorkspaceModel.getInstance(localProject.get().getEelDescriptor().machine).currentSnapshot.entities(StringEntity::class.java).toList()
|
||||
Assertions.assertTrue(localEntities.find { it.data == "local sample" } != null)
|
||||
Assertions.assertFalse(localEntities.find { it.data == "eel sample" } != null)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.intellij.workspaceModel.ide.impl.jps.serialization
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.JpsGlobalFileEntitySource
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryRootTypeId
|
||||
@@ -46,7 +47,7 @@ class JpsGlobalEntitiesLoaderTest {
|
||||
Assert.assertEquals(librariesNames.size, libraryBridges.size)
|
||||
UsefulTestCase.assertSameElements(librariesNames, libraryBridges.map { it.name })
|
||||
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
val libraryEntities = workspaceModel.currentSnapshot.entities(LibraryEntity::class.java).toList()
|
||||
Assert.assertEquals(librariesNames.size, libraryEntities.size)
|
||||
UsefulTestCase.assertSameElements(librariesNames, libraryEntities.map { it.name })
|
||||
@@ -73,7 +74,7 @@ class JpsGlobalEntitiesLoaderTest {
|
||||
Assert.assertEquals(sdkInfos.size, sdkBridges.size)
|
||||
UsefulTestCase.assertSameElements(sdkInfos, sdkBridges.map { SdkTestInfo(it.name, it.versionString!!, it.sdkType.name) })
|
||||
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
val sdkEntities = workspaceModel.currentSnapshot.entities(SdkEntity::class.java).toList()
|
||||
Assert.assertEquals(sdkInfos.size, sdkEntities.size)
|
||||
UsefulTestCase.assertSameElements(sdkInfos, sdkEntities.map { SdkTestInfo(it.name, it.version!!, it.type) })
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.roots.PersistentOrderRootType
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.entities.*
|
||||
import com.intellij.testFramework.ApplicationRule
|
||||
import com.intellij.testFramework.DisposableRule
|
||||
@@ -44,7 +45,7 @@ class JpsGlobalEntitiesSavingTest {
|
||||
libraryTable as GlobalLibraryTableBridgeImpl
|
||||
Assert.assertEquals(0, libraryTable.libraries.size)
|
||||
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
Assert.assertEquals(0, workspaceModel.currentSnapshot.entities(LibraryEntity::class.java).toList().size)
|
||||
|
||||
val virtualFileManager = workspaceModel.getVirtualFileUrlManager()
|
||||
@@ -80,7 +81,7 @@ class JpsGlobalEntitiesSavingTest {
|
||||
val sdks = ProjectJdkTable.getInstance().allJdks
|
||||
Assert.assertEquals(0, sdks.size)
|
||||
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val workspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
Assert.assertEquals(0, workspaceModel.currentSnapshot.entities(SdkEntity::class.java).toList().size)
|
||||
|
||||
val virtualFileManager = workspaceModel.getVirtualFileUrlManager()
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.platform.backend.workspace.WorkspaceModel
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.entities.*
|
||||
import com.intellij.testFramework.ApplicationRule
|
||||
import com.intellij.testFramework.DisposableRule
|
||||
@@ -50,7 +51,7 @@ class JpsGlobalEntitiesSyncTest {
|
||||
parentDisposable = disposableRule.disposable, ) { _, entitySource ->
|
||||
val sdkInfos = mutableListOf(SdkTestInfo("corretto-20", "Amazon Corretto version 20.0.2", "JavaSDK"),
|
||||
SdkTestInfo("jbr-17", "java version \"17.0.7\"", "JavaSDK"))
|
||||
val sdkEntities = GlobalWorkspaceModel.getInstance(LocalEelDescriptor).currentSnapshot.entities(SdkEntity::class.java).toList()
|
||||
val sdkEntities = GlobalWorkspaceModel.getInstance(LocalEelMachine).currentSnapshot.entities(SdkEntity::class.java).toList()
|
||||
UsefulTestCase.assertSameElements(sdkInfos, sdkEntities.map { SdkTestInfo(it.name, it.version!!, it.type) })
|
||||
|
||||
val loadedProjects = listOf(loadProject(), loadProject())
|
||||
@@ -59,7 +60,7 @@ class JpsGlobalEntitiesSyncTest {
|
||||
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
runWriteAction {
|
||||
GlobalWorkspaceModel.getInstance(LocalEelDescriptor).updateModel("Test update") { builder ->
|
||||
GlobalWorkspaceModel.getInstance(LocalEelMachine).updateModel("Test update") { builder ->
|
||||
val sdkEntity = builder.entities(SdkEntity::class.java).first { it.name == "corretto-20" }
|
||||
val sdkNameToRemove = sdkEntity.name
|
||||
builder.removeEntity(sdkEntity)
|
||||
@@ -111,7 +112,7 @@ class JpsGlobalEntitiesSyncTest {
|
||||
val sdkBridges = ProjectJdkTable.getInstance().allJdks
|
||||
UsefulTestCase.assertSameElements(sdkBridges.map { SdkTestInfo(it.name, it.versionString!!, it.sdkType.name) }, sdkInfos)
|
||||
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
val globalVirtualFileUrlManager = globalWorkspaceModel.getVirtualFileUrlManager()
|
||||
|
||||
val sdkEntities = globalWorkspaceModel.currentSnapshot.entities(SdkEntity::class.java).toList()
|
||||
@@ -144,7 +145,7 @@ class JpsGlobalEntitiesSyncTest {
|
||||
val projectLibrariesNames = mutableListOf("spring", "junit", "kotlin")
|
||||
val globalLibrariesNames = mutableListOf("aws.s3", "org.maven.common", "com.google.plugin", "org.microsoft")
|
||||
|
||||
val globalLibraryEntities = GlobalWorkspaceModel.getInstance(LocalEelDescriptor).currentSnapshot.entities(LibraryEntity::class.java).toList()
|
||||
val globalLibraryEntities = GlobalWorkspaceModel.getInstance(LocalEelMachine).currentSnapshot.entities(LibraryEntity::class.java).toList()
|
||||
UsefulTestCase.assertSameElements(globalLibrariesNames, globalLibraryEntities.map { it.name })
|
||||
|
||||
val loadedProjects = listOf(loadProject(), loadProject())
|
||||
@@ -153,7 +154,7 @@ class JpsGlobalEntitiesSyncTest {
|
||||
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
runWriteAction {
|
||||
GlobalWorkspaceModel.getInstance(LocalEelDescriptor).updateModel("Test update") { builder ->
|
||||
GlobalWorkspaceModel.getInstance(LocalEelMachine).updateModel("Test update") { builder ->
|
||||
val libraryEntity = builder.entities(LibraryEntity::class.java).first{ it.name == "aws.s3" }
|
||||
val libraryNameToRemove = libraryEntity.name
|
||||
builder.removeEntity(libraryEntity)
|
||||
@@ -201,7 +202,7 @@ class JpsGlobalEntitiesSyncTest {
|
||||
val libraryBridges = libraryTable.libraries
|
||||
UsefulTestCase.assertSameElements(globalLibrariesNames, libraryBridges.map { it.name })
|
||||
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelDescriptor)
|
||||
val globalWorkspaceModel = GlobalWorkspaceModel.getInstance(LocalEelMachine)
|
||||
val globalVirtualFileUrlManager = globalWorkspaceModel.getVirtualFileUrlManager()
|
||||
|
||||
val globalLibraryEntities = globalWorkspaceModel.currentSnapshot.entities(LibraryEntity::class.java).associateBy { it.name }
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.LocalEelMachine
|
||||
import com.intellij.platform.workspace.jps.*
|
||||
import com.intellij.platform.workspace.jps.entities.LibraryEntity
|
||||
import com.intellij.platform.workspace.jps.serialization.impl.*
|
||||
@@ -460,7 +461,7 @@ internal fun copyAndLoadGlobalEntities(originalFile: String? = null,
|
||||
ApplicationManager.getApplication().replaceService(GlobalWorkspaceModelRegistry::class.java, GlobalWorkspaceModelRegistry(), parentDisposable)
|
||||
|
||||
// Entity source for global entities
|
||||
val virtualFileManager = GlobalWorkspaceModel.getInstance(LocalEelDescriptor).getVirtualFileUrlManager()
|
||||
val virtualFileManager = GlobalWorkspaceModel.getInstance(LocalEelMachine).getVirtualFileUrlManager()
|
||||
val globalLibrariesFile = virtualFileManager.getOrCreateFromUrl("$testDir/options/applicationLibraries.xml")
|
||||
val libraryEntitySource = JpsGlobalFileEntitySource(globalLibrariesFile)
|
||||
|
||||
@@ -473,7 +474,7 @@ internal fun copyAndLoadGlobalEntities(originalFile: String? = null,
|
||||
application.invokeAndWait { saveDocumentsAndProjectsAndApp(true) }
|
||||
val globalEntitiesFolder = File(PathManagerEx.getCommunityHomePath(),
|
||||
"platform/workspace/jps/tests/testData/serialization/global/$expectedFile")
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(LocalEelDescriptor).entityStorage.current
|
||||
val entityStorage = GlobalWorkspaceModel.getInstance(LocalEelMachine).entityStorage.current
|
||||
if (entityStorage.entities(LibraryEntity::class.java).toList().isEmpty()) {
|
||||
optionsFolder.assertMatches(directoryContentOf(globalEntitiesFolder.toPath()),
|
||||
filePathFilter = { it.contains("jdk.table.xml") })
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.intellij.platform.eel.EelTunnelsApi.HostAddress
|
||||
import com.intellij.platform.eel.fs.getPath
|
||||
import com.intellij.platform.eel.provider.LocalEelDescriptor
|
||||
import com.intellij.platform.eel.provider.asEelPath
|
||||
import com.intellij.platform.eel.provider.asNioPathOrNull
|
||||
import com.intellij.platform.eel.provider.asNioPath
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.eel.provider.utils.forwardLocalPort
|
||||
import com.intellij.util.PathMapper
|
||||
@@ -43,7 +43,7 @@ class EelTargetEnvironmentConfigurationProvider(val eel: EelApi, val project: Pr
|
||||
override fun convertToLocal(remotePath: String): String {
|
||||
val nio = Path.of(remotePath)
|
||||
val eelPath = eel.fs.getPath(nio.toCanonicalPath())
|
||||
return eelPath.asNioPathOrNull(project)!!.toCanonicalPath()
|
||||
return eelPath.asNioPath().toCanonicalPath()
|
||||
}
|
||||
|
||||
override fun canReplaceRemote(remotePath: String): Boolean {
|
||||
|
||||
@@ -347,7 +347,7 @@ class MavenShCommandLineState(val environment: ExecutionEnvironment, private val
|
||||
if (type is MavenWrapper) {
|
||||
val path = getPathToWrapperScript()
|
||||
val file = workingDir.resolve(path)
|
||||
if (file.asNioPath(myConfiguration.project).exists()) {
|
||||
if (file.asNioPath().exists()) {
|
||||
return path
|
||||
}
|
||||
return getMavenExecutablePath(BundledMaven3, eel)
|
||||
|
||||
@@ -55,7 +55,7 @@ class EelRemotePathTransformFactory : RemotePathTransformerFactory {
|
||||
val canonicalPath = Paths.get(remotePath).toCanonicalPath()
|
||||
return runCatching {
|
||||
val eelPath = eel.fs.getPath(canonicalPath)
|
||||
val fullyQualifiedPath = eelPath.asNioPath(project)
|
||||
val fullyQualifiedPath = eelPath.asNioPath()
|
||||
return@runCatching fullyQualifiedPath.toString()
|
||||
}.getOrNull() ?: remotePath
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.openapi.util.text.HtmlChunk
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.path.EelPath.Companion.parse
|
||||
import com.intellij.platform.eel.pathSeparator
|
||||
import com.intellij.platform.eel.provider.asNioPath
|
||||
@@ -87,14 +88,14 @@ internal class ShDocumentationProvider(private val scope: CoroutineScope) : Docu
|
||||
return contextElement
|
||||
}
|
||||
|
||||
private val myManExecutableCache = ConcurrentHashMap<EelDescriptor, SuspendingLazy<String?>>()
|
||||
private val myManCache = ConcurrentHashMap<Pair<EelDescriptor, String>, SuspendingLazy<String>>()
|
||||
private val myManExecutableCache = ConcurrentHashMap<EelMachine, SuspendingLazy<String?>>()
|
||||
private val myManCache = ConcurrentHashMap<Pair<EelMachine, String>, SuspendingLazy<String>>()
|
||||
|
||||
private fun fetchInfo(commandName: String?, project: Project): @NlsSafe String? {
|
||||
val eelDescriptor = project.getEelDescriptor()
|
||||
|
||||
if (commandName == null) return null
|
||||
val manExecutablePromise = myManExecutableCache.computeIfAbsent(eelDescriptor) {
|
||||
val manExecutablePromise = myManExecutableCache.computeIfAbsent(eelDescriptor.machine) {
|
||||
scope.suspendingLazy {
|
||||
val eel = eelDescriptor.toEelApi()
|
||||
val path = eel.exec.fetchLoginShellEnvVariables()["PATH"]
|
||||
@@ -115,7 +116,7 @@ internal class ShDocumentationProvider(private val scope: CoroutineScope) : Docu
|
||||
}
|
||||
|
||||
return runBlockingMaybeCancellable { // fixme: is this good idea call blocking code here?
|
||||
myManCache.computeIfAbsent(eelDescriptor to commandName) {
|
||||
myManCache.computeIfAbsent(eelDescriptor.machine to commandName) {
|
||||
scope.suspendingLazy {
|
||||
val manExecutable = manExecutablePromise.getValue()
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ suspend fun ExecService.execGetStdout(
|
||||
procListener: PyProcessListener? = null,
|
||||
): PyResult<String> {
|
||||
val binary = eelApi.exec.findExeFilesInPath(binaryName).firstOrNull()?.asNioPath()
|
||||
?: return PyResult.localizedError(PyExecBundle.message("py.exec.fileNotFound", binaryName, eelApi.descriptor.userReadableDescription))
|
||||
?: return PyResult.localizedError(PyExecBundle.message("py.exec.fileNotFound", binaryName, eelApi.descriptor.machine.name))
|
||||
return execGetStdout(binary, args, options, procListener)
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class ExecServiceShowCaseTest {
|
||||
}
|
||||
SimpleApiExecType.FULL_PATH -> {
|
||||
var fullPath = eel.exec.findExeFilesInPath(binary).firstOrNull()
|
||||
?: error("no $binary found on ${eel.descriptor.userReadableDescription}")
|
||||
?: error("no $binary found on ${eel.descriptor.machine.name}")
|
||||
if (rainyDay) {
|
||||
fullPath = fullPath.resolve("junk")
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.openapi.util.registry.RegistryManager
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelMachine
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.eel.provider.localEel
|
||||
import com.intellij.python.community.impl.installer.PySdkToInstallManager
|
||||
@@ -49,13 +50,13 @@ internal suspend fun getCacheTimeout(): Duration? =
|
||||
@Internal
|
||||
internal class SystemPythonServiceImpl(scope: CoroutineScope) : SystemPythonService, SimplePersistentStateComponent<MyServiceState>(MyServiceState()) {
|
||||
private val findPythonsMutex = Mutex()
|
||||
private val _cacheImpl: CompletableDeferred<Cache<EelDescriptor, SystemPython>?> = CompletableDeferred()
|
||||
private val _cacheImpl: CompletableDeferred<Cache<EelMachine, SystemPython>?> = CompletableDeferred()
|
||||
private suspend fun cache() = _cacheImpl.await()
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
_cacheImpl.complete(getCacheTimeout()?.let { interval ->
|
||||
Cache<EelDescriptor, SystemPython>(scope, interval) { eelDescriptor ->
|
||||
Cache<EelMachine, SystemPython>(scope, interval) { eelDescriptor ->
|
||||
searchPythonsPhysicallyNoCache(eelDescriptor.toEelApi())
|
||||
}
|
||||
})
|
||||
@@ -67,7 +68,7 @@ internal class SystemPythonServiceImpl(scope: CoroutineScope) : SystemPythonServ
|
||||
.getOr(PySystemPythonBundle.message("py.system.python.service.python.is.broken", pythonPath)) { return it }
|
||||
val systemPython = SystemPython(pythonWithLangLevel, null)
|
||||
state.userProvidedPythons.add(pythonPath.pathString)
|
||||
cache()?.get(pythonPath.getEelDescriptor())?.add(systemPython)
|
||||
cache()?.get(pythonPath.getEelDescriptor().machine)?.add(systemPython)
|
||||
return Result.success(systemPython)
|
||||
}
|
||||
|
||||
@@ -80,10 +81,10 @@ internal class SystemPythonServiceImpl(scope: CoroutineScope) : SystemPythonServ
|
||||
cache.startUpdate()
|
||||
if (forceRefresh) {
|
||||
logger.info("pythons refresh requested")
|
||||
cache.updateCache(eelApi.descriptor) // Update cache and suspend till update finished
|
||||
cache.updateCache(eelApi.descriptor.machine) // Update cache and suspend till update finished
|
||||
}
|
||||
else {
|
||||
cache.get(eelApi.descriptor)
|
||||
cache.get(eelApi.descriptor.machine)
|
||||
}.sorted()
|
||||
} ?: searchPythonsPhysicallyNoCache(eelApi).sorted()
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ suspend fun detectPipEnvExecutable(): PyResult<Path> {
|
||||
}
|
||||
val executablePath = localEel.exec.where(name)?.asNioPath()
|
||||
if (executablePath == null) {
|
||||
return PyResult.localizedError(PyBundle.message("cannot.find.executable", name, localEel.descriptor.userReadableDescription))
|
||||
return PyResult.localizedError(PyBundle.message("cannot.find.executable", name, localEel.descriptor.machine.name))
|
||||
}
|
||||
|
||||
return PyResult.success(executablePath)
|
||||
|
||||
Reference in New Issue
Block a user