From e56e987cbf601f6caffac7edfdd580a0b7da921f Mon Sep 17 00:00:00 2001 From: dannyfreeman Date: Thu, 3 Nov 2022 09:39:16 -0400 Subject: [PATCH 1/2] Eglot: Only handle URIs with the file:// scheme This fixes Bug#58790 * lisp/progmodes/eglot.el (eglot--path-to-uri, eglot--uri-to-path): Eglot will not attempt to parse URIs that are not file:// type at all, instead let `file-name-handler-alist' entries to deal with them. Not parsing them at all allows the `file-name-handler-alist' regexps to identify them more accurately. By also checking if eglot received a URI in `eglot--path-to-uri', the `file-name-handler-alist' can provide the non-file type URI back to the lsp server, which presumably will know how to handle them since it is also giving them out to clients. This issue originated with clojure-lsp sending clients "jar": type URIs that emacs is unable to handle out of the box. Before this change, jar: URIs were parsed once, but since jar: URIs contain a nested URI, this resulted in a file being dispatched with a partially parsed path that looked like "file://path/to.jar!/path/in/jar". --- lisp/progmodes/eglot.el | 43 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 1b1302d689..2463f68f97 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1501,29 +1501,38 @@ eglot--uri-path-allowed-chars (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 (url-type (url-generic-parse-url truepath)) + ;; Path is already a URI, so forward it to the lsp server untouched. + truepath + (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--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)))) - ;; Remove the leading "/" for local MS Windows-style paths. - (normalized (if (and (not remote-prefix) - (eq system-type 'windows-nt) - (cl-plusp (length retval))) - (substring retval 1) - retval))) - (concat remote-prefix normalized))) + (url (url-generic-parse-url uri))) + ;; Only attempt to parse URIs with the file scheme. + (if (string= "file" (url-type url)) + (let* ((retval (url-unhex-string (url-filename url))) + ;; Remove the leading "/" for local MS Windows-style paths. + (normalized (if (and (not remote-prefix) + (eq system-type 'windows-nt) + (cl-plusp (length retval))) + (substring retval 1) + retval))) + (concat remote-prefix normalized)) + ;; Leave non-file type URIs untouched, `file-name-handler-alist' + ;; handlers can be used to dispatch them properly. + uri))) (defun eglot--snippet-expansion-fn () "Compute a function to expand snippets. -- 2.38.1