we have macros like (defcommand name-of-command ...), which are later referenced elsewhere using keywords (e.g., {:command :name-of-command}). I already have a hook for the macro but what I would like to add is the ability to navigate using LSP from the keyword to the macro definition location.
the existing hook expands the macro to something like
(let [command-parameters {..}]
(defn command-name-of-command
[]
....))
and I tried naively to modify it to return something like
(let [command-parameters {..}
unused-placeholder :name-of-command]
(defn command-name-of-command
[]
....))
but clojure-lsp doesn't seem to care about that :name-of-commandso my question is: is this something that ought to work (and any problems are caused by bugs in my hook) or is there some fundamental reason this cannot work?
I don't think this will work since lsp just sees the keyword and doesn't know what to navigate to, but maybe @ericdallo could say more about this.
I can use something like lsp-find-references on existing literal instances of :name-of-command in my code to jump between them but it would be nice if it could also include the (defcommand name-of-command .. case in the results so I could also jump to the "definition"
of course the easy way out would be to refactor the macro to include the keyword, but I thought maybe with some hook magic I could achieve the same without altering existing code
ah so you mean lsp would find the keyword although you don't literally write this?
clj-kondo does have the concept of a keyword "definition" e.g. for re-frame. So I think that could work
yeah, lsp-find-references applied on a keyword will find all instances of the keyword and allow me to jump to them. what I would like to do is to fool clojure-lsp into thinking that (defcommand some-command-name ...) also includes :some-command-name within so that it would be included in the list of references for :some-command-name
reg-keyword!: indicates that a keyword's analysis should be marked as a definition. Expects the keyword node and either true or the fully-qualified function that registered it. This can be used to implement keyword navigation for clojure-lsphttps://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md
yes, I think this is possible, at least clj-kondo exposes all the data that clojure-lsp needs and you should use reg-keyword! on the keyword to mark it as the definition. note that you should still use the return value of reg-keyword! and put it in the new node
(the exclamation mark in the reg-keyword! function is a poor choice)
cool, that reg-keyword! thing sounds like something I should try, thanks 🙇
yeah reg-keyword! I think is the best way here
it's what re-frame uses under the hood, that's why navigation of re-frame/reg-event! etc works
No idea what I'm doing, but somehow I managed to get it working. Thanks gentlemen 🙇
nice!
Is potemkin import-vars :rename https://github.com/clj-commons/potemkin#import-vars? Just double checking in case I missed something before raising issue/pr.
(import-vars
[clojure.walk :refer [prewalk postwalk] :rename {prewalk pre-walk}])
Probably not, but feel free to post an issue (+ PR if you're up for it)
Here's a prior issue that looks similar: https://github.com/clj-kondo/clj-kondo/issues/2498
So maybe just add to this issue
(and upvote it)