diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/actions/RestartLspAction.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/actions/RestartLspAction.kt deleted file mode 100644 index 32e36e6..0000000 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/actions/RestartLspAction.kt +++ /dev/null @@ -1,19 +0,0 @@ -package dev.slint.ideaplugin.ide.actions - -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.components.service -import com.intellij.openapi.project.DumbAware -import dev.slint.ideaplugin.ide.services.SlintServerService - -class RestartLspAction: AnAction(), DumbAware { - override fun actionPerformed(e: AnActionEvent) { - val project = e.project ?: return - val slintServerService = project.service() - slintServerService.restartServer() - } - - companion object { - const val ID: String = "Slint.RestartLspAction" - } -} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/formatter/SlintLspFormattingService.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/formatter/SlintLspFormattingService.kt deleted file mode 100644 index 88b3bcb..0000000 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/formatter/SlintLspFormattingService.kt +++ /dev/null @@ -1,59 +0,0 @@ -package dev.slint.ideaplugin.ide.formatter - -import com.intellij.formatting.service.AsyncDocumentFormattingService -import com.intellij.formatting.service.AsyncFormattingRequest -import com.intellij.formatting.service.FormattingService -import com.intellij.openapi.command.WriteCommandAction -import com.intellij.openapi.components.service -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.psi.PsiFile -import com.jetbrains.rd.util.enumSetOf -import dev.slint.ideaplugin.ide.services.FileEditorService -import dev.slint.ideaplugin.ide.services.SlintServerService -import dev.slint.ideaplugin.lang.psi.SlintFile -import org.eclipse.lsp4j.DocumentFormattingParams -import org.eclipse.lsp4j.FormattingOptions -import org.eclipse.lsp4j.TextDocumentIdentifier -import kotlin.io.path.Path - -class SlintLspFormattingService : AsyncDocumentFormattingService() { - override fun getFeatures(): Set = FEATURES - - override fun canFormat(file: PsiFile): Boolean = file is SlintFile - - override fun createFormattingTask(request: AsyncFormattingRequest): FormattingTask? { - val context = request.context - val project = context.project - val file = context.virtualFile ?: return null - - val uriFile = Path(file.path).toUri() - - val slintServerService = project.service() - val fileEditorManager = FileEditorManager.getInstance(project) - val editor = fileEditorManager.selectedTextEditor ?: return null - - return object : FormattingTask { - override fun run() { - val edits = slintServerService.formatting(uriFile.toString(), 4, true) - - edits?.forEach { textEdit -> - WriteCommandAction.runWriteCommandAction(project) { - FileEditorService.applyTextChanges(textEdit, editor) - } - } - } - - override fun cancel(): Boolean { - return true - } - } - } - - override fun getNotificationGroupId(): String = "Slint Plugin" - - override fun getName(): String = "slint-lsp" - - companion object { - private val FEATURES: Set = enumSetOf() - } -} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/ServerProcessHandler.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/ServerProcessHandler.kt deleted file mode 100644 index 7054f51..0000000 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/ServerProcessHandler.kt +++ /dev/null @@ -1,53 +0,0 @@ -package dev.slint.ideaplugin.ide.lsp - -import com.intellij.execution.process.OSProcessHandler -import com.intellij.execution.process.ProcessAdapter -import com.intellij.execution.process.ProcessEvent -import com.intellij.openapi.components.service -import com.intellij.openapi.project.Project -import dev.slint.ideaplugin.ide.services.SlintServerService -import dev.slint.ideaplugin.ide.settings.SlintSettingsState -import java.util.* -import kotlin.concurrent.schedule - -object ServerProcessHandler { - fun addListeners(handler: OSProcessHandler, project: Project): OSProcessHandler { - handler.addProcessListener(object : ProcessAdapter() { - override fun processTerminated(event: ProcessEvent) { - super.processTerminated(event) - - val slintServerService = project.service() - if (slintServerService.isRestarting) { - return - } - - slintServerService.setTerminatingStatus() - - val settingState = SlintSettingsState.getInstance().lspSettings - if (!settingState.isRestartLsp) { - return - } - - Timer().schedule(3000) { - slintServerService.restartServer() - } - } - - override fun processNotStarted() { - super.processNotStarted() - - val slintServerService = project.service() - slintServerService.setTerminatingStatus() - } - - override fun startNotified(event: ProcessEvent) { - super.startNotified(event) - - val slintServerService = project.service() - slintServerService.setRunningStatus() - } - }) - - return handler - } -} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLanguageClient.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspClient.kt similarity index 93% rename from src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLanguageClient.kt rename to src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspClient.kt index bc1813f..83bba3a 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLanguageClient.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspClient.kt @@ -4,7 +4,7 @@ import com.intellij.platform.lsp.api.Lsp4jClient import com.intellij.platform.lsp.api.LspServerNotificationsHandler import org.eclipse.lsp4j.jsonrpc.services.JsonNotification -class SlintLanguageClient( +class SlintLspClient( serverNotificationsHandler: LspServerNotificationsHandler ) : Lsp4jClient(serverNotificationsHandler) { @JsonNotification("experimental/serverStatus") diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspFormattingSupport.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspFormattingSupport.kt new file mode 100644 index 0000000..10312bc --- /dev/null +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspFormattingSupport.kt @@ -0,0 +1,14 @@ +package dev.slint.ideaplugin.ide.lsp + +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.platform.lsp.api.customization.LspFormattingSupport +import dev.slint.ideaplugin.lang.SlintFileType + +@Suppress("UnstableApiUsage") +class SlintLspFormattingSupport : LspFormattingSupport() { + override fun shouldFormatThisFileExclusivelyByServer( + file: VirtualFile, + ideCanFormatThisFileItself: Boolean, + serverExplicitlyWantsToFormatThisFile: Boolean + ) = file.fileType == SlintFileType +} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLanguageServer.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServer.kt similarity index 84% rename from src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLanguageServer.kt rename to src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServer.kt index f719709..0c10e95 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLanguageServer.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServer.kt @@ -4,7 +4,8 @@ import org.eclipse.lsp4j.jsonrpc.services.JsonRequest import org.eclipse.lsp4j.services.LanguageServer import java.util.concurrent.CompletableFuture -interface SlintLanguageServer : LanguageServer { +interface SlintLspServer : LanguageServer { @JsonRequest("slint/load_file") fun loadFile(path: String): CompletableFuture -} \ No newline at end of file +} + diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt index 82bbb4d..d4780a6 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerDescriptor.kt @@ -1,14 +1,11 @@ package dev.slint.ideaplugin.ide.lsp import com.intellij.execution.configurations.GeneralCommandLine -import com.intellij.execution.process.OSProcessHandler import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile -import com.intellij.platform.lsp.api.Lsp4jClient -import com.intellij.platform.lsp.api.LspServerListener -import com.intellij.platform.lsp.api.LspServerNotificationsHandler -import com.intellij.platform.lsp.api.ProjectWideLspServerDescriptor +import com.intellij.platform.lsp.api.* import com.intellij.platform.lsp.api.customization.LspCompletionSupport +import com.intellij.platform.lsp.api.customization.LspFormattingSupport import dev.slint.ideaplugin.ide.settings.SlintSettingsState import dev.slint.ideaplugin.lang.SlintFileType import org.eclipse.lsp4j.services.LanguageServer @@ -22,13 +19,10 @@ class SlintLspServerDescriptor(project: Project) : ProjectWideLspServerDescripto override fun createInitializationOptions(): Any = SlintSettingsState.getInstance().lspSettings - // Suppression of the verifier plugin warning - // override fun createLsp4jClient(handler: LspServerNotificationsHandler): Lsp4jClient = LspLanguageClient(handler) + override fun createLsp4jClient(handler: LspServerNotificationsHandler): Lsp4jClient = SlintLspClient(handler) - override fun startServerProcess(): OSProcessHandler = - ServerProcessHandler.addListeners(super.startServerProcess(), project) - - override val lsp4jServerClass: Class = SlintLanguageServer::class.java + override val lsp4jServerClass: Class = SlintLspServer::class.java override val lspServerListener: LspServerListener = SlintLspServerListener(project) override val lspCompletionSupport: LspCompletionSupport = SlintLspCompletionSupport() + override val lspFormattingSupport: LspFormattingSupport = SlintLspFormattingSupport() } \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerSupportProvider.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerSupportProvider.kt index b23dc00..2626da7 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerSupportProvider.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/lsp/SlintLspServerSupportProvider.kt @@ -2,7 +2,11 @@ package dev.slint.ideaplugin.ide.lsp import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile +import com.intellij.platform.lsp.api.LspServer import com.intellij.platform.lsp.api.LspServerSupportProvider +import com.intellij.platform.lsp.api.lsWidget.LspServerWidgetItem +import dev.slint.ideaplugin.SlintIcons +import dev.slint.ideaplugin.ide.settings.SlintSettingsConfigurable import dev.slint.ideaplugin.lang.SlintFileType @Suppress("UnstableApiUsage") @@ -15,4 +19,7 @@ class SlintLspServerSupportProvider : LspServerSupportProvider { if (file.fileType != SlintFileType) return serverStarter.ensureServerStarted(SlintLspServerDescriptor(project)) } + + override fun createLspServerWidgetItem(lspServer: LspServer, currentFile: VirtualFile?): LspServerWidgetItem = + LspServerWidgetItem(lspServer, currentFile, SlintIcons.SLINT, SlintSettingsConfigurable::class.java) } \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt index 0519c2f..0dcf6aa 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/services/SlintServerService.kt @@ -1,40 +1,19 @@ package dev.slint.ideaplugin.ide.services -import com.intellij.notification.NotificationGroupManager -import com.intellij.notification.NotificationType import com.intellij.openapi.components.Service import com.intellij.openapi.project.Project import com.intellij.platform.lsp.api.LspServer import com.intellij.platform.lsp.api.LspServerManager import com.intellij.platform.lsp.api.LspServerState -import dev.slint.ideaplugin.SlintBundle import dev.slint.ideaplugin.ide.lsp.SlintLspServerSupportProvider import org.eclipse.lsp4j.* @Service(Service.Level.PROJECT) @Suppress("UnstableApiUsage") class SlintServerService(private val project: Project) { - private var status = Status.TERMINATING - - val isRunning get() = status == Status.RUNNING - - val isRestarting get() = status == Status.RESTARTING - - fun setRunningStatus() { - status = Status.RUNNING - } - - fun setTerminatingStatus() { - status = Status.TERMINATING - notifyTerminating() - } - fun restartServer() { LspServerManager.getInstance(project) .stopAndRestartIfNeeded(SlintLspServerSupportProvider::class.java) - - status = Status.RESTARTING - notifyRestart() } fun previewComponent(path: String, component: String) { @@ -50,60 +29,10 @@ class SlintServerService(private val project: Project) { } } - fun formatting(path: String, tabSize: Int, insertSpaces: Boolean): List? { - val server = getActiveServer() ?: return null - - val params = DocumentFormattingParams( - TextDocumentIdentifier(path), - FormattingOptions(tabSize, insertSpaces) - ) - - return server.sendRequestSync { it.textDocumentService.formatting(params) } - } - private fun getActiveServer(): LspServer? { val servers = LspServerManager.getInstance(project) .getServersForProvider(SlintLspServerSupportProvider::class.java) return servers.firstOrNull { it.state == LspServerState.Running } } - - private fun notifyRun() { - NotificationGroupManager.getInstance() - .getNotificationGroup("Slint") - .createNotification( - SlintBundle.message("slint.language.server.is.running"), - "", - NotificationType.INFORMATION - ) - .notify(project) - } - - private fun notifyRestart() { - NotificationGroupManager.getInstance() - .getNotificationGroup("Slint") - .createNotification( - SlintBundle.message("slint.language.server.restarted"), - "", - NotificationType.INFORMATION - ) - .notify(project) - } - - private fun notifyTerminating() { - NotificationGroupManager.getInstance() - .getNotificationGroup("Slint") - .createNotification( - SlintBundle.message("slint.language.server.is.stopped"), - "", - NotificationType.WARNING - ) - .notify(project) - } - - private enum class Status { - RUNNING, - RESTARTING, - TERMINATING - } } \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt index c36ad36..88aec93 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintLspSettings.kt @@ -10,7 +10,6 @@ data class SlintLspSettings( var noToolbar: Boolean = false, var includePaths: MutableList = mutableListOf(), var useExternalLsp: Boolean = false, - var isRestartLsp: Boolean = true, ) enum class SlintStyle { diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt index ad2bd93..ed86a8b 100644 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt +++ b/src/main/kotlin/dev/slint/ideaplugin/ide/settings/SlintSettingsComponent.kt @@ -41,15 +41,6 @@ class SlintSettingsComponent(lspSettings: SlintLspSettings) { .onApply { pathsTablePanel.onApply(lspSettings.includePaths) } .onReset { pathsTablePanel.onReset(lspSettings.includePaths) } } - row { - checkBox("Restart LSP server") - .comment( - "Restarting the LSP server after a crash or shutdown. " + - "If there are critical errors in the LSP server, the server will restart indefinitely." + - "
Manually restart the server: 'Tools -> Restart Slint LSP'" - ) - .bindSelected(lspSettings::isRestartLsp) - } } group("Preview") { row { diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidget.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidget.kt deleted file mode 100644 index 11af53a..0000000 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidget.kt +++ /dev/null @@ -1,89 +0,0 @@ -package dev.slint.ideaplugin.ide.widgets - -import com.intellij.openapi.actionSystem.ActionManager -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.actionSystem.DefaultActionGroup -import com.intellij.openapi.components.service -import com.intellij.openapi.module.ModuleUtil -import com.intellij.openapi.project.Project -import com.intellij.openapi.project.ProjectLocator -import com.intellij.openapi.ui.popup.JBPopupFactory -import com.intellij.openapi.ui.popup.ListPopup -import com.intellij.openapi.util.IconLoader.getDisabledIcon -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.wm.CustomStatusBarWidget -import com.intellij.openapi.wm.StatusBarWidget -import com.intellij.openapi.wm.impl.status.EditorBasedStatusBarPopup -import com.intellij.ui.AnimatedIcon -import com.intellij.util.concurrency.EdtExecutorService -import dev.slint.ideaplugin.SlintBundle -import dev.slint.ideaplugin.SlintIcons -import dev.slint.ideaplugin.ide.actions.RestartLspAction -import dev.slint.ideaplugin.ide.services.SlintServerService -import dev.slint.ideaplugin.lang.SlintFileType -import java.util.concurrent.ScheduledFuture -import java.util.concurrent.TimeUnit - -class SlintStatusBarWidget(project: Project) : EditorBasedStatusBarPopup(project, false), CustomStatusBarWidget { - private companion object { - const val ID = "Slint.StatusBarWidget" - } - - private var future: ScheduledFuture<*>? = null - - init { - this.future = EdtExecutorService - .getScheduledExecutorInstance() - .scheduleWithFixedDelay({ this.update() }, 2, 2, TimeUnit.SECONDS) - } - - override fun ID(): String = ID - - override fun createInstance(project: Project): StatusBarWidget = SlintStatusBarWidget(project) - - override fun createPopup(context: DataContext): ListPopup? { - val group = DefaultActionGroup.createPopupGroupWithEmptyText() - group.add(ActionManager.getInstance().getAction(RestartLspAction.ID)) - - return JBPopupFactory.getInstance() - .createActionGroupPopup( - "Slint Actions", - group, - context, - JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, - true - ) - } - - override fun getWidgetState(file: VirtualFile?): WidgetState { - if (file?.fileType !is SlintFileType) return WidgetState.HIDDEN - - val project = ProjectLocator.getInstance().guessProjectForFile(file) - project ?: return WidgetState.HIDDEN - val module = ModuleUtil.findModuleForFile(file, this.project) - module ?: return WidgetState.HIDDEN - - val slintServerService = project.service() - - return when (slintServerService.isRunning) { - true -> { - val state = WidgetState(SlintBundle.message("slint.language.server.is.running"), "Slint", false) - state.icon = SlintIcons.SLINT - state - } - - false -> { - val state = WidgetState(SlintBundle.message("slint.language.server.is.stopped"), "Slint", true) - state.icon = AnimatedIcon(1000, SlintIcons.SLINT, getDisabledIcon(SlintIcons.SLINT)) - state - } - } - } - - override fun dispose() { - this.future?.cancel(true) - this.future = null - - super.dispose() - } -} \ No newline at end of file diff --git a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidgetFactory.kt b/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidgetFactory.kt deleted file mode 100644 index 1b34cd2..0000000 --- a/src/main/kotlin/dev/slint/ideaplugin/ide/widgets/SlintStatusBarWidgetFactory.kt +++ /dev/null @@ -1,19 +0,0 @@ -package dev.slint.ideaplugin.ide.widgets - -import com.intellij.openapi.project.Project -import com.intellij.openapi.wm.StatusBarWidget -import com.intellij.openapi.wm.StatusBarWidgetFactory - -class SlintStatusBarWidgetFactory : StatusBarWidgetFactory { - override fun getId(): String { - return "SlintWidget" - } - - override fun getDisplayName(): String { - return "Slint" - } - - override fun createWidget(project: Project): StatusBarWidget { - return SlintStatusBarWidget(project) - } -} \ No newline at end of file diff --git a/src/main/resources/META-INF/slint-idea-lsp-support.xml b/src/main/resources/META-INF/slint-idea-lsp-support.xml index 230c6a3..9e5e2ed 100644 --- a/src/main/resources/META-INF/slint-idea-lsp-support.xml +++ b/src/main/resources/META-INF/slint-idea-lsp-support.xml @@ -2,13 +2,6 @@ - - - - - - @@ -21,13 +14,5 @@ icon="AllIcons.Actions.Preview" /> - - - - \ No newline at end of file