Compare commits

..

32 commits
master ... 241

Author SHA1 Message Date
5e1f2e4bb2
backport: 25.2.0 2025-04-20 16:11:03 +02:00
ce9692ecdb
backport: 25.1.0 2025-04-17 13:59:05 +02:00
c726efc858
backport: 25.0.2 2025-04-16 00:44:40 +02:00
150d85f96e
backport: 25.0.1 2025-04-11 18:52:05 +02:00
3dfe8731cc
backport: 25.0.0 2025-04-11 18:29:47 +02:00
f41b0f2e3d
backport: 24.0.1 2025-03-27 23:05:20 +01:00
db85b56084
backport: 24.0.0 2025-03-27 22:07:37 +01:00
3954ff8ff5
backport: 23.1.2 2025-03-27 11:53:48 +01:00
06f933a69c
backport: 23.1.1 2025-03-26 23:34:16 +01:00
dd9c6daae7
backport: 23.1.0 2025-03-26 16:23:57 +01:00
9176cdd439
backport: 23.0.2 2025-03-23 14:42:07 +01:00
1450dd76eb
backport: 23.0.1 2025-03-20 00:20:35 +01:00
8a7a5aa1cb
backport: 23.0.0 2025-03-15 16:52:25 +01:00
0ec03d6030
backport: 22.0.1 2025-03-13 23:08:52 +01:00
add259d506
backport: 22.0.0 2025-03-13 16:41:36 +01:00
c209294479
backport: 21.1.0 2025-03-11 14:21:31 +01:00
0a7d5cb4c6
backport: 21.0.0 2025-03-11 01:57:19 +01:00
b360873857
backport: 20.3.0 2025-02-06 00:59:45 +01:00
808f45bb35
backport: 20.2.2 2025-01-30 13:27:12 +01:00
456425f35a
backport: 20.2.1 2025-01-22 12:29:53 +01:00
b4cb04dcde
backport: 20.2.0 2025-01-21 15:52:32 +01:00
062aeaaa97
backport: 20.1.3 2025-01-15 20:16:29 +01:00
655f05c3b8
backport: 20.1.2 2025-01-12 14:41:58 +01:00
d3755fbc70
backport: 20.1.1 2024-12-24 12:54:41 +01:00
323ba12fbc
backport: 20.1.0 2024-12-22 23:12:04 +01:00
808d82b44f
backport: 20.0.4 2024-12-11 17:15:28 +01:00
e63ad21db7
backport: 20.0.3 2024-11-28 13:29:38 +01:00
90744797b6
backport: 20.0.2 2024-11-11 12:18:11 +01:00
24e886f13c
backport: 20.0.1 2024-11-09 12:02:34 +01:00
72eaae23fa
ci: publishing fixes 2024-11-07 17:50:32 +01:00
fb29d221a9
backport: 20.0.0 2024-11-07 17:22:17 +01:00
c2e20b7f0f
ci: downgrade to 2024.1 2024-11-07 17:07:45 +01:00
37 changed files with 69 additions and 300 deletions

View file

@ -152,7 +152,6 @@ Changelog structure reference:
- Project - Project
- Occasional "AWT events are not allowed inside write action" error coming from LSP - Occasional "AWT events are not allowed inside write action" error coming from LSP
- IllegalStateException coming from the standard library handler
## [22.0.0] ## [22.0.0]
@ -195,8 +194,6 @@ This (and newer) versions of the plugin will automatically upgrade tasks from 21
### Added ### Added
- Zig
- Changing the zig standard library path in the project settings now properly updates the dependency
- ZLS - ZLS
- All of the config options are now exposed in the GUI - All of the config options are now exposed in the GUI

View file

@ -6,8 +6,8 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
plugins { plugins {
kotlin("jvm") version "2.1.10" apply false kotlin("jvm") version "1.9.22" apply false
kotlin("plugin.serialization") version "2.1.10" apply false kotlin("plugin.serialization") version "1.9.22" apply false
id("org.jetbrains.intellij.platform") version "2.5.0" id("org.jetbrains.intellij.platform") version "2.5.0"
id("org.jetbrains.changelog") version "2.2.1" id("org.jetbrains.changelog") version "2.2.1"
id("org.jetbrains.grammarkit") version "2022.3.2.2" apply false id("org.jetbrains.grammarkit") version "2022.3.2.2" apply false
@ -90,7 +90,6 @@ allprojects {
intellijPlatform { intellijPlatform {
defaultRepositories() defaultRepositories()
snapshots()
} }
} }
} }

View file

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

View file

@ -211,7 +211,7 @@ abstract class DAPDriver<Server : IDebugProtocolServer, Client : IDebugProtocolC
val cli = installer.install() val cli = installer.install()
val args = HashMap<String, Any>() val args = HashMap<String, Any>()
args["program"] = Util.toWinPath(cli.exePath) args["program"] = Util.toWinPath(cli.exePath)
args["cmd"] = cli.workingDirectory.toString() args["cmd"] = cli.workDirectory.toString()
args["name"] = "CPP Debug" args["name"] = "CPP Debug"
args["type"] = "cppvsdbg" args["type"] = "cppvsdbg"
args["request"] = "launch" args["request"] = "launch"
@ -954,7 +954,7 @@ abstract class DAPDriver<Server : IDebugProtocolServer, Client : IDebugProtocolC
cli.withCharset(Charsets.UTF_8) cli.withCharset(Charsets.UTF_8)
val cwd = args.cwd?.ifBlank { null }?.toNioPathOrNull() val cwd = args.cwd?.ifBlank { null }?.toNioPathOrNull()
if (cwd != null) { if (cwd != null) {
cli.withWorkingDirectory(cwd) cli.withWorkDirectory(cwd.toFile())
} }
val childProcess = ZigProcessHandler(cli) val childProcess = ZigProcessHandler(cli)
this@DAPDriver.childProcess = childProcess this@DAPDriver.childProcess = childProcess

