diff --git a/CHANGELOG.md b/CHANGELOG.md index 4106120d..787f7aa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,17 @@ Changelog structure reference: ## [Unreleased] +## [22.0.1] + +### Fixed + +- LSP + - Changing ZLS configs would not restart ZLS + +- Project + - Occasional "AWT events are not allowed inside write action" error coming from LSP + - IllegalStateException coming from the standard library handler + ## [22.0.0] ### Added diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/stdlib/ZigSyntheticLibrary.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/stdlib/ZigSyntheticLibrary.kt index f81dab44..a915a8de 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/stdlib/ZigSyntheticLibrary.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/stdlib/ZigSyntheticLibrary.kt @@ -79,31 +79,23 @@ class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresen suspend fun reload(project: Project, state: ZigProjectSettings) { val moduleId = ModuleId(ZIG_MODULE_ID) val workspaceModel = WorkspaceModel.getInstance(project) - if (moduleId !in workspaceModel.currentSnapshot) { - val baseModuleDir = project.guessProjectDir()?.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()) ?: return - - val moduleEntitySource = LegacyBridgeJpsEntitySourceFactory - .createEntitySourceForModule(project, baseModuleDir, null) - - val moduleEntity = ModuleEntity(ZIG_MODULE_ID, emptyList(), moduleEntitySource) - workspaceModel.update("Add new module") {builder -> - builder.addEntity(moduleEntity) - } - } - val moduleEntity = workspaceModel.currentSnapshot.resolve(moduleId) ?: return val root = getRoot(state, project) ?: return val libRoot = LibraryRoot(root.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()), LibraryRootTypeId.SOURCES) val libraryTableId = LibraryTableId.ProjectLibraryTableId val libraryId = LibraryId(ZIG_LIBRARY_ID, libraryTableId) - if (libraryId in workspaceModel.currentSnapshot) { - val library = workspaceModel.currentSnapshot.resolve(libraryId) ?: return - workspaceModel.update("Update library") { builder -> - builder.modifyLibraryEntity(library) { - roots.clear() - roots.add(libRoot) - } + val baseModuleDir = project.guessProjectDir()?.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()) ?: return + workspaceModel.update("Update Zig std") { builder -> + builder.resolve(moduleId)?.let { moduleEntity -> + builder.removeEntity(moduleEntity) + } + val moduleEntitySource = LegacyBridgeJpsEntitySourceFactory + .createEntitySourceForModule(project, baseModuleDir, null) + + val moduleEntity = builder.addEntity(ModuleEntity(ZIG_MODULE_ID, emptyList(), moduleEntitySource)) + + builder.resolve(libraryId)?.let { libraryEntity -> + builder.removeEntity(libraryEntity) } - } else { val libraryEntitySource = LegacyBridgeJpsEntitySourceFactory .createEntitySourceForProjectLibrary(project, null) val libraryEntity = LibraryEntity( @@ -113,13 +105,11 @@ class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresen ) { roots.add(libRoot) } - workspaceModel.update("Add new library") { builder -> - builder.addEntity(libraryEntity) - } - } - workspaceModel.update("Link dep") { builder -> + builder.addEntity(libraryEntity) builder.modifyModuleEntity(moduleEntity) { - dependencies.add(LibraryDependency(libraryId, false, DependencyScope.COMPILE)) + val dep = LibraryDependency(libraryId, false, DependencyScope.COMPILE) + dependencies.clear() + dependencies.add(dep) } } } diff --git a/gradle.properties b/gradle.properties index e9c3c5e8..dae2e0cf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ pluginName=ZigBrains pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains -pluginVersion=22.0.0 +pluginVersion=22.0.1 pluginSinceBuild=242 pluginUntilBuild=242.* diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStartup.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStartup.kt index f126be57..370a2408 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStartup.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStartup.kt @@ -55,6 +55,9 @@ class ZLSStartup: ProjectActivity { EditorNotifications.getInstance(project).updateAllNotifications() } currentState = running + if (handleStartLSP(project)) { + EditorNotifications.getInstance(project).updateAllNotifications() + } delay(1000) } } diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZigLanguageServerFactory.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZigLanguageServerFactory.kt index d1c61d49..c46e9ac7 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZigLanguageServerFactory.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZigLanguageServerFactory.kt @@ -39,8 +39,11 @@ import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures import com.redhat.devtools.lsp4ij.client.features.LSPFormattingFeature import com.redhat.devtools.lsp4ij.client.features.LSPInlayHintFeature import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock class ZigLanguageServerFactory: LanguageServerFactory, LanguageServerEnablementSupport { override fun createConnectionProvider(project: Project): StreamConnectionProvider { @@ -93,35 +96,67 @@ fun Project.zlsEnabled(value: Boolean) { suspend fun Project.zlsRunningAsync(): Boolean { if (!zlsEnabledAsync()) return false - return zlsRunningLsp4ij() + return lsm.isRunning } fun Project.zlsRunningSync(): Boolean { if (!zlsEnabledSync()) return false - return zlsRunningLsp4ij() + return lsm.isRunning } -private fun Project.zlsRunningLsp4ij(): Boolean { - val manager = service() - val status = manager.getServerStatus("ZigBrains") +private val Project.lsm get() = service() + +private val LanguageServerManager.isRunning get(): Boolean { + val status = getServerStatus("ZigBrains") return status == ServerStatus.started || status == ServerStatus.starting } +private val START_MUTEX = Mutex() + class ZLSStarter: LanguageServerStarter { override fun startLSP(project: Project, restart: Boolean) { project.zigCoroutineScope.launch { - val manager = project.service() - val status = manager.getServerStatus("ZigBrains") - if ((status == ServerStatus.started || status == ServerStatus.starting) && !restart) - return@launch - manager.stop("ZigBrains") - if (project.zlsSettings.validateAsync()) { - manager.start("ZigBrains") + START_MUTEX.withLock { + if (restart) { + project.putUserData(RESTART_KEY, Unit) + } else { + project.putUserData(START_KEY, Unit) + } } } } - } -private val ENABLED_KEY = Key.create("ZLS_ENABLED") \ No newline at end of file +private suspend fun doStart(project: Project, restart: Boolean) { + if (!restart && project.lsm.isRunning) + return + while (!project.isDisposed && project.lsm.isRunning) { + project.lsm.stop("ZigBrains") + delay(250) + } + if (project.zlsSettings.validateAsync()) { + delay(250) + project.lsm.start("ZigBrains") + } +} + +suspend fun handleStartLSP(project: Project) = START_MUTEX.withLock { + if (project.getUserData(RESTART_KEY) != null) { + project.putUserData(RESTART_KEY, null) + project.putUserData(START_KEY, null) + doStart(project, true) + true + } else if (project.getUserData(START_KEY) != null) { + project.putUserData(START_KEY, null) + doStart(project, false) + true + } else { + false + } +} + +private val ENABLED_KEY = Key.create("ZLS_ENABLED") + +private val RESTART_KEY = Key.create("ZLS_RESTART_REQUEST") +private val START_KEY = Key.create("ZLS_START_REQUEST") diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt index cccda858..5536bf4a 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt @@ -82,7 +82,7 @@ class ZLSProjectSettingsService(val project: Project): PersistentStateComponent< } } - fun validateSync() = if (application.isDispatchThread) { + fun validateSync() = if (application.isDispatchThread && !application.isWriteAccessAllowed) { runWithModalProgressBlocking(ModalTaskOwner.project(project), ZLSBundle.message("progress.title.validate")) { validateAsync() } diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt index edb49349..85363a92 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt @@ -22,7 +22,6 @@ package com.falsepattern.zigbrains.lsp.settings -import com.falsepattern.zigbrains.lsp.startLSP import com.falsepattern.zigbrains.shared.SubConfigurable import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer diff --git a/lsp/src/main/resources/META-INF/zigbrains-lsp.xml b/lsp/src/main/resources/META-INF/zigbrains-lsp.xml index a9c5f872..d07aaa59 100644 --- a/lsp/src/main/resources/META-INF/zigbrains-lsp.xml +++ b/lsp/src/main/resources/META-INF/zigbrains-lsp.xml @@ -88,10 +88,10 @@ /> - + - + \ No newline at end of file