godotengine / emacs-gdscript-mode

An Emacs package to get GDScript support and syntax highlighting.
GNU General Public License v3.0
308 stars 35 forks source link

GDScript eglot connects but times out. #137

Open bbbscarter opened 1 year ago

bbbscarter commented 1 year ago

Using emacs 29.1 and Godot 4.1 on MacOS, configured to use port 6008.

eglot connects to the Godot instance, but doesn't do anything - and then times-out after 30 seconds. By contrast, lsp-mode connects and continues working, albeit with a warning: "Unknown notification: gdscript/capabilities"

eglot-stderr-buffer shows nothing, with "No current JSON-RPC connection".

eglot-events-buffer shows the following after connecting:

----------b---y---e---b---y---e---------- [internal] Thu Sep 14 12:02:33 2023: (:message "Running language server: localhost:6008") [client-request] (id:1) Thu Sep 14 12:02:33 2023: (:jsonrpc "2.0" :id 1 :method "initialize" :params (:processId nil :rootPath "/Users/scarter/dev/godot-project/" :rootUri "file:///Users/scarter/dev/godot-project" :initializationOptions #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8125 data ()) :capabilities (:workspace (:applyEdit t :executeCommand (:dynamicRegistration :json-false) :workspaceEdit (:documentChanges t) :didChangeWatchedFiles (:dynamicRegistration t) :symbol (:dynamicRegistration :json-false) :configuration t :workspaceFolders t) :textDocument (:synchronization (:dynamicRegistration :json-false :willSave t :willSaveWaitUntil t :didSave t) :completion (:dynamicRegistration :json-false :completionItem (:snippetSupport :json-false :deprecatedSupport t :resolveSupport (:properties ["documentation" "details" "additionalTextEdits"]) :tagSupport (:valueSet [1])) :contextSupport t) :hover (:dynamicRegistration :json-false :contentFormat ["markdown" "plaintext"]) :signatureHelp (:dynamicRegistration :json-false :signatureInformation (:parameterInformation (:labelOffsetSupport t) :activeParameterSupport t)) :references (:dynamicRegistration :json-false) :definition (:dynamicRegistration :json-false :linkSupport t) :declaration (:dynamicRegistration :json-false :linkSupport t) :implementation (:dynamicRegistration :json-false :linkSupport t) :typeDefinition (:dynamicRegistration :json-false :linkSupport t) :documentSymbol (:dynamicRegistration :json-false :hierarchicalDocumentSymbolSupport t :symbolKind (:valueSet [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26])) :documentHighlight (:dynamicRegistration :json-false) :codeAction (:dynamicRegistration :json-false :codeActionLiteralSupport (:codeActionKind (:valueSet ["quickfix" "refactor" "refactor.extract" "refactor.inline" "refactor.rewrite" "source" "source.organizeImports"])) :isPreferredSupport t) :formatting (:dynamicRegistration :json-false) :rangeFormatting (:dynamicRegistration :json-false) :rename (:dynamicRegistration :json-false) :inlayHint (:dynamicRegistration :json-false) :publishDiagnostics (:relatedInformation :json-false :codeDescriptionSupport :json-false :tagSupport (:valueSet [1 2]))) :window (:workDoneProgress t) :general (:positionEncodings ["utf-32" "utf-8" "utf-16"]) :experimental #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8125 data ())) :workspaceFolders [(:uri "file:///Users/scarter/dev/godot-project" :name "~/dev/godot-project/")]))

jcs090218 commented 1 year ago

It looks strange. I'm going to ping who originally implemented this feature.

cc @RuijieYu @xiliuya

RuijieYu commented 1 year ago

Since Emacs has figured out the 6008 port, it seems that the function I added has finished successfully. Can you use something like netstat (not sure if Mac has this program or any alternatives to it) to verify that Emacs indeed makes a connection to port 6008?

Other than that, I have no clue -- I only based my work on mailing list discussions and my reading of some Emacs documentation, and don't have much experience in the internals of eglot.

xiliuya commented 1 year ago

~~Hello, @bbbscarter The automatic eglot configuration in the current version has not been tested on Macos, You can check ~/.config/godot/editor_settings-4.tres exists. If not exists , to find editor_settings-4.tres in what directories, and then we can fix this program.~~

xiliuya commented 1 year ago

Using emacs 29.1 and Godot 4.1 on MacOS, configured to use port 6008.

eglot connects to the Godot instance, but doesn't do anything - and then times-out after 30 seconds. By contrast, lsp-mode connects and continues working, albeit with a warning: "Unknown notification: gdscript/capabilities"

eglot-stderr-buffer shows nothing, with "No current JSON-RPC connection".

@bbbscarter Can you disable lsp-mode and shutdown lsp-mode's connection. Then test eglot ? Or you can just use eglot.

bbbscarter commented 1 year ago

Yup, to confirm on both these points:

I'm not particularly familiar with debugging lsp servers in general, or eglot specifically - but if someone can tell me where to start I'm happy to give it a go!

xiliuya commented 1 year ago

@bbbscarter You can debug LSP relevant .

bbbscarter commented 1 year ago

Okay - done that, and attached the results. The main obvious difference is that the initialisation payload is very different between LSP and eglot, but not sure if that's relevant.

I've pulled out the relevant JSON sections below.

eglot.txt lsp.txt

wireshark.zip

xiliuya commented 1 year ago

@bbbscarter I think this is because the last request package did not send content in json-rpc format. Please confirm if the eglot version is too low, and then you can send an error report to report-emacs-bug On my machine, the following compiled versions are available.

In GNU Emacs 29.1.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.24.38, cairo version 1.17.8) of 2023-07-31 built on xiliuya-pc
Repository revision: 525d05c1b8ac54a4f7ad166b97f2fa913f80e73c
Repository branch: makepkg
System Description: Arch Linux
xiliuya commented 1 year ago

@bbbscarter To debug eglot , you can edebug-defun eglot--connect, in the following areas:

                    :success-fn
                      (eglot--lambda ((InitializeResult) capabilities serverInfo)
                        (unless canceled
                          (push server
                                (gethash project eglot--servers-by-project))
                          (setf (eglot--capabilities server) capabilities)
                          (setf (eglot--server-info server) serverInfo)
                          (jsonrpc-notify server :initialized eglot--{})
bbbscarter commented 1 year ago

I was running the version that comes with emacs 29.1 - 1.12.29.

I've just upgraded eglot to 1.15 and I'm getting the same behaviour.

I will see if I get anywhere with edebug.

bbbscarter commented 1 year ago

Tried both edebug, and adding logging messages to eglot--connect - neither the succed-fn nor the error-fn callbacks are being called, only the timeout-fn.

(I also checked that they are being called in other eglot connections, such as csharp, and they are).

xiliuya commented 1 year ago

@bbbscarter You can tracking stack information timeout-fn(edebug-mode key 'd'). And based on your packet capture information, for some reason, the 'initialized' packet that eglot should have sent was not generated correctly on your machine.

(:jsonrpc "2.0" :method "initialized"

This may be the problem, I think you should provide bug reports to emacs maill list.

xiliuya commented 1 year ago

I think maybe this code has problem:

(with-eval-after-load 'eglot
  (defvar eglot-server-programs)
  (push (cons 'gdscript-mode #'gdscript-eglot-contact)
        eglot-server-programs))

Can you test to eval:


(setq eglot-server-programs (list (cons 'gdscript-mode  #'gdscript-eglot-contact)))

Then try again.

bbbscarter commented 1 year ago

Since gdscript-eglot-contact doesn't work for me, in order to connect I'm already setting that list directly (in my case to ("localhost" 6008). As it is, I think the existing line should work - push will put it at the front of the list, which in an alist will override later entries.

In any case, I think you're correct - this looks like it's either an eglot problem, or a Godot problem. I'll fire something over to the emacs lists.

Thanks!

Simon

kkkykin commented 1 month ago

I'm facing this issue on windows.

Fix by advice jsonrpc--process-filter:

(with-eval-after-load 'eglot
  (define-advice jsonrpc--process-filter (:filter-args (args) fix-newline)
    "gdscript eglot."
    (when (string-match-p "\\` \\*EGLOT (.+/.*gdscript-.+) output\\*\\'"
                          (buffer-name (process-buffer (car args))))
      (setcdr args (list (string-replace "\n\n" "\r\n\r\n" (cadr args)))))
    args))

Because jsonrpc--process-filter not find Content-Length via the regexp "\\(?:.*: .*\r\n\\)*Content-Length: \ *\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"

jsonrpc.el version: 1.0.25 godot version: 4.3

I'm not sure it can help you.

-- Sorry for my poor english.

bbbscarter commented 1 month ago

Thanks @kkkykin!

I should say, within the last few months Eglot started working for me reliably.

I'm not sure if this is from an update in Emacs/Eglot, or because I've recently added the following to my eglot config for performance reasons, which also happens to remove a bunch of messages:

  (eglot-events-buffer-size 0)
  (eglot-ignored-server-capabilities '(:inlayHintProvider :documentOnTypeFormattingProvider))
kkkykin commented 1 month ago

Good news, but it not work for me. :sob: