chore: refactor new project panel and zls settings

This commit is contained in:
FalsePattern 2025-03-10 21:23:50 +01:00
parent 0982b3488d
commit f26be52940
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
13 changed files with 432 additions and 133 deletions

View file

@ -17,6 +17,16 @@ Changelog structure reference:
## [Unreleased] ## [Unreleased]
### Added
- ZLS
- All of the config options are now exposed in the GUI
### Changed
- Project
- New project panel is now much more compact
## [20.3.0] ## [20.3.0]
- Zig - Zig

View file

@ -24,6 +24,7 @@ package com.falsepattern.zigbrains.project.settings
import com.falsepattern.zigbrains.shared.SubConfigurable import com.falsepattern.zigbrains.shared.SubConfigurable
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider { class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider {
override fun handleMainConfigChanged(project: Project) { override fun handleMainConfigChanged(project: Project) {
@ -34,7 +35,7 @@ class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider {
} }
override fun createNewProjectSettingsPanel(): ZigProjectConfigurationProvider.SettingsPanel { override fun createNewProjectSettingsPanel(): ZigProjectConfigurationProvider.SettingsPanel {
return ZigProjectSettingsPanel(null) return ZigProjectSettingsPanel(ProjectManager.getInstance().defaultProject)
} }
override val priority: Int override val priority: Int

View file

@ -32,7 +32,7 @@ import com.intellij.ui.dsl.builder.Panel
interface ZigProjectConfigurationProvider { interface ZigProjectConfigurationProvider {
fun handleMainConfigChanged(project: Project) fun handleMainConfigChanged(project: Project)
fun createConfigurable(project: Project): SubConfigurable fun createConfigurable(project: Project): SubConfigurable
fun createNewProjectSettingsPanel(): SettingsPanel fun createNewProjectSettingsPanel(): SettingsPanel?
val priority: Int val priority: Int
companion object { companion object {
private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigProjectConfigurationProvider>("com.falsepattern.zigbrains.projectConfigProvider") private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigProjectConfigurationProvider>("com.falsepattern.zigbrains.projectConfigProvider")
@ -43,7 +43,7 @@ interface ZigProjectConfigurationProvider {
return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.map { it.createConfigurable(project) } return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.map { it.createConfigurable(project) }
} }
fun createNewProjectSettingsPanels(): List<SettingsPanel> { fun createNewProjectSettingsPanels(): List<SettingsPanel> {
return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.map { it.createNewProjectSettingsPanel() } return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.mapNotNull { it.createNewProjectSettingsPanel() }
} }
} }
interface SettingsPanel: Disposable { interface SettingsPanel: Disposable {

View file

@ -52,7 +52,7 @@ import kotlinx.coroutines.launch
import javax.swing.event.DocumentEvent import javax.swing.event.DocumentEvent
import kotlin.io.path.pathString import kotlin.io.path.pathString
class ZigProjectSettingsPanel(private val project: Project?) : ZigProjectConfigurationProvider.SettingsPanel { class ZigProjectSettingsPanel(private val project: Project) : ZigProjectConfigurationProvider.SettingsPanel {
private val direnv = JBCheckBox(ZigBrainsBundle.message("settings.project.label.direnv")).apply { addActionListener { private val direnv = JBCheckBox(ZigBrainsBundle.message("settings.project.label.direnv")).apply { addActionListener {
dispatchAutodetect(true) dispatchAutodetect(true)
} } } }
@ -96,7 +96,7 @@ class ZigProjectSettingsPanel(private val project: Project?) : ZigProjectConfigu
if (!force && pathToToolchain.text.isNotBlank()) if (!force && pathToToolchain.text.isNotBlank())
return return
val data = UserDataHolderBase() val data = UserDataHolderBase()
data.putUserData(LocalZigToolchain.DIRENV_KEY, DirenvCmd.direnvInstalled() && project?.isDefault == false && direnv.isSelected) data.putUserData(LocalZigToolchain.DIRENV_KEY, !project.isDefault && direnv.isSelected && DirenvCmd.direnvInstalled())
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")
@ -124,21 +124,29 @@ class ZigProjectSettingsPanel(private val project: Project?) : ZigProjectConfigu
} }
override fun attach(p: Panel): Unit = with(p) { override fun attach(p: Panel): Unit = with(p) {
val project = project ?: ProjectManager.getInstance().defaultProject
data = project.zigProjectSettings.state data = project.zigProjectSettings.state
group(ZigBrainsBundle.message("settings.project.group.title")) { if (project.isDefault) {
row(ZigBrainsBundle.message("settings.project.label.toolchain")) { row(ZigBrainsBundle.message("settings.project.label.toolchain")) {
cell(pathToToolchain).resizableColumn().align(AlignX.FILL) cell(pathToToolchain).resizableColumn().align(AlignX.FILL)
if (DirenvCmd.direnvInstalled() && !project.isDefault) {
cell(direnv)
}
} }
row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) { row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) {
cell(toolchainVersion) cell(toolchainVersion)
} }
row(ZigBrainsBundle.message("settings.project.label.std-location")) { } else {
cell(pathToStd).resizableColumn().align(AlignX.FILL) group(ZigBrainsBundle.message("settings.project.group.title")) {
cell(stdFieldOverride) row(ZigBrainsBundle.message("settings.project.label.toolchain")) {
cell(pathToToolchain).resizableColumn().align(AlignX.FILL)
if (DirenvCmd.direnvInstalled()) {
cell(direnv)
}
}
row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) {
cell(toolchainVersion)
}
row(ZigBrainsBundle.message("settings.project.label.std-location")) {
cell(pathToStd).resizableColumn().align(AlignX.FILL)
cell(stdFieldOverride)
}
} }
} }
dispatchAutodetect(false) dispatchAutodetect(false)

View file

@ -27,6 +27,7 @@ import com.falsepattern.zigbrains.lsp.settings.ZLSSettingsPanel
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.shared.SubConfigurable import com.falsepattern.zigbrains.shared.SubConfigurable
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
class ZLSProjectConfigurationProvider: ZigProjectConfigurationProvider { class ZLSProjectConfigurationProvider: ZigProjectConfigurationProvider {
override fun handleMainConfigChanged(project: Project) { override fun handleMainConfigChanged(project: Project) {
@ -38,7 +39,7 @@ class ZLSProjectConfigurationProvider: ZigProjectConfigurationProvider {
} }
override fun createNewProjectSettingsPanel(): ZigProjectConfigurationProvider.SettingsPanel { override fun createNewProjectSettingsPanel(): ZigProjectConfigurationProvider.SettingsPanel {
return ZLSSettingsPanel(null) return ZLSSettingsPanel(ProjectManager.getInstance().defaultProject)
} }
override val priority: Int override val priority: Int

View file

@ -51,28 +51,7 @@ import kotlin.io.path.isRegularFile
import kotlin.io.path.pathString import kotlin.io.path.pathString
class ZLSStreamConnectionProvider private constructor(private val project: Project, commandLine: GeneralCommandLine?) : OSProcessStreamConnectionProvider(commandLine) { class ZLSStreamConnectionProvider private constructor(private val project: Project, commandLine: GeneralCommandLine?) : OSProcessStreamConnectionProvider(commandLine) {
override fun handleMessage(message: Message?, languageServer: LanguageServer?, rootUri: VirtualFile?) {
if (project.zlsSettings.state.inlayHintsCompact) {
if (message is ResponseMessage) {
val res = message.result
if (res is Collection<*>) {
res.forEach { e ->
if (e is InlayHint) {
tryMutateInlayHint(e)
}
}
} else if (res is InlayHint) {
tryMutateInlayHint(res)
}
}
}
super.handleMessage(message, languageServer, rootUri)
}
companion object { companion object {
private val LOG = Logger.getInstance(ZLSStreamConnectionProvider::class.java)
private val ERROR_BLOCK = Regex("error\\{.*?}", RegexOption.DOT_MATCHES_ALL)
suspend fun create(project: Project): ZLSStreamConnectionProvider { suspend fun create(project: Project): ZLSStreamConnectionProvider {
val projectDir = project.guessProjectDir()?.toNioPathOrNull() val projectDir = project.guessProjectDir()?.toNioPathOrNull()
val commandLine = getCommand(project)?.let { GeneralCommandLine(it) }?.withWorkingDirectory(projectDir) val commandLine = getCommand(project)?.let { GeneralCommandLine(it) }?.withWorkingDirectory(projectDir)
@ -154,7 +133,7 @@ class ZLSStreamConnectionProvider private constructor(private val project: Proje
} }
} ?: run { } ?: run {
val config = ZLSConfigProviderBase.findEnvironment(project) val config = ZLSConfigProviderBase.findEnvironment(project)
if (config.zigExePath.isNullOrEmpty() || config.zigLibPath.isNullOrEmpty()) { if (config.zig_exe_path.isNullOrEmpty() || config.zig_lib_path.isNullOrEmpty()) {
Notification( Notification(
"zigbrains-lsp", "zigbrains-lsp",
ZLSBundle.message("notification.message.zls-config-autogen-failed.content"), ZLSBundle.message("notification.message.zls-config-autogen-failed.content"),
@ -174,14 +153,6 @@ class ZLSStreamConnectionProvider private constructor(private val project: Proje
cmd.add(configPath.pathString) cmd.add(configPath.pathString)
} }
if (state.debug) {
cmd.add("--enable-debug-log")
}
if (state.messageTrace) {
cmd.add("--enable-message-tracing")
}
if (SystemInfo.isWindows) { if (SystemInfo.isWindows) {
val sb: StringBuilder by lazy { StringBuilder() } val sb: StringBuilder by lazy { StringBuilder() }
for (i in 0..<cmd.size) { for (i in 0..<cmd.size) {
@ -194,12 +165,6 @@ class ZLSStreamConnectionProvider private constructor(private val project: Proje
} }
return cmd return cmd
} }
private fun tryMutateInlayHint(inlayHint: InlayHint) {
val str = inlayHint.label?.left ?: return
val shortened = ERROR_BLOCK.replace(str, "error{...}")
inlayHint.setLabel(shortened)
}
} }
} }

View file

@ -26,12 +26,35 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
@Suppress("PropertyName")
@Serializable @Serializable
data class ZLSConfig( data class ZLSConfig(
@SerialName("zig_exe_path") val zigExePath: @NonNls String? = null, val enable_snippets: Boolean = true,
@SerialName("zig_lib_path") val zigLibPath: @NonNls String? = null, val enable_argument_placeholders: Boolean = true,
@SerialName("enable_build_on_save") val buildOnSave: Boolean? = null, val completion_label_details: Boolean = true,
@SerialName("build_on_save_step") val buildOnSaveStep: @NonNls String? = null, val enable_build_on_save: Boolean? = null,
@SerialName("dangerous_comptime_experiments_do_not_enable") val comptimeInterpreter: Boolean? = null, val build_on_save_args: List<String> = emptyList(),
@SerialName("highlight_global_var_declarations") val globalVarDeclarations: Boolean? = null val semantic_tokens: SemanticTokens = SemanticTokens.full,
val inlay_hints_show_variable_type_hints: Boolean = true,
val inlay_hints_show_struct_literal_field_type: Boolean = true,
val inlay_hints_show_parameter_name: Boolean = true,
val inlay_hints_show_builtin: Boolean = true,
val inlay_hints_exclude_single_argument: Boolean = true,
val inlay_hints_hide_redundant_param_names: Boolean = false,
val inlay_hints_hide_redundant_param_names_last_token: Boolean = false,
val force_autofix: Boolean = false,
val warn_style: Boolean = false,
val highlight_global_var_declarations: Boolean = false,
val skip_std_references: Boolean = false,
val prefer_ast_check_as_child_process: Boolean = true,
val builtin_path: String? = null,
val zig_lib_path: @NonNls String? = null,
val zig_exe_path: @NonNls String? = null,
val build_runner_path: @NonNls String? = null,
val global_cache_path: @NonNls String? = null,
) )
enum class SemanticTokens {
none,
partial,
full,
}

View file

@ -22,22 +22,38 @@
package com.falsepattern.zigbrains.lsp.settings package com.falsepattern.zigbrains.lsp.settings
import com.falsepattern.zigbrains.lsp.config.SemanticTokens
import com.falsepattern.zigbrains.lsp.config.ZLSConfig
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
@Suppress("PropertyName")
data class ZLSSettings( data class ZLSSettings(
var direnv: Boolean = false, var direnv: Boolean = false,
var zlsPath: @NonNls String = "", var zlsPath: @NonNls String = "",
var zlsConfigPath: @NonNls String = "", var zlsConfigPath: @NonNls String = "",
var debug: Boolean = false, val inlayHints: Boolean = true,
var messageTrace: Boolean = false, val enable_snippets: Boolean = true,
var buildOnSave: Boolean = false, val enable_argument_placeholders: Boolean = true,
var buildOnSaveStep: @NonNls String = "install", val completion_label_details: Boolean = true,
var globalVarDeclarations: Boolean = false, val enable_build_on_save: Boolean = false,
var comptimeInterpreter: Boolean = false, val build_on_save_args: List<String> = emptyList(),
var inlayHints: Boolean = true, val semantic_tokens: SemanticTokens = SemanticTokens.full,
var inlayHintsCompact: Boolean = true val inlay_hints_show_variable_type_hints: Boolean = true,
val inlay_hints_show_struct_literal_field_type: Boolean = true,
val inlay_hints_show_parameter_name: Boolean = true,
val inlay_hints_show_builtin: Boolean = true,
val inlay_hints_exclude_single_argument: Boolean = true,
val inlay_hints_hide_redundant_param_names: Boolean = false,
val inlay_hints_hide_redundant_param_names_last_token: Boolean = false,
val warn_style: Boolean = false,
val highlight_global_var_declarations: Boolean = false,
val skip_std_references: Boolean = false,
val prefer_ast_check_as_child_process: Boolean = true,
val builtin_path: String? = null,
val build_runner_path: @NonNls String? = null,
val global_cache_path: @NonNls String? = null,
): ZigProjectConfigurationProvider.Settings { ): ZigProjectConfigurationProvider.Settings {
override fun apply(project: Project) { override fun apply(project: Project) {
project.zlsSettings.loadState(this) project.zlsSettings.loadState(this)

View file

@ -30,10 +30,26 @@ class ZLSSettingsConfigProvider: ZLSConfigProvider {
override fun getEnvironment(project: Project, previous: ZLSConfig): ZLSConfig { override fun getEnvironment(project: Project, previous: ZLSConfig): ZLSConfig {
val state = project.zlsSettings.state val state = project.zlsSettings.state
return previous.copy( return previous.copy(
buildOnSave = state.buildOnSave, enable_snippets = state.enable_snippets,
buildOnSaveStep = state.buildOnSaveStep, enable_argument_placeholders = state.enable_argument_placeholders,
globalVarDeclarations = state.globalVarDeclarations, completion_label_details = state.completion_label_details,
comptimeInterpreter = state.comptimeInterpreter enable_build_on_save = state.enable_build_on_save,
build_on_save_args = state.build_on_save_args,
semantic_tokens = state.semantic_tokens,
inlay_hints_show_variable_type_hints = state.inlay_hints_show_variable_type_hints,
inlay_hints_show_struct_literal_field_type = state.inlay_hints_show_struct_literal_field_type,
inlay_hints_show_parameter_name = state.inlay_hints_show_parameter_name,
inlay_hints_show_builtin = state.inlay_hints_show_builtin,
inlay_hints_exclude_single_argument = state.inlay_hints_exclude_single_argument,
inlay_hints_hide_redundant_param_names = state.inlay_hints_hide_redundant_param_names,
inlay_hints_hide_redundant_param_names_last_token = state.inlay_hints_hide_redundant_param_names_last_token,
warn_style = state.warn_style,
highlight_global_var_declarations = state.highlight_global_var_declarations,
skip_std_references = state.skip_std_references,
prefer_ast_check_as_child_process = state.prefer_ast_check_as_child_process,
builtin_path = state.builtin_path,
build_runner_path = state.build_runner_path,
global_cache_path = state.global_cache_path,
) )
} }
} }

View file

@ -27,12 +27,13 @@ import com.falsepattern.zigbrains.direnv.Env
import com.falsepattern.zigbrains.direnv.emptyEnv import com.falsepattern.zigbrains.direnv.emptyEnv
import com.falsepattern.zigbrains.direnv.getDirenv import com.falsepattern.zigbrains.direnv.getDirenv
import com.falsepattern.zigbrains.lsp.ZLSBundle import com.falsepattern.zigbrains.lsp.ZLSBundle
import com.falsepattern.zigbrains.lsp.config.SemanticTokens
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
import com.falsepattern.zigbrains.shared.zigCoroutineScope import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.openapi.Disposable
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import com.intellij.platform.ide.progress.ModalTaskOwner import com.intellij.platform.ide.progress.ModalTaskOwner
import com.intellij.platform.ide.progress.TaskCancellation import com.intellij.platform.ide.progress.TaskCancellation
@ -42,50 +43,157 @@ import com.intellij.ui.components.fields.ExtendableTextField
import com.intellij.ui.components.textFieldWithBrowseButton import com.intellij.ui.components.textFieldWithBrowseButton
import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.Panel import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.builder.Row
import com.jetbrains.rd.generator.nova.GenerationSpec.Companion.nullIfEmpty
import org.jetbrains.annotations.PropertyKey
import java.lang.IllegalArgumentException
import java.util.*
import kotlin.io.path.pathString import kotlin.io.path.pathString
class ZLSSettingsPanel(private val project: Project?) : ZigProjectConfigurationProvider.SettingsPanel { @Suppress("PrivatePropertyName")
class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationProvider.SettingsPanel {
private val zlsPath = textFieldWithBrowseButton( private val zlsPath = textFieldWithBrowseButton(
project, project,
FileChooserDescriptorFactory.createSingleFileDescriptor().withTitle(ZLSBundle.message("settings.zls-path.browse.title")), FileChooserDescriptorFactory.createSingleFileDescriptor()
.withTitle(ZLSBundle.message("settings.zls-path.browse.title")),
).also { Disposer.register(this, it) } ).also { Disposer.register(this, it) }
private val zlsConfigPath = textFieldWithBrowseButton( private val zlsConfigPath = textFieldWithBrowseButton(
project, project,
FileChooserDescriptorFactory.createSingleFileDescriptor().withTitle(ZLSBundle.message("settings.zls-config-path.browse.title")) FileChooserDescriptorFactory.createSingleFileDescriptor()
.withTitle(ZLSBundle.message("settings.zls-config-path.browse.title"))
).also { Disposer.register(this, it) } ).also { Disposer.register(this, it) }
private val buildOnSave = JBCheckBox().apply { toolTipText = ZLSBundle.message("settings.build-on-save.tooltip") }
private val buildOnSaveStep = ExtendableTextField().apply { toolTipText = ZLSBundle.message("settings.build-on-save-step.tooltip") }
private val globalVarDeclarations = JBCheckBox()
private val comptimeInterpreter = JBCheckBox()
private val inlayHints = JBCheckBox() private val inlayHints = JBCheckBox()
private val inlayHintsCompact = JBCheckBox().apply { toolTipText = ZLSBundle.message("settings.inlay-hints-compact.tooltip") } private val enable_snippets = JBCheckBox()
private val enable_argument_placeholders = JBCheckBox()
private val completion_label_details = JBCheckBox()
private val enable_build_on_save = JBCheckBox()
private val build_on_save_args = ExtendableTextField()
private val semantic_tokens = ComboBox(SemanticTokens.entries.toTypedArray())
private val inlay_hints_show_variable_type_hints = JBCheckBox()
private val inlay_hints_show_struct_literal_field_type = JBCheckBox()
private val inlay_hints_show_parameter_name = JBCheckBox()
private val inlay_hints_show_builtin = JBCheckBox()
private val inlay_hints_exclude_single_argument = JBCheckBox()
private val inlay_hints_hide_redundant_param_names = JBCheckBox()
private val inlay_hints_hide_redundant_param_names_last_token = JBCheckBox()
private val warn_style = JBCheckBox()
private val highlight_global_var_declarations = JBCheckBox()
private val skip_std_references = JBCheckBox()
private val prefer_ast_check_as_child_process = JBCheckBox()
private val builtin_path = ExtendableTextField()
private val build_runner_path = ExtendableTextField()
private val global_cache_path = ExtendableTextField()
private val messageTrace = JBCheckBox() private val direnv = JBCheckBox(ZLSBundle.message("settings.zls-path.use-direnv.label")).apply {
private val debug = JBCheckBox() addActionListener {
private val direnv = JBCheckBox(ZLSBundle.message("settings.zls-path.use-direnv.label")).apply { addActionListener { dispatchAutodetect(true)
dispatchAutodetect(true)
} }
override 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?.isDefault == false) {
cell(direnv)
}
}
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-compact.label")) { cell(inlayHintsCompact) }
row(ZLSBundle.message("settings.build-on-save.label")) { cell(buildOnSave) }
row(ZLSBundle.message("settings.build-on-save-step.label")) { cell(buildOnSaveStep).resizableColumn().align(AlignX.FILL) }
row(ZLSBundle.message("settings.global-var-declarations.label")) { cell(globalVarDeclarations) }
row(ZLSBundle.message("settings.comptime-interpreter.label")) { cell(comptimeInterpreter) }
} }
group(ZLSBundle.message("dev-settings.group.title")) { }
row(ZLSBundle.message("dev-settings.debug.label")) { cell(debug) }
row(ZLSBundle.message("dev-settings.message-trace.label")) { cell(messageTrace) } override fun attach(p: Panel) = with(p) {
if (!project.isDefault) {
group(ZLSBundle.message("settings.group.title")) {
fancyRow(
"settings.zls-path.label",
"settings.zls-path.tooltip"
) {
cell(zlsPath).resizableColumn().align(AlignX.FILL)
if (DirenvCmd.direnvInstalled()) {
cell(direnv)
}
}
fancyRow(
"settings.zls-config-path.label",
"settings.zls-config-path.tooltip"
) { cell(zlsConfigPath).align(AlignX.FILL) }
fancyRow(
"settings.enable_snippets.label",
"settings.enable_snippets.tooltip"
) { cell(enable_snippets) }
fancyRow(
"settings.enable_argument_placeholders.label",
"settings.enable_argument_placeholders.tooltip"
) { cell(enable_argument_placeholders) }
fancyRow(
"settings.completion_label_details.label",
"settings.completion_label_details.tooltip"
) { cell(completion_label_details) }
fancyRow(
"settings.enable_build_on_save.label",
"settings.enable_build_on_save.tooltip"
) { cell(enable_build_on_save) }
fancyRow(
"settings.build_on_save_args.label",
"settings.build_on_save_args.tooltip"
) { cell(build_on_save_args).resizableColumn().align(AlignX.FILL) }
fancyRow(
"settings.semantic_tokens.label",
"settings.semantic_tokens.tooltip"
) { cell(semantic_tokens) }
group(ZLSBundle.message("settings.inlay-hints-group.label")) {
fancyRow(
"settings.inlay-hints-enable.label",
"settings.inlay-hints-enable.tooltip"
) { cell(inlayHints) }
fancyRow(
"settings.inlay_hints_show_variable_type_hints.label",
"settings.inlay_hints_show_variable_type_hints.tooltip"
) { cell(inlay_hints_show_variable_type_hints) }
fancyRow(
"settings.inlay_hints_show_struct_literal_field_type.label",
"settings.inlay_hints_show_struct_literal_field_type.tooltip"
) { cell(inlay_hints_show_struct_literal_field_type) }
fancyRow(
"settings.inlay_hints_show_parameter_name.label",
"settings.inlay_hints_show_parameter_name.tooltip"
) { cell(inlay_hints_show_parameter_name) }
fancyRow(
"settings.inlay_hints_show_builtin.label",
"settings.inlay_hints_show_builtin.tooltip"
) { cell(inlay_hints_show_builtin) }
fancyRow(
"settings.inlay_hints_exclude_single_argument.label",
"settings.inlay_hints_exclude_single_argument.tooltip"
) { cell(inlay_hints_exclude_single_argument) }
fancyRow(
"settings.inlay_hints_hide_redundant_param_names.label",
"settings.inlay_hints_hide_redundant_param_names.tooltip"
) { cell(inlay_hints_hide_redundant_param_names) }
fancyRow(
"settings.inlay_hints_hide_redundant_param_names_last_token.label",
"settings.inlay_hints_hide_redundant_param_names_last_token.tooltip"
) { cell(inlay_hints_hide_redundant_param_names_last_token) }
}
fancyRow(
"settings.warn_style.label",
"settings.warn_style.tooltip"
) { cell(warn_style) }
fancyRow(
"settings.highlight_global_var_declarations.label",
"settings.highlight_global_var_declarations.tooltip"
) { cell(highlight_global_var_declarations) }
fancyRow(
"settings.skip_std_references.label",
"settings.skip_std_references.tooltip"
) { cell(skip_std_references) }
fancyRow(
"settings.prefer_ast_check_as_child_process.label",
"settings.prefer_ast_check_as_child_process.tooltip"
) { cell(prefer_ast_check_as_child_process) }
fancyRow(
"settings.builtin_path.label",
"settings.builtin_path.tooltip"
) { cell(builtin_path).resizableColumn().align(AlignX.FILL) }
fancyRow(
"settings.build_runner_path.label",
"settings.build_runner_path.tooltip"
) { cell(build_runner_path).resizableColumn().align(AlignX.FILL) }
fancyRow(
"settings.global_cache_path.label",
"settings.global_cache_path.tooltip"
) { cell(global_cache_path).resizableColumn().align(AlignX.FILL) }
}
} }
dispatchAutodetect(false) dispatchAutodetect(false)
} }
@ -95,27 +203,61 @@ class ZLSSettingsPanel(private val project: Project?) : ZigProjectConfigurationP
direnv.isSelected, direnv.isSelected,
zlsPath.text, zlsPath.text,
zlsConfigPath.text, zlsConfigPath.text,
debug.isSelected,
messageTrace.isSelected,
buildOnSave.isSelected,
buildOnSaveStep.text,
globalVarDeclarations.isSelected,
comptimeInterpreter.isSelected,
inlayHints.isSelected, inlayHints.isSelected,
inlayHintsCompact.isSelected enable_snippets.isSelected,
enable_argument_placeholders.isSelected,
completion_label_details.isSelected,
enable_build_on_save.isSelected,
run {
val args = build_on_save_args.text ?: ""
return@run if (args.isEmpty()) {
emptyList()
} else {
translateCommandline(args).toList()
}
},
semantic_tokens.item ?: SemanticTokens.full,
inlay_hints_show_variable_type_hints.isSelected,
inlay_hints_show_struct_literal_field_type.isSelected,
inlay_hints_show_parameter_name.isSelected,
inlay_hints_show_builtin.isSelected,
inlay_hints_exclude_single_argument.isSelected,
inlay_hints_hide_redundant_param_names.isSelected,
inlay_hints_hide_redundant_param_names_last_token.isSelected,
warn_style.isSelected,
highlight_global_var_declarations.isSelected,
skip_std_references.isSelected,
prefer_ast_check_as_child_process.isSelected,
builtin_path.text?.nullIfEmpty(),
build_runner_path.text?.nullIfEmpty(),
global_cache_path.text?.nullIfEmpty(),
) )
set(value) { set(value) {
direnv.isSelected = value.direnv direnv.isSelected = value.direnv
zlsPath.text = value.zlsPath zlsPath.text = value.zlsPath
zlsConfigPath.text = value.zlsConfigPath zlsConfigPath.text = value.zlsConfigPath
debug.isSelected = value.debug
messageTrace.isSelected = value.messageTrace
buildOnSave.isSelected = value.buildOnSave
buildOnSaveStep.text = value.buildOnSaveStep
globalVarDeclarations.isSelected = value.globalVarDeclarations
comptimeInterpreter.isSelected = value.comptimeInterpreter
inlayHints.isSelected = value.inlayHints inlayHints.isSelected = value.inlayHints
inlayHintsCompact.isSelected = value.inlayHintsCompact enable_snippets.isSelected = value.enable_snippets
enable_argument_placeholders.isSelected = value.enable_argument_placeholders
completion_label_details.isSelected = value.completion_label_details
enable_build_on_save.isSelected = value.enable_build_on_save
build_on_save_args.text = value.build_on_save_args.joinToString(separator = " ") { it }
semantic_tokens.item = value.semantic_tokens
inlay_hints_show_variable_type_hints.isSelected = value.inlay_hints_show_variable_type_hints
inlay_hints_show_struct_literal_field_type.isSelected = value.inlay_hints_show_struct_literal_field_type
inlay_hints_show_parameter_name.isSelected = value.inlay_hints_show_parameter_name
inlay_hints_show_builtin.isSelected = value.inlay_hints_show_builtin
inlay_hints_exclude_single_argument.isSelected = value.inlay_hints_exclude_single_argument
inlay_hints_hide_redundant_param_names.isSelected = value.inlay_hints_hide_redundant_param_names
inlay_hints_hide_redundant_param_names_last_token.isSelected =
value.inlay_hints_hide_redundant_param_names_last_token
warn_style.isSelected = value.warn_style
highlight_global_var_declarations.isSelected = value.highlight_global_var_declarations
skip_std_references.isSelected = value.skip_std_references
prefer_ast_check_as_child_process.isSelected = value.prefer_ast_check_as_child_process
builtin_path.text = value.builtin_path ?: ""
build_runner_path.text = value.build_runner_path ?: ""
global_cache_path.text = value.global_cache_path ?: ""
} }
private fun dispatchAutodetect(force: Boolean) { private fun dispatchAutodetect(force: Boolean) {
@ -140,8 +282,93 @@ class ZLSSettingsPanel(private val project: Project?) : ZigProjectConfigurationP
} }
private suspend fun getDirenv(): Env { private suspend fun getDirenv(): Env {
if (DirenvCmd.direnvInstalled() && project?.isDefault == false && direnv.isSelected) if (!project.isDefault && DirenvCmd.direnvInstalled() && direnv.isSelected)
return project.getDirenv() return project.getDirenv()
return emptyEnv return emptyEnv
} }
} }
private fun Panel.fancyRow(
label: @PropertyKey(resourceBundle = "zigbrains.lsp.Bundle") String,
tooltip: @PropertyKey(resourceBundle = "zigbrains.lsp.Bundle") String,
cb: Row.() -> Unit
) = row(ZLSBundle.message(label)) {
contextHelp(ZLSBundle.message(tooltip))
cb()
}
@Throws(Exception::class)
private fun translateCommandline(toProcess: String): List<String> {
if (toProcess.isEmpty()) {
return emptyList()
}
val normal = 0
val inQuote = 1
val inDoubleQuote = 2
val inEscape = 3
var state = normal
var escapeState = normal
val tok = StringTokenizer(toProcess, "\\\"' ", true)
val v = ArrayList<String>()
val current = StringBuilder()
while (tok.hasMoreTokens()) {
val nextTok = tok.nextToken()
when (state) {
inQuote -> if ("'" == nextTok) {
state = normal
} else if ("\\" == nextTok) {
escapeState = inQuote
state = inEscape
} else {
current.append(nextTok)
}
inDoubleQuote -> if ("\"" == nextTok) {
state = normal
} else if ("\\" == nextTok) {
escapeState = inDoubleQuote
state = inEscape
} else {
current.append(nextTok)
}
inEscape -> {
current.append(when(nextTok) {
"n" -> "\n"
"r" -> "\r"
"t" -> "\t"
else -> nextTok
})
state = escapeState
}
else -> if ("'" == nextTok) {
state = inQuote
} else if ("\"" == nextTok) {
state = inDoubleQuote
} else if (" " == nextTok) {
if (current.isNotEmpty()) {
v.add(current.toString())
current.setLength(0)
}
} else if ("\\" == nextTok) {
escapeState = normal
state = inEscape
} else {
current.append(nextTok)
}
}
}
if (current.isNotEmpty()) {
v.add(current.toString())
}
if (state != inQuote && state != inDoubleQuote) {
return v
} else {
throw IllegalArgumentException("unbalanced quotes in $toProcess")
}
}

View file

@ -81,6 +81,6 @@ class ToolchainZLSConfigProvider: SuspendingZLSConfigProvider {
if (lib == null) if (lib == null)
return previous return previous
return previous.copy(zigExePath = exe.pathString, zigLibPath = lib.pathString) return previous.copy(zig_exe_path = exe.pathString, zig_lib_path = lib.pathString)
} }
} }

View file

@ -21,7 +21,6 @@
--> -->
<idea-plugin> <idea-plugin>
<resource-bundle>zigbrains.lsp.Bundle</resource-bundle>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<!-- LSP textDocument/signatureHelp --> <!-- LSP textDocument/signatureHelp -->
<codeInsight.parameterInfo <codeInsight.parameterInfo

View file

@ -1,21 +1,54 @@
settings.group.title=ZLS Settings settings.group.title=ZLS Settings
settings.zls-path.label=Executable path settings.zls-path.label=Executable path
settings.zls-path.tooltip=Path to the ZLS Binary
settings.zls-path.browse.title=Path to the ZLS Binary settings.zls-path.browse.title=Path to the ZLS Binary
settings.zls-config-path.label=Config path (leave empty to use built-in config) settings.zls-config-path.label=Config path
settings.zls-config-path.tooltip=Leave empty to use built-in config generated from the settings below
settings.zls-config-path.browse.title=Path to the Custom ZLS Config File (Optional) settings.zls-config-path.browse.title=Path to the Custom ZLS Config File (Optional)
settings.inlay-hints.label=Inlay hints
settings.inlay-hints-compact.label=Compact errors in inlay hint
settings.inlay-hints-compact.tooltip=Replace extremely long error{...} snippets in inlay hints with a placeholder
settings.build-on-save.label=Build on save
settings.build-on-save.tooltip=Enable build-on-save diagnostics
settings.build-on-save-step.label=Build on save step
settings.build-on-save-step.tooltip=Which step should be executed on build-on-save
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.use-direnv.label=Use direnv
dev-settings.group.title=ZLS Developer Settings settings.inlay-hints-group.label=Inlay Hints
dev-settings.debug.label=Debug log settings.inlay-hints-enable.label=Enable
dev-settings.message-trace.label=Message trace settings.inlay-hints-enable.tooltip=Toggle this to enable/disable all inlay hints
settings.enable_snippets.label=Enable snippets
settings.enable_snippets.tooltip=Enables snippet completions when the client also supports them
settings.enable_argument_placeholders.label=Enable argument placeholders
settings.enable_argument_placeholders.tooltip=Whether to enable function argument placeholder completions
settings.completion_label_details.label=Completion label details
settings.completion_label_details.tooltip=Whether to show the function signature in completion results. May improve readability in some editors when disabled
settings.enable_build_on_save.label=Enable build on save
settings.enable_build_on_save.tooltip=Whether to enable build-on-save diagnostics. Will be automatically enabled if the `build.zig` has declared a 'check' step.\n\nFor more infromation, checkout the [Build-On-Save](https://zigtools.org/zls/guides/build-on-save/) Guide.
settings.build_on_save_args.label=Build on save args
settings.build_on_save_args.tooltip=Specify which arguments should be passed to Zig when running build-on-save.\n\nIf the `build.zig` has declared a 'check' step, it will be preferred over the default 'install' step.
settings.semantic_tokens.label=Semantic tokens
settings.semantic_tokens.tooltip=Set level of semantic tokens. `partial` only includes information that requires semantic analysis.
settings.inlay_hints_show_variable_type_hints.label=Show variable type hints
settings.inlay_hints_show_variable_type_hints.tooltip=Enable inlay hints for variable types
settings.inlay_hints_show_struct_literal_field_type.label=Show struct literal field type
settings.inlay_hints_show_struct_literal_field_type.tooltip=Enable inlay hints for fields in struct and union literals
settings.inlay_hints_show_parameter_name.label=Show parameter name
settings.inlay_hints_show_parameter_name.tooltip=Enable inlay hints for parameter names
settings.inlay_hints_show_builtin.label=Show builtin
settings.inlay_hints_show_builtin.tooltip=Enable inlay hints for builtin functions
settings.inlay_hints_exclude_single_argument.label=Exclude single argument
settings.inlay_hints_exclude_single_argument.tooltip=Don't show inlay hints for single argument calls
settings.inlay_hints_hide_redundant_param_names.label=Hide redundant param names
settings.inlay_hints_hide_redundant_param_names.tooltip=Hides inlay hints when parameter name matches the identifier (e.g. `foo: foo`)
settings.inlay_hints_hide_redundant_param_names_last_token.label=Hide redundant param names last token
settings.inlay_hints_hide_redundant_param_names_last_token.tooltip=Hides inlay hints when parameter name matches the last token of a parameter node (e.g. `foo: bar.foo`, `foo: &foo`)
settings.warn_style.label=Warn style
settings.warn_style.tooltip=Enables warnings for style guideline mismatches
settings.highlight_global_var_declarations.label=Highlight global var declarations
settings.highlight_global_var_declarations.tooltip=Whether to highlight global var declarations
settings.skip_std_references.label=Skip std references
settings.skip_std_references.tooltip=When true, skips searching for references in the standard library. Improves lookup speed for functions in user's code. Renaming and go-to-definition will continue to work as is
settings.prefer_ast_check_as_child_process.label=Prefer AST check as child process
settings.prefer_ast_check_as_child_process.tooltip=Favor using `zig ast-check` instead of the builtin one
settings.builtin_path.label=Builtin path
settings.builtin_path.tooltip=Override the path to 'builtin' module. Automatically resolved if unset.
settings.build_runner_path.label=Build runner path
settings.build_runner_path.tooltip=Specify a custom build runner to resolve build system information.
settings.global_cache_path.label=Global cache path
settings.global_cache_path.tooltip=Path to a directory that will be used as zig's cache. Will default to `${KnownFolders.Cache}/zls`.
configurable.name.zls.settings=ZLS Settings configurable.name.zls.settings=ZLS Settings
notification.group.zigbrains-lsp=ZigBrains LSP Integration notification.group.zigbrains-lsp=ZigBrains LSP Integration
notification.message.could-not-detect.content=Could not detect ZLS binary, please configure it notification.message.could-not-detect.content=Could not detect ZLS binary, please configure it