View file

@ -34,7 +34,7 @@ class ZigProfileStateBinary(environment: ExecutionEnvironment, configuration: Zi
override suspend fun getCommandLine(toolchain: ZigToolchain, debug: Boolean): GeneralCommandLine { override suspend fun getCommandLine(toolchain: ZigToolchain, debug: Boolean): GeneralCommandLine {
val cli = GeneralCommandLine() val cli = GeneralCommandLine()
val cfg = configuration val cfg = configuration
cfg.workingDirectory.path?.let { cli.withWorkingDirectory(it) } cfg.workingDirectory.path?.let { cli.withWorkDirectory(it.toFile()) }
cli.withExePath(cfg.exePath.path?.pathString ?: throw ExecutionException(ZigDebugBundle.message("exception.missing-exe-path"))) cli.withExePath(cfg.exePath.path?.pathString ?: throw ExecutionException(ZigDebugBundle.message("exception.missing-exe-path")))
cli.withCharset(Charsets.UTF_8) cli.withCharset(Charsets.UTF_8)
cli.addParameters(cfg.args.args) cli.addParameters(cfg.args.args)

View file

@ -41,7 +41,7 @@ class ZigDebugEmitBinaryInstaller<ProfileState: ZigProfileState<*>>(
override fun install(): GeneralCommandLine { override fun install(): GeneralCommandLine {
val cfg = profileState.configuration val cfg = profileState.configuration
val cli = PtyCommandLine().withConsoleMode(false).withExePath(executableFile.absolutePath) val cli = PtyCommandLine().withConsoleMode(false).withExePath(executableFile.absolutePath)
cfg.workingDirectory.path?.let { x -> cli.withWorkingDirectory(x) } cfg.workingDirectory.path?.let { x -> cli.withWorkDirectory(x.toFile()) }
cli.addParameters(exeArgs) cli.addParameters(exeArgs)
cli.withCharset(Charsets.UTF_8) cli.withCharset(Charsets.UTF_8)
cli.withRedirectErrorStream(true) cli.withRedirectErrorStream(true)

View file

@ -29,7 +29,6 @@ import com.intellij.openapi.options.SimpleConfigurable
import com.intellij.util.xmlb.XmlSerializerUtil import com.intellij.util.xmlb.XmlSerializerUtil
import com.intellij.xdebugger.settings.DebuggerSettingsCategory import com.intellij.xdebugger.settings.DebuggerSettingsCategory
import com.intellij.xdebugger.settings.XDebuggerSettings import com.intellij.xdebugger.settings.XDebuggerSettings
import java.util.function.Supplier
class ZigDebuggerSettings: XDebuggerSettings<ZigDebuggerSettings>("Zig") { class ZigDebuggerSettings: XDebuggerSettings<ZigDebuggerSettings>("Zig") {
var debuggerKind = DebuggerKind.default var debuggerKind = DebuggerKind.default
@ -59,10 +58,9 @@ class ZigDebuggerSettings: XDebuggerSettings<ZigDebuggerSettings>("Zig") {
GENERAL_SETTINGS_ID, GENERAL_SETTINGS_ID,
ZigDebugBundle.message("settings.debugger.title"), ZigDebugBundle.message("settings.debugger.title"),
ZigDebuggerGeneralSettingsConfigurableUi::class.java, ZigDebuggerGeneralSettingsConfigurableUi::class.java,
Supplier { ) {
instance instance
} }
)
} }
companion object { companion object {

View file

@ -29,12 +29,12 @@ import com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService
import com.falsepattern.zigbrains.shared.coroutine.withCurrentEDTModalityContext import com.falsepattern.zigbrains.shared.coroutine.withCurrentEDTModalityContext
import com.intellij.notification.Notification import com.intellij.notification.Notification
import com.intellij.notification.NotificationType import com.intellij.notification.NotificationType
import com.intellij.openapi.progress.coroutineToIndicator
import com.intellij.openapi.ui.DialogBuilder import com.intellij.openapi.ui.DialogBuilder
import com.intellij.platform.util.progress.withProgressText import com.intellij.platform.util.progress.withProgressText
import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBLabel
import com.intellij.ui.components.JBPanel import com.intellij.ui.components.JBPanel
import com.intellij.util.download.DownloadableFileService import com.intellij.util.download.DownloadableFileService
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
@ -96,7 +96,7 @@ private suspend fun downloadMSVCProps(): Properties {
val downloader = service.createDownloader(listOf(desc), "Debugger metadata downloading") val downloader = service.createDownloader(listOf(desc), "Debugger metadata downloading")
val downloadDirectory = downloadPath().toFile() val downloadDirectory = downloadPath().toFile()
val prop = Properties() val prop = Properties()
val downloadResults = coroutineToIndicator { val downloadResults = runBlocking {
downloader.download(downloadDirectory) downloader.download(downloadDirectory)
} }
for (result in downloadResults) { for (result in downloadResults) {

View file

@ -30,7 +30,7 @@ import com.intellij.openapi.application.PathManager
import com.intellij.openapi.components.Service import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.progress.coroutineToIndicator import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogBuilder import com.intellij.openapi.ui.DialogBuilder
import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemInfo
@ -222,7 +222,7 @@ class ZigDebuggerToolchainService {
val downloader = service.createDownloader(descriptions, "Debugger downloading") val downloader = service.createDownloader(descriptions, "Debugger downloading")
val downloadDirectory = downloadPath().toFile() val downloadDirectory = downloadPath().toFile()
val downloadResults = reporter.sizedStep(100) { val downloadResults = reporter.sizedStep(100) {
coroutineToIndicator { blockingContext {
downloader.download(downloadDirectory) downloader.download(downloadDirectory)
} }
} }
@ -233,7 +233,7 @@ class ZigDebuggerToolchainService {
val propertyName = binaryToDownload.propertyName val propertyName = binaryToDownload.propertyName
val archiveFile = result.first val archiveFile = result.first
reporter.indeterminateStep { reporter.indeterminateStep {
coroutineToIndicator { blockingContext {
Unarchiver.unarchive(archiveFile.toPath(), baseDir, binaryToDownload.prefix) Unarchiver.unarchive(archiveFile.toPath(), baseDir, binaryToDownload.prefix)
} }
} }

View file

@ -42,7 +42,7 @@ abstract class MSVCDriverConfiguration: DAPDebuggerDriverConfiguration() {
val cli = GeneralCommandLine() val cli = GeneralCommandLine()
cli.withExePath(path.pathString) cli.withExePath(path.pathString)
cli.addParameters("--interpreter=vscode", "--extconfigdir=%USERPROFILE%\\.cppvsdbg\\extensions") cli.addParameters("--interpreter=vscode", "--extconfigdir=%USERPROFILE%\\.cppvsdbg\\extensions")
cli.withWorkingDirectory(path.parent) cli.withWorkDirectory(path.parent.toFile())
return cli return cli
} }

View file

@ -103,7 +103,7 @@ class DirenvService(val project: Project): SerializablePersistentStateComponent<
} }
private suspend fun run(workDir: Path, vararg args: String): DirenvOutput { private suspend fun run(workDir: Path, vararg args: String): DirenvOutput {
val cli = GeneralCommandLine("direnv", *args).withWorkingDirectory(workDir) val cli = GeneralCommandLine("direnv", *args).withWorkDirectory(workDir.toFile())
val (process, exitCode) = withProgressText("Running ${cli.commandLineString}") { val (process, exitCode) = withProgressText("Running ${cli.commandLineString}") {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {

View file

@ -160,6 +160,7 @@ class WorkDirectoryConfigurable(@Transient override val serializedName: String)
class WorkDirectoryConfigModule(private val serializedName: String) : PathConfigModule<WorkDirectoryConfigurable>() { class WorkDirectoryConfigModule(private val serializedName: String) : PathConfigModule<WorkDirectoryConfigurable>() {
private val field = textFieldWithBrowseButton( private val field = textFieldWithBrowseButton(
null, null,
ZigBrainsBundle.message("dialog.title.working-directory"),
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.working-directory")) FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.working-directory"))
).also { Disposer.register(this, it) } ).also { Disposer.register(this, it) }
@ -198,7 +199,8 @@ class FilePathConfigurable(
class FilePathConfigModule(private val serializedName: String, @Nls private val label: String) : PathConfigModule<FilePathConfigurable>() { class FilePathConfigModule(private val serializedName: String, @Nls private val label: String) : PathConfigModule<FilePathConfigurable>() {
private val field = textFieldWithBrowseButton( private val field = textFieldWithBrowseButton(
null, null,
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor(), null,
FileChooserDescriptorFactory.createSingleFileDescriptor(),
) )
override var stringValue by field::text override var stringValue by field::text

View file

@ -66,7 +66,7 @@ abstract class ZigProfileState<T: ZigExecConfig<T>> (
val cli = PtyCommandLine().withConsoleMode(false) val cli = PtyCommandLine().withConsoleMode(false)
cli.withExePath(zigExePath.pathString) cli.withExePath(zigExePath.pathString)
workingDir.path?.let { cli.withWorkingDirectory(it) } workingDir.path?.let { cli.withWorkDirectory(it.toFile()) }
cli.withCharset(Charsets.UTF_8) cli.withCharset(Charsets.UTF_8)
cli.addParameters(configuration.buildCommandLineArgs(debug)) cli.addParameters(configuration.buildCommandLineArgs(debug))
return configuration.patchCommandLine(cli) return configuration.patchCommandLine(cli)

View file

@ -68,7 +68,7 @@ class ZigModuleBuilder: ModuleBuilder() {
internal val peer = ZigProjectGeneratorPeer(true).also { Disposer.register(parent ?: return@also) {it.dispose()} } internal val peer = ZigProjectGeneratorPeer(true).also { Disposer.register(parent ?: return@also) {it.dispose()} }
override fun getComponent(): JComponent { override fun getComponent(): JComponent {
return peer.myComponent.withBorder() return peer.component.withBorder()
} }
override fun disposeUIResources() { override fun disposeUIResources() {

View file

@ -50,7 +50,7 @@ class ZigNewProjectWizard: LanguageGeneratorNewProjectWizard {
override fun setupUI(builder: Panel): Unit = with(builder) { override fun setupUI(builder: Panel): Unit = with(builder) {
row { row {
cell(peer.myComponent).align(AlignX.FILL) cell(peer.component).align(AlignX.FILL)
} }
} }

View file

@ -23,7 +23,6 @@
package com.falsepattern.zigbrains.project.newproject package com.falsepattern.zigbrains.project.newproject
import com.intellij.ide.util.projectWizard.SettingsStep import com.intellij.ide.util.projectWizard.SettingsStep
import com.intellij.openapi.ui.TextFieldWithBrowseButton
import com.intellij.openapi.ui.ValidationInfo import com.intellij.openapi.ui.ValidationInfo
import com.intellij.platform.ProjectGeneratorPeer import com.intellij.platform.ProjectGeneratorPeer
import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.panel
@ -33,13 +32,12 @@ class ZigProjectGeneratorPeer(var handleGit: Boolean): ProjectGeneratorPeer<ZigP
val newProjectPanel by lazy { val newProjectPanel by lazy {
ZigNewProjectPanel(handleGit) ZigNewProjectPanel(handleGit)
} }
val myComponent: JComponent by lazy { private val myComponent: JComponent by lazy {
panel { panel {
newProjectPanel.attach(this) newProjectPanel.attach(this)
} }
} }
override fun getComponent(): JComponent {
override fun getComponent(myLocationField: TextFieldWithBrowseButton, checkValid: Runnable): JComponent {
return myComponent return myComponent
} }

View file

@ -1,33 +0,0 @@
/*
* This file is part of ZigBrains.
*
* Copyright (C) 2023-2025 FalsePattern
* All Rights Reserved
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* ZigBrains is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, only version 3 of the License.
*
* ZigBrains is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
*/
package com.falsepattern.zigbrains.project.stdlib
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.AdditionalLibraryRootsProvider
import com.intellij.openapi.roots.SyntheticLibrary
class ZigLibraryRootProvider: AdditionalLibraryRootsProvider() {
override fun getAdditionalProjectLibraries(project: Project): Collection<SyntheticLibrary> {
return setOf(ZigSyntheticLibrary(project))
}
}

View file

@ -1,190 +0,0 @@
/*
* This file is part of ZigBrains.
*
* Copyright (C) 2023-2025 FalsePattern
* All Rights Reserved
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* ZigBrains is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, only version 3 of the License.
*
* ZigBrains is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
*/
package com.falsepattern.zigbrains.project.stdlib
import com.falsepattern.zigbrains.Icons
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
import com.intellij.navigation.ItemPresentation
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.roots.SyntheticLibrary
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.refreshAndFindVirtualDirectory
import com.intellij.platform.backend.workspace.WorkspaceModel
import com.intellij.platform.backend.workspace.toVirtualFileUrl
import com.intellij.platform.workspace.jps.entities.*
import com.intellij.project.isDirectoryBased
import com.intellij.project.stateStore
import com.intellij.workspaceModel.ide.legacyBridge.LegacyBridgeJpsEntitySourceFactory
import kotlinx.coroutines.runBlocking
import java.util.*
import javax.swing.Icon
class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresentation {
private var toolchain: ZigToolchain? = ZigToolchainService.getInstance(project).toolchain
private val roots by lazy {
runBlocking {getRoot(toolchain, project)}?.let { setOf(it) } ?: emptySet()
}
private val name by lazy {
getName(toolchain, project)
}
override fun equals(other: Any?): Boolean {
if (other !is ZigSyntheticLibrary)
return false
return toolchain == other.toolchain
}
override fun hashCode(): Int {
return Objects.hash(roots)
}
override fun getPresentableText(): String {
return name
}
override fun getIcon(unused: Boolean): Icon {
return Icons.Zig
}
override fun getSourceRoots(): Collection<VirtualFile> {
return roots
}
override fun isShowInExternalLibrariesNode(): Boolean {
return !roots.isEmpty()
}
companion object {
private const val ZIG_LIBRARY_ID = "Zig SDK"
private const val ZIG_MODULE_ID = "ZigBrains"
private val libraryTableId = LibraryTableId.ProjectLibraryTableId
private val libraryId = LibraryId(ZIG_LIBRARY_ID, libraryTableId)
private val moduleId = ModuleId(ZIG_MODULE_ID)
suspend fun reload(project: Project, toolchain: ZigToolchain?) {
val root = getRoot(toolchain, project)
if (root != null) {
add(project, root)
} else {
remove(project)
}
}
private suspend fun remove(project: Project) {
val workspaceModel = WorkspaceModel.getInstance(project)
workspaceModel.update("Update Zig std") { builder ->
builder.resolve(moduleId)?.let { moduleEntity ->
builder.removeEntity(moduleEntity)
}
builder.resolve(libraryId)?.let { libraryEntity ->
builder.removeEntity(libraryEntity)
}
}
}
private suspend fun add(project: Project, root: VirtualFile) {
val workspaceModel = WorkspaceModel.getInstance(project)
val libRoot = LibraryRoot(root.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()), LibraryRootTypeId.SOURCES)
var baseModuleDirFile: VirtualFile? = null
if (project.isDirectoryBased) {
baseModuleDirFile = project.stateStore.directoryStorePath?.refreshAndFindVirtualDirectory()
}
if (baseModuleDirFile == null) {
baseModuleDirFile = project.guessProjectDir()
}
val baseModuleDir = baseModuleDirFile?.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()) ?: return
workspaceModel.update("Update Zig std") { builder ->
builder.resolve(moduleId)?.let { moduleEntity ->
builder.removeEntity(moduleEntity)
}
val moduleEntitySource = LegacyBridgeJpsEntitySourceFactory.getInstance(project)
.createEntitySourceForModule(baseModuleDir, null)
val moduleEntity = builder.addEntity(ModuleEntity(ZIG_MODULE_ID, emptyList(), moduleEntitySource))
builder.resolve(libraryId)?.let { libraryEntity ->
builder.removeEntity(libraryEntity)
}
val libraryEntitySource = LegacyBridgeJpsEntitySourceFactory
.getInstance(project)
.createEntitySourceForProjectLibrary(null)
val libraryEntity = LibraryEntity(
ZIG_LIBRARY_ID,
libraryTableId, emptyList(),
libraryEntitySource
) {
roots.add(libRoot)
}
builder.addEntity(libraryEntity)
builder.modifyModuleEntity(moduleEntity) {
val dep = LibraryDependency(libraryId, false, DependencyScope.COMPILE)
dependencies.clear()
dependencies.add(dep)
}
}
}
}
}
private fun getName(
toolchain: ZigToolchain?,
project: Project
): String {
val tc = toolchain ?: return "Zig"
toolchain.name?.let { return it }
runBlocking { tc.zig.getEnv(project) }
.mapCatching { it.version }
.getOrNull()
?.let { return "Zig $it" }
return "Zig"
}
suspend fun getRoot(
toolchain: ZigToolchain?,
project: Project
): VirtualFile? {
//TODO universal
if (toolchain !is LocalZigToolchain) {
return null
}
if (toolchain.std != null) run {
val ePath = toolchain.std
if (ePath.isAbsolute) {
val roots = ePath.refreshAndFindVirtualDirectory() ?: return@run
return roots
}
val stdPath = toolchain.location.resolve(ePath)
if (stdPath.isAbsolute) {
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return@run
return roots
}
}
val stdPath = toolchain.zig.getEnv(project).mapCatching { it.stdPath(toolchain, project) }.getOrNull() ?: return null
val roots = stdPath.refreshAndFindVirtualDirectory() ?: return null
return roots
}

View file

@ -22,16 +22,11 @@
package com.falsepattern.zigbrains.project.toolchain package com.falsepattern.zigbrains.project.toolchain
import com.falsepattern.zigbrains.project.stdlib.ZigSyntheticLibrary
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.shared.asUUID import com.falsepattern.zigbrains.shared.asUUID
import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.* import com.intellij.openapi.components.*
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.* import java.util.*
@Service(Service.Level.PROJECT) @Service(Service.Level.PROJECT)
@ -55,9 +50,6 @@ class ZigToolchainService(private val project: Project): SerializablePersistentS
updateState { updateState {
it.copy(toolchain = value?.toString() ?: "") it.copy(toolchain = value?.toString() ?: "")
} }
zigCoroutineScope.launch(Dispatchers.EDT) {
ZigSyntheticLibrary.reload(project, toolchain)
}
} }
val toolchain: ZigToolchain? val toolchain: ZigToolchain?

View file

@ -56,7 +56,7 @@ class LocalToolchainSelector(component: Component): LocalSelector<LocalZigToolch
} else { } else {
val existingToolchain = zigToolchainList val existingToolchain = zigToolchainList
.mapNotNull { it.second as? LocalZigToolchain } .mapNotNull { it.second as? LocalZigToolchain }
.firstOrNull { it.location == tc.location } .firstOrNull { it.location == tc!!.location }
if (existingToolchain != null) { if (existingToolchain != null) {
result = VerifyResult( result = VerifyResult(
null, null,

View file

@ -27,7 +27,7 @@ import com.falsepattern.zigbrains.shared.downloader.VersionInfo
import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball
import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible
import com.falsepattern.zigbrains.shared.downloader.tempPluginDir import com.falsepattern.zigbrains.shared.downloader.tempPluginDir
import com.intellij.openapi.progress.coroutineToIndicator import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.asSafely import com.intellij.util.asSafely
import com.intellij.util.download.DownloadableFileService import com.intellij.util.download.DownloadableFileService
@ -54,7 +54,7 @@ data class ZigVersionInfo(
val tempFile = FileUtil.createTempFile(tempPluginDir, "index", ".json", false, false) val tempFile = FileUtil.createTempFile(tempPluginDir, "index", ".json", false, false)
val desc = service.createFileDescription("https://ziglang.org/download/index.json", tempFile.name) val desc = service.createFileDescription("https://ziglang.org/download/index.json", tempFile.name)
val downloader = service.createDownloader(listOf(desc), ZigBrainsBundle.message("settings.toolchain.downloader.service.index")) val downloader = service.createDownloader(listOf(desc), ZigBrainsBundle.message("settings.toolchain.downloader.service.index"))
val downloadResults = coroutineToIndicator { val downloadResults = blockingContext {
downloader.download(tempPluginDir) downloader.download(tempPluginDir)
} }
if (downloadResults.isEmpty()) if (downloadResults.isEmpty())

View file

@ -47,7 +47,8 @@ import kotlin.io.path.pathString
class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchain>() { class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchain>() {
private val pathToToolchain = textFieldWithBrowseButton( private val pathToToolchain = textFieldWithBrowseButton(
null, null,
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.zig-toolchain")) ZigBrainsBundle.message("dialog.title.zig-toolchain"),
FileChooserDescriptorFactory.createSingleFolderDescriptor()
).also { ).also {
it.textField.document.addDocumentListener(object : DocumentAdapter() { it.textField.document.addDocumentListener(object : DocumentAdapter() {
override fun textChanged(e: DocumentEvent) { override fun textChanged(e: DocumentEvent) {
@ -69,7 +70,8 @@ class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchai
} }
private val pathToStd = textFieldWithBrowseButton( private val pathToStd = textFieldWithBrowseButton(
null, null,
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.zig-std")) ZigBrainsBundle.message("dialog.title.zig-std"),
FileChooserDescriptorFactory.createSingleFolderDescriptor()
).also { Disposer.register(this, it) } ).also { Disposer.register(this, it) }
private var debounce: Job? = null private var debounce: Job? = null

View file

@ -31,6 +31,7 @@ import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.ui.SimpleTextAttributes import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.icons.EMPTY_ICON import com.intellij.ui.icons.EMPTY_ICON
import com.intellij.util.ui.EmptyIcon
import javax.swing.JList import javax.swing.JList
class TCComboBox(model: ZBModel<ZigToolchain>): ZBComboBox<ZigToolchain>(model, ::TCCellRenderer) class TCComboBox(model: ZBModel<ZigToolchain>): ZBComboBox<ZigToolchain>(model, ::TCCellRenderer)
@ -67,7 +68,7 @@ class TCCellRenderer(getModel: () -> ZBModel<ZigToolchain>): ZBCellRenderer<ZigT
append(ZigBrainsBundle.message("settings.toolchain.model.from-disk.text")) append(ZigBrainsBundle.message("settings.toolchain.model.from-disk.text"))
} }
is ListElem.Pending -> { is ListElem.Pending -> {
icon = AllIcons.Empty icon = EMPTY_ICON
append(ZigBrainsBundle.message("settings.toolchain.model.loading.text"), SimpleTextAttributes.GRAYED_ATTRIBUTES) append(ZigBrainsBundle.message("settings.toolchain.model.loading.text"), SimpleTextAttributes.GRAYED_ATTRIBUTES)
} }
is ListElem.None, null -> { is ListElem.None, null -> {
@ -77,4 +78,5 @@ class TCCellRenderer(getModel: () -> ZBModel<ZigToolchain>): ZBCellRenderer<ZigT
} }
} }
} }
private val EMPTY_ICON = EmptyIcon.create(16, 16)

View file

@ -123,7 +123,7 @@ fun createCommandLineSafe(
return Result.failure(IllegalArgumentException("file is a directory: ${exe.pathString}")) return Result.failure(IllegalArgumentException("file is a directory: ${exe.pathString}"))
val cli = GeneralCommandLine() val cli = GeneralCommandLine()
.withExePath(exe.toString()) .withExePath(exe.toString())
.withWorkingDirectory(workingDirectory) .withWorkDirectory(workingDirectory?.toFile())
.withParameters(*parameters) .withParameters(*parameters)
.withCharset(Charsets.UTF_8) .withCharset(Charsets.UTF_8)
return Result.success(cli) return Result.success(cli)

View file

@ -33,7 +33,7 @@ import kotlinx.coroutines.*
import java.awt.Component import java.awt.Component
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
inline fun <T> runModalOrBlocking(taskOwnerFactory: () -> ModalTaskOwner, titleFactory: () -> String, cancellationFactory: () -> TaskCancellation = {TaskCancellation.cancellable()}, noinline action: suspend CoroutineScope.() -> T): T { inline fun <T> runModalOrBlocking(taskOwnerFactory: () -> ModalTaskOwner, titleFactory: () -> String, cancellationFactory: () -> TaskCancellation = TaskCancellation::cancellable, noinline action: suspend CoroutineScope.() -> T): T {
return if (application.isDispatchThread) { return if (application.isDispatchThread) {
runWithModalProgressBlocking(taskOwnerFactory(), titleFactory(), cancellationFactory(), action) runWithModalProgressBlocking(taskOwnerFactory(), titleFactory(), cancellationFactory(), action)
} else { } else {

View file

@ -96,7 +96,7 @@ abstract class Downloader<T, V: VersionInfo>(val component: Component) {
value?.let { append(it.version.rawVersion) } value?.let { append(it.version.rawVersion) }
} }
} }
val outputPath = textFieldWithBrowseButton(null, selector.descriptor) val outputPath = textFieldWithBrowseButton(null, selector.descriptor.title, selector.descriptor)
Disposer.register(dialog, outputPath) Disposer.register(dialog, outputPath)
outputPath.textField.columns = 50 outputPath.textField.columns = 50

View file

@ -66,7 +66,7 @@ abstract class LocalSelector<T>(val component: Component) {
private suspend fun doBrowseFromDisk(preSelected: Path?): T? { private suspend fun doBrowseFromDisk(preSelected: Path?): T? {
val dialog = DialogBuilder() val dialog = DialogBuilder()
val name = JBTextField().also { it.columns = 25 } val name = JBTextField().also { it.columns = 25 }
val path = textFieldWithBrowseButton(null, descriptor) val path = textFieldWithBrowseButton(null, descriptor.title, descriptor)
Disposer.register(dialog, path) Disposer.register(dialog, path)
lateinit var errorMessageBox: JBLabel lateinit var errorMessageBox: JBLabel
suspend fun verifyAndUpdate(path: Path?) { suspend fun verifyAndUpdate(path: Path?) {

View file

@ -28,7 +28,7 @@ import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball
import com.intellij.openapi.application.PathManager import com.intellij.openapi.application.PathManager
import com.intellij.openapi.progress.EmptyProgressIndicator import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.coroutineToIndicator import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.platform.util.progress.ProgressReporter import com.intellij.platform.util.progress.ProgressReporter
@ -83,7 +83,7 @@ suspend fun downloadTarball(dist: Tarball, into: Path, reporter: ProgressReporte
val desc = service.createFileDescription(dist.tarball, tempFile.name) val desc = service.createFileDescription(dist.tarball, tempFile.name)
val downloader = service.createDownloader(listOf(desc), ZigBrainsBundle.message("settings.toolchain.downloader.service.tarball")) val downloader = service.createDownloader(listOf(desc), ZigBrainsBundle.message("settings.toolchain.downloader.service.tarball"))
val downloadResults = reporter.sizedStep(100) { val downloadResults = reporter.sizedStep(100) {
coroutineToIndicator { blockingContext {
downloader.download(into.toFile()) downloader.download(into.toFile())
} }
} }
@ -99,7 +99,7 @@ suspend fun flattenDownloadDir(dir: Path, reporter: ProgressReporter) {
if (contents.size == 1 && contents[0].isDirectory()) { if (contents.size == 1 && contents[0].isDirectory()) {
val src = contents[0] val src = contents[0]
reporter.indeterminateStep { reporter.indeterminateStep {
coroutineToIndicator { blockingContext {
val indicator = ProgressManager.getInstance().progressIndicator ?: EmptyProgressIndicator() val indicator = ProgressManager.getInstance().progressIndicator ?: EmptyProgressIndicator()
indicator.isIndeterminate = true indicator.isIndeterminate = true
indicator.text = ZigBrainsBundle.message("settings.toolchain.downloader.progress.flatten") indicator.text = ZigBrainsBundle.message("settings.toolchain.downloader.progress.flatten")
@ -121,7 +121,7 @@ suspend fun unpackTarball(tarball: Path, into: Path, reporter: ProgressReporter)
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
try { try {
reporter.indeterminateStep { reporter.indeterminateStep {
coroutineToIndicator { blockingContext {
Unarchiver.unarchive(tarball, into) Unarchiver.unarchive(tarball, into)
} }
} }

View file

@ -87,7 +87,7 @@ abstract class UUIDMapSelector<T>(val driver: UUIDComboBoxDriver<T>): Disposable
val actual = item is ListElem.One.Actual<*> val actual = item is ListElem.One.Actual<*>
editButton?.isEnabled = actual editButton?.isEnabled = actual
editButton?.repaint() editButton?.repaint()
onSelection(if (actual) item.uuid else null) onSelection(if (actual) (item as ListElem.One.Actual<*>).uuid else null)
} }
private fun itemStateChanged(event: ItemEvent) { private fun itemStateChanged(event: ItemEvent) {

View file

@ -76,9 +76,13 @@ private fun <T : PsiElement> ZigMultilineAssistant<T>.preprocessEnter(
val indentPost = parts[1].measureSpaces() val indentPost = parts[1].measureSpaces()
val newLine = StringBuilder(1 + indentPre + prefix.length + indentPost) val newLine = StringBuilder(1 + indentPre + prefix.length + indentPost)
.append('\n') .append('\n')
.repeat(' '.code, indentPre) for (i in 0..<indentPre) {
.append(prefix) newLine.append(' ')
.repeat(' '.code, indentPost) }
newLine.append(prefix)
for (i in 0..<indentPost) {
newLine.append(' ')
}
document.insertString(offset, newLine) document.insertString(offset, newLine)
PsiDocumentManager.getInstance(project).commitDocument(document) PsiDocumentManager.getInstance(project).commitDocument(document)
editor.caretModel.moveToOffset(offset + newLine.length) editor.caretModel.moveToOffset(offset + newLine.length)

View file

@ -165,10 +165,6 @@
implementation="com.falsepattern.zigbrains.project.console.ZigSourceFileFilter" implementation="com.falsepattern.zigbrains.project.console.ZigSourceFileFilter"
/> />
<additionalLibraryRootsProvider
implementation="com.falsepattern.zigbrains.project.stdlib.ZigLibraryRootProvider"
/>
<!--suppress PluginXmlValidity --> <!--suppress PluginXmlValidity -->
<toolWindow <toolWindow
factoryClass="com.falsepattern.zigbrains.project.steps.ui.BuildToolWindowFactory" factoryClass="com.falsepattern.zigbrains.project.steps.ui.BuildToolWindowFactory"

View file

@ -3,13 +3,13 @@ pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains
pluginVersion=25.2.0 pluginVersion=25.2.0
pluginSinceBuild=251 pluginSinceBuild=241
pluginUntilBuild= pluginUntilBuild=241.*
ideaCommunityVersion=2025.1 ideaCommunityVersion=2024.1.7
clionVersion=2025.1 clionVersion=2024.1.6
useInstaller=true useInstaller=true
javaVersion=21 javaVersion=17
# ideaCommunity / clion # ideaCommunity / clion
runIdeTarget=clion runIdeTarget=clion
@ -17,7 +17,7 @@ lsp4jVersion=0.21.1
lsp4ijVersion=0.12.0 lsp4ijVersion=0.12.0
lsp4ijNightly=false lsp4ijNightly=false
serializationVersion=1.7.3 serializationVersion=1.6.3
kotlin.stdlib.default.dependency=false kotlin.stdlib.default.dependency=false
kotlin.code.style=official kotlin.code.style=official

View file

@ -46,7 +46,7 @@ class ZLSStreamConnectionProvider private constructor(private val project: Proje
companion object { companion object {
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) }?.withWorkDirectory(projectDir?.toFile())
return ZLSStreamConnectionProvider(project, commandLine) return ZLSStreamConnectionProvider(project, commandLine)
} }

View file

@ -43,8 +43,8 @@ import javax.swing.text.PlainDocument
class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> { class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
private val zlsConfigPath = textFieldWithBrowseButton( private val zlsConfigPath = textFieldWithBrowseButton(
null, null,
ZLSBundle.message("settings.zls-config-path.browse.title"),
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor() FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()
.withTitle(ZLSBundle.message("settings.zls-config-path.browse.title"))
).also { Disposer.register(this, it) } ).also { Disposer.register(this, it) }
private val inlayHints = JBCheckBox() private val inlayHints = JBCheckBox()
private val inlayHintsMaxFileSize = ExtendableTextField(5).also { (it.document as PlainDocument).documentFilter = object: DocumentFilter() { private val inlayHintsMaxFileSize = ExtendableTextField(5).also { (it.document as PlainDocument).documentFilter = object: DocumentFilter() {

View file

@ -49,7 +49,8 @@ import kotlin.io.path.pathString
class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() { class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() {
private val pathToZLS = textFieldWithBrowseButton( private val pathToZLS = textFieldWithBrowseButton(
null, null,
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle(ZLSBundle.message("dialog.title.zls")) ZLSBundle.message("dialog.title.zls"),
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()
).also { ).also {
it.textField.document.addDocumentListener(object : DocumentAdapter() { it.textField.document.addDocumentListener(object : DocumentAdapter() {
override fun textChanged(e: DocumentEvent) { override fun textChanged(e: DocumentEvent) {

View file

@ -28,7 +28,7 @@ import com.falsepattern.zigbrains.shared.downloader.VersionInfo
import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball
import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible
import com.falsepattern.zigbrains.shared.downloader.tempPluginDir import com.falsepattern.zigbrains.shared.downloader.tempPluginDir
import com.intellij.openapi.progress.coroutineToIndicator import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.asSafely import com.intellij.util.asSafely
@ -52,7 +52,7 @@ data class ZLSVersionInfo(
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val single = toolchain != null val single = toolchain != null
val url = if (single) { val url = if (single) {
getToolchainURL(toolchain, project) ?: return@withContext emptyList() getToolchainURL(toolchain!!, project) ?: return@withContext emptyList()
} else { } else {
multiURL multiURL
} }
@ -60,7 +60,7 @@ data class ZLSVersionInfo(
val tempFile = FileUtil.createTempFile(tempPluginDir, "zls_version_info", ".json", false, false) val tempFile = FileUtil.createTempFile(tempPluginDir, "zls_version_info", ".json", false, false)
val desc = service.createFileDescription(url, tempFile.name) val desc = service.createFileDescription(url, tempFile.name)
val downloader = service.createDownloader(listOf(desc), ZLSBundle.message("settings.downloader.service.index")) val downloader = service.createDownloader(listOf(desc), ZLSBundle.message("settings.downloader.service.index"))
val downloadResults = coroutineToIndicator { val downloadResults = blockingContext {
downloader.download(tempPluginDir) downloader.download(tempPluginDir)
} }
if (downloadResults.isEmpty()) if (downloadResults.isEmpty())

View file

@ -30,6 +30,7 @@ import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.ui.SimpleTextAttributes import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.icons.EMPTY_ICON import com.intellij.ui.icons.EMPTY_ICON
import com.intellij.util.ui.EmptyIcon
import javax.swing.JList import javax.swing.JList
import kotlin.io.path.pathString import kotlin.io.path.pathString
@ -70,7 +71,7 @@ class ZLSCellRenderer(getModel: () -> ZBModel<ZLSVersion>): ZBCellRenderer<ZLSVe
append(ZLSBundle.message("settings.model.from-disk.text")) append(ZLSBundle.message("settings.model.from-disk.text"))
} }
is ListElem.Pending -> { is ListElem.Pending -> {
icon = AllIcons.Empty icon = EMPTY_ICON
append(ZLSBundle.message("settings.model.loading.text"), SimpleTextAttributes.GRAYED_ATTRIBUTES) append(ZLSBundle.message("settings.model.loading.text"), SimpleTextAttributes.GRAYED_ATTRIBUTES)
} }
is ListElem.None, null -> { is ListElem.None, null -> {
@ -80,4 +81,5 @@ class ZLSCellRenderer(getModel: () -> ZBModel<ZLSVersion>): ZBCellRenderer<ZLSVe
} }
} }
} }
private val EMPTY_ICON = EmptyIcon.create(16, 16)