Compare commits

..

31 commits
master ... 241

Author SHA1 Message Date
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

@ -135,7 +135,6 @@ Changelog structure reference:
- Project
- Occasional "AWT events are not allowed inside write action" error coming from LSP
- IllegalStateException coming from the standard library handler
## [22.0.0]
@ -178,8 +177,6 @@ This (and newer) versions of the plugin will automatically upgrade tasks from 21
### Added
- Zig
- Changing the zig standard library path in the project settings now properly updates the dependency
- ZLS
- 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
plugins {
kotlin("jvm") version "2.1.10" apply false
kotlin("plugin.serialization") version "2.1.10" apply false
kotlin("jvm") version "1.9.22" apply false
kotlin("plugin.serialization") version "1.9.22" 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
@ -90,7 +90,6 @@ allprojects {
intellijPlatform {
defaultRepositories()
snapshots()
}
}
}

View file

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

View file

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

View file

@ -41,7 +41,7 @@ class ZigDebugEmitBinaryInstaller<ProfileState: ZigProfileState<*>>(
override fun install(): GeneralCommandLine {
val cfg = profileState.configuration
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.withCharset(Charsets.UTF_8)
cli.withRedirectErrorStream(true)

View file

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

View file

@ -29,12 +29,12 @@ import com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService
import com.falsepattern.zigbrains.shared.coroutine.withCurrentEDTModalityContext
import com.intellij.notification.Notification
import com.intellij.notification.NotificationType
import com.intellij.openapi.progress.coroutineToIndicator
import com.intellij.openapi.ui.DialogBuilder
import com.intellij.platform.util.progress.withProgressText
import com.intellij.ui.components.JBLabel
import com.intellij.ui.components.JBPanel
import com.intellij.util.download.DownloadableFileService
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withTimeoutOrNull
@ -96,7 +96,7 @@ private suspend fun downloadMSVCProps(): Properties {
val downloader = service.createDownloader(listOf(desc), "Debugger metadata downloading")
val downloadDirectory = downloadPath().toFile()
val prop = Properties()
val downloadResults = coroutineToIndicator {
val downloadResults = runBlocking {
downloader.download(downloadDirectory)
}
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.diagnostic.logger
import com.intellij.openapi.progress.coroutineToIndicator
import com.intellij.openapi.progress.blockingContext
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogBuilder
import com.intellij.openapi.util.SystemInfo
@ -222,7 +222,7 @@ class ZigDebuggerToolchainService {
val downloader = service.createDownloader(descriptions, "Debugger downloading")
val downloadDirectory = downloadPath().toFile()
val downloadResults = reporter.sizedStep(100) {
coroutineToIndicator {
blockingContext {
downloader.download(downloadDirectory)
}
}
@ -233,7 +233,7 @@ class ZigDebuggerToolchainService {
val propertyName = binaryToDownload.propertyName
val archiveFile = result.first
reporter.indeterminateStep {
coroutineToIndicator {
blockingContext {
Unarchiver.unarchive(archiveFile.toPath(), baseDir, binaryToDownload.prefix)
}
}

View file

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

View file

@ -103,7 +103,7 @@ class DirenvService(val project: Project): SerializablePersistentStateComponent<
}
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}") {
withContext(Dispatchers.IO) {

View file

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

View file

@ -66,7 +66,7 @@ abstract class ZigProfileState<T: ZigExecConfig<T>> (
val cli = PtyCommandLine().withConsoleMode(false)
cli.withExePath(zigExePath.pathString)
workingDir.path?.let { cli.withWorkingDirectory(it) }
workingDir.path?.let { cli.withWorkDirectory(it.toFile()) }
cli.withCharset(Charsets.UTF_8)
cli.addParameters(configuration.buildCommandLineArgs(debug))
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()} }
override fun getComponent(): JComponent {
return peer.myComponent.withBorder()
return peer.component.withBorder()
}
override fun disposeUIResources() {

View file

@ -50,7 +50,7 @@ class ZigNewProjectWizard: LanguageGeneratorNewProjectWizard {
override fun setupUI(builder: Panel): Unit = with(builder) {
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
import com.intellij.ide.util.projectWizard.SettingsStep
import com.intellij.openapi.ui.TextFieldWithBrowseButton
import com.intellij.openapi.ui.ValidationInfo
import com.intellij.platform.ProjectGeneratorPeer
import com.intellij.ui.dsl.builder.panel
@ -33,13 +32,12 @@ class ZigProjectGeneratorPeer(var handleGit: Boolean): ProjectGeneratorPeer<ZigP
val newProjectPanel by lazy {
ZigNewProjectPanel(handleGit)
}
val myComponent: JComponent by lazy {
private val myComponent: JComponent by lazy {
panel {
newProjectPanel.attach(this)
}
}
override fun getComponent(myLocationField: TextFieldWithBrowseButton, checkValid: Runnable): JComponent {
override fun getComponent(): JComponent {
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
import com.falsepattern.zigbrains.project.stdlib.ZigSyntheticLibrary
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
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.project.Project
import com.intellij.util.xmlb.annotations.Attribute
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.*
@Service(Service.Level.PROJECT)
@ -55,9 +50,6 @@ class ZigToolchainService(private val project: Project): SerializablePersistentS
updateState {
it.copy(toolchain = value?.toString() ?: "")
}
zigCoroutineScope.launch(Dispatchers.EDT) {
ZigSyntheticLibrary.reload(project, toolchain)
}
}
val toolchain: ZigToolchain?

View file

@ -56,7 +56,7 @@ class LocalToolchainSelector(component: Component): LocalSelector<LocalZigToolch
} else {
val existingToolchain = zigToolchainList
.mapNotNull { it.second as? LocalZigToolchain }
.firstOrNull { it.location == tc.location }
.firstOrNull { it.location == tc!!.location }
if (existingToolchain != null) {
result = VerifyResult(
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.getTarballIfCompatible
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.util.asSafely
import com.intellij.util.download.DownloadableFileService
@ -54,7 +54,7 @@ data class ZigVersionInfo(
val tempFile = FileUtil.createTempFile(tempPluginDir, "index", ".json", false, false)
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 downloadResults = coroutineToIndicator {
val downloadResults = blockingContext {
downloader.download(tempPluginDir)
}
if (downloadResults.isEmpty())

View file

@ -47,7 +47,8 @@ import kotlin.io.path.pathString
class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchain>() {
private val pathToToolchain = textFieldWithBrowseButton(
null,
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.zig-toolchain"))
ZigBrainsBundle.message("dialog.title.zig-toolchain"),
FileChooserDescriptorFactory.createSingleFolderDescriptor()
).also {
it.textField.document.addDocumentListener(object : DocumentAdapter() {
override fun textChanged(e: DocumentEvent) {
@ -69,7 +70,8 @@ class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchai
}
private val pathToStd = textFieldWithBrowseButton(
null,
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.zig-std"))
ZigBrainsBundle.message("dialog.title.zig-std"),
FileChooserDescriptorFactory.createSingleFolderDescriptor()
).also { Disposer.register(this, it) }
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.ui.SimpleTextAttributes
import com.intellij.ui.icons.EMPTY_ICON
import com.intellij.util.ui.EmptyIcon
import javax.swing.JList
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"))
}
is ListElem.Pending -> {
icon = AllIcons.Empty
icon = EMPTY_ICON
append(ZigBrainsBundle.message("settings.toolchain.model.loading.text"), SimpleTextAttributes.GRAYED_ATTRIBUTES)
}
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}"))
val cli = GeneralCommandLine()
.withExePath(exe.toString())
.withWorkingDirectory(workingDirectory)
.withWorkDirectory(workingDirectory?.toFile())
.withParameters(*parameters)
.withCharset(Charsets.UTF_8)
return Result.success(cli)

View file

@ -33,7 +33,7 @@ import kotlinx.coroutines.*
import java.awt.Component
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) {
runWithModalProgressBlocking(taskOwnerFactory(), titleFactory(), cancellationFactory(), action)
} else {

View file

@ -96,7 +96,7 @@ abstract class Downloader<T, V: VersionInfo>(val component: Component) {
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)
outputPath.textField.columns = 50

View file

@ -66,7 +66,7 @@ abstract class LocalSelector<T>(val component: Component) {
private suspend fun doBrowseFromDisk(preSelected: Path?): T? {
val dialog = DialogBuilder()
val name = JBTextField().also { it.columns = 25 }
val path = textFieldWithBrowseButton(null, descriptor)
val path = textFieldWithBrowseButton(null, descriptor.title, descriptor)
Disposer.register(dialog, path)
lateinit var errorMessageBox: JBLabel
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.progress.EmptyProgressIndicator
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.toNioPathOrNull
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 downloader = service.createDownloader(listOf(desc), ZigBrainsBundle.message("settings.toolchain.downloader.service.tarball"))
val downloadResults = reporter.sizedStep(100) {
coroutineToIndicator {
blockingContext {
downloader.download(into.toFile())
}
}
@ -99,7 +99,7 @@ suspend fun flattenDownloadDir(dir: Path, reporter: ProgressReporter) {
if (contents.size == 1 && contents[0].isDirectory()) {
val src = contents[0]
reporter.indeterminateStep {
coroutineToIndicator {
blockingContext {
val indicator = ProgressManager.getInstance().progressIndicator ?: EmptyProgressIndicator()
indicator.isIndeterminate = true
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) {
try {
reporter.indeterminateStep {
coroutineToIndicator {
blockingContext {
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<*>
editButton?.isEnabled = actual
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) {

View file

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

View file

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

View file

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

View file

@ -46,7 +46,7 @@ class ZLSStreamConnectionProvider private constructor(private val project: Proje
companion object {
suspend fun create(project: Project): ZLSStreamConnectionProvider {
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)
}

View file

@ -43,8 +43,8 @@ import javax.swing.text.PlainDocument
class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
private val zlsConfigPath = textFieldWithBrowseButton(
null,
ZLSBundle.message("settings.zls-config-path.browse.title"),
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()
.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() {

View file

@ -49,7 +49,8 @@ import kotlin.io.path.pathString
class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() {
private val pathToZLS = textFieldWithBrowseButton(
null,
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle(ZLSBundle.message("dialog.title.zls"))
ZLSBundle.message("dialog.title.zls"),
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()
).also {
it.textField.document.addDocumentListener(object : DocumentAdapter() {
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.getTarballIfCompatible
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.util.io.FileUtil
import com.intellij.util.asSafely
@ -52,7 +52,7 @@ data class ZLSVersionInfo(
return withContext(Dispatchers.IO) {
val single = toolchain != null
val url = if (single) {
getToolchainURL(toolchain, project) ?: return@withContext emptyList()
getToolchainURL(toolchain!!, project) ?: return@withContext emptyList()
} else {
multiURL
}
@ -60,7 +60,7 @@ data class ZLSVersionInfo(
val tempFile = FileUtil.createTempFile(tempPluginDir, "zls_version_info", ".json", false, false)
val desc = service.createFileDescription(url, tempFile.name)
val downloader = service.createDownloader(listOf(desc), ZLSBundle.message("settings.downloader.service.index"))
val downloadResults = coroutineToIndicator {
val downloadResults = blockingContext {
downloader.download(tempPluginDir)
}
if (downloadResults.isEmpty())

View file

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