Compare commits

...

10 commits

30 changed files with 198 additions and 116 deletions

View file

@ -17,6 +17,22 @@ Changelog structure reference:
## [Unreleased]
## [25.1.0]
### Added
- IDEA 2025.1 support
- LSP
- Configurable inlay hints file size limit to reduce IDE lag
## [25.0.2]
### Fixed
- Project
- ZLS settings not scrollable in the language server list
## [25.0.1]
### Fixed

View file

@ -15,6 +15,7 @@ through the built-in plugin browser:
1. Go to `Settings -> Plugins`
2. To the right of the `Installed` button at the top, click on the `...` dropdown menu, then select `Manage Plugin Repositories...`
3. Click the add button, and then enter the ZigBrains updater URL, based on your IDE version:
- `2025.1.*` or newer: https://falsepattern.com/zigbrains/updatePlugins-251.xml
- `2024.3.*`: https://falsepattern.com/zigbrains/updatePlugins-243.xml
- `2024.2.*`: https://falsepattern.com/zigbrains/updatePlugins-242.xml
- `2024.1.*`: https://falsepattern.com/zigbrains/updatePlugins-241.xml

View file

@ -6,15 +6,15 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
plugins {
kotlin("jvm") version "2.0.21" apply false
kotlin("plugin.serialization") version "2.0.21" apply false
kotlin("jvm") version "2.1.10" apply false
kotlin("plugin.serialization") version "2.1.10" apply false
id("org.jetbrains.intellij.platform") version "2.5.0"
id("org.jetbrains.changelog") version "2.2.1"
id("org.jetbrains.grammarkit") version "2022.3.2.2" apply false
idea
`maven-publish`
}
val publishVersions = listOf("241", "242", "243")
val publishVersions = listOf("241", "242", "243", "251")
val pluginVersionFull get() = "$pluginVersion-$pluginSinceBuild"
val pluginVersion: String by project
val pluginSinceBuild: String by project

View file

@ -23,7 +23,7 @@
set -e
declare -a branches=("master" "242" "241")
declare -a branches=("master" "243" "242" "241")
DEFAULT_BRANCH="${branches[0]}"

View file

@ -58,7 +58,8 @@ class ZigClionDebuggerDriverConfigurationProvider: ZigDebuggerDriverConfiguratio
return when(toolchain.debuggerKind) {
CPPDebugger.Kind.BUNDLED_GDB,
CPPDebugger.Kind.CUSTOM_GDB -> CLionGDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
CPPDebugger.Kind.BUNDLED_LLDB -> CLionLLDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
CPPDebugger.Kind.BUNDLED_LLDB,
CPPDebugger.Kind.CUSTOM_LLDB -> CLionLLDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
}
}
}

View file

@ -9,12 +9,15 @@ plugins {
val ideaCommunityVersion: String by project
val useInstaller = property("useInstaller").toString().toBoolean()
val serializationVersion: String by project
dependencies {
intellijPlatform {
create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller)
}
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3")
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:$serializationVersion") {
isTransitive = false
}
}
//region grammars

View file

