Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

+ added command line option --clientProcessId=XXX that allows the server to #151

Merged
merged 1 commit into from
Jan 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 48 additions & 6 deletions nimlangserver.nim
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ type
checkInProgress: bool
needsChecking: bool

CommandLineParams = object
clientProcessId: Option[int]

LanguageServer* = ref object
clientCapabilities*: ClientCapabilities
initializeParams*: InitializeParams
Expand All @@ -66,6 +69,7 @@ type
lastNimsuggest: Future[Nimsuggest]
isShutdown*: bool
storageDir*: string
cmdLineClientProcessId: Option[int]

Certainty = enum
None,
Expand Down Expand Up @@ -210,7 +214,16 @@ proc initialize(p: tuple[ls: LanguageServer, pipeInput: AsyncInputStream], param
let pid = params.processId.get
if pid.kind == JInt:
debug "Registering monitor for process ", pid=pid.num
hookAsyncProcMonitor(int(pid.num), onClientProcessExit)
var pidInt = int(pid.num)
if p.ls.cmdLineClientProcessId.isSome:
if p.ls.cmdLineClientProcessId.get == pidInt:
debug "Process ID already specified in command line, no need to register monitor again"
else:
debug "Warning! Client Process ID in initialize request differs from the one, specified in the command line. This means the client violates the LSP spec!"
debug "Will monitor both process IDs..."
hookAsyncProcMonitor(pidInt, onClientProcessExit)
else:
hookAsyncProcMonitor(pidInt, onClientProcessExit)
p.ls.initializeParams = params
p.ls.clientCapabilities = params.capabilities
result = InitializeResult(
Expand Down Expand Up @@ -1120,15 +1133,17 @@ proc didChangeConfiguration(ls: LanguageServer, conf: JsonNode):

proc registerHandlers*(connection: StreamConnection,
pipeInput: AsyncInputStream,
storageDir: string): LanguageServer =
storageDir: string,
cmdLineParams: CommandLineParams): LanguageServer =
let ls = LanguageServer(
connection: connection,
workspaceConfiguration: Future[JsonNode](),
projectFiles: initTable[string, Future[Nimsuggest]](),
cancelFutures: initTable[int, Future[void]](),
filesWithDiags: initHashSet[string](),
openFiles: initTable[string, FileInfo](),
storageDir: storageDir)
storageDir: storageDir,
cmdLineClientProcessId: cmdLineParams.clientProcessId)
result = ls

connection.register("initialize", partial(initialize, (ls: ls, pipeInput: pipeInput)))
Expand Down Expand Up @@ -1172,15 +1187,27 @@ when isMainModule:
return v.split("=")[^1].strip(chars = {' ', '"'})
return "unknown"

proc handleParams() =
proc handleParams(): CommandLineParams =
if paramCount() > 0 and paramStr(1) in ["-v", "--version"]:
const version = getVersionFromNimble()
echo version
quit()
var i = 1
while i <= paramCount():
var para = paramStr(i)
if para.startsWith("--clientProcessId="):
var pidStr = para.substr(18)
try:
var pid = pidStr.parseInt
result.clientProcessId = some(pid)
except ValueError:
stderr.writeLine("Invalid client process ID: ", pidStr)
quit 1
inc i

proc main =
try:
handleParams()
let cmdLineParams = handleParams()
let storageDir = ensureStorageDir()
var
pipe = createPipe(register = true, nonBlockingWrite = false)
Expand All @@ -1191,7 +1218,22 @@ when isMainModule:
let
connection = StreamConnection.new(Async(fileOutput(stdout, allowAsyncOps = true)))
pipeInput = asyncPipeInput(pipe)
ls = registerHandlers(connection, pipeInput, storageDir)
ls = registerHandlers(connection, pipeInput, storageDir, cmdLineParams)

if cmdLineParams.clientProcessId.isSome:
debug "Registering monitor for process id, specified on command line", clientProcessId=cmdLineParams.clientProcessId.get

proc onCmdLineClientProcessExitAsync(): Future[void] {.async.} =
debug "onCmdLineClientProcessExitAsync"
await ls.stopNimsuggestProcesses
pipeInput.close()

proc onCmdLineClientProcessExit(fd: AsyncFD): bool =
debug "onCmdLineClientProcessExit"
waitFor onCmdLineClientProcessExitAsync()
result = true

hookAsyncProcMonitor(cmdLineParams.clientProcessId.get, onCmdLineClientProcessExit)

waitFor connection.start(pipeInput)
debug "exiting main thread", isShutdown=ls.isShutdown
Expand Down
Loading