Skip to content
Open
Show file tree
Hide file tree
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
18 changes: 13 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Setup Nimble
uses: nim-lang/setup-nimble-action@v1
with:
nimble-version: "latest"
nimble-version: "nightly"
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Restore nimble dependencies from cache
Expand All @@ -35,10 +35,18 @@ jobs:
restore-keys: |
${{ runner.os }}-${{ env.cache_nonce }}-

- name: Install dependencies
shell: bash
run: nimble -y install -l

- name: Nimble Test
shell: bash
run: nimble test

nph:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Check `nph` formatting
uses: arnetheduck/nph-action@v1
with:
version: 0.6.2
options: "*.nim protocol"
fail: true
suggest: true
2 changes: 1 addition & 1 deletion asyncprocmonitor.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ when defined(posix):
import posix_utils
import posix

type Callback* = proc() {.closure, gcsafe, raises: [].}
type Callback* = proc() {.gcsafe, raises: [].}

when defined(windows):
import winlean, sugar
Expand Down
50 changes: 30 additions & 20 deletions ls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import
chronos/asyncproc,
stew/byteutils

chronicles.formatIt(JsonNode):
$it

proc getVersionFromNimble(): string =
#We should static run nimble dump instead
const content = staticRead("nimlangserver.nimble")
Expand Down Expand Up @@ -160,7 +163,8 @@ type
nimDumpCache*: Table[string, NimbleDumpInfo] #path to NimbleDumpInfo
entryPoints*: seq[string]
responseMap*: TableRef[string, Future[JsonNode]]
testRunProcess*: Option[AsyncProcessRef] #There is only one test run process at a time
testRunProcess*: Option[AsyncProcessRef]
#There is only one test run process at a time

#id to future. Represents the pending requests as result of calling ls.call
srv*: RpcSocketServer
Expand All @@ -178,7 +182,7 @@ type
failTable*: Table[string, int]
#Project file to fail count
#List of errors (crashes) nimsuggest has had since the lsp session started
checkInProgress*: bool
checkInProgress*: bool

Certainty* = enum
None
Expand Down Expand Up @@ -256,7 +260,9 @@ proc supportSignatureHelp*(cc: ClientCapabilities): bool =
let caps = cc.textDocument
caps.isSome and caps.get.signatureHelp.isSome

proc getNimbleDumpInfo*(ls: LanguageServer, nimbleFile: string): Future[NimbleDumpInfo] {.async.}=
proc getNimbleDumpInfo*(
ls: LanguageServer, nimbleFile: string
): Future[NimbleDumpInfo] {.async.} =
if nimbleFile in ls.nimDumpCache:
return ls.nimDumpCache.getOrDefault(nimbleFile)
var process: AsyncProcessRef
Expand Down Expand Up @@ -290,10 +296,9 @@ proc getNimbleDumpInfo*(ls: LanguageServer, nimbleFile: string): Future[NimbleDu
ls.nimDumpCache[nimbleFile] = result
except OSError, IOError:
debug "Failed to get nimble dump info", nimbleFile = nimbleFile
finally:
finally:
await shutdownChildProcess(process)


proc parseWorkspaceConfiguration*(conf: JsonNode): NlsConfig =
try:
if conf.kind == JObject and conf["settings"].kind == JObject:
Expand Down Expand Up @@ -487,7 +492,7 @@ proc getNimVersion(nimDir: string): string =

proc getNimSuggestPathAndVersion(
ls: LanguageServer, conf: NlsConfig, workingDir: string
): Future[(string, string)] {.async.}=
): Future[(string, string)] {.async.} =
#Attempting to see if the project is using a custom Nim version, if it's the case this will be slower than usual
let nimbleDumpInfo = await ls.getNimbleDumpInfo("")
let nimDir = nimbleDumpInfo.nimDir.get ""
Expand Down Expand Up @@ -518,7 +523,9 @@ proc getNimPath*(conf: NlsConfig): Option[string] =
warn "Failed to find nim path"
none(string)

