Fix edge cases in eglot-java JDT uri handling

This commit is contained in:
Jeremy Dormitzer 2023-05-01 13:20:53 -04:00
parent c82bf55102
commit b1052b4509

View File

@ -80,6 +80,16 @@
"Eclipse JDT breaks spec and replies with edits as arguments."
(mapc #'eglot--apply-workspace-edit arguments))
;; Support jdtls' ability to jump into class files
(define-advice file-relative-name
(:before-until (filename &optional directory) jdt-uri)
(when (string-match-p "\\`jdt://" filename)
filename))
(define-hash-table-test 'jdt-file-to-uri-hash 'equal 'sxhash-equal)
(defvar eglot-java--jdt-file-to-uri (make-hash-table :test 'jdt-file-to-uri-hash)
"Internal variable to map temporary filepaths to JDT URIs.")
(define-advice eglot--path-to-uri
(:before-until (path) jdt-path)
(gethash (file-truename path) eglot-java--jdt-file-to-uri))
(defun jdt-class-file-name-handler (operation &rest args)
"File name handler for jdtls' `jdt://' URIs."
(cond
@ -88,15 +98,10 @@
file-name-case-insensitive-p
make-auto-save-file-name
find-file-backup-name)) nil)
((member operation '(expand-file-name
directory-file-name
file-truename
file-relative-name
file-name-nondirectory)) (car args))
(t (let* ((uri (car args))
(uri-hash (secure-hash 'md5 uri))
(filename (save-match-data
(string-match "jdt://contents/\\(.*?\\)/\\(.*\\)\.class\\?" uri)
(string-match "jdt://contents/\\(.*?\\)/\\(.*?\\)\.class\\?" uri)
(format "%s.java"
(replace-regexp-in-string "/" "." (match-string 2 uri) t t))))
(temp-dir (expand-file-name "eglot-jdtls" temporary-file-directory))
@ -105,6 +110,8 @@
(metadata-path (format "%s.%s.metadata"
(file-name-directory filepath)
(file-name-base filepath))))
(unless (gethash (file-truename filepath) eglot-java--jdt-file-to-uri)
(puthash (file-truename filepath) uri eglot-java--jdt-file-to-uri))
(unless (or (file-readable-p filepath) (not (eglot-current-server)))
(let ((contents
(jsonrpc-request (eglot-current-server)
@ -114,8 +121,12 @@
(with-temp-file filepath (insert contents))
(with-temp-file metadata-path (insert uri))))
(cond
((eq operation 'file-name-directory) uri-temp-dir)
((eq operation 'get-file-buffer) (get-buffer filename))
((member operation '(expand-file-name
directory-file-name
file-truename
file-name-directory
file-name-nondirectory)) (apply operation filepath (cdr args)))
((eq operation 'insert-file-contents)
(seq-let (uri visit beg end replace) args
(let ((content (with-temp-buffer
@ -123,8 +134,7 @@
(buffer-substring (point-min) (point-max)))))
(insert content)
(when visit
(set-visited-file-name uri t)
(rename-buffer filename)
(set-visited-file-name filepath t)
(set-buffer-modified-p nil)
(read-only-mode))
(list uri (length content)))))