From cbacc240f908a3928bc15bf2f79d8a7196d79438 Mon Sep 17 00:00:00 2001 From: bung87 Date: Sun, 22 May 2022 03:18:35 +0800 Subject: [PATCH 1/3] windows compatibility through multisync --- .gitignore | 1 + nimlsp.nimble | 4 +- src/nimlsp.nim | 117 +++++++++++++++++++++------------ src/nimlsppkg/baseprotocol.nim | 43 ++++++++---- tests/tnimlsp.nim | 14 ++-- 5 files changed, 117 insertions(+), 62 deletions(-) diff --git a/.gitignore b/.gitignore index db7c4a9..6da5cd7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ nimcache/ nimlsp +tests/tnimlsp \ No newline at end of file diff --git a/nimlsp.nimble b/nimlsp.nimble index 66491e2..17e64bb 100644 --- a/nimlsp.nimble +++ b/nimlsp.nimble @@ -11,6 +11,7 @@ bin = @["nimlsp"] requires "nim >= 1.0.0" requires "jsonschema >= 0.2.1" +requires "asynctools" # nimble test does not work for me out of the box #task test, "Runs the test suite": @@ -21,8 +22,7 @@ task debug, "Builds the language server": exec "nim c --threads:on -d:nimcore -d:nimsuggest -d:debugCommunication -d:debugLogging -o:nimlsp src/nimlsp" before test: - if not fileExists("nimlsp"): - exec "nimble build" + exec "nimble build" task findNim, "Tries to find the current Nim installation": echo NimVersion diff --git a/src/nimlsp.nim b/src/nimlsp.nim index 52b7430..6a029b5 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -37,8 +37,6 @@ for i in 1..paramCount(): infoLog("Argument " & $i & ": " & paramStr(i)) var - ins = newAsyncFile(stdin.getOsFileHandle().AsyncFD) - outs = newAsyncFile(stdout.getOsFileHandle().AsyncFD) gotShutdown = false initialized = false projectFiles = initTable[string, tuple[nimsuggest: NimSuggest, openFiles: OrderedSet[string]]]() @@ -133,14 +131,23 @@ proc parseId(node: JsonNode): int = else: raise newException(MalformedFrame, "Invalid id node: " & repr(node)) -proc respond(request: RequestMessage, data: JsonNode) {.async.} = - await outs.sendJson create(ResponseMessage, "2.0", parseId(request["id"]), some(data), none(ResponseError)).JsonNode +template multisyncTask(outs: Stream | AsyncFile, body) = + when outs is Stream: + body + else: + await body + +proc respond(outs: Stream | AsyncFile, request: RequestMessage, data: JsonNode) {.multisync.} = + let resp = create(ResponseMessage, "2.0", parseId(request["id"]), some(data), none(ResponseError)).JsonNode + multisyncTask outs: outs.sendJson resp -proc error(request: RequestMessage, errorCode: int, message: string, data: JsonNode) {.async.} = - await outs.sendJson create(ResponseMessage, "2.0", parseId(request["id"]), none(JsonNode), some(create(ResponseError, errorCode, message, data))).JsonNode +proc error(outs: Stream | AsyncFile,request: RequestMessage, errorCode: int, message: string, data: JsonNode) {.multisync.} = + let resp = create(ResponseMessage, "2.0", parseId(request["id"]), none(JsonNode), some(create(ResponseError, errorCode, message, data))).JsonNode + multisyncTask outs: outs.sendJson resp -proc notify(notification: string, data: JsonNode) {.async.} = - await outs.sendJson create(NotificationMessage, "2.0", notification, some(data)).JsonNode +proc notify(outs: Stream | AsyncFile,notification: string, data: JsonNode) {.multisync.} = + let resp = create(NotificationMessage, "2.0", notification, some(data)).JsonNode + multisyncTask outs: outs.sendJson resp type Certainty = enum None, @@ -203,28 +210,31 @@ if not fileExists(nimpath / "config/nim.cfg"): "Supply the Nim project folder by adding it as an argument.\n" quit 1 -proc main(){.async.} = +proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = while true: try: debugLog "Trying to read frame" - let frame = await ins.readFrame + let frame = when ins is Stream: ins.readFrame else: await ins.readFrame debugLog "Got frame:" infoLog frame let message = frame.parseJson whenValidStrict(message, RequestMessage): debugLog "Got valid Request message of type " & message["method"].getStr if not initialized and message["method"].getStr != "initialize": - await message.error(-32002, "Unable to accept requests before being initialized", newJNull()) + multisyncTask outs: + outs.error(message, -32002, "Unable to accept requests before being initialized", newJNull()) continue case message["method"].getStr: of "shutdown": debugLog "Got shutdown request, answering" - await message.respond(newJNull()) + let resp = newJNull() + multisyncTask outs: + outs.respond(message, resp) gotShutdown = true of "initialize": debugLog "Got initialize request, answering" initialized = true - await message.respond(create(InitializeResult, create(ServerCapabilities, + let resp = create(InitializeResult, create(ServerCapabilities, textDocumentSync = some(create(TextDocumentSyncOptions, openClose = some(true), change = some(TextDocumentSyncKind.Full.int), @@ -258,7 +268,9 @@ proc main(){.async.} = executeCommandProvider = none(ExecuteCommandOptions), #?: ExecuteCommandOptions workspace = none(WorkspaceCapability), #?: WorkspaceCapability experimental = none(JsonNode) #?: any - )).JsonNode) + )).JsonNode + multisyncTask outs: + outs.respond(message,resp) of "textDocument/completion": message.textDocumentRequest(CompletionParams, compRequest): debugLog "Running equivalent of: sug ", uriToPath(fileuri), ";", filestash, ":", @@ -306,7 +318,8 @@ proc main(){.async.} = command = none(Command), data = none(JsonNode) ).JsonNode - await message.respond completionItems + multisyncTask outs: + outs.respond(message, completionItems) of "textDocument/hover": message.textDocumentRequest(TextDocumentPositionParams, hoverRequest): debugLog "Running equivalent of: def ", uriToPath(fileuri), ";", filestash, ":", @@ -319,8 +332,9 @@ proc main(){.async.} = debugLog "Found suggestions: ", suggestions[0..(if suggestions.len > 10: 10 else: suggestions.high)], (if suggestions.len > 10: " and " & $(suggestions.len-10) & " more" else: "") + var resp: JsonNode if suggestions.len == 0: - await message.respond newJNull() + resp = newJNull() else: var label = suggestions[0].qualifiedPath.join(".") if suggestions[0].forth != "": @@ -333,7 +347,7 @@ proc main(){.async.} = )) markedString = create(MarkedStringOption, "nim", label) if suggestions[0].doc != "": - await message.respond create(Hover, + resp = create(Hover, @[ markedString, create(MarkedStringOption, "", suggestions[0].nimDocstring), @@ -341,7 +355,9 @@ proc main(){.async.} = rangeopt ).JsonNode else: - await message.respond create(Hover, markedString, rangeopt).JsonNode + resp = create(Hover, markedString, rangeopt).JsonNode; + multisyncTask outs: + outs.respond(message, resp) of "textDocument/references": message.textDocumentRequest(ReferenceParams, referenceRequest): debugLog "Running equivalent of: use ", uriToPath(fileuri), ";", filestash, ":", @@ -365,9 +381,12 @@ proc main(){.async.} = ) ).JsonNode if response.len == 0: - await message.respond newJNull() + multisyncTask outs: + outs.respond(message, newJNull()) else: - await message.respond response + multisyncTask outs: + outs.respond(message, response) + of "textDocument/rename": message.textDocumentRequest(RenameParams, renameRequest): debugLog "Running equivalent of: use ", uriToPath(fileuri), ";", filestash, ":", @@ -380,8 +399,9 @@ proc main(){.async.} = debugLog "Found suggestions: ", suggestions[0..(if suggestions.len > 10: 10 else: suggestions.high)], (if suggestions.len > 10: " and " & $(suggestions.len-10) & " more" else: "") + var resp: JsonNode if suggestions.len == 0: - await message.respond newJNull() + resp = newJNull() else: var textEdits = newJObject() for suggestion in suggestions: @@ -394,10 +414,11 @@ proc main(){.async.} = ), renameRequest["newName"].getStr ).JsonNode - await message.respond create(WorkspaceEdit, + resp = create(WorkspaceEdit, some(textEdits), none(seq[TextDocumentEdit]) ).JsonNode + multisyncTask outs: outs.respond(message, resp) of "textDocument/definition": message.textDocumentRequest(TextDocumentPositionParams, definitionRequest): debugLog "Running equivalent of: def ", uriToPath(fileuri), ";", filestash, ":", @@ -410,19 +431,21 @@ proc main(){.async.} = debugLog "Found suggestions: ", declarations[0..(if declarations.len > 10: 10 else: declarations.high)], (if declarations.len > 10: " and " & $(declarations.len-10) & " more" else: "") + var resp: JsonNode if declarations.len == 0: - await message.respond newJNull() + resp = newJNull() else: - var response = newJarray() + resp = newJarray() for declaration in declarations: - response.add create(Location, + resp.add create(Location, "file://" & pathToUri(declaration.filepath), create(Range, create(Position, declaration.line-1, declaration.column), create(Position, declaration.line-1, declaration.column + declaration.qualifiedPath[^1].len) ) ).JsonNode - await message.respond response + multisyncTask outs: + outs.respond(message, resp) of "textDocument/documentSymbol": message.textDocumentRequest(DocumentSymbolParams, symbolRequest): debugLog "Running equivalent of: outline ", uriToPath(fileuri), ";", filestash @@ -430,14 +453,15 @@ proc main(){.async.} = debugLog "Found outlines: ", syms[0..(if syms.len > 10: 10 else: syms.high)], (if syms.len > 10: " and " & $(syms.len-10) & " more" else: "") + var resp: JsonNode if syms.len == 0: - await message.respond newJNull() + resp = newJNull() else: - var response = newJarray() + resp = newJarray() for sym in syms.sortedByIt((it.line,it.column,it.quality)): if sym.qualifiedPath.len != 2: continue - response.add create( + resp.add create( SymbolInformation, sym.name[], nimSymToLSPKind(sym.symKind).int, @@ -451,7 +475,8 @@ proc main(){.async.} = ), none(string) ).JsonNode - await message.respond response + multisyncTask outs: + outs.respond(message, resp) of "textDocument/signatureHelp": message.textDocumentRequest(TextDocumentPositionParams, sigHelpRequest): debugLog "Running equivalent of: con ", uriToPath(fileuri), ";", filestash, ":", @@ -468,15 +493,17 @@ proc main(){.async.} = documentation = some(suggestion.nimDocstring), parameters = none(seq[ParameterInformation]) ) - - await message.respond create(SignatureHelp, + let resp = create(SignatureHelp, signatures = signatures, activeSignature = some(0), activeParameter = some(0) ).JsonNode + multisyncTask outs: + outs.respond(message, resp) else: debugLog "Unknown request" - await message.error(errorCode = -32600, message = "Unknown request: " & frame, data = newJObject()) + multisyncTask outs: + outs.error(message, errorCode = -32600, message = "Unknown request: " & frame, data = newJObject()) continue whenValidStrict(message, NotificationMessage): debugLog "Got valid Notification message of type " & message["method"].getStr @@ -613,15 +640,14 @@ proc main(){.async.} = message, none(seq[DiagnosticRelatedInformation]) ) - - await notify( - "textDocument/publishDiagnostics", - create(PublishDiagnosticsParams, f, response).JsonNode - ) - await notify("textDocument/publishDiagnostics", create(PublishDiagnosticsParams, + let resp = create(PublishDiagnosticsParams, f, response).JsonNode + multisyncTask outs: + outs.notify("textDocument/publishDiagnostics", resp) + let resp = create(PublishDiagnosticsParams, fileuri, response).JsonNode - ) + multisyncTask outs: + outs.notify("textDocument/publishDiagnostics", resp) else: warnLog "Got unknown notification message" continue @@ -635,4 +661,13 @@ proc main(){.async.} = warnLog "Got exception: ", e.msg continue -waitFor main() +when defined(windows): + var + ins = newFileStream(stdin) + outs = newFileStream(stdout) + main(ins, outs) +else: + var + ins = newAsyncFile(stdin.getOsFileHandle().AsyncFD) + outs = newAsyncFile(stdout.getOsFileHandle().AsyncFD) + waitFor main(ins, outs) diff --git a/src/nimlsppkg/baseprotocol.nim b/src/nimlsppkg/baseprotocol.nim index 2d0db6b..a2cd38d 100644 --- a/src/nimlsppkg/baseprotocol.nim +++ b/src/nimlsppkg/baseprotocol.nim @@ -1,6 +1,8 @@ import strutils, parseutils, json import asyncfile, asyncdispatch import logger +import std/streams + type BaseProtocolError* = object of Defect @@ -12,23 +14,38 @@ proc skipWhitespace(x: string, pos: int): int = while result < x.len and x[result] in Whitespace: inc result -proc sendFrame*(s: AsyncFile, frame: string) {.async} = +proc sendFrame*(s: Stream | AsyncFile, frame: string) {.multisync} = when defined(debugCommunication): infoLog(frame) - await s.write "Content-Length: " & $frame.len & "\r\n\r\n" & frame + let content = "Content-Length: " & $frame.len & "\r\n\r\n" & frame + when s is Stream: + s.write content + s.flush + else: + await s.write content + +proc formFrame*( data: JsonNode): string = + var frame = newStringOfCap(1024) + toUgly(frame, data) + result = "Content-Length: " & $frame.len & "\r\n\r\n" & frame -proc sendJson*(s: AsyncFile, data: JsonNode) {.async.} = +proc sendJson*(s: Stream | AsyncFile, data: JsonNode) {.multisync.} = var frame = newStringOfCap(1024) toUgly(frame, data) - await s.sendFrame(frame) + when s is Stream: + s.sendFrame(frame) + else: + await s.sendFrame(frame) -proc readFrame*(s: AsyncFile): Future[string] {.async.} = +proc readFrame*(s: Stream | AsyncFile): Future[string] {.multisync.} = var contentLen = -1 var headerStarted = false - + var ln: string while true: - var ln = await s.readLine() - + when s is Stream: + ln = s.readLine() + else: + ln = await s.readLine() if ln.len != 0: headerStarted = true let sep = ln.find(':') @@ -52,11 +69,11 @@ proc readFrame*(s: AsyncFile): Future[string] {.async.} = continue else: if contentLen != -1: - var buf = newString(contentLen) - var i = 0 - while i < contentLen: - let r = await s.readBuffer(buf[i].addr, contentLen - i) - i += r + when s is Stream: + var buf = s.readStr(contentLen) + else: + var buf = newString(contentLen) + discard await s.readBuffer(buf[0].addr, contentLen) when defined(debugCommunication): infoLog(buf) return buf diff --git a/tests/tnimlsp.nim b/tests/tnimlsp.nim index 7354dee..a079c28 100644 --- a/tests/tnimlsp.nim +++ b/tests/tnimlsp.nim @@ -1,13 +1,13 @@ import unittest -import std/[asyncdispatch, asyncfile, os, osproc, options, json] +import std/[asyncdispatch, asyncfile, os, options, json, strutils] import .. / src / nimlsppkg / baseprotocol include .. / src / nimlsppkg / messages +import streams +import asynctools let nimlsp = parentDir(parentDir(currentSourcePath())) / "nimlsp" p = startProcess(nimlsp, options = {}) - i = newAsyncFile(p.inputHandle().AsyncFD) - o = newAsyncFile(p.outputHandle().AsyncFD) suite "Nim LSP basic operation": test "Nim LSP can be initialised": @@ -26,10 +26,12 @@ suite "Nim LSP basic operation": workspaceFolders = none(seq[WorkspaceFolder]) ).JsonNode) ).JsonNode - waitFor i.sendJson ir + var frame = newString(1024) + var d = formFrame(ir) + discard waitFor p.inputHandle().write(cast[pointer](d[0].addr), d.len) + let n = waitFor p.outputHandle().readInto(frame[0].addr, 1024) - var frame = o.readFrame - var message = parseJson waitFor frame + var message = parseJson frame.split("\r\n\r\n")[1] if message.isValid(ResponseMessage): var data = ResponseMessage(message) check data["id"].getInt == 0 From c6efee9e92494ddf45e91d00ed1dcfc4a89cfb16 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 23 May 2022 19:11:48 +0800 Subject: [PATCH 2/3] re-organize all imports --- src/config.nims | 2 +- src/nimlsp.nim | 11 +---------- src/nimlsppkg/baseprotocol.nim | 4 +--- src/nimlsppkg/logger.nim | 2 +- src/nimlsppkg/messages.nim | 6 ++---- src/nimlsppkg/suggestlib.nim | 2 +- src/nimlsppkg/utfmapping.nim | 2 +- tests/test_messages2.nim | 2 +- tests/tnimlsp.nim | 6 ++---- 9 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/config.nims b/src/config.nims index e06379f..ddff2a5 100644 --- a/src/config.nims +++ b/src/config.nims @@ -1,3 +1,3 @@ -import os +import std / [os] switch "path", getCurrentCompilerExe().parentDir.parentDir diff --git a/src/nimlsp.nim b/src/nimlsp.nim index 6a029b5..0ccf62d 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -1,15 +1,6 @@ +import std / [os, osproc, tables, sets, hashes, strutils, uri, algorithm, asyncfile, asyncdispatch, streams] import nimlsppkg / [baseprotocol, utfmapping, suggestlib, logger] include nimlsppkg / messages -import algorithm -import streams -import tables -import strutils -import os -import hashes -import sets -import uri -import osproc -import asyncfile, asyncdispatch const version = block: diff --git a/src/nimlsppkg/baseprotocol.nim b/src/nimlsppkg/baseprotocol.nim index a2cd38d..d2bb821 100644 --- a/src/nimlsppkg/baseprotocol.nim +++ b/src/nimlsppkg/baseprotocol.nim @@ -1,7 +1,5 @@ -import strutils, parseutils, json -import asyncfile, asyncdispatch +import std / [strutils, parseutils, json, asyncfile, asyncdispatch, streams] import logger -import std/streams type BaseProtocolError* = object of Defect diff --git a/src/nimlsppkg/logger.nim b/src/nimlsppkg/logger.nim index cf4be22..e8da6f7 100644 --- a/src/nimlsppkg/logger.nim +++ b/src/nimlsppkg/logger.nim @@ -1,4 +1,4 @@ -import os, logging +import std / [os, logging] const storage* = getTempDir() / "nimlsp" discard existsOrCreateDir(storage) diff --git a/src/nimlsppkg/messages.nim b/src/nimlsppkg/messages.nim index 83970d5..cfafbbb 100644 --- a/src/nimlsppkg/messages.nim +++ b/src/nimlsppkg/messages.nim @@ -1,9 +1,7 @@ +import std / [json, sequtils, options,] import messageenums # Anything below here comes from the LSP specification -import jsonschema -import json -import options -import sequtils +import pkg / jsonschema jsonSchema: diff --git a/src/nimlsppkg/suggestlib.nim b/src/nimlsppkg/suggestlib.nim index e9ae59e..8ce1997 100644 --- a/src/nimlsppkg/suggestlib.nim +++ b/src/nimlsppkg/suggestlib.nim @@ -1,4 +1,4 @@ -import macros, os +import std / [macros, os] const explicitSourcePath {.strdefine.} = getCurrentCompilerExe().parentDir.parentDir diff --git a/src/nimlsppkg/utfmapping.nim b/src/nimlsppkg/utfmapping.nim index a89cb0e..e59586b 100644 --- a/src/nimlsppkg/utfmapping.nim +++ b/src/nimlsppkg/utfmapping.nim @@ -1,4 +1,4 @@ -import unicode +import std / [unicode] type FingerTable = seq[tuple[u16pos, offset: int]] diff --git a/tests/test_messages2.nim b/tests/test_messages2.nim index ab12810..a1f1723 100644 --- a/tests/test_messages2.nim +++ b/tests/test_messages2.nim @@ -1,4 +1,4 @@ -import unittest +import std / [unittest] include nimlsppkg / messages #import packedjson diff --git a/tests/tnimlsp.nim b/tests/tnimlsp.nim index a079c28..5f4bd1b 100644 --- a/tests/tnimlsp.nim +++ b/tests/tnimlsp.nim @@ -1,9 +1,7 @@ -import unittest -import std/[asyncdispatch, asyncfile, os, options, json, strutils] +import std/[unittest, asyncdispatch, asyncfile, os, options, json, strutils, streams] import .. / src / nimlsppkg / baseprotocol include .. / src / nimlsppkg / messages -import streams -import asynctools +import pkg/asynctools let nimlsp = parentDir(parentDir(currentSourcePath())) / "nimlsp" From 9cda046012ff502f770b746b390f1fb73f6d4e18 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 23 May 2022 19:58:45 +0800 Subject: [PATCH 3/3] make multisyncTask beautiful --- src/nimlsp.nim | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/nimlsp.nim b/src/nimlsp.nim index 0ccf62d..3fe5914 100644 --- a/src/nimlsp.nim +++ b/src/nimlsp.nim @@ -122,23 +122,25 @@ proc parseId(node: JsonNode): int = else: raise newException(MalformedFrame, "Invalid id node: " & repr(node)) -template multisyncTask(outs: Stream | AsyncFile, body) = - when outs is Stream: - body - else: - await body +macro multisyncTask(body): untyped = + let arg = body[0][1] + result = quote do: + when `arg` is Stream: + `body` + else: + await `body` proc respond(outs: Stream | AsyncFile, request: RequestMessage, data: JsonNode) {.multisync.} = let resp = create(ResponseMessage, "2.0", parseId(request["id"]), some(data), none(ResponseError)).JsonNode - multisyncTask outs: outs.sendJson resp + multisyncTask: outs.sendJson resp proc error(outs: Stream | AsyncFile,request: RequestMessage, errorCode: int, message: string, data: JsonNode) {.multisync.} = let resp = create(ResponseMessage, "2.0", parseId(request["id"]), none(JsonNode), some(create(ResponseError, errorCode, message, data))).JsonNode - multisyncTask outs: outs.sendJson resp + multisyncTask: outs.sendJson resp proc notify(outs: Stream | AsyncFile,notification: string, data: JsonNode) {.multisync.} = let resp = create(NotificationMessage, "2.0", notification, some(data)).JsonNode - multisyncTask outs: outs.sendJson resp + multisyncTask: outs.sendJson resp type Certainty = enum None, @@ -205,21 +207,21 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = while true: try: debugLog "Trying to read frame" - let frame = when ins is Stream: ins.readFrame else: await ins.readFrame + let frame = multisyncTask: ins.readFrame debugLog "Got frame:" infoLog frame let message = frame.parseJson whenValidStrict(message, RequestMessage): debugLog "Got valid Request message of type " & message["method"].getStr if not initialized and message["method"].getStr != "initialize": - multisyncTask outs: + multisyncTask: outs.error(message, -32002, "Unable to accept requests before being initialized", newJNull()) continue case message["method"].getStr: of "shutdown": debugLog "Got shutdown request, answering" let resp = newJNull() - multisyncTask outs: + multisyncTask: outs.respond(message, resp) gotShutdown = true of "initialize": @@ -260,7 +262,7 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = workspace = none(WorkspaceCapability), #?: WorkspaceCapability experimental = none(JsonNode) #?: any )).JsonNode - multisyncTask outs: + multisyncTask: outs.respond(message,resp) of "textDocument/completion": message.textDocumentRequest(CompletionParams, compRequest): @@ -309,7 +311,7 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = command = none(Command), data = none(JsonNode) ).JsonNode - multisyncTask outs: + multisyncTask: outs.respond(message, completionItems) of "textDocument/hover": message.textDocumentRequest(TextDocumentPositionParams, hoverRequest): @@ -347,7 +349,7 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = ).JsonNode else: resp = create(Hover, markedString, rangeopt).JsonNode; - multisyncTask outs: + multisyncTask: outs.respond(message, resp) of "textDocument/references": message.textDocumentRequest(ReferenceParams, referenceRequest): @@ -372,10 +374,10 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = ) ).JsonNode if response.len == 0: - multisyncTask outs: + multisyncTask: outs.respond(message, newJNull()) else: - multisyncTask outs: + multisyncTask: outs.respond(message, response) of "textDocument/rename": @@ -409,7 +411,7 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = some(textEdits), none(seq[TextDocumentEdit]) ).JsonNode - multisyncTask outs: outs.respond(message, resp) + multisyncTask: outs.respond(message, resp) of "textDocument/definition": message.textDocumentRequest(TextDocumentPositionParams, definitionRequest): debugLog "Running equivalent of: def ", uriToPath(fileuri), ";", filestash, ":", @@ -435,7 +437,7 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = create(Position, declaration.line-1, declaration.column + declaration.qualifiedPath[^1].len) ) ).JsonNode - multisyncTask outs: + multisyncTask: outs.respond(message, resp) of "textDocument/documentSymbol": message.textDocumentRequest(DocumentSymbolParams, symbolRequest): @@ -466,7 +468,7 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = ), none(string) ).JsonNode - multisyncTask outs: + multisyncTask: outs.respond(message, resp) of "textDocument/signatureHelp": message.textDocumentRequest(TextDocumentPositionParams, sigHelpRequest): @@ -489,11 +491,11 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = activeSignature = some(0), activeParameter = some(0) ).JsonNode - multisyncTask outs: + multisyncTask: outs.respond(message, resp) else: debugLog "Unknown request" - multisyncTask outs: + multisyncTask: outs.error(message, errorCode = -32600, message = "Unknown request: " & frame, data = newJObject()) continue whenValidStrict(message, NotificationMessage): @@ -632,12 +634,12 @@ proc main(ins: Stream | AsyncFile, outs: Stream | AsyncFile) {.multisync.} = none(seq[DiagnosticRelatedInformation]) ) let resp = create(PublishDiagnosticsParams, f, response).JsonNode - multisyncTask outs: + multisyncTask: outs.notify("textDocument/publishDiagnostics", resp) let resp = create(PublishDiagnosticsParams, fileuri, response).JsonNode - multisyncTask outs: + multisyncTask: outs.notify("textDocument/publishDiagnostics", resp) else: warnLog "Got unknown notification message"