proc getProjectFileAutoGuess*(ls: LanguageServer, fileUri: string): Future[string] {.async.}=
proc getProjectFileAutoGuess*(
ls: LanguageServer, fileUri: string
): Future[string] {.async.} =
let file = fileUri.decodeUrl
debug "Auto-guessing project file for", file = file
result = file
Expand Down Expand Up @@ -742,7 +749,7 @@ proc sendDiagnostics*(

proc warnIfUnknown*(
ls: LanguageServer, ns: Nimsuggest, uri: string, projectFile: string
): Future[void] {.async, gcsafe.} =
): Future[void] {.async.} =
let path = uri.uriToPath
let isFileKnown = await ns.isKnown(path)
if not isFileKnown and not ns.canHandleUnknown:
Expand Down Expand Up @@ -799,7 +806,7 @@ proc tryGetNimsuggest*(

proc checkFile*(ls: LanguageServer, uri: string): Future[void] {.raises: [], gcsafe.}

proc didCloseFile*(ls: LanguageServer, uri: string): Future[void] {.async, gcsafe.} =
proc didCloseFile*(ls: LanguageServer, uri: string): Future[void] {.async.} =
debug "Closed the following document:", uri = uri

if ls.openFiles[uri].changed:
Expand All @@ -808,9 +815,7 @@ proc didCloseFile*(ls: LanguageServer, uri: string): Future[void] {.async, gcsaf

ls.openFiles.del uri

proc makeIdleFile*(
ls: LanguageServer, file: NlsFileInfo
): Future[void] {.async, gcsafe.} =
proc makeIdleFile*(ls: LanguageServer, file: NlsFileInfo): Future[void] {.async.} =
let uri = file.textDocument.uri
if uri in ls.openFiles:
await ls.didCloseFile(uri)
Expand All @@ -819,11 +824,11 @@ proc makeIdleFile*(

proc getProjectFile*(
fileUri: string, ls: LanguageServer
): Future[string] {.raises: [], gcsafe.}
): Future[string] {.gcsafe, raises: [].}

proc didOpenFile*(
ls: LanguageServer, textDocument: TextDocumentItem
): Future[void] {.async, gcsafe.} =
): Future[void] {.async.} =
with textDocument:
debug "New document opened for URI:", uri = uri
let
Expand Down Expand Up @@ -891,11 +896,12 @@ proc tryGetNimsuggest*(
debug "Nimsuggest not found after retries", uri = uri
return none(NimSuggest)

proc checkProject*(ls: LanguageServer, uri: string): Future[void] {.async, gcsafe.} =
proc checkProject*(ls: LanguageServer, uri: string): Future[void] {.async.} =
if ls.checkInProgress:
return
ls.checkInProgress = true
defer: ls.checkInProgress = false
defer:
ls.checkInProgress = false

if not ls.getWorkspaceConfiguration.await().autoCheckProject.get(true):
return
Expand Down Expand Up @@ -950,7 +956,7 @@ proc checkProject*(ls: LanguageServer, uri: string): Future[void] {.async, gcsaf
ls.workDoneProgressCreate(token)
ls.progress(token, "begin", fmt "Checking project {uri.uriToPath}")
nimsuggest.checkProjectInProgress = true
defer:
defer:
nimsuggest.checkProjectInProgress = false
ls.progress(token, "end")

Expand Down Expand Up @@ -1021,7 +1027,8 @@ proc createOrRestartNimsuggest*(
let
configuration = ls.getWorkspaceConfiguration().waitFor()
workingDir = ls.getWorkingDir(projectFile).waitFor()
(nimsuggestPath, version) = ls.getNimSuggestPathAndVersion(configuration, workingDir).waitFor()
(nimsuggestPath, version) =
ls.getNimSuggestPathAndVersion(configuration, workingDir).waitFor()
timeout = configuration.timeout.get(REQUEST_TIMEOUT)
restartCallback = proc(ns: Nimsuggest) {.gcsafe, raises: [].} =
warn "Restarting the server due to requests being to slow",
Expand Down Expand Up @@ -1089,7 +1096,9 @@ proc maybeRegisterCapabilityDidChangeConfiguration*(ls: LanguageServer) =
)
ls.didChangeConfigurationRegistrationRequest =
ls.call("client/registerCapability", %registrationParams)
ls.didChangeConfigurationRegistrationRequest.addCallback do(res: Future[JsonNode]):
ls.didChangeConfigurationRegistrationRequest.addCallback do(res: Future[JsonNode]) {.
gcsafe
.}:
debug "Got response for the didChangeConfiguration registration:",
res = res.read()

Expand Down Expand Up @@ -1184,7 +1193,8 @@ proc getProjectFile*(fileUri: string, ls: LanguageServer): Future[string] {.asyn
let shouldSpawn = await ls.shouldSpawnNimsuggest()
if not shouldSpawn:
result = ls.projectFiles.keys.toSeq[0]
debug "Reached the maximum instances of nimsuggest, reusing the first nimsuggest instance", project = result
debug "Reached the maximum instances of nimsuggest, reusing the first nimsuggest instance",
project = result
return result

result = await ls.getProjectFileAutoGuess(fileUri)
Expand Down
1 change: 1 addition & 0 deletions lstransports.nim
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ proc startSocketServer*(ls: LanguageServer, port: Port) =
return
while ls.socketTransport.isNil:
await sleepAsync(0)

debug "Waiting for socket server to be ready"
waitFor waitUntilSocketTransportIsReady(ls)
debug "Socket server started"
5 changes: 1 addition & 4 deletions nim.cfg
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
--threads:on
--define:"async_backend=asyncdispatch"
--define:"chronicles_default_output_device=stderr"
--define:"chronicles_colors=None"
--define:"chronicles_disable_thread_id"
--define:"chronicles_thread_ids=no"
--define:"debugLogging"
#--define:"chronicles_log_level=TRACE"
--define:"chronicles_log_level=DEBUG"
--define:"chronicles_timestamps=None"
--define:"asyncBackend=none"
--warning[deprecated]:off

#--define:"chronicles_sinks=textlines[file]"
Loading
Loading