From ad808e267ed622dc838af9b8b8b401feae92bc14 Mon Sep 17 00:00:00 2001 From: Andrii Zinchenko Date: Mon, 30 Sep 2024 16:17:50 +0200 Subject: [PATCH] [eel] generalize all eel result types into a single EelResult Motivation: 1. Allows removing identical "unwrap" functions for each result type 2. Makes it easier to add helper functions GitOrigin-RevId: fd05408f6c756b3220120c87c8738df45573b008 --- .../com/intellij/platform/eel/EelExecApi.kt | 10 +-- .../com/intellij/platform/eel/EelResult.kt | 22 ++++++ .../intellij/platform/eel/EelTunnelsApi.kt | 32 ++------ .../platform/eel/fs/EelFileSystemApi.kt | 43 +++++------ .../intellij/platform/eel/fs/EelFsResult.kt | 13 ---- .../eel/path/ArrayListEelAbsolutePath.kt | 73 +++++++++---------- .../eel/path/ArrayListEelRelativePath.kt | 26 ++++--- .../com/intellij/platform/eel/path/EelPath.kt | 53 ++++++-------- .../platform/eel/path/EelPathResultImpl.kt | 7 +- .../platform/eel/path/EelAbsolutePathTest.kt | 5 +- .../eel/impl/local/EelLocalExecApi.kt | 9 ++- .../eel/impl/local/LocalEelApiImpl.kt | 4 +- .../platform/eel/provider/EelFsResultImpl.kt | 6 +- .../eel/provider/EelProcessResultImpl.kt | 17 +++++ .../eel/provider/utils/eelPathUtils.kt | 8 -- .../eel/provider/utils/eelProcessUtils.kt | 20 +---- .../ijent/AbstractIjentVerificationAction.kt | 6 +- .../impl/IjentFailSafeFileSystemPosixApi.kt | 22 +++--- .../community/impl/nio/IjentNioFileSystem.kt | 4 +- .../impl/nio/IjentNioFileSystemUtil.kt | 9 +-- .../execution/eel/EelApiWithPathsMapping.kt | 7 +- .../intellij/execution/wsl/WslIjentUtil.kt | 7 +- .../execution/eel/EelLocalExecApiTest.kt | 7 +- .../execution/wsl/WSLDistributionTest.kt | 12 +-- 24 files changed, 208 insertions(+), 214 deletions(-) create mode 100644 platform/eel/src/com/intellij/platform/eel/EelResult.kt create mode 100644 platform/eelProvider/src/com/intellij/platform/eel/provider/EelProcessResultImpl.kt diff --git a/platform/eel/src/com/intellij/platform/eel/EelExecApi.kt b/platform/eel/src/com/intellij/platform/eel/EelExecApi.kt index 05d6aa917465..9e488dc03539 100644 --- a/platform/eel/src/com/intellij/platform/eel/EelExecApi.kt +++ b/platform/eel/src/com/intellij/platform/eel/EelExecApi.kt @@ -17,7 +17,7 @@ interface EelExecApi { * * See [executeProcessBuilder] */ - suspend fun execute(builder: ExecuteProcessBuilder): ExecuteProcessResult + suspend fun execute(builder: ExecuteProcessBuilder): EelResult /** Docs: [executeProcessBuilder] */ interface ExecuteProcessBuilder { @@ -63,9 +63,9 @@ interface EelExecApi { */ suspend fun fetchLoginShellEnvVariables(): Map - sealed interface ExecuteProcessResult { - class Success(val process: EelProcess) : ExecuteProcessResult - data class Failure(val errno: Int, val message: String) : ExecuteProcessResult + interface ExecuteProcessError { + val errno: Int + val message: String } /** [echo] must be true in general and must be false when the user is asked for a password. */ @@ -73,7 +73,7 @@ interface EelExecApi { } /** Docs: [EelExecApi.executeProcessBuilder] */ -suspend fun EelExecApi.executeProcess(exe: String, vararg args: String): EelExecApi.ExecuteProcessResult = +suspend fun EelExecApi.executeProcess(exe: String, vararg args: String): EelResult = execute(EelExecApi.executeProcessBuilder(exe).args(listOf(*args))) /** Docs: [EelExecApi.executeProcessBuilder] */ diff --git a/platform/eel/src/com/intellij/platform/eel/EelResult.kt b/platform/eel/src/com/intellij/platform/eel/EelResult.kt new file mode 100644 index 000000000000..d44fef8c5ce8 --- /dev/null +++ b/platform/eel/src/com/intellij/platform/eel/EelResult.kt @@ -0,0 +1,22 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.eel + +sealed interface EelResult { + interface Ok : EelResult { + val value: P + } + + interface Error : EelResult { + val error: E + } +} + +inline fun EelResult.getOrThrow(action: (E) -> Nothing = { throw RuntimeException(it.toString()) }): T = when (this) { + is EelResult.Ok -> this.value + is EelResult.Error -> action(this.error) +} + +fun EelResult.getOrNull(): T? = when (this) { + is EelResult.Ok -> this.value + is EelResult.Error -> null +} diff --git a/platform/eel/src/com/intellij/platform/eel/EelTunnelsApi.kt b/platform/eel/src/com/intellij/platform/eel/EelTunnelsApi.kt index 9480fe26527c..a1ea4bf571a7 100644 --- a/platform/eel/src/com/intellij/platform/eel/EelTunnelsApi.kt +++ b/platform/eel/src/com/intellij/platform/eel/EelTunnelsApi.kt @@ -2,7 +2,6 @@ package com.intellij.platform.eel import com.intellij.platform.eel.EelTunnelsApi.Connection -import com.intellij.platform.eel.impl.IpProtocolPreferenceImpl import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.ReceiveChannel import kotlinx.coroutines.channels.SendChannel @@ -36,7 +35,7 @@ sealed interface EelTunnelsApi { * * One should not forget to invoke [Connection.close] when the connection is not needed. */ - suspend fun getConnectionToRemotePort(address: HostAddress): EelNetworkResult + suspend fun getConnectionToRemotePort(address: HostAddress): EelResult /** * Creates a builder for address on the remote host. @@ -204,7 +203,7 @@ sealed interface EelTunnelsApi { * * One should not forget to invoke [Connection.close] when the connection is not needed. */ - suspend fun getAcceptorForRemotePort(address: HostAddress): EelNetworkResult + suspend fun getAcceptorForRemotePort(address: HostAddress): EelResult /** * This is a representation of a remote server bound to [boundAddress]. @@ -311,8 +310,8 @@ suspend fun EelTunnelsApi.withConnectionToRemotePort( action: suspend CoroutineScope.(Connection) -> T, ): T = when (val connectionResult = getConnectionToRemotePort(hostAddress)) { - is EelNetworkResult.Error -> errorHandler(connectionResult.error) - is EelNetworkResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() }) + is EelResult.Error -> errorHandler(connectionResult.error) + is EelResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() }) } private suspend fun closeWithExceptionHandling(action: suspend CoroutineScope.() -> T, close: suspend () -> Unit): T { @@ -360,8 +359,8 @@ suspend fun EelTunnelsApi.withAcceptorForRemotePort( action: suspend CoroutineScope.(EelTunnelsApi.ConnectionAcceptor) -> T, ): T = when (val connectionResult = getAcceptorForRemotePort(hostAddress)) { - is EelNetworkResult.Error -> errorHandler(connectionResult.error) - is EelNetworkResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() }) + is EelResult.Error -> errorHandler(connectionResult.error) + is EelResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() }) } /** @@ -369,25 +368,6 @@ suspend fun EelTunnelsApi.withAcceptorForRemotePort( */ sealed interface EelNetworkError -/** - * Represents a result of a network operation - */ -sealed interface EelNetworkResult { - /** - * Used when a network operation completed successfully - */ - interface Ok : EelNetworkResult { - val value: T - } - - /** - * Used when a network operation completed with an error - */ - interface Error : EelNetworkResult { - val error: E - } -} - /** * An error that can happen during the creation of a connection to a remote server */ diff --git a/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt b/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt index 4cc8ddd11e0d..2ef9c8628c1e 100644 --- a/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt +++ b/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt @@ -1,15 +1,16 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.eel.fs +import com.intellij.platform.eel.EelResult import com.intellij.platform.eel.EelUserInfo import com.intellij.platform.eel.EelUserPosixInfo import com.intellij.platform.eel.EelUserWindowsInfo import com.intellij.platform.eel.fs.EelFileSystemApi.StatError import com.intellij.platform.eel.path.EelPath -import com.intellij.platform.eel.path.EelPathResult +import com.intellij.platform.eel.path.EelPathError import java.nio.ByteBuffer -fun EelFileSystemApi.getPath(string: String, vararg other: String): EelPathResult { +fun EelFileSystemApi.getPath(string: String, vararg other: String): EelResult { return EelPath.Absolute.build(listOf(string, *other), when (this) { is EelFileSystemPosixApi -> EelPath.Absolute.OS.UNIX is EelFileSystemWindowsApi -> EelPath.Absolute.OS.WINDOWS @@ -37,7 +38,7 @@ interface EelFileSystemApi { /** * Returns names of files in a directory. If [path] is a symlink, it will be resolved, but no symlinks are resolved among children. */ - suspend fun listDirectory(path: EelPath.Absolute): EelFsResult< + suspend fun listDirectory(path: EelPath.Absolute): EelResult< Collection, ListDirectoryError> @@ -52,7 +53,7 @@ interface EelFileSystemApi { suspend fun listDirectoryWithAttrs( path: EelPath.Absolute, symlinkPolicy: SymlinkPolicy, - ): EelFsResult< + ): EelResult< Collection>, ListDirectoryError> @@ -67,7 +68,7 @@ interface EelFileSystemApi { /** * Resolves all symlinks in the path. Corresponds to realpath(3) on Unix and GetFinalPathNameByHandle on Windows. */ - suspend fun canonicalize(path: EelPath.Absolute): EelFsResult< + suspend fun canonicalize(path: EelPath.Absolute): EelResult< EelPath.Absolute, CanonicalizeError> @@ -82,7 +83,7 @@ interface EelFileSystemApi { /** * Similar to stat(2) and lstat(2). [symlinkPolicy] has an impact only on [EelFileInfo.type] if [path] points on a symlink. */ - suspend fun stat(path: EelPath.Absolute, symlinkPolicy: SymlinkPolicy): EelFsResult + suspend fun stat(path: EelPath.Absolute, symlinkPolicy: SymlinkPolicy): EelResult /** * Defines the behavior of FS operations on symbolic links @@ -118,7 +119,7 @@ interface EelFileSystemApi { * On Unix return true if both paths have the same inode. * On Windows some heuristics are used, for more details see https://docs.rs/same-file/1.0.6/same_file/ */ - suspend fun sameFile(source: EelPath.Absolute, target: EelPath.Absolute): EelFsResult< + suspend fun sameFile(source: EelPath.Absolute, target: EelPath.Absolute): EelResult< Boolean, SameFileError> @@ -133,7 +134,7 @@ interface EelFileSystemApi { /** * Opens the file only for reading */ - suspend fun openForReading(path: EelPath.Absolute): EelFsResult< + suspend fun openForReading(path: EelPath.Absolute): EelResult< EelOpenedFile.Reader, FileReaderError> @@ -151,7 +152,7 @@ interface EelFileSystemApi { */ suspend fun openForWriting( options: WriteOptions, - ): EelFsResult< + ): EelResult< EelOpenedFile.Writer, FileWriterError> @@ -193,7 +194,7 @@ interface EelFileSystemApi { interface Other : FileWriterError, EelFsError.Other } - suspend fun openForReadingAndWriting(options: WriteOptions): EelFsResult + suspend fun openForReadingAndWriting(options: WriteOptions): EelResult @Throws(DeleteException::class) suspend fun delete(path: EelPath.Absolute, removeContent: Boolean) @@ -297,7 +298,7 @@ sealed interface EelOpenedFile { : CloseException(where, additionalMessage), EelFsError.Other } - suspend fun tell(): EelFsResult< + suspend fun tell(): EelResult< Long, TellError> @@ -305,7 +306,7 @@ sealed interface EelOpenedFile { interface Other : TellError, EelFsError.Other } - suspend fun seek(offset: Long, whence: SeekWhence): EelFsResult< + suspend fun seek(offset: Long, whence: SeekWhence): EelResult< Long, SeekError> @@ -325,7 +326,7 @@ sealed interface EelOpenedFile { * Sometimes, the files are inaccessible via [EelFileSystemApi.stat] -- for example, if they are deleted. * In this case, one can get the information about the opened file with the use of this function. */ - suspend fun stat(): EelFsResult + suspend fun stat(): EelResult interface Reader : EelOpenedFile { @@ -341,7 +342,7 @@ sealed interface EelOpenedFile { * * The implementation MAY read less data than the capacity of the buffer even if it's possible to read the whole requested buffer. */ - suspend fun read(buf: ByteBuffer): EelFsResult + suspend fun read(buf: ByteBuffer): EelResult /** * Reads data from the position [offset] of the file. @@ -350,7 +351,7 @@ sealed interface EelOpenedFile { * * The implementation MAY read less than [offset] bytes even if it's possible to read the whole requested buffer. */ - suspend fun read(buf: ByteBuffer, offset: Long): EelFsResult + suspend fun read(buf: ByteBuffer, offset: Long): EelResult sealed interface ReadResult { interface EOF : ReadResult @@ -372,7 +373,7 @@ sealed interface EelOpenedFile { * * The implementation MAY write the part of the [buf] even if it's possible to write the whole buffer. */ - suspend fun write(buf: ByteBuffer): EelFsResult< + suspend fun write(buf: ByteBuffer): EelResult< Int, WriteError> @@ -381,7 +382,7 @@ sealed interface EelOpenedFile { * * The implementation MAY write the part of the [buf] even if it's possible to write the whole buffer. */ - suspend fun write(buf: ByteBuffer, pos: Long): EelFsResult< + suspend fun write(buf: ByteBuffer, pos: Long): EelResult< Int, WriteError> @@ -459,11 +460,11 @@ interface EelFileSystemPosixApi : EelFileSystemApi { override suspend fun listDirectoryWithAttrs( path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy, - ): EelFsResult< + ): EelResult< Collection>, EelFileSystemApi.ListDirectoryError> - override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelFsResult< + override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelResult< EelPosixFileInfo, StatError> @@ -528,11 +529,11 @@ interface EelFileSystemWindowsApi : EelFileSystemApi { override suspend fun listDirectoryWithAttrs( path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy, - ): EelFsResult< + ): EelResult< Collection>, EelFileSystemApi.ListDirectoryError> - override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelFsResult< + override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelResult< EelWindowsFileInfo, StatError> } \ No newline at end of file diff --git a/platform/eel/src/com/intellij/platform/eel/fs/EelFsResult.kt b/platform/eel/src/com/intellij/platform/eel/fs/EelFsResult.kt index 25df9f95927e..c126baa39b6f 100644 --- a/platform/eel/src/com/intellij/platform/eel/fs/EelFsResult.kt +++ b/platform/eel/src/com/intellij/platform/eel/fs/EelFsResult.kt @@ -5,19 +5,6 @@ import com.intellij.platform.eel.path.EelPath import org.jetbrains.annotations.Nls import java.io.IOException -/** - * [T] should not be `Unit`, throw a subclass of [EelFsIOException] in such cases instead. - */ -sealed interface EelFsResult { - interface Ok : EelFsResult { - val value: T - } - - interface Error : EelFsResult { - val error: E - } -} - sealed interface EelFsError { val where: EelPath.Absolute diff --git a/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelAbsolutePath.kt b/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelAbsolutePath.kt index 8b26f1ded2b2..a044256863bf 100644 --- a/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelAbsolutePath.kt +++ b/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelAbsolutePath.kt @@ -1,8 +1,7 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.eel.path -import com.intellij.platform.eel.path.EelPathResult.Err -import com.intellij.platform.eel.path.EelPathResult.Ok +import com.intellij.platform.eel.EelResult internal class ArrayListEelAbsolutePath private constructor( private val _root: Root, @@ -34,7 +33,7 @@ internal class ArrayListEelAbsolutePath private constructor( root.fileName == other.root.fileName && (0.. { + override fun normalize(): EelResult { val result = mutableListOf() for (part in parts) { when (part) { @@ -42,7 +41,7 @@ internal class ArrayListEelAbsolutePath private constructor( ".." -> if (result.isEmpty()) - return Err(toString(), "Traversing beyond the root") + return ErrorResult(Err(toString(), "Traversing beyond the root")) else result.dropLast(1) @@ -50,28 +49,28 @@ internal class ArrayListEelAbsolutePath private constructor( result += part } } - return Ok(ArrayListEelAbsolutePath(_root, result)) + return OkResult(ArrayListEelAbsolutePath(_root, result)) } - override fun resolve(other: EelPath.Relative): EelPathResult { + override fun resolve(other: EelPath.Relative): EelResult { val result = parts.toMutableList() for (index in 0.. { + override fun getChild(name: String): EelResult { val error = checkFileName(name) return if (error == null) - Ok(ArrayListEelAbsolutePath(_root, parts + name)) + OkResult(ArrayListEelAbsolutePath(_root, parts + name)) else - Err(name, error) + ErrorResult(Err(name, error)) } override fun scan(): Sequence = @@ -131,9 +130,9 @@ internal class ArrayListEelAbsolutePath private constructor( return nameCount - other.nameCount } - override fun relativize(other: EelPath.Absolute): EelPathResult { + override fun relativize(other: EelPath.Absolute): EelResult { if (root != other.root) { - return Err(other.root.toString(), "The other path has a different root") + return ErrorResult(Err(other.root.toString(), "The other path has a different root")) } var firstDifferenceIndex = 0 @@ -171,7 +170,7 @@ internal class ArrayListEelAbsolutePath private constructor( }) companion object { - fun build(parts: List, os: EelPath.Absolute.OS?): EelPathResult { + fun build(parts: List, os: EelPath.Absolute.OS?): EelResult { require(parts.isNotEmpty()) { "Can't build an absolute path from no path parts" } val windowsRoot = when (os) { @@ -190,44 +189,44 @@ internal class ArrayListEelAbsolutePath private constructor( else parts for (part in parts) { val error = checkFileName(part, isWindows = false) - if (error != null) return Err(part, error) + if (error != null) return ErrorResult(Err(part, error)) } - return Ok(ArrayListEelAbsolutePath(Root.Unix, parts)) + return OkResult(ArrayListEelAbsolutePath(Root.Unix, parts)) } - is Ok -> { + is EelResult.Ok -> { @Suppress("NAME_SHADOWING") val parts = parts.drop(1) for (part in parts) { val error = checkFileName(part, isWindows = true) - if (error != null) return Err(part, error) + if (error != null) return ErrorResult(Err(part, error)) } - return Ok(ArrayListEelAbsolutePath(windowsRoot.path._root, parts)) + return OkResult(ArrayListEelAbsolutePath(windowsRoot.value._root, parts)) } - is Err -> return windowsRoot + is EelResult.Error -> return windowsRoot } } - fun parse(raw: String, os: EelPath.Absolute.OS?): EelPathResult = + fun parse(raw: String, os: EelPath.Absolute.OS?): EelResult = when (os) { EelPath.Absolute.OS.WINDOWS -> findAbsoluteUncPath(raw) ?: findAbsoluteTraditionalDosPath(raw) - ?: reportError(raw) + ?: ErrorResult(createErr(raw)) EelPath.Absolute.OS.UNIX -> findAbsoluteUnixPath(raw) - ?: reportError(raw) + ?: ErrorResult(createErr(raw)) null -> findAbsoluteUncPath(raw) ?: findAbsoluteTraditionalDosPath(raw) ?: findAbsoluteUnixPath(raw) - ?: reportError(raw) + ?: ErrorResult(createErr(raw)) } /** https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths */ - private fun findAbsoluteUncPath(raw: String): EelPathResult? { + private fun findAbsoluteUncPath(raw: String): EelResult? { if (raw.length < 3) return null if (raw.getOrNull(0) != raw.getOrNull(1)) return null @@ -239,12 +238,12 @@ internal class ArrayListEelAbsolutePath private constructor( run { val error = checkFileName(raw.substring(2, index), isWindows = true) - if (error != null) return Err(raw, "Incorrect server name in UNC path") + if (error != null) return ErrorResult(Err(raw, "Incorrect server name in UNC path")) } val shareNameStart = index - if (++index == raw.length) return Err(raw, "Empty share name in UNC path") + if (++index == raw.length) return ErrorResult(Err(raw, "Empty share name in UNC path")) // Skipping the server/host name. while (raw[index] !in "/\\") { @@ -253,7 +252,7 @@ internal class ArrayListEelAbsolutePath private constructor( run { val error = checkFileName(raw.substring(shareNameStart, index), isWindows = true) - if (error != null) return Err(raw, "Incorrect share name in UNC path") + if (error != null) return ErrorResult(Err(raw, "Incorrect share name in UNC path")) } val parts = raw.substring(index) @@ -263,14 +262,14 @@ internal class ArrayListEelAbsolutePath private constructor( for (part in parts) { val error = checkFileName(part, isWindows = true) - if (error != null) return Err(raw, error) + if (error != null) return ErrorResult(Err(raw, error)) } - return Ok(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, index).replace("/", "\\")), parts)) + return OkResult(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, index).replace("/", "\\")), parts)) } /** https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#traditional-dos-paths */ - private fun findAbsoluteTraditionalDosPath(raw: String): EelPathResult? { + private fun findAbsoluteTraditionalDosPath(raw: String): EelResult? { if (raw.length < 3) return null if (!raw[0].isLetter()) return null if (raw[1] != ':') return null @@ -283,13 +282,13 @@ internal class ArrayListEelAbsolutePath private constructor( for (part in parts) { val error = checkFileName(part, isWindows = true) - if (error != null) return Err(raw, error) + if (error != null) return ErrorResult(Err(raw, error)) } - return Ok(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, 3)), parts)) + return OkResult(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, 3)), parts)) } - private fun findAbsoluteUnixPath(raw: String): EelPathResult? { + private fun findAbsoluteUnixPath(raw: String): EelResult? { if (raw.getOrNull(0) != '/') return null val parts = raw @@ -299,13 +298,13 @@ internal class ArrayListEelAbsolutePath private constructor( for (part in parts) { val error = checkFileName(part, isWindows = false) - if (error != null) return Err(raw, error) + if (error != null) return ErrorResult(Err(raw, error)) } - return Ok(ArrayListEelAbsolutePath(Root.Unix, parts)) + return OkResult(ArrayListEelAbsolutePath(Root.Unix, parts)) } - private fun reportError(raw: String): Err = + private fun createErr(raw: String): Err = Err( raw = raw, reason = run { diff --git a/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelRelativePath.kt b/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelRelativePath.kt index 9ccffd4a17b6..52fde320a7bb 100644 --- a/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelRelativePath.kt +++ b/platform/eel/src/com/intellij/platform/eel/path/ArrayListEelRelativePath.kt @@ -1,6 +1,8 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.eel.path +import com.intellij.platform.eel.EelResult + internal class ArrayListEelRelativePath private constructor( private val parts: List, ) : EelPath.Relative { @@ -24,7 +26,7 @@ internal class ArrayListEelRelativePath private constructor( return true } - override fun resolve(other: EelPath.Relative): EelPathResult { + override fun resolve(other: EelPath.Relative): EelResult { val result = mutableListOf() result += parts if (other != EMPTY) { @@ -33,14 +35,14 @@ internal class ArrayListEelRelativePath private constructor( result += fileName } } - return Ok(ArrayListEelRelativePath(result)) + return OkResult(ArrayListEelRelativePath(result)) } - override fun getChild(name: String): EelPathResult = + override fun getChild(name: String): EelResult = when { - name.isEmpty() -> Err(name, "Empty child name is not allowed") - "/" in name -> Err(name, "Invalid symbol in child name: /") - else -> Ok(ArrayListEelRelativePath(parts + name)) + name.isEmpty() -> ErrorResult(Err(name, "Empty child name is not allowed")) + "/" in name -> ErrorResult(Err(name, "Invalid symbol in child name: /")) + else -> OkResult(ArrayListEelRelativePath(parts + name)) } override fun compareTo(other: EelPath.Relative): Int { @@ -108,22 +110,22 @@ internal class ArrayListEelRelativePath private constructor( val EMPTY = ArrayListEelRelativePath(listOf()) private val REGEX = Regex("""[/\\]""") - fun parse(raw: String): EelPathResult = + fun parse(raw: String): EelResult = build(raw.splitToSequence(REGEX).filter(String::isNotEmpty).iterator()) - fun build(parts: List): EelPathResult = + fun build(parts: List): EelResult = build(parts.iterator()) - private fun build(parts: Iterator): EelPathResult { + private fun build(parts: Iterator): EelResult { // Not optimal, but DRY. var result = ArrayListEelRelativePath(listOf()) for (part in parts) { result = when (val r = result.getChild(part)) { - is EelPathResult.Ok -> r.path - is EelPathResult.Err -> return r + is EelResult.Ok -> r.value + is EelResult.Error -> return r } } - return Ok(result) + return OkResult(result) } } } \ No newline at end of file diff --git a/platform/eel/src/com/intellij/platform/eel/path/EelPath.kt b/platform/eel/src/com/intellij/platform/eel/path/EelPath.kt index de32ddcddb18..b47d7cec9b73 100644 --- a/platform/eel/src/com/intellij/platform/eel/path/EelPath.kt +++ b/platform/eel/src/com/intellij/platform/eel/path/EelPath.kt @@ -2,17 +2,14 @@ package com.intellij.platform.eel.path import com.intellij.platform.eel.EelPlatform +import com.intellij.platform.eel.EelResult +import com.intellij.platform.eel.getOrThrow import com.intellij.platform.eel.path.EelPath.Absolute.OS import java.nio.file.InvalidPathException -sealed interface EelPathResult

{ - interface Ok

: EelPathResult

{ - val path: P - } - interface Err

: EelPathResult

{ - val raw: String - val reason: String - } +interface EelPathError { + val raw: String + val reason: String } /** @@ -26,10 +23,10 @@ sealed interface EelPathResult

{ sealed interface EelPath { companion object { @JvmStatic - fun parse(raw: String, os: OS?): EelPathResult = + fun parse(raw: String, os: OS?): EelResult = when (val absoluteResult = Absolute.parse(raw, os)) { - is EelPathResult.Ok -> absoluteResult - is EelPathResult.Err -> Relative.parse(raw) + is EelResult.Ok -> absoluteResult + is EelResult.Error -> Relative.parse(raw) } } @@ -102,7 +99,7 @@ sealed interface EelPath { * // TODO Wouldn't it be better to return different types for relative and absolute paths? * It should fail in cases like Absolute("/").resolve(Relative("..")). */ - fun resolve(other: Relative): EelPathResult + fun resolve(other: Relative): EelResult /** * ```kotlin @@ -114,28 +111,28 @@ sealed interface EelPath { * IjentRelativePath.parse("abc", false).getChild("") == Err(...) * ``` */ - fun getChild(name: String): EelPathResult + fun getChild(name: String): EelResult override fun toString(): String interface Relative : EelPath, Comparable { companion object { @JvmStatic - fun parse(raw: String): EelPathResult = + fun parse(raw: String): EelResult = ArrayListEelRelativePath.parse(raw) /** * The parts of the path must not contain / or \. */ @JvmStatic - fun build(vararg parts: String): EelPathResult = + fun build(vararg parts: String): EelResult = build(listOf(*parts)) /** * The parts of the path must not contain / or \. */ @JvmStatic - fun build(parts: List): EelPathResult = + fun build(parts: List): EelResult = ArrayListEelRelativePath.build(parts) @JvmField @@ -147,9 +144,9 @@ sealed interface EelPath { /** See [java.nio.file.Path.startsWith] */ fun startsWith(other: Relative): Boolean - override fun resolve(other: Relative): EelPathResult + override fun resolve(other: Relative): EelResult - override fun getChild(name: String): EelPathResult + override fun getChild(name: String): EelResult override fun compareTo(other: Relative): Int @@ -177,15 +174,15 @@ sealed interface EelPath { interface Absolute : EelPath, Comparable { companion object { @JvmStatic - fun parse(raw: String, os: OS?): EelPathResult = + fun parse(raw: String, os: OS?): EelResult = ArrayListEelAbsolutePath.parse(raw, os) @JvmStatic - fun build(vararg parts: String): EelPathResult = + fun build(vararg parts: String): EelResult = build(listOf(*parts), null) @JvmStatic - fun build(parts: List, os: OS?): EelPathResult = + fun build(parts: List, os: OS?): EelResult = ArrayListEelAbsolutePath.build(parts, os) } @@ -204,10 +201,10 @@ sealed interface EelPath { fun startsWith(other: Absolute): Boolean /** See [java.nio.file.Path.normalize] */ - fun normalize(): EelPathResult + fun normalize(): EelResult /** See [java.nio.file.Path.resolve] */ - override fun resolve(other: Relative): EelPathResult + override fun resolve(other: Relative): EelResult /** * See [java.nio.file.Path.relativize]. @@ -217,9 +214,9 @@ sealed interface EelPath { * == IjentPathAbsolute.parse("..\..\oops", isWindows = true) * ``` */ - fun relativize(other: Absolute): EelPathResult + fun relativize(other: Absolute): EelResult - override fun getChild(name: String): EelPathResult + override fun getChild(name: String): EelResult fun scan(): Sequence @@ -232,11 +229,7 @@ sealed interface EelPath { } @Throws(InvalidPathException::class) -fun

EelPathResult

.getOrThrow(): P = - when (this) { - is EelPathResult.Ok -> path - is EelPathResult.Err -> throw InvalidPathException(raw, reason) - } +fun

EelResult.getOrThrow(): P = getOrThrow { throw InvalidPathException(it.raw, it.reason) } val EelPlatform.pathOs: OS get() = when (this) { diff --git a/platform/eel/src/com/intellij/platform/eel/path/EelPathResultImpl.kt b/platform/eel/src/com/intellij/platform/eel/path/EelPathResultImpl.kt index 4f0aa48036a1..c87b227fdc02 100644 --- a/platform/eel/src/com/intellij/platform/eel/path/EelPathResultImpl.kt +++ b/platform/eel/src/com/intellij/platform/eel/path/EelPathResultImpl.kt @@ -2,5 +2,8 @@ @file:JvmName("EelPathResultImpl") package com.intellij.platform.eel.path -internal data class Ok

(override val path: P) : EelPathResult.Ok

-internal data class Err

(override val raw: String, override val reason: String) : EelPathResult.Err

\ No newline at end of file +import com.intellij.platform.eel.EelResult + +internal data class OkResult

(override val value: P) : EelResult.Ok +internal data class ErrorResult

(override val error: EelPathError) : EelResult.Error +internal data class Err(override val raw: String, override val reason: String) : EelPathError \ No newline at end of file diff --git a/platform/eel/tests/com/intellij/platform/eel/path/EelAbsolutePathTest.kt b/platform/eel/tests/com/intellij/platform/eel/path/EelAbsolutePathTest.kt index 436b5937a691..c02e24b0454c 100644 --- a/platform/eel/tests/com/intellij/platform/eel/path/EelAbsolutePathTest.kt +++ b/platform/eel/tests/com/intellij/platform/eel/path/EelAbsolutePathTest.kt @@ -1,6 +1,7 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.eel.path +import com.intellij.platform.eel.EelResult import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf import org.junit.jupiter.api.DynamicTest @@ -36,8 +37,8 @@ class EelAbsolutePathTest { add(dynamicTest(rawPath) { val eelPath = EelPath.Absolute .parse(rawPath, null) - .shouldBeInstanceOf>() - .path + .shouldBeInstanceOf>() + .value eelPath.toString() shouldBe rawPath }) } diff --git a/platform/eelProvider/src/com/intellij/platform/eel/impl/local/EelLocalExecApi.kt b/platform/eelProvider/src/com/intellij/platform/eel/impl/local/EelLocalExecApi.kt index adfd3e943e1f..39d4852bbb08 100644 --- a/platform/eelProvider/src/com/intellij/platform/eel/impl/local/EelLocalExecApi.kt +++ b/platform/eelProvider/src/com/intellij/platform/eel/impl/local/EelLocalExecApi.kt @@ -2,6 +2,9 @@ package com.intellij.platform.eel.impl.local import com.intellij.platform.eel.EelExecApi +import com.intellij.platform.eel.EelProcess +import com.intellij.platform.eel.EelResult +import com.intellij.platform.eel.provider.EelProcessResultImpl import com.pty4j.PtyProcessBuilder import org.jetbrains.annotations.ApiStatus import java.io.File @@ -9,7 +12,7 @@ import java.io.IOException @ApiStatus.Internal class EelLocalExecApi : EelExecApi { - override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelExecApi.ExecuteProcessResult { + override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelResult { val args = builder.args.toTypedArray() val pty = builder.pty @@ -35,9 +38,9 @@ class EelLocalExecApi : EelExecApi { } } catch (e: IOException) { - return EelExecApi.ExecuteProcessResult.Failure(-1, e.toString()) + return EelProcessResultImpl.createErrorResult(-1, e.toString()) } - return EelExecApi.ExecuteProcessResult.Success(process) + return EelProcessResultImpl.createOkResult(process) } override suspend fun fetchLoginShellEnvVariables(): Map = System.getenv() diff --git a/platform/eelProvider/src/com/intellij/platform/eel/impl/local/LocalEelApiImpl.kt b/platform/eelProvider/src/com/intellij/platform/eel/impl/local/LocalEelApiImpl.kt index 0cf060ec6f39..47ebb39eb7ac 100644 --- a/platform/eelProvider/src/com/intellij/platform/eel/impl/local/LocalEelApiImpl.kt +++ b/platform/eelProvider/src/com/intellij/platform/eel/impl/local/LocalEelApiImpl.kt @@ -7,14 +7,14 @@ import com.intellij.platform.eel.fs.EelFileSystemPosixApi import com.intellij.platform.eel.fs.EelFileSystemWindowsApi import com.intellij.platform.eel.fs.getPath import com.intellij.platform.eel.path.EelPath +import com.intellij.platform.eel.path.getOrThrow import com.intellij.platform.eel.provider.EelUserPosixInfoImpl import com.intellij.platform.eel.provider.EelUserWindowsInfoImpl -import com.intellij.platform.eel.provider.utils.unwrap import java.nio.file.Path internal class LocalEelPathMapper(private val eelApi: EelApi) : EelPathMapper { override fun getOriginalPath(path: Path): EelPath.Absolute { - return eelApi.fs.getPath(path.toString()).unwrap() + return eelApi.fs.getPath(path.toString()).getOrThrow() } override fun toNioPath(path: EelPath.Absolute): Path { diff --git a/platform/eelProvider/src/com/intellij/platform/eel/provider/EelFsResultImpl.kt b/platform/eelProvider/src/com/intellij/platform/eel/provider/EelFsResultImpl.kt index 8a93ac411940..85c233bd1f8c 100644 --- a/platform/eelProvider/src/com/intellij/platform/eel/provider/EelFsResultImpl.kt +++ b/platform/eelProvider/src/com/intellij/platform/eel/provider/EelFsResultImpl.kt @@ -1,16 +1,16 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.eel.provider +import com.intellij.platform.eel.EelResult import com.intellij.platform.eel.fs.EelFileSystemApi import com.intellij.platform.eel.fs.EelFsError -import com.intellij.platform.eel.fs.EelFsResult import com.intellij.platform.eel.fs.EelOpenedFile import com.intellij.platform.eel.path.EelPath @Suppress("unused") // Usages are to be implemented later. object EelFsResultImpl { - data class Ok(override val value: T) : EelFsResult.Ok - data class Error(override val error: E) : EelFsResult.Error + data class Ok(override val value: T) : EelResult.Ok + data class Error(override val error: E) : EelResult.Error data class BytesReadImpl(override val bytesRead: Int) : EelOpenedFile.Reader.ReadResult.Bytes data object EOFImpl : EelOpenedFile.Reader.ReadResult.EOF diff --git a/platform/eelProvider/src/com/intellij/platform/eel/provider/EelProcessResultImpl.kt b/platform/eelProvider/src/com/intellij/platform/eel/provider/EelProcessResultImpl.kt new file mode 100644 index 000000000000..64a09e4ff6fe --- /dev/null +++ b/platform/eelProvider/src/com/intellij/platform/eel/provider/EelProcessResultImpl.kt @@ -0,0 +1,17 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.eel.provider + +import com.intellij.platform.eel.EelExecApi +import com.intellij.platform.eel.EelProcess +import com.intellij.platform.eel.EelResult +import org.jetbrains.annotations.ApiStatus.Internal + +@Internal +object EelProcessResultImpl { + private data class Ok(override val value: EelProcess) : EelResult.Ok + private data class Error(override val error: EelExecApi.ExecuteProcessError) : EelResult.Error + private data class ExecuteProcessError(override val errno: Int, override val message: String) : EelExecApi.ExecuteProcessError + + fun createOkResult(process: EelProcess): EelResult.Ok = Ok(process) + fun createErrorResult(errno: Int, message: String): EelResult.Error = Error(ExecuteProcessError(errno, message)) +} \ No newline at end of file diff --git a/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt b/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt index b3dc1889eb24..c485419b138a 100644 --- a/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt +++ b/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt @@ -4,14 +4,6 @@ package com.intellij.platform.eel.provider.utils import com.intellij.openapi.progress.runBlockingMaybeCancellable import com.intellij.platform.eel.fs.EelFileSystemApi import com.intellij.platform.eel.path.EelPath -import com.intellij.platform.eel.path.EelPathResult - -fun EelPathResult.unwrap(): T { - return when (this) { - is EelPathResult.Ok -> path - is EelPathResult.Err -> throw RuntimeException(reason) - } -} fun EelFileSystemApi.userHomeBlocking(): EelPath.Absolute? { return runBlockingMaybeCancellable { diff --git a/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelProcessUtils.kt b/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelProcessUtils.kt index 538451e6f22c..ec7ba9a2fa82 100644 --- a/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelProcessUtils.kt +++ b/platform/eelProvider/src/com/intellij/platform/eel/provider/utils/eelProcessUtils.kt @@ -5,27 +5,13 @@ import com.intellij.execution.process.ProcessOutput import com.intellij.platform.eel.* import com.intellij.platform.eel.fs.getPath import com.intellij.platform.eel.path.EelPath +import com.intellij.platform.eel.path.getOrThrow import com.intellij.util.io.computeDetached import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.channels.consumeEach import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import java.io.ByteArrayOutputStream -import java.io.IOException - -/** - * Unwraps the `ExecuteProcessResult` instance, returning the underlying `EelProcess` if the result is a success, - * or throws an `IOException` if the result is a failure. - * - * @throws IOException if the `ExecuteProcessResult` is `Failure`. - * @return the `EelProcess` if the `ExecuteProcessResult` is `Success`. - */ -fun EelExecApi.ExecuteProcessResult.unwrap(): EelProcess { - return when (this) { - is EelExecApi.ExecuteProcessResult.Success -> process - is EelExecApi.ExecuteProcessResult.Failure -> throw RuntimeException(toString()) - } -} /** * Function that awaits the completion of an [EelProcess] and retrieves its execution result, @@ -92,13 +78,13 @@ suspend fun EelApi.where(exe: String): EelPath.Absolute? { else -> throw IllegalArgumentException("Unsupported OS: $this") } - val result = exec.executeProcess(tool, exe).unwrap().awaitProcessResult() + val result = exec.executeProcess(tool, exe).getOrThrow().awaitProcessResult() if (result.exitCode != 0) { // TODO: log error?/throw Exception? return null } else { - return fs.getPath(result.stdout).unwrap() + return fs.getPath(result.stdout).getOrThrow() } } \ No newline at end of file diff --git a/platform/execution-impl/src/com/intellij/execution/wsl/ijent/AbstractIjentVerificationAction.kt b/platform/execution-impl/src/com/intellij/execution/wsl/ijent/AbstractIjentVerificationAction.kt index 7577c0faed20..87fcf7b13af8 100644 --- a/platform/execution-impl/src/com/intellij/execution/wsl/ijent/AbstractIjentVerificationAction.kt +++ b/platform/execution-impl/src/com/intellij/execution/wsl/ijent/AbstractIjentVerificationAction.kt @@ -14,7 +14,7 @@ import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.diagnostic.runAndLogException import com.intellij.openapi.project.DumbAwareAction import com.intellij.openapi.ui.Messages -import com.intellij.platform.eel.EelExecApi +import com.intellij.platform.eel.EelResult import com.intellij.platform.eel.executeProcess import com.intellij.platform.ide.progress.ModalTaskOwner import com.intellij.platform.ide.progress.TaskCancellation @@ -77,8 +77,8 @@ abstract class AbstractIjentVerificationAction : DumbAwareAction() { launch { val process = when (val p = ijent.exec.executeProcess("uname", "-a")) { - is EelExecApi.ExecuteProcessResult.Failure -> error(p) - is EelExecApi.ExecuteProcessResult.Success -> p.process + is EelResult.Error -> error(p) + is EelResult.Ok -> p.value } val stdout = ByteArrayOutputStream() process.stdout.consumeEach(stdout::write) diff --git a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt index b89f5b98d7db..26c2056db671 100644 --- a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt +++ b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt @@ -1,8 +1,12 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.ijent.community.impl +import com.intellij.platform.eel.EelResult import com.intellij.platform.eel.EelUserPosixInfo -import com.intellij.platform.eel.fs.* +import com.intellij.platform.eel.fs.EelFileSystemApi +import com.intellij.platform.eel.fs.EelFileSystemPosixApi +import com.intellij.platform.eel.fs.EelOpenedFile +import com.intellij.platform.eel.fs.EelPosixFileInfo import com.intellij.platform.eel.path.EelPath import com.intellij.platform.ijent.IjentApi import com.intellij.platform.ijent.IjentPosixApi @@ -104,7 +108,7 @@ private class IjentFailSafeFileSystemPosixApiImpl( override suspend fun listDirectory( path: EelPath.Absolute, - ): EelFsResult, EelFileSystemApi.ListDirectoryError> = + ): EelResult, EelFileSystemApi.ListDirectoryError> = holder.withDelegateRetrying { listDirectory(path) } @@ -121,7 +125,7 @@ private class IjentFailSafeFileSystemPosixApiImpl( override suspend fun listDirectoryWithAttrs( path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy, - ): EelFsResult>, EelFileSystemApi.ListDirectoryError> { + ): EelResult>, EelFileSystemApi.ListDirectoryError> { return holder.withDelegateRetrying { listDirectoryWithAttrs(path, symlinkPolicy) } @@ -129,7 +133,7 @@ private class IjentFailSafeFileSystemPosixApiImpl( override suspend fun canonicalize( path: EelPath.Absolute, - ): EelFsResult = + ): EelResult = holder.withDelegateRetrying { canonicalize(path) } @@ -137,7 +141,7 @@ private class IjentFailSafeFileSystemPosixApiImpl( override suspend fun stat( path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy, - ): EelFsResult = + ): EelResult = holder.withDelegateRetrying { stat(path, symlinkPolicy) } @@ -145,28 +149,28 @@ private class IjentFailSafeFileSystemPosixApiImpl( override suspend fun sameFile( source: EelPath.Absolute, target: EelPath.Absolute, - ): EelFsResult = + ): EelResult = holder.withDelegateRetrying { sameFile(source, target) } override suspend fun openForReading( path: EelPath.Absolute, - ): EelFsResult = + ): EelResult = holder.withDelegateRetrying { openForReading(path) } override suspend fun openForWriting( options: EelFileSystemApi.WriteOptions, - ): EelFsResult = + ): EelResult = holder.withDelegateRetrying { openForWriting(options) } override suspend fun openForReadingAndWriting( options: EelFileSystemApi.WriteOptions, - ): EelFsResult = + ): EelResult = holder.withDelegateRetrying { openForReadingAndWriting(options) } diff --git a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystem.kt b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystem.kt index 5fcae2b4796d..72d05513dc87 100644 --- a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystem.kt +++ b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystem.kt @@ -3,7 +3,9 @@ package com.intellij.platform.ijent.community.impl.nio import com.intellij.platform.eel.path.EelPath import com.intellij.platform.eel.path.getOrThrow -import com.intellij.platform.ijent.fs.* +import com.intellij.platform.ijent.fs.IjentFileSystemApi +import com.intellij.platform.ijent.fs.IjentFileSystemPosixApi +import com.intellij.platform.ijent.fs.IjentFileSystemWindowsApi import org.jetbrains.annotations.ApiStatus import java.net.URI import java.nio.file.FileStore diff --git a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemUtil.kt b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemUtil.kt index ac01db5a2a9b..999c9c5737e9 100644 --- a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemUtil.kt +++ b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemUtil.kt @@ -3,9 +3,9 @@ package com.intellij.platform.ijent.community.impl.nio +import com.intellij.platform.eel.EelResult import com.intellij.platform.eel.fs.EelFileSystemApi import com.intellij.platform.eel.fs.EelFsError -import com.intellij.platform.eel.fs.EelFsResult import com.intellij.platform.eel.fs.EelOpenedFile import com.intellij.platform.eel.path.EelPath import com.intellij.platform.eel.path.getOrThrow @@ -13,16 +13,15 @@ import com.intellij.util.text.nullize import kotlinx.coroutines.Dispatchers import java.io.IOException import java.nio.file.* -import kotlin.Throws import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.startCoroutine @Throws(FileSystemException::class) -internal fun EelFsResult.getOrThrowFileSystemException(): T = +internal fun EelResult.getOrThrowFileSystemException(): T = when (this) { - is EelFsResult.Ok -> value - is EelFsResult.Error -> error.throwFileSystemException() + is EelResult.Ok -> value + is EelResult.Error -> error.throwFileSystemException() } // TODO There's java.nio.file.FileSystemLoopException, so ELOOP should be added to all error codes for a decent support of all exceptions. diff --git a/platform/platform-impl/src/com/intellij/execution/eel/EelApiWithPathsMapping.kt b/platform/platform-impl/src/com/intellij/execution/eel/EelApiWithPathsMapping.kt index 5984e78bb796..bb40cec84b0c 100644 --- a/platform/platform-impl/src/com/intellij/execution/eel/EelApiWithPathsMapping.kt +++ b/platform/platform-impl/src/com/intellij/execution/eel/EelApiWithPathsMapping.kt @@ -4,9 +4,10 @@ package com.intellij.execution.eel import com.intellij.execution.ijent.nio.IjentEphemeralRootAwarePath import com.intellij.openapi.util.io.FileUtil import com.intellij.platform.eel.* +import com.intellij.platform.eel.EelExecApi.ExecuteProcessError import com.intellij.platform.eel.fs.getPath import com.intellij.platform.eel.path.EelPath -import com.intellij.platform.eel.provider.utils.unwrap +import com.intellij.platform.eel.path.getOrThrow import org.jetbrains.annotations.ApiStatus.Internal import java.nio.file.Path import kotlin.io.path.pathString @@ -47,7 +48,7 @@ private class EelEphemeralRootAwareMapper( ) : EelPathMapper { override fun getOriginalPath(path: Path): EelPath.Absolute? { return if (path is IjentEphemeralRootAwarePath) { - eelApi.fs.getPath(path.originalPath.toString()).unwrap() + eelApi.fs.getPath(path.originalPath.toString()).getOrThrow() } else { null @@ -72,7 +73,7 @@ private class EelExecApiWithNormalization( private val original: EelExecApi, private val normalize: (EelExecApi.ExecuteProcessBuilder) -> EelExecApi.ExecuteProcessBuilder, ) : EelExecApi by original { - override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelExecApi.ExecuteProcessResult { + override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelResult { return original.execute(normalize(builder)) } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/wsl/WslIjentUtil.kt b/platform/platform-impl/src/com/intellij/execution/wsl/WslIjentUtil.kt index d537aac0f868..27521eb9fb2f 100644 --- a/platform/platform-impl/src/com/intellij/execution/wsl/WslIjentUtil.kt +++ b/platform/platform-impl/src/com/intellij/execution/wsl/WslIjentUtil.kt @@ -14,6 +14,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtil import com.intellij.platform.eel.EelExecApi import com.intellij.platform.eel.EelExecApi.Arguments.executeProcessBuilder +import com.intellij.platform.eel.EelResult import com.intellij.platform.ijent.IjentChildProcess import com.intellij.util.concurrency.annotations.RequiresBackgroundThread import com.intellij.util.concurrency.annotations.RequiresBlockingContext @@ -136,13 +137,13 @@ fun runProcessBlocking( .pty(pty) .workingDirectory(workingDirectory) )) { - is EelExecApi.ExecuteProcessResult.Success -> - (processResult.process as IjentChildProcess).toProcess( + is EelResult.Ok -> + (processResult.value as IjentChildProcess).toProcess( coroutineScope = scope, isPty = pty != null, redirectStderr = processBuilder.redirectErrorStream(), ) - is EelExecApi.ExecuteProcessResult.Failure -> throw IOException(processResult.message) + is EelResult.Error -> throw IOException(processResult.error.message) } } diff --git a/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt b/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt index 97462f9cc526..ae150fb134ae 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.util.SystemInfoRt import com.intellij.platform.eel.EelExecApi import com.intellij.platform.eel.EelExecApi.Pty import com.intellij.platform.eel.EelProcess +import com.intellij.platform.eel.EelResult import com.intellij.platform.eel.impl.local.EelLocalExecApi import com.intellij.testFramework.UsefulTestCase.IS_UNDER_TEAMCITY import com.intellij.testFramework.common.timeoutRunBlocking @@ -90,9 +91,9 @@ class EelLocalExecApiTest { PTYManagement.PTY_RESIZE_LATER -> Pty(PTY_COLS - 1, PTY_ROWS - 1, true) // wrong tty size: will resize in the test }) when (val r = EelLocalExecApi().execute(builder)) { - is EelExecApi.ExecuteProcessResult.Failure -> Assertions.fail(r.message) - is EelExecApi.ExecuteProcessResult.Success -> { - val process = r.process + is EelResult.Error -> Assertions.fail(r.error.message) + is EelResult.Ok -> { + val process = r.value // Resize tty when (ptyManagement) { diff --git a/platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLDistributionTest.kt b/platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLDistributionTest.kt index a53713ce3ce2..688abf707260 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLDistributionTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/execution/wsl/WSLDistributionTest.kt @@ -14,9 +14,9 @@ import com.intellij.openapi.util.Computable import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Key import com.intellij.openapi.util.use -import com.intellij.platform.eel.EelExecApi -import com.intellij.platform.eel.EelPlatform -import com.intellij.platform.eel.EelUserPosixInfo +import com.intellij.platform.eel.* +import com.intellij.platform.eel.EelExecApi.ExecuteProcessError +import com.intellij.platform.eel.provider.EelProcessResultImpl import com.intellij.platform.ijent.IjentExecApi import com.intellij.platform.ijent.IjentPosixApi import com.intellij.platform.ijent.IjentProcessInfo @@ -501,7 +501,7 @@ class WSLDistributionTest { val err = shouldThrow { sourceCommandLine.createProcess() } - err.message should be(executeResultMock.message) + err.message should be(executeResultMock.error.message) } adapter } @@ -532,7 +532,7 @@ private class MockIjentApi(private val adapter: GeneralCommandLine, val rootUser private class MockIjentExecApi(private val adapter: GeneralCommandLine, private val rootUser: Boolean) : IjentExecApi { - override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelExecApi.ExecuteProcessResult = executeResultMock.also { + override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelResult = executeResultMock.also { adapter.exePath = builder.exe if (rootUser) { adapter.putUserData(TEST_ROOT_USER_SET, true) @@ -549,7 +549,7 @@ private val TEST_ROOT_USER_SET by lazy { Key.create("TEST_ROOT_USER_SET private val executeResultMock by lazy { - EelExecApi.ExecuteProcessResult.Failure(errno = 12345, message = "mock result ${Ksuid.generate()}") + EelProcessResultImpl.createErrorResult(errno = 12345, message = "mock result ${Ksuid.generate()}") } private class WslTestStrategyExtension