feat: Background toolchain autodetection
This commit is contained in:
parent
0ed6adff8d
commit
27160d6778
9 changed files with 80 additions and 35 deletions
|
@ -26,6 +26,7 @@ Changelog structure reference:
|
|||
|
||||
- Project
|
||||
- Direnv now only runs automatically in trusted projects
|
||||
- Toolchain autodetection is now done in the background on project load
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -22,6 +22,13 @@
|
|||
|
||||
package com.falsepattern.zigbrains
|
||||
|
||||
import com.falsepattern.zigbrains.direnv.DirenvCmd
|
||||
import com.falsepattern.zigbrains.direnv.emptyEnv
|
||||
import com.falsepattern.zigbrains.direnv.getDirenv
|
||||
import com.falsepattern.zigbrains.lsp.settings.zlsSettings
|
||||
import com.falsepattern.zigbrains.project.settings.zigProjectSettings
|
||||
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain
|
||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainProvider
|
||||
import com.intellij.ide.BrowserUtil
|
||||
import com.intellij.ide.plugins.PluginManager
|
||||
import com.intellij.notification.Notification
|
||||
|
@ -33,8 +40,10 @@ import com.intellij.openapi.options.Configurable
|
|||
import com.intellij.openapi.options.ShowSettingsUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.ProjectActivity
|
||||
import com.intellij.openapi.util.UserDataHolderBase
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Method
|
||||
import kotlin.io.path.pathString
|
||||
|
||||
class ZBStartup: ProjectActivity {
|
||||
var firstInit = true
|
||||
|
@ -67,6 +76,30 @@ class ZBStartup: ProjectActivity {
|
|||
notif.notify(null)
|
||||
}
|
||||
}
|
||||
//Autodetection
|
||||
val zigProjectState = project.zigProjectSettings.state
|
||||
if (zigProjectState.toolchainPath.isNullOrBlank()) {
|
||||
val data = UserDataHolderBase()
|
||||
data.putUserData(LocalZigToolchain.DIRENV_KEY,
|
||||
DirenvCmd.direnvInstalled() && !project.isDefault && zigProjectState.direnv
|
||||
)
|
||||
val tc = ZigToolchainProvider.suggestToolchain(project, data) ?: return
|
||||
if (tc is LocalZigToolchain) {
|
||||
zigProjectState.toolchainPath = tc.location.pathString
|
||||
project.zigProjectSettings.state = zigProjectState
|
||||
}
|
||||
}
|
||||
val zlsState = project.zlsSettings.state
|
||||
if (zlsState.zlsPath.isBlank()) {
|
||||
val env = if (DirenvCmd.direnvInstalled() && !project.isDefault && zlsState.direnv)
|
||||
project.getDirenv()
|
||||
else
|
||||
emptyEnv
|
||||
env.findExecutableOnPATH("zls")?.let {
|
||||
zlsState.zlsPath = it.pathString
|
||||
project.zlsSettings.state = zlsState
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ package com.falsepattern.zigbrains.lsp.settings
|
|||
import org.jetbrains.annotations.NonNls
|
||||
|
||||
data class ZLSSettings(
|
||||
var direnv: Boolean = true,
|
||||
var direnv: Boolean = false,
|
||||
var zlsPath: @NonNls String = "",
|
||||
var zlsConfigPath: @NonNls String = "",
|
||||
var debug: Boolean = false,
|
||||
|
|
|
@ -62,22 +62,17 @@ class ZLSSettingsPanel(private val project: Project?) : Disposable {
|
|||
|
||||
private val messageTrace = JBCheckBox()
|
||||
private val debug = JBCheckBox()
|
||||
private val direnv = JBCheckBox(ZLSBundle.message("settings.zls-path.use-direnv.label"))
|
||||
private val direnv = JBCheckBox(ZLSBundle.message("settings.zls-path.use-direnv.label")).apply { addActionListener {
|
||||
dispatchAutodetect(true)
|
||||
} }
|
||||
|
||||
fun attach(panel: Panel) = with(panel) {
|
||||
group(ZLSBundle.message("settings.group.title")) {
|
||||
row(ZLSBundle.message("settings.zls-path.label")) {
|
||||
cell(zlsPath).resizableColumn().align(AlignX.FILL)
|
||||
if (DirenvCmd.direnvInstalled() && project != null && !project.isDefault) {
|
||||
if (DirenvCmd.direnvInstalled() && project?.isDefault == false) {
|
||||
cell(direnv)
|
||||
}
|
||||
button(ZLSBundle.message("settings.zls-path.autodetect.label")) {
|
||||
project.zigCoroutineScope.launchWithEDT {
|
||||
withModalProgress(ModalTaskOwner.component(zlsPath), "Detecting ZLS...", TaskCancellation.cancellable()) {
|
||||
autodetect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
row(ZLSBundle.message("settings.zls-config-path.label")) { cell(zlsConfigPath).align(AlignX.FILL) }
|
||||
row(ZLSBundle.message("settings.inlay-hints.label")) { cell(inlayHints) }
|
||||
|
@ -91,6 +86,7 @@ class ZLSSettingsPanel(private val project: Project?) : Disposable {
|
|||
row(ZLSBundle.message("dev-settings.debug.label")) { cell(debug) }
|
||||
row(ZLSBundle.message("dev-settings.message-trace.label")) { cell(messageTrace) }
|
||||
}
|
||||
dispatchAutodetect(false)
|
||||
}
|
||||
|
||||
var data
|
||||
|
@ -121,16 +117,30 @@ class ZLSSettingsPanel(private val project: Project?) : Disposable {
|
|||
inlayHintsCompact.isSelected = value.inlayHintsCompact
|
||||
}
|
||||
|
||||
suspend fun autodetect() {
|
||||
getDirenv().findExecutableOnPATH("zls")?.let { zlsPath.text = it.pathString }
|
||||
private fun dispatchAutodetect(force: Boolean) {
|
||||
project.zigCoroutineScope.launchWithEDT {
|
||||
withModalProgress(ModalTaskOwner.component(zlsPath), "Detecting ZLS...", TaskCancellation.cancellable()) {
|
||||
autodetect(force)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun autodetect(force: Boolean) {
|
||||
if (force || zlsPath.text.isBlank()) {
|
||||
getDirenv().findExecutableOnPATH("zls")?.let {
|
||||
if (force || zlsPath.text.isBlank()) {
|
||||
zlsPath.text = it.pathString
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
}
|
||||
|
||||
private suspend fun getDirenv(): Env {
|
||||
if (!direnv.isSelected)
|
||||
return emptyEnv
|
||||
if (DirenvCmd.direnvInstalled() && project?.isDefault == false && direnv.isSelected)
|
||||
return project.getDirenv()
|
||||
return emptyEnv
|
||||
}
|
||||
}
|
|
@ -89,11 +89,6 @@ class ZigNewProjectPanel(private var handleGit: Boolean): Disposable {
|
|||
zlsConf.attach(p)
|
||||
}
|
||||
|
||||
suspend fun autodetect() {
|
||||
projConf.autodetect()
|
||||
zlsConf.autodetect()
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import com.intellij.util.xmlb.annotations.Transient
|
|||
import kotlin.io.path.pathString
|
||||
|
||||
data class ZigProjectSettings(
|
||||
var direnv: Boolean = true,
|
||||
var direnv: Boolean = false,
|
||||
var overrideStdPath: Boolean = false,
|
||||
var explicitPathToStd: String? = null,
|
||||
var toolchainPath: String? = null
|
||||
|
|
|
@ -56,7 +56,9 @@ import kotlin.io.path.notExists
|
|||
import kotlin.io.path.pathString
|
||||
|
||||
class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
||||
private val direnv = JBCheckBox(ZigBrainsBundle.message("settings.project.label.direnv"))
|
||||
private val direnv = JBCheckBox(ZigBrainsBundle.message("settings.project.label.direnv")).apply { addActionListener {
|
||||
dispatchAutodetect(true)
|
||||
} }
|
||||
private val pathToToolchain = textFieldWithBrowseButton(
|
||||
project,
|
||||
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.zig-toolchain"))
|
||||
|
@ -85,16 +87,28 @@ class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
|||
).also { Disposer.register(this, it) }
|
||||
private var debounce: Job? = null
|
||||
|
||||
suspend fun autodetect() {
|
||||
private fun dispatchAutodetect(force: Boolean) {
|
||||
project.zigCoroutineScope.launchWithEDT {
|
||||
withModalProgress(ModalTaskOwner.component(pathToToolchain), "Detecting Zig...", TaskCancellation.cancellable()) {
|
||||
autodetect(force)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun autodetect(force: Boolean) {
|
||||
if (!force && pathToToolchain.text.isNotBlank())
|
||||
return
|
||||
val data = UserDataHolderBase()
|
||||
data.putUserData(LocalZigToolchain.DIRENV_KEY, direnv.isSelected)
|
||||
data.putUserData(LocalZigToolchain.DIRENV_KEY, DirenvCmd.direnvInstalled() && project?.isDefault == false && direnv.isSelected)
|
||||
val tc = ZigToolchainProvider.suggestToolchain(project, data) ?: return
|
||||
if (tc !is LocalZigToolchain) {
|
||||
TODO("Implement non-local zig toolchain in config")
|
||||
}
|
||||
if (force || pathToToolchain.text.isBlank()) {
|
||||
pathToToolchain.text = tc.location.pathString
|
||||
dispatchUpdateUI()
|
||||
}
|
||||
}
|
||||
|
||||
var data
|
||||
get() = ZigProjectSettings(
|
||||
|
@ -121,13 +135,6 @@ class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
|||
if (DirenvCmd.direnvInstalled() && !project.isDefault) {
|
||||
cell(direnv)
|
||||
}
|
||||
button(ZigBrainsBundle.message("settings.project.label.toolchain-autodetect")) {
|
||||
project.zigCoroutineScope.launchWithEDT {
|
||||
withModalProgress(ModalTaskOwner.component(pathToToolchain), "Detecting Zig...", TaskCancellation.cancellable()) {
|
||||
autodetect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) {
|
||||
cell(toolchainVersion)
|
||||
|
@ -137,6 +144,7 @@ class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
|||
cell(stdFieldOverride)
|
||||
}
|
||||
}
|
||||
dispatchAutodetect(false)
|
||||
}
|
||||
|
||||
private fun dispatchUpdateUI() {
|
||||
|
|
|
@ -105,7 +105,6 @@ configuration.build.marker-name=Build and Run
|
|||
settings.project.group.title=Zig Settings
|
||||
settings.project.label.direnv=Use direnv
|
||||
settings.project.label.toolchain=Toolchain location
|
||||
settings.project.label.toolchain-autodetect=Autodetect
|
||||
settings.project.label.toolchain-version=Toolchain version
|
||||
settings.project.label.override-std=Override standard library
|
||||
settings.project.label.std-location=Standard library location
|
||||
|
|
|
@ -13,7 +13,6 @@ settings.build-on-save-step.tooltip=Which step should be executed on build-on-sa
|
|||
settings.global-var-declarations.label=Highlight global variable declarations
|
||||
settings.comptime-interpreter.label=Use the ZLS comptime interpreter (dangerous)
|
||||
settings.zls-path.use-direnv.label=Use direnv
|
||||
settings.zls-path.autodetect.label=Autodetect
|
||||
dev-settings.group.title=ZLS Developer Settings
|
||||
dev-settings.debug.label=Debug log
|
||||
dev-settings.message-trace.label=Message trace
|
||||
|
|
Loading…
Add table
Reference in a new issue