-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support JDT URIs from textDocument/defintion requests #6
Comments
Hi @dannyfreeman . Just wondering if you have any updates on this. |
None at all. I'm wondering if this repository is dead or obsolete? |
The repository is not "dead" per say, I will just say that the best way to contribute is via pull requests.
@dannyfreeman, I was hoping that when ready you would create a pull request addressing the issue. |
Thanks for the response! I also don't program in Java, but I'd still like to work on this. I'll see about getting a pull request against this repo. |
@dannyfreeman I was wondering if you were able to look into this issue? |
I was able to hack something (not lisp proficient). This is based on what I saw here: https://git.sr.ht/~dannyfreeman/jarchive/tree/main/item/jarchive.el
now you just need to run |
I have been too busy to work on this, my apologies. Your solution based on jarchive I wouldn't consider a long term or permanent one. JDT urls are not meant to be parsed by the client. They are basically tokens that the jdt lsp server can use to serve back up the contents of the file using a special extension method: eclipse-jdtls/eclipse.jdt.ls#2322 (comment) This comment from @theothornhill seems to be a lot more on point, though I haven't tried it out (again, I really don't do any java development). |
I like what is suggested by in that jdt.ls comment, that also seems aligned with what If I'm not mistaken @dannyfreeman , in comments from the eglot project issues (joaotavora/eglot#661), it feels like the maintainer strongly believed that any kind of URI handler belongs to core emacs from day one.
Still, kudos @husainaloos it's great that you were able to come up with a workaround! |
Fwiw I already started a discussion over at emacs-devel, so we'll see if that example could go in core. I'm a little undecided because it uses eglot/java/jsonrpc-specific code, so it's hard to find a definitive spot for it. Maybe when @joaotavora sees it we'll know some more :) |
Heads up, I'm not reading the emacs-devel daily lately. So if you want me to comment or weigh in on an issue, make sure to CC me in those emails (and even then I don't guarantee a timely response, but I do try). |
The issue you linked @yveszoundi isn't quite the same as this one. The eglot discussion was related to a standardized The issue here is how to open |
Thanks for clarifying, I didn't read the entire thread for that other ticket. I was mostly concerned about whether it's already possible to attach special "URI handlers" into emacs for arbitrary schemes and how well it plays along with URI related methods" in
tl;dr I do agree about the actual URI handling logic being in a specialized package such as this one. I hope that my position is "clear" enough. |
(it works, you just have to supply the extended capabilities thingy - i use it every day) |
@dannyfreeman @husainaloos , can you confirm that the code below works for you for now? 1. Initialize eglot with jdtlsPlease replace the (require 'eglot)
(setcdr (assoc 'java-mode eglot-server-programs)
'("/Users/yveszoundi/.emacs.d/share/eclipse.jdt.ls/bin/jdtls" :initializationOptions
(:extendedClientCapabilities (:classFileContentsSupport t)))) 2. Add the URI handling logicThis is based on the sample code from @theothornhill and the AOP advice logic from @husainaloos . (defun jdt-file-name-handler (operation &rest args)
"Support Eclipse jdtls `jdt://' uri scheme."
(let* ((uri (car args))
(cache-dir "/tmp/.eglot")
(source-file
(expand-file-name
(file-name-concat
cache-dir
(save-match-data
(when (string-match "jdt://contents/\\(.*?\\)/\\(.*\\)\.class\\?" uri)
(message "URI:%s" uri)
(format "%s.java" (replace-regexp-in-string "/" "." (match-string 2 uri) t t))))))))
(unless (file-readable-p source-file)
(let ((content (jsonrpc-request (eglot-current-server) :java/classFileContents (list :uri uri)))
(metadata-file (format "%s.%s.metadata"
(file-name-directory source-file)
(file-name-base source-file))))
(message "content:%s" content)
(unless (file-directory-p cache-dir) (make-directory cache-dir t))
(with-temp-file source-file (insert content))
(with-temp-file metadata-file (insert uri))))
source-file))
(add-to-list 'file-name-handler-alist '("\\`jdt://" . jdt-file-name-handler))
(defun jdthandler--wrap-legacy-eglot--path-to-uri (original-fn &rest args)
"Hack until eglot is updated.
ARGS is a list with one element, a file path or potentially a URI.
If path is a jar URI, don't parse. If it is not a jar call ORIGINAL-FN."
(let ((path (file-truename (car args))))
(if (equal "jdt" (url-type (url-generic-parse-url path)))
path
(apply original-fn args))))
(defun jdthandler--wrap-legacy-eglot--uri-to-path (original-fn &rest args)
"Hack until eglot is updated.
ARGS is a list with one element, a URI.
If URI is a jar URI, don't parse and let the `jdthandler--file-name-handler'
handle it. If it is not a jar call ORIGINAL-FN."
(let ((uri (car args)))
(if (string= "file" (url-type (url-generic-parse-url uri)))
(apply original-fn args)
uri)))
(defun jdthandler-patch-eglot ()
"Patch old versions of Eglot to work with Jdthandler."
(interactive) ;; TODO, remove when eglot is updated in melpa
(unless (or (and (advice-member-p #'jdthandler--wrap-legacy-eglot--path-to-uri 'eglot--path-to-uri)
(advice-member-p #'jdthandler--wrap-legacy-eglot--uri-to-path 'eglot--uri-to-path))
(<= 29 emacs-major-version))
(advice-add 'eglot--path-to-uri :around #'jdthandler--wrap-legacy-eglot--path-to-uri)
(advice-add 'eglot--uri-to-path :around #'jdthandler--wrap-legacy-eglot--uri-to-path)
(message "[jdthandler] Eglot successfully patched."))) 3. Patch eglot(jdthandler-patch-eglot ) 4. Test some codeI used the |
That should work just fine, @yveszoundi |
- This is achieved via a custom URI handler and an AOP advice around eglot URI functions - This doesn't handle further navigation for subsequent navigation within a "classfile contents buffer"
After visiting an initial "class contents buffer", further type navigation is not support. This can be mitigated by the following workflow:
|
Thank you all. The only change that I will make is from
to something like
This is because the Sorry, I don't really use eglot-java so I cannot comment on whether the code integrates well in the package. |
Thanks, that's great to know for the URI details, I'll perform a quick test and apply updates soon. Your code does integrate seamlessly with this package and saved me time (as I "tinker" significantly less with elisp nowadays). |
The URI processed is not always a string and maybe checks will change/improve over time
I have been looking at an issue over in the JDT LSP repository: eclipse-jdtls/eclipse.jdt.ls#2322
A summary of how I reproduce this issue (with the latest snapshot of jdtls, not using eglot-java at all)
eglot-server-programs
:(java-mode . ("jdtls" :initializationOptions (:extendedClientCapabilities (:classFileContentsSupport t))))
groot/src/main/java/org/jlab/groot/math/F1D.java
xref-find-definitions
on theExpression
symbol on line 23The relevant eglot logs
I think this package would be a good place to handle those JDT URIs. There is a reply in the issue over in JDTLS repository that explains the process for handling them. Essentially the client must make an extra request to the
java/classFileContents
method of the language server, which will serve back the contents of the decompiled class. From there the client is free to dump the contents into a buffer.I would be happy to take a swing at implementing this here at some point, but wanted to drop an issue here in case someone else wants to try and beat me to it.
The text was updated successfully, but these errors were encountered: