nim-lang / langserver

The Nim language server implementation (based on nimsuggest)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Windows: Failed to parse the configuration

veksha opened this issue · comments

i get error: DBG Failed to parse the configuration.

DBG Router: dispatching                        method=initialize id=0
DBG Initialize received...                    
DBG Router: sending response                   method=initialize id=0
DBG Router: dispatching                        method=initialized id=null
DBG Client initialized.                       
DBG Requesting configuration from the client  
DBG Router: dispatching                        method=workspace/didChangeConfiguration id=null
DBG Changed configuration:                     conf="{\"settings\":{\"nim\":{\"autoRestart\":true,\"projectMapping\":[{\"projectFile\":\"file.nim\",\"fileRegex\":\".*\\\\.nim\"}]}}}"
DBG Router: dispatching                        method=textDocument/didOpen id=null
DBG New document opened for URI:               uri=file:///C:/file.nim
DBG Failed to parse the configuration.        

investigated this in code:
there is a collision between workspace/didChangeConfiguration and workspace/configuration
they are handled with a common Future: ls.workspaceConfiguration

LSP clients send "didChangeConfiguration" notification just after "initialized" notification.
and after that "didOpen", so server requests configuration via "workspace/configuration" on this step.

so ls.workspaceConfiguration Future may still have .finished == false.

proc didChangeConfiguration(ls: LanguageServer, conf: JsonNode):
Future[void] {.async, gcsafe.} =
debug "Changed configuration: ", conf = conf
ls.workspaceConfiguration = newFuture[JsonNode]()
ls.workspaceConfiguration.complete(conf)

here i made this change:

-  ls.workspaceConfiguration = newFuture[JsonNode]()
-  ls.workspaceConfiguration.complete(conf)
+  if ls.workspaceConfiguration.finished:
+    ls.workspaceConfiguration = newFuture[JsonNode]()
+    ls.workspaceConfiguration.complete(conf)

just added check. and now finally i can see nimlangserver working.

bug reproduces on Windows, not on Linux.

I can reproduce the error on Ubuntu 20.04 using the following configuration in Spacemacs (Emacs 30.0.50) while using LSP-Mode:

(setq lsp-nim-project-mapping  [(:projectPath "main.nim" :fileRegex ".*\\.nim")])

Error message is the following:

DBG Received the following configuration       configuration="[{\"projectMapping\":[{\"projectPath\":\"main.nim\",\"fileRegex\":\".*\\\\.nim\"}],\"timeout\":120000,\"nimsuggestPath\":\"nimsuggest\",\"autoCheckFile\":true,\"autoCheckProject\":true}]"
DBG Failed to parse the configuration.        
DBG Failed to parse the configuration.        

on Windows the server is shutting down after that. on linux i have no such problem.

how i debugged the issue - i just commented out try-except in getWorkspaceConfiguration proc and got detailed information about this exception:

