Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
fox0430 committed Oct 17, 2024
1 parent 48f3958 commit 09faf2a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 53 deletions.
16 changes: 12 additions & 4 deletions src/moepkg/lsp/client.nim
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ proc exit*(c: LspClient) {.inline.} =

discard c.serverProcess.terminate

proc kill*(c: LspClient): Result[(), string] =
## kill a LSP server process.

let r = c.serverProcess.kill
if r.isErr:
return Result[(), string].err $r.error

return Result[(), string].ok ()

template isInitialized*(c: LspClient): bool = c.capabilities.isSome

template addRequestLog*(c: var LspClient, m: JsonNode) =
Expand Down Expand Up @@ -238,7 +247,6 @@ proc readable*(c: LspClient, timeout: int = 1): LspClientReadableResult =
## Also, if data can be read from the output stream, return true.
## timeout is milliseconds.

# Check a server response.
const FdLen = 1
let r = c.pollFd.addr.poll(FdLen.Tnfds, timeout)
return LspClientReadableResult.ok r == 1
Expand Down Expand Up @@ -370,8 +378,8 @@ proc getForegroundWaitingResponse*(
if v.bufferId == bufferId and v.lspMethod.isForegroundWait:
return some(v)

proc getFdStdout(p: AsyncProcessRef): AsyncFD {.inline.} =
p.stdoutStream.tsource.fd
proc getFdStdout(p: AsyncProcessRef): cint {.inline.} =
p.stdoutStream.tsource.fd.cint

proc initLspClient*(command: string): initLspClientResult =
## Start a LSP server process and init streams.
Expand Down Expand Up @@ -405,7 +413,7 @@ proc initLspClient*(command: string): initLspClientResult =
c.pollFd.addr.zeroMem(sizeof(c.pollFd))

# Registers fd and events.
c.pollFd.fd = c.serverProcess.getFdStdout.cint
c.pollFd.fd = c.serverProcess.getFdStdout
c.pollFd.events = POLLIN or POLLERR

c.serverStreams = Streams(
Expand Down
92 changes: 43 additions & 49 deletions src/moepkg/lsp/jsonrpc.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[###################### GNU General Public License 3.0 ######################]#
# #
# Copyright (C) 2017─2023 Shuhei Nogawa #
# Copyright (C) 2017─2024 Shuhei Nogawa #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
Expand Down Expand Up @@ -46,6 +46,8 @@ type
input*: InputStream
output*: OutputStream

let Timeout = 10.milliseconds

proc skipWhitespace(x: string, pos: int): int =
result = pos
while result < x.len and x[result] in Whitespace:
Expand All @@ -71,71 +73,63 @@ proc debugLog(messageType: MessageType, message: string) =
proc readFrame(s: AsyncStreamReader): ReadFrameResult =
## Read text from the stream and return json node.

var
contentLen = -1
headerStarted = false

while true:
let ln =
let buf =
try:
let
f = s.readLine(sep="\n")
r = waitFor f.withTimeout(10.milliseconds)
if not r:
""
let f = s.readLine(sep="\n")
if waitFor f.withTimeout(Timeout):
f.value
else:
var ln = f.value
ln.removeSuffix("\r")
ln
return ReadFrameResult.err fmt"readLine: timeout"
except CatchableError as e:
return ReadFrameResult.err fmt"readLine failed: {e.msg}"

if ln.len == 0:
return ReadFrameResult.err fmt"readLine: timeout"
if buf.len == 0:
return ReadFrameResult.err fmt"readLine: empty"

debugLog(MessageType.read, fmt"readLine: {buf}")

debugLog(MessageType.read, fmt"readLine: {ln}")
var header: Option[tuple[ln: string, sep: int]]
for ln in buf.splitLines:
if ln.startsWith("Content-"):
let sep = ln.find(':')
if sep > -1:
header = some((ln, sep))
break

let sep = ln.find(':')
if sep == -1:
if header.isNone:
# Skip line if not JSON-RPC.
continue

headerStarted = true
let valueStart = header.get.ln.skipWhitespace(header.get.sep + 1)

let valueStart = ln.skipWhitespace(sep + 1)

case ln[0 ..< sep]
var contentLen = -1
case header.get.ln[0 ..< header.get.sep]
of "Content-Type":
if isInvalidContentType(ln, valueStart):
if isInvalidContentType(header.get.ln, valueStart):
return ReadFrameResult.err "Only utf-8 is supported"
of "Content-Length":
if parseInt(ln, contentLen, valueStart) == 0:
return ReadFrameResult.err fmt"Invalid Content-Length: {ln.substr(valueStart)}"
if parseInt(header.get.ln, contentLen, valueStart) == 0:
return
ReadFrameResult.err fmt"Invalid Content-Length: {header.get.ln.substr(valueStart)}"
else:
# Unrecognized headers are ignored
discard

if not headerStarted:
continue
else:
if contentLen != -1:
let bytes =
try:
block removeCr:
let f = s.read(1)
discard waitFor f.withTimeout(10.milliseconds)
let
f = s.read(contentLen + 1)
r = waitFor f.withTimeout(10.milliseconds)
if not r: @[]
else: f.value
except:
continue

if contentLen != -1:
let buf=
try:
let f = s.read(contentLen + 1)
if waitFor f.withTimeout(Timeout):
string.fromBytes(f.value)
else:
return ReadFrameResult.err fmt"readStr failed"
let str = string.fromBytes(bytes)
debugLog(MessageType.read, fmt"Response: {str}")
return ReadFrameResult.ok str
else:
return ReadFrameResult.err "Missing Content-Length header"
except:
return ReadFrameResult.err fmt"readStr failed"
debugLog(MessageType.read, fmt"Response: {buf}")
return ReadFrameResult.ok buf
else:
return ReadFrameResult.err "Missing Content-Length header"

proc read*(s: AsyncStreamReader): JsonRpcResponseResult =
## Return a json-rpc response from the stream.
Expand Down Expand Up @@ -165,7 +159,7 @@ proc send(
debugLog(MessageType.write, req)

try:
if not waitFor s.write(req).withTimeout(100.milliseconds):
if not waitFor s.write(req).withTimeout(Timeout):
return Result[(), string].err "write: Timeout"
except CatchableError as e:
return Result[(), string].err e.msg
Expand Down

0 comments on commit 09faf2a

Please sign in to comment.