@ -25,6 +25,7 @@ package com.falsepattern.zigbrains.project.toolchain.base
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.project.toolchain.ui.ImmutableElementPanel
import com.falsepattern.zigbrains.project.toolchain.zigToolchainList
import com.falsepattern.zigbrains.shared.ui.UUIDComboBoxDriver.Companion.wrapModal
import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.NlsContexts
@ -37,7 +38,7 @@ abstract class ZigToolchainConfigurable<T: ZigToolchain>(
val uuid: UUID,
tc: T,
val data: ZigProjectConfigurationProvider.IUserDataBridge?,
val modal: Boolean
private val modal: Boolean
): NamedConfigurable<UUID>() {
var toolchain: T = tc
set(value) {
@ -64,7 +65,7 @@ abstract class ZigToolchainConfigurable<T: ZigToolchain>(
views.forEach { it.attach(this@panel) }
}.withMinimumWidth(20)
views.forEach { it.reset(toolchain) }
return p
return wrapModal(p, modal)
}
override fun getEditableObject(): UUID? {

View file

@ -24,15 +24,15 @@ package com.falsepattern.zigbrains.project.toolchain.downloader
import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
import com.falsepattern.zigbrains.project.toolchain.local.getSuggestedLocalToolchainPath
import com.falsepattern.zigbrains.project.toolchain.local.suggestedLocalToolchainPath
import com.falsepattern.zigbrains.shared.downloader.Downloader
import java.awt.Component
class LocalToolchainDownloader(component: Component) : Downloader<LocalZigToolchain, ZigVersionInfo>(component) {
override val windowTitle get() = ZigBrainsBundle.message("settings.toolchain.downloader.title")
override val versionInfoFetchTitle get() = ZigBrainsBundle.message("settings.toolchain.downloader.progress.fetch")
override val suggestedPath get() = suggestedLocalToolchainPath
override fun downloadProgressTitle(version: ZigVersionInfo) = ZigBrainsBundle.message("settings.toolchain.downloader.progress.install", version.version.rawVersion)
override fun localSelector() = LocalToolchainSelector(component)
override suspend fun downloadVersionList() = ZigVersionInfo.downloadVersionList()
override fun getSuggestedPath() = getSuggestedLocalToolchainPath()
}

View file

@ -73,8 +73,8 @@ class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchai
).also { Disposer.register(this, it) }
private var debounce: Job? = null
override fun attach(p: Panel): Unit = with(p) {
super.attach(p)
override fun attach(panel: Panel): Unit = with(panel) {
super.attach(panel)
row(ZigBrainsBundle.message("settings.toolchain.local.path.label")) {
cell(pathToToolchain).resizableColumn().align(AlignX.FILL)
}
@ -87,23 +87,23 @@ class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchai
}
}
override fun isModified(toolchain: LocalZigToolchain): Boolean {
override fun isModified(elem: LocalZigToolchain): Boolean {
val name = nameFieldValue ?: return false
val location = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull() ?: return false
val std = if (stdFieldOverride.isSelected) pathToStd.text.ifBlank { null }?.toNioPathOrNull() else null
return name != toolchain.name || toolchain.location != location || toolchain.std != std
return name != elem.name || elem.location != location || elem.std != std
}
override fun apply(toolchain: LocalZigToolchain): LocalZigToolchain? {
override fun apply(elem: LocalZigToolchain): LocalZigToolchain? {
val location = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull() ?: return null
val std = if (stdFieldOverride.isSelected) pathToStd.text.ifBlank { null }?.toNioPathOrNull() else null
return toolchain.copy(location = location, std = std, name = nameFieldValue ?: "")
return elem.copy(location = location, std = std, name = nameFieldValue ?: "")
}
override fun reset(toolchain: LocalZigToolchain?) {
nameFieldValue = toolchain?.name ?: ""
this.pathToToolchain.text = toolchain?.location?.pathString ?: ""
val std = toolchain?.std
override fun reset(elem: LocalZigToolchain?) {
nameFieldValue = elem?.name ?: ""
this.pathToToolchain.text = elem?.location?.pathString ?: ""
val std = elem?.std
if (std != null) {
stdFieldOverride.isSelected = true
pathToStd.text = std.pathString

View file

@ -28,18 +28,18 @@ import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvid
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainProvider
import com.falsepattern.zigbrains.shared.downloader.homePath
import com.falsepattern.zigbrains.shared.downloader.xdgDataHome
import com.falsepattern.zigbrains.shared.ui.renderPathNameComponent
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.UserDataHolder
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.ui.SimpleColoredComponent
import com.intellij.util.system.OS
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import java.nio.file.Files
import java.nio.file.Path
import java.util.*
import kotlin.io.path.isDirectory
import kotlin.io.path.pathString
class LocalZigToolchainProvider: ZigToolchainProvider {
@ -93,7 +93,7 @@ class LocalZigToolchainProvider: ZigToolchainProvider {
Env.empty
}
val pathToolchains = env.findAllExecutablesOnPATH("zig").mapNotNull { it.parent }
val wellKnown = getWellKnown().asFlow().flatMapConcat { dir ->
val wellKnown = wellKnown.asFlow().flatMapConcat { dir ->
runCatching {
Files.newDirectoryStream(dir).use { stream ->
stream.toList().filterNotNull().asFlow()
@ -112,8 +112,8 @@ class LocalZigToolchainProvider: ZigToolchainProvider {
}
}
fun getSuggestedLocalToolchainPath(): Path? {
return getWellKnown().getOrNull(0)
val suggestedLocalToolchainPath: Path? by lazy {
wellKnown.getOrNull(0)
}
/**
@ -130,18 +130,12 @@ fun getSuggestedLocalToolchainPath(): Path? {
*
* and HOME is the user home path
*/
private fun getWellKnown(): List<Path> {
val home = System.getProperty("user.home")?.toNioPathOrNull() ?: return emptyList()
val xdgDataHome = when(OS.CURRENT) {
OS.macOS -> home.resolve("Library")
OS.Windows -> System.getenv("LOCALAPPDATA")?.toNioPathOrNull()
else -> System.getenv("XDG_DATA_HOME")?.toNioPathOrNull() ?: home.resolve(Path.of(".local", "share"))
}
private val wellKnown: List<Path> by lazy {
val res = ArrayList<Path>()
if (xdgDataHome != null && xdgDataHome.isDirectory()) {
res.add(xdgDataHome.resolve("zig"))
res.add(xdgDataHome.resolve("zigup"))
xdgDataHome?.let {
res.add(it.resolve("zig"))
res.add(it.resolve("zigup"))
}
res.add(home.resolve(".zig"))
return res
}
homePath?.let { res.add(it.resolve(".zig")) }
res
}

View file

@ -26,7 +26,7 @@ import com.intellij.openapi.Disposable
import com.intellij.ui.dsl.builder.Panel
interface ImmutableElementPanel<T>: Disposable {
fun attach(p: Panel)
fun attach(panel: Panel)
fun isModified(elem: T): Boolean
/**
* Returned object must be the exact same class as the provided one.

View file

@ -34,7 +34,7 @@ abstract class ImmutableNamedElementPanelBase<T>: ImmutableElementPanel<T> {
get() = nameField.text.ifBlank { null }
set(value) {nameField.text = value ?: ""}
override fun attach(p: Panel): Unit = with(p) {
override fun attach(panel: Panel): Unit = with(panel) {
row(ZigBrainsBundle.message("settings.toolchain.base.name.label")) {
cell(nameField).resizableColumn().align(AlignX.FILL)
}

View file

@ -60,7 +60,7 @@ class ZigToolchainEditor(private val sharedState: ZigProjectConfigurationProvide
}
override fun attach(p: Panel): Unit = with(p) {
override fun attach(panel: Panel): Unit = with(panel) {
row(ZigBrainsBundle.message(
if (sharedState.getUserData(PROJECT_KEY)?.isDefault == true)
"settings.toolchain.editor.toolchain-default.label"
@ -75,7 +75,7 @@ class ZigToolchainEditor(private val sharedState: ZigProjectConfigurationProvide
views.addAll(createZigToolchainExtensionPanels(sharedState, PanelState.ProjectEditor))
myViews = views
}
views.forEach { it.attach(p) }
views.forEach { it.attach(panel) }
}
override fun onSelection(uuid: UUID?) {

View file

@ -76,10 +76,10 @@ abstract class Downloader<T, V: VersionInfo>(val component: Component) {
protected abstract val windowTitle: String
protected abstract val versionInfoFetchTitle: @NlsContexts.ProgressTitle String
protected abstract val suggestedPath: Path?
protected abstract fun downloadProgressTitle(version: V): @NlsContexts.ProgressTitle String
protected abstract fun localSelector(): LocalSelector<T>
protected abstract suspend fun downloadVersionList(): List<V>
protected abstract fun getSuggestedPath(): Path?
@RequiresEdt
private fun selectVersion(info: List<V>, selector: LocalSelector<T>): Pair<Path, V>? {
@ -131,7 +131,7 @@ abstract class Downloader<T, V: VersionInfo>(val component: Component) {
})
var archiveSizeCell: Cell<*>? = null
fun detect(item: V) {
outputPath.text = getSuggestedPath()?.resolve(item.version.rawVersion)?.pathString ?: ""
outputPath.text = suggestedPath?.resolve(item.version.rawVersion)?.pathString ?: ""
val size = item.dist.size
val sizeMb = size / (1024f * 1024f)
archiveSizeCell?.comment?.text = ZigBrainsBundle.message("settings.shared.downloader.archive-size.text", "%.2fMB".format(sizeMb))

View file

@ -41,11 +41,13 @@ import com.intellij.ui.components.textFieldWithBrowseButton
import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.panel
import com.intellij.util.concurrency.annotations.RequiresEdt
import com.intellij.util.system.OS
import java.awt.Component
import java.nio.file.Path
import java.util.concurrent.atomic.AtomicBoolean
import javax.swing.Icon
import javax.swing.event.DocumentEvent
import kotlin.io.path.isDirectory
import kotlin.io.path.pathString
abstract class LocalSelector<T>(val component: Component) {
@ -135,4 +137,16 @@ abstract class LocalSelector<T>(val component: Component) {
val errorIcon: Icon,
val errorText: String,
)
}
val homePath: Path? by lazy {
System.getProperty("user.home")?.toNioPathOrNull()?.takeIf { it.isDirectory() }
}
val xdgDataHome: Path? by lazy {
when(OS.CURRENT) {
OS.macOS -> homePath?.resolve("Library")
OS.Windows -> System.getenv("LOCALAPPDATA")?.toNioPathOrNull()
else -> System.getenv("XDG_DATA_HOME")?.toNioPathOrNull() ?: homePath?.resolve(Path.of(".local", "share"))
}?.takeIf { it.isDirectory() }
}

View file

@ -24,8 +24,11 @@ package com.falsepattern.zigbrains.shared.ui
import com.falsepattern.zigbrains.shared.UUIDMapSerializable
import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.ui.components.JBScrollPane
import java.awt.Component
import java.awt.Dimension
import java.util.*
import javax.swing.JComponent
interface UUIDComboBoxDriver<T> {
val theMap: UUIDMapSerializable.Converting<T, *, *>
@ -34,4 +37,15 @@ interface UUIDComboBoxDriver<T> {
fun createComboBox(model: ZBModel<T>): ZBComboBox<T>
suspend fun resolvePseudo(context: Component, elem: ListElem.Pseudo<T>): UUID?
fun createNamedConfigurable(uuid: UUID, elem: T): NamedConfigurable<UUID>
companion object {
fun wrapModal(component: JComponent, modal: Boolean): JComponent {
if (modal) {
component.preferredSize = Dimension(640, 480)
return component
} else {
return JBScrollPane(component)
}
}
}
}

View file

@ -161,7 +161,7 @@ abstract class UUIDMapSelector<T>(val driver: UUIDComboBoxDriver<T>): Disposable
protected fun attachComboBoxRow(row: Row): Unit = with(row) {
cell(comboBox).resizableColumn().align(AlignX.FILL)
button(ZigBrainsBundle.message("settings.toolchain.editor.toolchain.edit-button.name")) { e ->
button(ZigBrainsBundle.message("settings.toolchain.editor.toolchain.edit-button.name")) {
zigCoroutineScope.launchWithEDT(comboBox.asContextElement()) {
var selectedUUID = comboBox.selectedUUID ?: return@launchWithEDT
val elem = driver.theMap[selectedUUID] ?: return@launchWithEDT

View file

@ -250,16 +250,16 @@ abstract class ZBCellRenderer<T>(val getModel: () -> ZBModel<T>) : ColoredListCe
}
fun renderPathNameComponent(path: String, name: String?, nameFallback: String, component: SimpleColoredComponent, isSuggestion: Boolean, isSelected: Boolean) {
val path = presentDetectedPath(path)
val thePath = presentDetectedPath(path)
val primary: String
var secondary: String?
val tooltip: String?
if (isSuggestion) {
primary = path
primary = thePath
secondary = name
} else {
primary = name ?: nameFallback
secondary = path
secondary = thePath
}
if (isSelected) {
tooltip = secondary
@ -277,12 +277,12 @@ fun renderPathNameComponent(path: String, name: String?, nameFallback: String, c
fun presentDetectedPath(home: String, maxLength: Int = 50, suffixLength: Int = 30): String {
//for macOS, let's try removing Bundle internals
var home = home
home = StringUtil.trimEnd(home, "/Contents/Home") //NON-NLS
home = StringUtil.trimEnd(home, "/Contents/MacOS") //NON-NLS
home = FileUtil.getLocationRelativeToUserHome(home, false)
home = StringUtil.shortenTextWithEllipsis(home, maxLength, suffixLength)
return home
var theHome = home
theHome = StringUtil.trimEnd(theHome, "/Contents/Home") //NON-NLS
theHome = StringUtil.trimEnd(theHome, "/Contents/MacOS") //NON-NLS
theHome = FileUtil.getLocationRelativeToUserHome(theHome, false)
theHome = StringUtil.shortenTextWithEllipsis(theHome, maxLength, suffixLength)
return theHome
}
private val EMPTY_ICON = EmptyIcon.create(1, 16)

View file

@ -1,13 +1,13 @@
pluginName=ZigBrains
pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains
pluginVersion=25.0.1
pluginVersion=25.1.0
pluginSinceBuild=243
pluginSinceBuild=251
pluginUntilBuild=
ideaCommunityVersion=2024.3
clionVersion=2024.3
ideaCommunityVersion=2025.1
clionVersion=2025.1
useInstaller=true
javaVersion=21
# ideaCommunity / clion
@ -17,6 +17,8 @@ lsp4jVersion=0.21.1
lsp4ijVersion=0.12.0
lsp4ijNightly=false
serializationVersion=1.7.3
kotlin.stdlib.default.dependency=false
kotlin.code.style=official
org.gradle.configuration-cache=true

View file

@ -8,12 +8,15 @@ val lsp4ijVersion: String by project
val lsp4jVersion: String by project
val ideaCommunityVersion: String by project
val useInstaller = property("useInstaller").toString().toBoolean()
val serializationVersion: String by project
dependencies {
intellijPlatform {
create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller)
}
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3")
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:$serializationVersion") {
isTransitive = false
}
compileOnly("com.redhat.devtools.intellij:lsp4ij:$lsp4ijVersion")
compileOnly("org.eclipse.lsp4j:org.eclipse.lsp4j:$lsp4jVersion")
implementation(project(":core")) {

View file

@ -68,7 +68,14 @@ class ZigLanguageServerFactory: LanguageServerFactory, LanguageServerEnablementS
}
features.inlayHintFeature = object: LSPInlayHintFeature() {
override fun isEnabled(file: PsiFile): Boolean {
return project.zls?.settings?.inlayHints == true
val settings = project.zls?.settings ?: return false
if (!settings.inlayHints)
return false
val maxFileSizeKb = settings.inlayHintsMaxFileSizeKb
if (maxFileSizeKb == 0)
return true
val fileSizeKb = file.fileDocument.textLength / 1024
return fileSizeKb <= maxFileSizeKb
}
}
return features

View file

@ -30,6 +30,7 @@ import org.jetbrains.annotations.NonNls
data class ZLSSettings(
@JvmField @Attribute val zlsConfigPath: @NonNls String = "",
@JvmField @Attribute val inlayHints: Boolean = true,
@JvmField @Attribute val inlayHintsMaxFileSizeKb: Int = 128,
@JvmField @Attribute val enable_snippets: Boolean = true,
@JvmField @Attribute val enable_argument_placeholders: Boolean = true,
@JvmField @Attribute val completion_label_details: Boolean = true,

View file

@ -35,6 +35,9 @@ import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.builder.Row
import org.jetbrains.annotations.PropertyKey
import javax.swing.text.AttributeSet
import javax.swing.text.DocumentFilter
import javax.swing.text.PlainDocument
@Suppress("PrivatePropertyName")
class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
@ -44,6 +47,27 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
.withTitle(ZLSBundle.message("settings.zls-config-path.browse.title"))
).also { Disposer.register(this, it) }
private val inlayHints = JBCheckBox()
private val inlayHintsMaxFileSize = ExtendableTextField(5).also { (it.document as PlainDocument).documentFilter = object: DocumentFilter() {
override fun insertString(fb: FilterBypass?, offset: Int, string: String?, attr: AttributeSet?) {
if (string != null && !string.isEmpty() && string.toIntOrNull() == null) {
return
}
super.insertString(fb, offset, string, attr)
}
override fun replace(
fb: FilterBypass?,
offset: Int,
length: Int,
text: String?,
attrs: AttributeSet?
) {
if (text != null && !text.isEmpty() && text.toIntOrNull() == null) {
return
}
super.replace(fb, offset, length, text, attrs)
}
} }
private val enable_snippets = JBCheckBox()
private val enable_argument_placeholders = JBCheckBox()
private val completion_label_details = JBCheckBox()
@ -65,7 +89,7 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
private val build_runner_path = ExtendableTextField()
private val global_cache_path = ExtendableTextField()
override fun attach(p: Panel): Unit = with(p) {
override fun attach(panel: Panel): Unit = with(panel) {
fancyRow(
"settings.zls-config-path.label",
"settings.zls-config-path.tooltip"
@ -99,6 +123,13 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
"settings.inlay-hints-enable.label",
"settings.inlay-hints-enable.tooltip"
) { cell(inlayHints) }
fancyRow(
"settings.inlay-hints-max-size.label",
"settings.inlay-hints-max-size.tooltip",
) {
cell(inlayHintsMaxFileSize)
text(ZLSBundle.message("settings.inlay-hints-max-size.unit"))
}
fancyRow(
"settings.inlay_hints_show_variable_type_hints.label",
"settings.inlay_hints_show_variable_type_hints.tooltip"
@ -174,6 +205,7 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
get() = ZLSSettings(
zlsConfigPath.text,
inlayHints.isSelected,
inlayHintsMaxFileSize.text.toIntOrNull() ?: 128,
enable_snippets.isSelected,
enable_argument_placeholders.isSelected,
completion_label_details.isSelected,
@ -198,6 +230,7 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
set(value) {
zlsConfigPath.text = value.zlsConfigPath
inlayHints.isSelected = value.inlayHints
inlayHintsMaxFileSize.text = value.inlayHintsMaxFileSizeKb.toString()
enable_snippets.isSelected = value.enable_snippets
enable_argument_placeholders.isSelected = value.enable_argument_placeholders
completion_label_details.isSelected = value.completion_label_details

View file

@ -22,14 +22,14 @@
package com.falsepattern.zigbrains.lsp.zls
import com.falsepattern.zigbrains.shared.ui.UUIDComboBoxDriver.Companion.wrapModal
import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.openapi.util.NlsContexts
import com.intellij.ui.dsl.builder.panel
import java.awt.Dimension
import java.util.*
import javax.swing.JComponent
class ZLSConfigurable(val uuid: UUID, zls: ZLSVersion): NamedConfigurable<UUID>() {
class ZLSConfigurable(val uuid: UUID, zls: ZLSVersion, private val modal: Boolean): NamedConfigurable<UUID>() {
var zls: ZLSVersion = zls
set(value) {
zlsInstallations[uuid] = value
@ -59,8 +59,7 @@ class ZLSConfigurable(val uuid: UUID, zls: ZLSVersion): NamedConfigurable<UUID>(
val p = panel {
view.attach(this@panel)
}
p.preferredSize = Dimension(640, 480)
return p
return wrapModal(p, modal)
}
override fun getDisplayName(): @NlsContexts.ConfigurableName String? {

View file

@ -62,8 +62,8 @@ class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() {
private var settingsPanel: ZLSSettingsPanel? = null
private var debounce: Job? = null
override fun attach(p: Panel): Unit = with(p) {
super.attach(p)
override fun attach(panel: Panel): Unit = with(panel) {
super.attach(panel)
row(ZLSBundle.message("settings.panel.path.label")) {
cell(pathToZLS).resizableColumn().align(AlignX.FILL)
}
@ -71,27 +71,27 @@ class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() {
cell(zlsVersion)
}
val sp = ZLSSettingsPanel()
p.collapsibleGroup(ZLSBundle.message("settings.panel.settings.group.label"), indent = false) {
panel.collapsibleGroup(ZLSBundle.message("settings.panel.settings.group.label"), indent = false) {
sp.attach(this@collapsibleGroup)
}
settingsPanel = sp
}
override fun isModified(version: ZLSVersion): Boolean {
override fun isModified(elem: ZLSVersion): Boolean {
val name = nameFieldValue ?: return false
val path = this.pathToZLS.text.ifBlank { null }?.toNioPathOrNull() ?: return false
return name != version.name || version.path != path || settingsPanel?.isModified(version.settings) == true
return name != elem.name || elem.path != path || settingsPanel?.isModified(elem.settings) == true
}
override fun apply(version: ZLSVersion): ZLSVersion? {
override fun apply(elem: ZLSVersion): ZLSVersion? {
val path = this.pathToZLS.text.ifBlank { null }?.toNioPathOrNull() ?: return null
return version.copy(path = path, name = nameFieldValue ?: "", settings = settingsPanel?.apply(version.settings) ?: version.settings)
return elem.copy(path = path, name = nameFieldValue ?: "", settings = settingsPanel?.apply(elem.settings) ?: elem.settings)
}
override fun reset(version: ZLSVersion?) {
nameFieldValue = version?.name ?: ""
this.pathToZLS.text = version?.path?.pathString ?: ""
settingsPanel?.reset(version?.settings)
override fun reset(elem: ZLSVersion?) {
nameFieldValue = elem?.name ?: ""
this.pathToZLS.text = elem?.path?.pathString ?: ""
settingsPanel?.reset(elem?.settings)
dispatchUpdateUI()
}

View file

@ -24,7 +24,7 @@ package com.falsepattern.zigbrains.lsp.zls.downloader
import com.falsepattern.zigbrains.lsp.ZLSBundle
import com.falsepattern.zigbrains.lsp.zls.ZLSVersion
import com.falsepattern.zigbrains.lsp.zls.ui.getSuggestedZLSPath
import com.falsepattern.zigbrains.lsp.zls.ui.suggestedZLSPath
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider.IUserDataBridge
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable
@ -34,6 +34,7 @@ import java.awt.Component
class ZLSDownloader(component: Component, private val data: IUserDataBridge?) : Downloader<ZLSVersion, ZLSVersionInfo>(component) {
override val windowTitle get() = ZLSBundle.message("settings.downloader.title")
override val versionInfoFetchTitle get() = ZLSBundle.message("settings.downloader.progress.fetch")
override val suggestedPath get() = suggestedZLSPath
override fun downloadProgressTitle(version: ZLSVersionInfo) = ZLSBundle.message("settings.downloader.progress.install", version.version.rawVersion)
override fun localSelector() = ZLSLocalSelector(component)
override suspend fun downloadVersionList(): List<ZLSVersionInfo> {
@ -41,5 +42,4 @@ class ZLSDownloader(component: Component, private val data: IUserDataBridge?) :
val project = data?.getUserData(ZigProjectConfigurationProvider.PROJECT_KEY)
return ZLSVersionInfo.downloadVersionInfoFor(toolchain, project)
}
override fun getSuggestedPath() = getSuggestedZLSPath()
}

View file

@ -33,14 +33,14 @@ import com.falsepattern.zigbrains.lsp.zls.zlsInstallations
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable.Companion.TOOLCHAIN_KEY
import com.falsepattern.zigbrains.shared.UUIDMapSerializable
import com.falsepattern.zigbrains.shared.downloader.homePath
import com.falsepattern.zigbrains.shared.downloader.xdgDataHome
import com.falsepattern.zigbrains.shared.ui.*
import com.falsepattern.zigbrains.shared.ui.ListElem.One.Actual
import com.falsepattern.zigbrains.shared.withUniqueName
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.util.system.OS
import com.intellij.util.text.SemVer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
@ -67,10 +67,6 @@ sealed interface ZLSDriver: UUIDComboBoxDriver<ZLSVersion> {
return ZLSComboBox(model)
}
override fun createNamedConfigurable(uuid: UUID, elem: ZLSVersion): NamedConfigurable<UUID> {
return ZLSConfigurable(uuid, elem)
}
override suspend fun resolvePseudo(
context: Component,
elem: ListElem.Pseudo<ZLSVersion>
@ -93,6 +89,10 @@ sealed interface ZLSDriver: UUIDComboBoxDriver<ZLSVersion> {
return res
}
override fun createNamedConfigurable(uuid: UUID, elem: ZLSVersion): NamedConfigurable<UUID> {
return ZLSConfigurable(uuid, elem, false)
}
override val data: ZigProjectConfigurationProvider.IUserDataBridge?
get() = null
}
@ -113,6 +113,10 @@ sealed interface ZLSDriver: UUIDComboBoxDriver<ZLSVersion> {
res.add(suggestZLSVersions(project, data, toolchainVersion).asPending())
return res
}
override fun createNamedConfigurable(uuid: UUID, elem: ZLSVersion): NamedConfigurable<UUID> {
return ZLSConfigurable(uuid, elem, true)
}
}
}
@ -142,16 +146,16 @@ private fun suggestZLSVersions(project: Project? = null, data: ZigProjectConfigu
emitIfCompatible(path, toolchainVersion)
}
val exe = if (SystemInfo.isWindows) "zls.exe" else "zls"
getWellKnownZLS().forEach { wellKnown ->
wellKnownZLS.forEach { wellKnown ->
runCatching {
Files.newDirectoryStream(wellKnown).use { stream ->
stream.asSequence().filterNotNull().forEach { dir ->
stream.asSequence().filterNotNull().forEach streamForEach@{ dir ->
val path = dir.resolve(exe)
if (!path.isRegularFile() || !path.isExecutable()) {
return@forEach
return@streamForEach
}
if (existing.any { it.path == path }) {
return@forEach
return@streamForEach
}
emitIfCompatible(path, toolchainVersion)
}
@ -188,8 +192,8 @@ private fun numericVersionEquals(a: SemVer, b: SemVer): Boolean {
}
fun getSuggestedZLSPath(): Path? {
return getWellKnownZLS().getOrNull(0)
val suggestedZLSPath: Path? by lazy {
wellKnownZLS.getOrNull(0)
}
/**
@ -205,17 +209,9 @@ fun getSuggestedZLSPath(): Path? {
*
* and HOME is the user home path
*/
private fun getWellKnownZLS(): List<Path> {
val home = System.getProperty("user.home")?.toNioPathOrNull() ?: return emptyList()
val xdgDataHome = when(OS.CURRENT) {
OS.macOS -> home.resolve("Library")
OS.Windows -> System.getenv("LOCALAPPDATA")?.toNioPathOrNull()
else -> System.getenv("XDG_DATA_HOME")?.toNioPathOrNull() ?: home.resolve(Path.of(".local", "share"))
}
private val wellKnownZLS: List<Path> by lazy {
val res = ArrayList<Path>()
if (xdgDataHome != null && xdgDataHome.isDirectory()) {
res.add(xdgDataHome.resolve("zls"))
}
res.add(home.resolve(".zls"))
return res
xdgDataHome?.let { res.add(it.resolve("zls")) }
homePath?.let { res.add(it.resolve(".zls")) }
res
}

View file

@ -55,21 +55,21 @@ class ZLSEditor<T: ZigToolchain>(private val sharedState: ZigProjectConfiguratio
}
}
override fun isModified(toolchain: T): Boolean {
override fun isModified(elem: T): Boolean {
if (isEmpty)
return false
return toolchain.zlsUUID != selectedUUID
return elem.zlsUUID != selectedUUID
}
override fun apply(toolchain: T): T {
return toolchain.withZLS(selectedUUID)
override fun apply(elem: T): T {
return elem.withZLS(selectedUUID)
}
override fun reset(toolchain: T?) {
selectedUUID = toolchain?.zlsUUID
override fun reset(elem: T?) {
selectedUUID = elem?.zlsUUID
zigCoroutineScope.launch {
listChanged()
selectedUUID = toolchain?.zlsUUID
selectedUUID = elem?.zlsUUID
}
}

View file

@ -4,6 +4,9 @@ settings.zls-config-path.browse.title=Path to the Custom ZLS Config File (Option
settings.inlay-hints-group.label=Inlay Hints
settings.inlay-hints-enable.label=Enable
settings.inlay-hints-enable.tooltip=Toggle this to enable/disable all inlay hints
settings.inlay-hints-max-size.label=Maximum Size
settings.inlay-hints-max-size.tooltip=The maximum size of a zig file to show inlay hints for.\nInlay hints in very large files make the IDE lag.\nSet to 0 to disable.
settings.inlay-hints-max-size.unit=KB
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

View file

@ -23,8 +23,6 @@
set -e
declare -a branches=("dev" "master" "242" "241")
die () {
echo >&2 "$@"
exit 1
@ -32,8 +30,4 @@ die () {
[ "$#" -eq 1 ] || die "1 argument required, $# provided"
for i in "${branches[@]}"
do
echo "Pushing branch $i"
git push "$1" "$i"
done
git push --atomic "$1" "dev" "master" "243" "242" "241"