unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Danny Freeman via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: "Dmitry Gutov" <dgutov@yandex.ru>, "João Távora" <joaotavora@gmail.com>
Cc: 58790@debbugs.gnu.org, Stefan Kangas <stefankangas@gmail.com>
Subject: bug#58790: Eglot URI parsing bug when using clojure-lsp server
Date: Mon, 31 Oct 2022 10:40:22 -0400	[thread overview]
Message-ID: <4d50b820-7053-75eb-5b11-d3d36a02b013@dfreeman.email> (raw)
In-Reply-To: <9bb290c8-f000-31d8-265d-b5441c33eb38@dfreeman.email>

[-- Attachment #1: Type: text/plain, Size: 3644 bytes --]

I have a new patch attached that does what João suggested in the 5 point 
list,
which I will respond to again

 > 2. Eglot converts the URI X into a some file designator Y, using
 >    eglot--uri-to-path.  Y may or may not be === X, as long as there is
 >    exactly one X for every Y.  Eglot makes xref-item objects from it
 >    using xref-make-match and xref-make-file-location.  The designator Y
 >    goes into the 'file' slot of the xref-file-location object.

The patch leaves X === Y for `jar` type URIs. My updated packages now 
deals with
the full jar URIs. No conversion are done. My new package can be found here:
https://git.sr.ht/~dannyfreeman/jarchive/tree/9148ed7ada03ff2516f6e4ede20c453974d6da19/item/jarchive.el

 > 4. B2 can be setup in a way so that project-current returns the same
 >    object which is returned in B.  If this is true,
 >    eglot--current-server discovers the same connection which also
 >    manages B1 and Eglot adds buffer B2 to the list of managed buffers in
 >    that connection.
 >
 >    However, if eglot-extend-to-xref is non-nil, eglot--current-server
 >    should also discover the correct connection.  This is less ideal than
 >    making project-current know that the buffers of source code inside
 >    the jar are also in the same project, but it works.  I can explain
 >    the downsides, but it's not very relevant right now.

My newly updated package does nothing with `project-current`, as I have no
obvious way to access the previous project when extracting files from 
the jar.
(Extracting now happens in `insert-file-contents` instead of 
`get-file-buffer`)

BUT eglot-extend-to-xref works as it should with this, and I think I 
prefer that.
It allows people who don't want that behavior to disable 
`eglot-extend-to-xref`
and have eglot start up a new lsp server when visiting the file.
Idk why anyone would want that but you never know.

 > 5. Upon findin the "file", Eglot transmits a :textDocument/didOpen
 >    notification to the server.  This requires eglot--path-to-uri, the
 >    reciprocal of eglot--uri-to-path to convert the path Y to URI X
 >    again.  Again, maybe this conversion is just #'identity.
 >
 >    Eventually, the LSP server knows that the client is now working on a
 >    textDocument whose relationship to other opened documents in the
 >    workspace it understands (which may or may not be read-only).

Sending the full jar uri back to the lsp server worked exactly as 
intended here.
I am honestly surprised I didn't have to change anything in clojure-lsp. 
It can
do it's analysis on the file without issue.

 > 6. xref-find-definition on any part of the B2 should now work similarly
 >    to this whole flow.

It does!!!!!

As for this question

 > I don't know what happens if another server also points to the same file.
 > Probably nothing very bad, but there may be some suprising behavior: I
 > haven't tested.

The same file continues to work with respect to the original lsp server
that was used to open it. The second lsp server is not conidered. I
guess because eglot can only work with one lsp server at a time. If you 
want to
associate the un-jar'd file with the second server, close it and
xref-find-defintions to it from a file in the second server. That seems 
like a
fine workaround to me, and its not something I've ever encountered in my 
routine
development workflow.


So, what do yall think about the patch? Is that something you might 
consider for
eglot? I believe I could also accomplish something similar with "advice" 
in my
package and leave eglot alone, but I would be poking at eglot internals 
which
seems not ideal.

[-- Attachment #2: 0001-Do-not-parse-jar-type-URIs-provided-by-lsp-servers-i.patch --]
[-- Type: text/x-patch, Size: 4931 bytes --]

From 671d3117bd9a810616dd5bbdfffa18e91a4d9896 Mon Sep 17 00:00:00 2001
From: dannyfreeman <danny@dfreeman.email>
Date: Mon, 31 Oct 2022 10:01:21 -0400
Subject: [PATCH] Do not parse jar type URIs provided by lsp servers in eglot

Clojure-lsp and possibly other lsp servers for JVM languages, can
provide file locations as jar scheme URIs for dependencies located
inside of jar archives. These URIs contain nested URIs that Emacs out of
the box does not know how to work with. Example:
  jar:file:///path/to/lib.jar!/path/inside/jar/source.ext

Even if they are parsed twice, the locations are of the format
  /path/to/lib.jar!/path/inside/jar/source.ext
which Emacs also does not know how to handle.

This commit introduces a var `eglot-preserve-jar-uri` that, when true,
will pass along jar URIs without parsing them. This allows other
packages to handle them through the `file-name-handler-alist` mechanism.
Additionally, any jars sent BACK to the lsp server by eglot will also
remain in the `jar` format, which at least clojure-lsp knows how to
interpret.

Given the correct file-name-handler-alist implementation, this change
allows xref to navigate to a file within a jar. When
`eglot-extend-to-xref` option is enabled, eglot can correctly connect to
the previous lsp server and continue to work in the newly opened file.

To ensure clojure-lsp servers always use the "jar" URI scheme for these
types of dependencies, an initialization option is set. The default
option, the "zipfile" scheme, is very similar to the jar
scheme. However, the "zipfile" scheme is something that the clojure-lsp
maintainers want to move away from and eventually remove.
---
 lisp/progmodes/eglot.el | 37 +++++++++++++++++++++++++------------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index c587061837..b8f50e3cd8 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -231,7 +231,7 @@ eglot-server-programs
                                 (html-mode . ,(eglot-alternatives '(("vscode-html-language-server" "--stdio") ("html-languageserver" "--stdio"))))
                                 (dockerfile-mode . ("docker-langserver" "--stdio"))
                                 ((clojure-mode clojurescript-mode clojurec-mode)
-                                 . ("clojure-lsp"))
+                                 . ("clojure-lsp" :initializationOptions (:dependency-scheme "jar")))
                                 (csharp-mode . ("omnisharp" "-lsp"))
                                 (purescript-mode . ("purescript-language-server" "--stdio"))
                                 (perl-mode . ("perl" "-MPerl::LanguageServer" "-e" "Perl::LanguageServer::run"))
@@ -1492,25 +1492,38 @@ eglot--uri-path-allowed-chars
     vec)
   "Like `url-path-allows-chars' but more restrictive.")
 
+(defvar eglot-preserve-jar-uri nil
+  "If non-nil, jar: type URIs will not be converted to paths.
+This means they will be provided to xref as URIs and not file paths.")
+
 (defun eglot--path-to-uri (path)
   "URIfy PATH."
-  (let ((truepath (file-truename path)))
-    (concat "file://"
-            ;; Add a leading "/" for local MS Windows-style paths.
-            (if (and (eq system-type 'windows-nt)
-                     (not (file-remote-p truepath)))
-                "/")
-            (url-hexify-string
-             ;; Again watch out for trampy paths.
-             (directory-file-name (file-local-name truepath))
-             eglot--uri-path-allowed-chars))))
+  (if (and eglot-preserve-jar-uri (equal "jar" (url-type (url-generic-parse-url path))))
+      path
+    (let ((truepath (file-truename path)))
+      (concat "file://"
+              ;; Add a leading "/" for local MS Windows-style paths.
+              (if (and (eq system-type 'windows-nt)
+                       (not (file-remote-p truepath)))
+                  "/")
+              (url-hexify-string
+               ;; Again watch out for trampy paths.
+               (directory-file-name (file-local-name truepath))
+               eglot--uri-path-allowed-chars)))))
+
+(defun eglot--parse-uri (uri)
+  "Try to parse a URI."
+  (let ((url (url-generic-parse-url uri)))
+    (if (and eglot-preserve-jar-uri (string= "jar" (url-type url)))
+        uri
+      (url-unhex-string (url-filename url)))))
 
 (defun eglot--uri-to-path (uri)
   "Convert URI to file path, helped by `eglot--current-server'."
   (when (keywordp uri) (setq uri (substring (symbol-name uri) 1)))
   (let* ((server (eglot-current-server))
          (remote-prefix (and server (eglot--trampish-p server)))
-         (retval (url-unhex-string (url-filename (url-generic-parse-url uri))))
+         (retval (eglot--parse-uri uri))
          ;; Remove the leading "/" for local MS Windows-style paths.
          (normalized (if (and (not remote-prefix)
                               (eq system-type 'windows-nt)
-- 
2.37.3


  reply	other threads:[~2022-10-31 14:40 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-25 21:44 bug#58790: Eglot URI parsing bug when using clojure-lsp server Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-26  6:22 ` Stefan Kangas
2022-10-26 19:50   ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-27 15:09     ` João Távora
2022-10-29  1:22       ` Dmitry Gutov
2022-10-29  2:02         ` João Távora
2022-10-29 14:54           ` Dmitry Gutov
2022-10-29 19:35             ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-31 14:40               ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2022-11-02  8:09                 ` João Távora
2022-11-02 13:15                   ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-03 17:10                   ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-10  9:49                     ` Eli Zaretskii
2022-11-10 11:00                       ` João Távora
2022-11-10 13:47                         ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-10 15:38                         ` Eli Zaretskii
2022-11-10 21:45                           ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-10 21:59                             ` João Távora
2022-11-10 22:22                               ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-10 22:30                                 ` João Távora
2022-11-10 22:48                                   ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-10 22:48                                 ` João Távora
2022-11-10 22:57                                   ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-11  7:29                                   ` Eli Zaretskii
2022-11-12 17:03                                     ` Michael Albinus
2022-11-13 21:04                                       ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-15 19:04                                         ` Michael Albinus
2022-11-15 22:28                                           ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-16  7:53                                             ` Michael Albinus
2022-11-16 10:21                                               ` João Távora
2022-11-16 15:45                                                 ` Michael Albinus
2022-11-16 16:20                                                   ` João Távora
2022-11-16 22:59                                                     ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-02 16:14                                                       ` Michael Albinus
2022-12-07 18:56                                                         ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-08 13:46                                                           ` Michael Albinus
2022-12-08 19:07                                                             ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-09 16:04                                                               ` Michael Albinus
2022-12-10 17:21                                                                 ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-10 17:45                                                                   ` Michael Albinus
2022-11-22 14:30                                                     ` Michael Albinus
2022-11-23 11:55                                                       ` Richard Copley
2022-11-23 12:36                                                         ` João Távora
2022-11-23 12:42                                                           ` Arash Esbati
2022-11-23 12:49                                                             ` Richard Copley
2022-11-23 12:54                                                               ` João Távora
2022-11-23 13:33                                                           ` Eli Zaretskii
2022-11-23 13:44                                                             ` João Távora
2022-11-23 14:03                                                               ` Danny Freeman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-23 19:53                                                                 ` João Távora
2022-11-11  8:30                               ` Eli Zaretskii
2022-11-11  9:45                                 ` João Távora
2022-11-11 12:01                                   ` Eli Zaretskii
2022-11-11 14:02                                     ` João Távora
2022-11-11 14:45                                       ` Eli Zaretskii
2022-11-12  9:04                                         ` João Távora
2022-11-11  7:16                             ` Eli Zaretskii
2022-11-01 17:25         ` Juri Linkov
2022-10-29 15:36 ` Felician Nemeth
2022-10-29 17:09   ` João Távora
2022-11-09  0:59 ` bug#58790: Robert Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4d50b820-7053-75eb-5b11-d3d36a02b013@dfreeman.email \
    --to=bug-gnu-emacs@gnu.org \
    --cc=58790@debbugs.gnu.org \
    --cc=danny@dfreeman.email \
    --cc=dgutov@yandex.ru \
    --cc=joaotavora@gmail.com \
    --cc=stefankangas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).