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
|
- Project
|
||||||
- Direnv now only runs automatically in trusted projects
|
- Direnv now only runs automatically in trusted projects
|
||||||
|
- Toolchain autodetection is now done in the background on project load
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,13 @@
|
||||||
|
|
||||||
package com.falsepattern.zigbrains
|
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.BrowserUtil
|
||||||
import com.intellij.ide.plugins.PluginManager
|
import com.intellij.ide.plugins.PluginManager
|
||||||
import com.intellij.notification.Notification
|
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.options.ShowSettingsUtil
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.startup.ProjectActivity
|
import com.intellij.openapi.startup.ProjectActivity
|
||||||
|
import com.intellij.openapi.util.UserDataHolderBase
|
||||||
import java.lang.reflect.Constructor
|
import java.lang.reflect.Constructor
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
class ZBStartup: ProjectActivity {
|
class ZBStartup: ProjectActivity {
|
||||||
var firstInit = true
|
var firstInit = true
|
||||||
|
@ -67,6 +76,30 @@ class ZBStartup: ProjectActivity {
|
||||||
notif.notify(null)
|
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
|
import org.jetbrains.annotations.NonNls
|
||||||
|
|
||||||
data class ZLSSettings(
|
data class ZLSSettings(
|
||||||
var direnv: Boolean = true,
|
var direnv: Boolean = false,
|
||||||
var zlsPath: @NonNls String = "",
|
var zlsPath: @NonNls String = "",
|
||||||
var zlsConfigPath: @NonNls String = "",
|
var zlsConfigPath: @NonNls String = "",
|
||||||
var debug: Boolean = false,
|
var debug: Boolean = false,
|
||||||
|
|
|
@ -62,22 +62,17 @@ class ZLSSettingsPanel(private val project: Project?) : Disposable {
|
||||||
|
|
||||||
private val messageTrace = JBCheckBox()
|
private val messageTrace = JBCheckBox()
|
||||||
private val debug = 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) {
|
fun attach(panel: Panel) = with(panel) {
|
||||||
group(ZLSBundle.message("settings.group.title")) {
|
group(ZLSBundle.message("settings.group.title")) {
|
||||||
row(ZLSBundle.message("settings.zls-path.label")) {
|
row(ZLSBundle.message("settings.zls-path.label")) {
|
||||||
cell(zlsPath).resizableColumn().align(AlignX.FILL)
|
cell(zlsPath).resizableColumn().align(AlignX.FILL)
|
||||||
if (DirenvCmd.direnvInstalled() && project != null && !project.isDefault) {
|
if (DirenvCmd.direnvInstalled() && project?.isDefault == false) {
|
||||||
cell(direnv)
|
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.zls-config-path.label")) { cell(zlsConfigPath).align(AlignX.FILL) }
|
||||||
row(ZLSBundle.message("settings.inlay-hints.label")) { cell(inlayHints) }
|
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.debug.label")) { cell(debug) }
|
||||||
row(ZLSBundle.message("dev-settings.message-trace.label")) { cell(messageTrace) }
|
row(ZLSBundle.message("dev-settings.message-trace.label")) { cell(messageTrace) }
|
||||||
}
|
}
|
||||||
|
dispatchAutodetect(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
var data
|
var data
|
||||||
|
@ -121,16 +117,30 @@ class ZLSSettingsPanel(private val project: Project?) : Disposable {
|
||||||
inlayHintsCompact.isSelected = value.inlayHintsCompact
|
inlayHintsCompact.isSelected = value.inlayHintsCompact
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun autodetect() {
|
private fun dispatchAutodetect(force: Boolean) {
|
||||||
getDirenv().findExecutableOnPATH("zls")?.let { zlsPath.text = it.pathString }
|
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() {
|
override fun dispose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getDirenv(): Env {
|
private suspend fun getDirenv(): Env {
|
||||||
if (!direnv.isSelected)
|
if (DirenvCmd.direnvInstalled() && project?.isDefault == false && direnv.isSelected)
|
||||||
return emptyEnv
|
return project.getDirenv()
|
||||||
return project.getDirenv()
|
return emptyEnv
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -89,11 +89,6 @@ class ZigNewProjectPanel(private var handleGit: Boolean): Disposable {
|
||||||
zlsConf.attach(p)
|
zlsConf.attach(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun autodetect() {
|
|
||||||
projConf.autodetect()
|
|
||||||
zlsConf.autodetect()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import com.intellij.util.xmlb.annotations.Transient
|
||||||
import kotlin.io.path.pathString
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
data class ZigProjectSettings(
|
data class ZigProjectSettings(
|
||||||
var direnv: Boolean = true,
|
var direnv: Boolean = false,
|
||||||
var overrideStdPath: Boolean = false,
|
var overrideStdPath: Boolean = false,
|
||||||
var explicitPathToStd: String? = null,
|
var explicitPathToStd: String? = null,
|
||||||
var toolchainPath: String? = null
|
var toolchainPath: String? = null
|
||||||
|
|
|
@ -56,7 +56,9 @@ import kotlin.io.path.notExists
|
||||||
import kotlin.io.path.pathString
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
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(
|
private val pathToToolchain = textFieldWithBrowseButton(
|
||||||
project,
|
project,
|
||||||
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.zig-toolchain"))
|
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.zig-toolchain"))
|
||||||
|
@ -85,15 +87,27 @@ class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
||||||
).also { Disposer.register(this, it) }
|
).also { Disposer.register(this, it) }
|
||||||
private var debounce: Job? = null
|
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()
|
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
|
val tc = ZigToolchainProvider.suggestToolchain(project, data) ?: return
|
||||||
if (tc !is LocalZigToolchain) {
|
if (tc !is LocalZigToolchain) {
|
||||||
TODO("Implement non-local zig toolchain in config")
|
TODO("Implement non-local zig toolchain in config")
|
||||||
}
|
}
|
||||||
pathToToolchain.text = tc.location.pathString
|
if (force || pathToToolchain.text.isBlank()) {
|
||||||
dispatchUpdateUI()
|
pathToToolchain.text = tc.location.pathString
|
||||||
|
dispatchUpdateUI()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var data
|
var data
|
||||||
|
@ -121,13 +135,6 @@ class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
||||||
if (DirenvCmd.direnvInstalled() && !project.isDefault) {
|
if (DirenvCmd.direnvInstalled() && !project.isDefault) {
|
||||||
cell(direnv)
|
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")) {
|
row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) {
|
||||||
cell(toolchainVersion)
|
cell(toolchainVersion)
|
||||||
|
@ -137,6 +144,7 @@ class ZigProjectSettingsPanel(private val project: Project?) : Disposable {
|
||||||
cell(stdFieldOverride)
|
cell(stdFieldOverride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dispatchAutodetect(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dispatchUpdateUI() {
|
private fun dispatchUpdateUI() {
|
||||||
|
|
|
@ -105,7 +105,6 @@ configuration.build.marker-name=Build and Run
|
||||||
settings.project.group.title=Zig Settings
|
settings.project.group.title=Zig Settings
|
||||||
settings.project.label.direnv=Use direnv
|
settings.project.label.direnv=Use direnv
|
||||||
settings.project.label.toolchain=Toolchain location
|
settings.project.label.toolchain=Toolchain location
|
||||||
settings.project.label.toolchain-autodetect=Autodetect
|
|
||||||
settings.project.label.toolchain-version=Toolchain version
|
settings.project.label.toolchain-version=Toolchain version
|
||||||
settings.project.label.override-std=Override standard library
|
settings.project.label.override-std=Override standard library
|
||||||
settings.project.label.std-location=Standard library location
|
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.global-var-declarations.label=Highlight global variable declarations
|
||||||
settings.comptime-interpreter.label=Use the ZLS comptime interpreter (dangerous)
|
settings.comptime-interpreter.label=Use the ZLS comptime interpreter (dangerous)
|
||||||
settings.zls-path.use-direnv.label=Use direnv
|
settings.zls-path.use-direnv.label=Use direnv
|
||||||
settings.zls-path.autodetect.label=Autodetect
|
|
||||||
dev-settings.group.title=ZLS Developer Settings
|
dev-settings.group.title=ZLS Developer Settings
|
||||||
dev-settings.debug.label=Debug log
|
dev-settings.debug.label=Debug log
|
||||||
dev-settings.message-trace.label=Message trace
|
dev-settings.message-trace.label=Message trace
|
||||||
|
|
Loading…
Add table
Reference in a new issue