From 88df5b142638cf256ef8ffad71880ce294ae6608 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Mon, 10 Mar 2025 23:57:56 +0100 Subject: [PATCH] feat: Improved missing toolchain resistance --- CHANGELOG.md | 1 + .../newproject/ZigProjectConfigurationData.kt | 10 +++++++++- .../zigbrains/project/settings/ZigProjectSettings.kt | 9 ++++++++- .../steps/discovery/ZigStepDiscoveryListener.kt | 1 + .../steps/discovery/ZigStepDiscoveryService.kt | 4 +++- .../project/steps/ui/BuildToolWindowContext.kt | 1 + .../project/toolchain/tools/ZigCompilerTool.kt | 2 +- .../zigbrains/project/toolchain/tools/ZigTool.kt | 12 ++++++++---- core/src/main/resources/zigbrains/Bundle.properties | 1 + 9 files changed, 33 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35460755..53795c33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Changelog structure reference: - Zig - `zig env` failure causes an IDE error + - A local toolchain disappearing (std directory or zig exe deleted) is now handled properly ## [20.3.0] diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigProjectConfigurationData.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigProjectConfigurationData.kt index 595555c2..e15d2636 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigProjectConfigurationData.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigProjectConfigurationData.kt @@ -74,12 +74,20 @@ data class ZigProjectConfigurationData( return@indeterminateStep false } val result = zig.callWithArgs(workDir, "init") + if (result == null) { + Notification( + "zigbrains", + "\"zig init\" could not run because the zig executable was missing!", + NotificationType.ERROR + ).notify(project) + return@indeterminateStep false + } if (result.exitCode != 0) { Notification( "zigbrains", "\"zig init\" failed with exit code ${result.exitCode}! Check the IDE log files!", NotificationType.ERROR - ) + ).notify(project) System.err.println(result.stderr) return@indeterminateStep false } diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettings.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettings.kt index 00fb67e0..facf092c 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettings.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettings.kt @@ -26,6 +26,7 @@ import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.util.xmlb.annotations.Transient +import kotlin.io.path.isDirectory import kotlin.io.path.pathString data class ZigProjectSettings( @@ -41,7 +42,13 @@ data class ZigProjectSettings( @get:Transient @set:Transient override var toolchain: LocalZigToolchain? - get() = toolchainPath?.toNioPathOrNull()?.let { LocalZigToolchain(it) } + get() { + val nioPath = toolchainPath?.toNioPathOrNull() ?: return null + if (!nioPath.isDirectory()) { + return null + } + return LocalZigToolchain(nioPath) + } set(value) { toolchainPath = value?.location?.pathString } diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryListener.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryListener.kt index e3a2e0e9..42ba2f00 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryListener.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryListener.kt @@ -30,6 +30,7 @@ interface ZigStepDiscoveryListener { enum class ErrorType { MissingToolchain, + MissingZigExe, MissingBuildZig, GeneralError } diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryService.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryService.kt index ccd230a5..0b704283 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryService.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/discovery/ZigStepDiscoveryService.kt @@ -85,7 +85,9 @@ class ZigStepDiscoveryService(private val project: Project) { "build", "-l", timeoutMillis = currentTimeoutSec * 1000L ) - if (result.checkSuccess(LOG)) { + if (result == null) { + errorReload(ErrorType.MissingZigExe) + } else if (result.checkSuccess(LOG)) { currentTimeoutSec = DEFAULT_TIMEOUT_SEC val lines = result.stdoutLines val steps = ArrayList>() diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/ui/BuildToolWindowContext.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/ui/BuildToolWindowContext.kt index 2f30e83e..3112ec4e 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/ui/BuildToolWindowContext.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/steps/ui/BuildToolWindowContext.kt @@ -166,6 +166,7 @@ class BuildToolWindowContext(private val project: Project): Disposable { withEDTContext { getViewport(project)?.setViewportError(ZigBrainsBundle.message(when(type) { ZigStepDiscoveryListener.ErrorType.MissingToolchain -> "build.tool.window.status.error.missing-toolchain" + ZigStepDiscoveryListener.ErrorType.MissingZigExe -> "build.tool.window.status.error.missing-zig-exe" ZigStepDiscoveryListener.ErrorType.MissingBuildZig -> "build.tool.window.status.error.missing-build-zig" ZigStepDiscoveryListener.ErrorType.GeneralError -> "build.tool.window.status.error.general" }), details) diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigCompilerTool.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigCompilerTool.kt index 37a5f726..baa0c441 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigCompilerTool.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigCompilerTool.kt @@ -38,7 +38,7 @@ class ZigCompilerTool(toolchain: AbstractZigToolchain) : ZigTool(toolchain) { } suspend fun getEnv(project: Project?): ZigToolchainEnvironmentSerializable? { - val stdout = callWithArgs(toolchain.workingDirectory(project), "env").stdout + val stdout = callWithArgs(toolchain.workingDirectory(project), "env")?.stdout ?: return null return try { envJson.decodeFromString(stdout) } catch (e: SerializationException) { diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigTool.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigTool.kt index 81458116..de5e0e7a 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigTool.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/tools/ZigTool.kt @@ -31,12 +31,13 @@ import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull import java.nio.file.Path +import kotlin.io.path.isRegularFile abstract class ZigTool(val toolchain: AbstractZigToolchain) { abstract val toolName: String - suspend fun callWithArgs(workingDirectory: Path?, vararg parameters: String, timeoutMillis: Long = Long.MAX_VALUE): ProcessOutput { - val cli = createBaseCommandLine(workingDirectory, *parameters) + suspend fun callWithArgs(workingDirectory: Path?, vararg parameters: String, timeoutMillis: Long = Long.MAX_VALUE): ProcessOutput? { + val cli = createBaseCommandLine(workingDirectory, *parameters) ?: return null val (process, exitCode) = withContext(Dispatchers.IO) { val process = cli.createProcess() @@ -59,9 +60,12 @@ abstract class ZigTool(val toolchain: AbstractZigToolchain) { private suspend fun createBaseCommandLine( workingDirectory: Path?, vararg parameters: String - ): GeneralCommandLine { + ): GeneralCommandLine? { + val exe = toolchain.pathToExecutable(toolName) + if (!exe.isRegularFile()) + return null val cli = GeneralCommandLine() - .withExePath(toolchain.pathToExecutable(toolName).toString()) + .withExePath(exe.toString()) .withWorkingDirectory(workingDirectory) .withParameters(*parameters) .withCharset(Charsets.UTF_8) diff --git a/core/src/main/resources/zigbrains/Bundle.properties b/core/src/main/resources/zigbrains/Bundle.properties index c40b6893..53db873f 100644 --- a/core/src/main/resources/zigbrains/Bundle.properties +++ b/core/src/main/resources/zigbrains/Bundle.properties @@ -113,6 +113,7 @@ build.tool.window.status.not-scanned=Build steps not yet scanned. Click the refr build.tool.window.status.loading=Running zig build -l build.tool.window.status.error.missing-build-zig=No build.zig file found build.tool.window.status.error.missing-toolchain=No zig toolchain configured +build.tool.window.status.error.missing-zig-exe=Zig executable missing build.tool.window.status.error.general=Error while running zig build -l build.tool.window.status.timeout=zig build -l timed out after {0} seconds. zig=Zig \ No newline at end of file