DBG Error occurred within RPC                  methodName=textDocument/didOpen err="Incorrect JSON kind. Wanted \'{JArray}\' in \'\' but got \'JObject\'.\nAsync traceback:\n  D:\\Programm\\Nim\\langserver\\nimlangserver.nim(1025) nimlangserver\n  D:\\Programm\\Nim\\langserver\\nimlangserver.nim(1018) main\n  D:\\Programm\\Nim\\Nim-devel\\lib\\pure\\asyncdispatch.nim(2022) waitFor\n  D:\\Programm\\Nim\\Nim-devel\\lib\\pure\\asyncdispatch.nim(1711) poll\n  D:\\Programm\\Nim\\Nim-devel\\lib\\pure\\asyncdispatch.nim(456) runOnce\n  D:\\Programm\\Nim\\Nim-devel\\lib\\system\\threadimpl.nim(269) processPendingCallbacks\n  C:\\Users\\yura\\.nimble\\pkgs\\json_rpc-#notif-changes\\json_rpc\\streamconnection.nim(141) start (Async)\n  C:\\Users\\yura\\.nimble\\pkgs\\json_rpc-#notif-changes\\json_rpc\\server.nim(32) route\n  C:\\Users\\yura\\.nimble\\pkgs\\json_rpc-#notif-changes\\json_rpc\\router.nim(121) route (Async)\n  D:\\Programm\\Nim\\Nim-devel\\lib\\system.nim(919) route (Async)\n  D:\\Programm\\Nim\\Nim-devel\\lib\\pure\\asyncmacro.nim(293) :anonymous\n  C:\\Users\\yura\\.nimble\\pkgs\\json_rpc-#notif-changes\\json_rpc\\streamconnection.nim(52) anonymous (Async)\n  D:\\Programm\\Nim\\langserver\\nimlangserver.nim(68) :anonymous\n  D:\\Programm\\Nim\\langserver\\nimlangserver.nim(495) didOpen (Async)\n  D:\\Programm\\Nim\\langserver\\nimlangserver.nim(125) getProjectFile (Async)\n  D:\\Programm\\Nim\\langserver\\nimlangserver.nim(115) getWorkspaceConfiguration (Async)\n  D:\\Programm\\Nim\\Nim-devel\\lib\\pure\\json.nim(1366) to\n  D:\\Programm\\Nim\\Nim-devel\\lib\\pure\\json.nim(1068) initFromJson\nException message: Incorrect JSON kind. Wanted \'{JArray}\' in \'\' but got \'JObject\'.\n"
Traceback (most recent call last)
D:\Programm\Nim\langserver\nimlangserver.nim(1025) nimlangserver
D:\Programm\Nim\langserver\nimlangserver.nim(1018) main
D:\Programm\Nim\Nim-devel\lib\pure\asyncdispatch.nim(2022) waitFor
D:\Programm\Nim\Nim-devel\lib\pure\asyncdispatch.nim(1711) poll
D:\Programm\Nim\Nim-devel\lib\pure\asyncdispatch.nim(456) runOnce
D:\Programm\Nim\Nim-devel\lib\system\threadimpl.nim(269) processPendingCallbacks
C:\Users\yura\.nimble\pkgs\json_rpc-#notif-changes\json_rpc\streamconnection.nim(141) start (Async)
C:\Users\yura\.nimble\pkgs\json_rpc-#notif-changes\json_rpc\server.nim(32) route
C:\Users\yura\.nimble\pkgs\json_rpc-#notif-changes\json_rpc\router.nim(121) route (Async)
C:\Users\yura\.nimble\pkgs\json_rpc-#notif-changes\json_rpc\router.nim(107) route (Async)
C:\Users\yura\.nimble\pkgs\json_rpc-#notif-changes\json_rpc\router.nim(64) wrapError
D:\Programm\Nim\Nim-devel\lib\pure\json.nim(826) $
D:\Programm\Nim\Nim-devel\lib\pure\json.nim(512) len
SIGSEGV: Illegal storage access. (Attempt to read from nil?)

I fixed my error: projectPath should instead be projectFile. The documentation is wrong here.
But how can I get the language server to treat a separate module in the same folder as the main project file as belonging to that project?
I have the following project structure:

projfolder/
-- proj.nimble
-- tests/
---- config.nims
---- test1.nim
-- proj/
---- proj.nim
---- otherfile.nim

Every time I open otherfile.nim the language server complains about either importing the module in proj.nim or configuring nim.projectMapping. But how?
I set nim.projectMapping to:

[{"projectFile": "proj/proj.nim", "fileRegex": "proj/.*\\.nim"}]

this is working for me on Windows. try to replace \\\\ with / if you are on Linux and try:

{
    "nim.projectMapping": [
      {
        "projectFile": "proj/proj.nim",
        "fileRegex": "proj\\\\(?!otherfile).*\\.nim"
      },
      {
        "projectFile": "proj/otherfile.nim",
        "fileRegex": "proj\\\\.*\\.nim"
      }
    ]
}
  1. (?!otherfile) is needed. but i think langserver should skip it for the 1st projectFile, because it is present in then second projectFile
  2. on windows it is needed to put \\\\ instead of / in fileRegex value. maybe this could be improved, (to use only /)
    and pathRelativeToRoot var should be then normalized to Unix path separator before regex search: pathRelativeToRoot = pathRelativeToRoot.replace("\\", "/") in getProjectFile procedure.

Thanks @veksha! This made it work for me. Now I just need to figure out how to apply this configuration using .dir-locals.el so I don't have to add a configuration for every one of my projects in my global Emacs config.

Fix applied. Thanks, @veksha for the fix! README also updated with the correct configuration key (projectFile, not projectPath).