From 9a262c53befbda27a7cb759bc05a05814a3377cf Mon Sep 17 00:00:00 2001 From: Shuu Date: Mon, 9 Sep 2024 09:20:25 +0900 Subject: [PATCH] lsp: Add command for restarting lsp server (#2181) --- ...844_github-actions[bot]_add-lsprestart.rst | 7 +++ documents/howtouse.md | 2 + src/moepkg/editorstatus.nim | 2 +- src/moepkg/exmode.nim | 30 +++++++++++ src/moepkg/exmodeutils.nim | 10 +++- src/moepkg/helputils.nim | 2 + src/moepkg/lsp/client.nim | 24 +++++++++ tests/tlspclient.nim | 54 +++++++++++++++++++ 8 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 changelog.d/20240909_000844_github-actions[bot]_add-lsprestart.rst diff --git a/changelog.d/20240909_000844_github-actions[bot]_add-lsprestart.rst b/changelog.d/20240909_000844_github-actions[bot]_add-lsprestart.rst new file mode 100644 index 000000000..fbc8b29a1 --- /dev/null +++ b/changelog.d/20240909_000844_github-actions[bot]_add-lsprestart.rst @@ -0,0 +1,7 @@ +.. _#2181: https://github.com/fox0430/moe/pull/2181 + +Added +..... + +- `#2181`_ lsp: Add command for restarting lsp server + diff --git a/documents/howtouse.md b/documents/howtouse.md index 587e3b2bf..db7697aaf 100644 --- a/documents/howtouse.md +++ b/documents/howtouse.md @@ -138,6 +138,7 @@ | **z** **d**
| Delete fold lines | | **z** **R**
| Delete fold lines | | **Ctrl** **s**
| Selection Range (LSP) | +| **Space** **o**
| Document Symbol (LSP) | @@ -346,6 +347,7 @@ | `lspFold` | LSP Folding Range | | `log` | Open a log viewer for editor log | | `lspLog` | Open a log viewer for LSP log | +| `lspRestart` | Result the current LSP server | | `help` | Open help | | `putConfigFile` | Put a sample configuration file in ~/.config/moe | | `run` | Quick run | diff --git a/src/moepkg/editorstatus.nim b/src/moepkg/editorstatus.nim index 3cfb2c698..071fd74fa 100644 --- a/src/moepkg/editorstatus.nim +++ b/src/moepkg/editorstatus.nim @@ -308,7 +308,7 @@ proc cancelLspForegroundRequest*(status: var EditorStatus) {.inline.} = if status.lspClients.contains(currentBufStatus.langId): lspClient.cancelLspForegroundRequest(currentBufStatus.id) -proc initLspExperimentalParams( +proc initLspExperimentalParams*( serverName: string, settings: LspServerSettings): Option[JsonNode] = diff --git a/src/moepkg/exmode.nim b/src/moepkg/exmode.nim index 99d8b8309..91276a0c5 100644 --- a/src/moepkg/exmode.nim +++ b/src/moepkg/exmode.nim @@ -1160,6 +1160,34 @@ proc lspFoldingRange(status: var EditorStatus) = if r.isErr: status.commandLine.writeLspFoldingRangeError(r.error) +proc lspRestartClient(status: var EditorStatus) = + status.changeMode(currentBufStatus.prevMode) + + if not status.lspClients.contains(currentBufStatus.langId): + status.commandLine.writeLspError("Client not found") + return + + let r = lspClient.restart + if r.isOk: + status.commandLine.writeStandard(fmt"lsp: restarted client: {lspClient.serverName}") + else: + status.commandLine.writeLspError("Client not found") + + let langId = currentBufStatus.langId + for b in status.bufStatus: + if b.langId == langId: + let r = lspClient.initialize( + status.bufStatus[^1].id, + initInitializeParams( + lspClient.serverName, + $b.openDir, + status.settings.lsp.languages[langId].trace, + initLspExperimentalParams( + status.lspClients[langId].serverName, + status.settings.lsp.servers))) + if r.isErr: + status.commandLine.writeLspError(r.error) + proc saveExCommandHistory( exCommandHistory: var seq[Runes], command: seq[Runes], @@ -1355,6 +1383,8 @@ proc exModeCommand*(status: var EditorStatus, command: seq[Runes]) = status.lspExecuteCommand(command[1 .. ^1]) elif isLspFoldingCommand(command): status.lspFoldingRange + elif isLspRestartCommand(command): + status.lspRestartClient else: status.commandLine.writeNotEditorCommandError(command) status.changeMode(currentBufStatus.prevMode) diff --git a/src/moepkg/exmodeutils.nim b/src/moepkg/exmodeutils.nim index 11b7706f2..7fc11160e 100644 --- a/src/moepkg/exmodeutils.nim +++ b/src/moepkg/exmodeutils.nim @@ -187,6 +187,10 @@ const command: "lspLog", description: "Open the LSP log viewer", argsType: ArgsType.none), + ExCommandInfo( + command: "lspRestart", + description: "Restart the current LSP server", + argsType: ArgsType.none), ExCommandInfo( command: "man", description: "Show the given UNIX manual page, if available", @@ -759,6 +763,9 @@ proc isLspExeCommand*(command: seq[Runes]): bool {.inline.} = proc isLspFoldingCommand*(command: seq[Runes]): bool {.inline.} = command.len == 1 and cmpIgnoreCase($command[0], "lspfold") == 0 +proc isLspRestartCommand*(command: seq[Runes]): bool {.inline.} = + command.len == 1 and cmpIgnoreCase($command[0], "lsprestart") == 0 + proc isValidExCommand*(commandSplit: seq[Runes]): bool = ## Return true if valid ex command and valid args. @@ -836,7 +843,8 @@ proc isValidExCommand*(commandSplit: seq[Runes]): bool = isHighlightCurrentLineSettingCommand(commandSplit) or isBuildCommand(commandSplit) or isLspExeCommand(commandSplit) or - isLspFoldingCommand(commandSplit) + isLspFoldingCommand(commandSplit) or + isLspRestartCommand(commandSplit) proc getArgsType*(command: Runes): Result[ArgsType, string] = ## Return ArgsType if valid ex command. diff --git a/src/moepkg/helputils.nim b/src/moepkg/helputils.nim index ac25a2d8e..029d407cf 100644 --- a/src/moepkg/helputils.nim +++ b/src/moepkg/helputils.nim @@ -306,6 +306,8 @@ lspFold - LSP Folding Range log - Open a log viewer for editor log lspLog- Open a log viewer for LSP log +lspRestart - Restart the current LSP server + help - Open this help putConfigFile - Put a sample configuration file in ~/.config/moe diff --git a/src/moepkg/lsp/client.nim b/src/moepkg/lsp/client.nim index 3f167084a..9e3e11ae9 100644 --- a/src/moepkg/lsp/client.nim +++ b/src/moepkg/lsp/client.nim @@ -94,6 +94,9 @@ type lastId*: RequestId # Last request ID serverName*: string + # The LSP server name + command*: string + # The LSP server start command type R = Result @@ -102,6 +105,8 @@ type initLspClientResult* = R[LspClient, string] + LspRestartClientResult* = R[(), string] + LspErrorParseResult* = R[LspError, string] LspSendRequestResult* = R[(), string] LspSendNotifyResult* = R[(), string] @@ -438,8 +443,27 @@ proc initLspClient*(command: string): initLspClientResult = c.serverName = commandSplit[0] + c.command = command + return initLspClientResult.ok c +proc restart*(c: var LspClient): LspRestartClientResult = + ## Restart the LSP server process. + ## Logs will be taken over. + + if c.serverProcess.running: c.exit + + let beforeLog = c.log + + var newClient = initLspClient(c.command) + if newClient.isErr: + return LspRestartClientResult.err newClient.error + + c = newClient.get + c.log = beforeLog + + return LspRestartClientResult.ok () + proc initInitializeParams*( serverName, workspaceRoot: string, trace: TraceValue, diff --git a/tests/tlspclient.nim b/tests/tlspclient.nim index 37c181fa8..880017ed4 100644 --- a/tests/tlspclient.nim +++ b/tests/tlspclient.nim @@ -18,7 +18,9 @@ #[############################################################################]# import std/[unittest, importutils, os, osproc, options, tables, json] + import pkg/results + import moepkg/independentutils import moepkg/lsp/protocol/[enums, types] import moepkg/lsp/utils @@ -83,6 +85,58 @@ suite "lsp: initInitializeParams": check r.capabilities.experimental.get == experimental +suite "lsp: restart": + privateAccess(LspClient) + + const + ServerName = "nimlangserver" + Command = "nimlangserver" + Trace = TraceValue.verbose + + var client: LspClient + + setup: + if isNimlangserverAvailable(): + client = initLspClient(Command).get + + test "Basic 1": + if not isNimlangserverAvailable(): + skip() + else: + const BufferId = 1 + let params = initInitializeParams(ServerName, "/", Trace) + check client.initialize(BufferId, params).isOk + + let + beforePid = client.serverProcessId + beforeLogLen = client.log.len + + check client.running + + check client.restart.isOk + + check beforePid != client.serverProcessId + check client.log.len == beforeLogLen + + test "Basic 2": + if not isNimlangserverAvailable(): + skip() + else: + const BufferId = 1 + let params = initInitializeParams(ServerName, "/", Trace) + check client.initialize(BufferId, params).isOk + + let + beforePid = client.serverProcessId + beforeLogLen = client.log.len + + client.serverProcess.kill + + check client.restart.isOk + + check beforePid != client.serverProcessId + check client.log.len == beforeLogLen + suite "lsp: setCapabilities": var client: LspClient