jeapostrophe / racket-langserver

Other
262 stars 24 forks source link

Exception when formatting ("textDocument/formatting") #126

Closed adrianchong518 closed 11 months ago

adrianchong518 commented 11 months ago

I have set up racket-langserver with neovim via nvim-lspconfig.

When I try to format code via :lua vim.lsp.buf.format(), the code is not formatted and a "method not found" exception can be seen in the logs.

Here is the complete log (:LspLog):

[ERROR][2023-10-18 14:05:12] .../vim/lsp/rpc.lua:734    "rpc"   "/opt/homebrew/bin/racket"  "stderr"    "Caught exn in request "
[ERROR][2023-10-18 14:05:12] .../vim/lsp/rpc.lua:734    "rpc"   "/opt/homebrew/bin/racket"  "stderr"    '"textDocument/formatting"\nsend: no such method\n  method name: position-paragraph\n  class name: lsp-editor%\n  context...:\n   /Applications/Racket v8.10/collects/racket/private/class-internal.rkt:4728:0: obj-error\n   /Applications/Racket v8.10/share/pkgs/gui-lib/scribble/private/indentation.rkt:408:0: determine-spaces\n   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/doc.rkt:268:2\n   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/doc.rkt:302:0: indent-line!\n   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/doc.rkt:237:6: loop\n   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/text-document.rkt:426:0: formatting!\n   /Applications/Racket v8.10/collects/racket/contract/private/arrow-val-first.rkt:486:18\n   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/methods.rkt:26:0: process-message\n   /Applications/Racket v8.10/collects/racket/contract/private/arrow-val-first.rkt:486:18\n   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/main.rkt:60:2: consume\n\n'

And a formatted version:

"textDocument/formatting"
send: no such method
  method name: position-paragraph
  class name: lsp-editor%
  context...:
   /Applications/Racket v8.10/collects/racket/private/class-internal.rkt:4728:0: obj-error
   /Applications/Racket v8.10/share/pkgs/gui-lib/scribble/private/indentation.rkt:408:0: determine-spaces
   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/doc.rkt:268:2
   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/doc.rkt:302:0: indent-line!
   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/doc.rkt:237:6: loop
   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/text-document.rkt:426:0: formatting!
   /Applications/Racket v8.10/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/methods.rkt:26:0: process-message
   /Applications/Racket v8.10/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /Users/<user>/Library/Racket/8.10/pkgs/racket-langserver/main.rkt:60:2: consume

After a brief look at the relevant code, I assume that the position-paragraph method should be called on a racket:text% object, but somehow an lsp-editor% is used. I believe that there are some issues with how the indenter passed into indent-line! works.

However, my limited experience with Racket (as I'm still starting out) prevented me to dive deeper into how the whole thing works. Some help is greatly appreciated!

6cdh commented 11 months ago

The error might come from here: https://github.com/jeapostrophe/racket-langserver/blob/3f23f437eac0206a45abe79e0edc2d1a3ed48161/doc.rkt#L276

indenter is a function of this type:

(-> (is-a?/c racket:text<%>)
    exact-nonnegative-integer?
    (or/c #f exact-nonnegative-integer?))

but doc-text is a lsp-editor% object. I think add a new method to lsp-editor% called like indent can solve it.

6cdh commented 11 months ago

I made a change: https://github.com/6cdh/racket-langserver/tree/fix-formatting please try it

adrianchong518 commented 11 months ago

I've tried it and it works! (It looks like a simple fix in hindsight, but I just couldn't get my head around how all the things go together 🙃 )

6cdh commented 11 months ago

In an older version, doc-text is a text% object, and the code is correct. But then I refactored that wrapped text% object in lsp-editor% class, that is the core variable. That was a mistake to leave that line of code unchanged. So this change basically replace doc-text with core. core is a class private variable, so I added a new method.