Fork me on GitHub
#lsp
<
2021-09-12
>
lispers-anonymous16:09:33

With clojure-lsp I can use lsp-find-definition in emacs when my cursor is over a keyword, and it will jump to re-frame subscription and event definitions, or clojure specs if that makes sense. Is there a way to extend this behavior to also jump to other places that I would consider the "definition" of a keyword?

all-clear 2
ericdallo16:09:24

sure, this is mainly done by clj-kondo, you can achive that with custom hooks

ericdallo16:09:10

the re-frame thing is just built-in on clj-kondo but it's possible to achieve the same using clj-kondo hooks. where you would tell to clj-kondo that var is a definition

ericdallo16:09:23

maybe @U04V15CAJ can help explaining that better, but AFAIK but if the analysis contains a :reg clojure-lsp will try to search for a var-definition that contains that the name is that :reg

lispers-anonymous16:09:11

Excellent. I wasn't sure if this was something special yall did in lsp or it was an extension of clj-kondo. I'll start investigating. Thanks for pointing me in the right direction.

ericdallo16:09:24

The need started on clojure-lsp and we agreed on adding support for that on clj-kondo analysis where makes more sense :)

ericdallo17:09:26

I may be wrong but I think clj-kondo don't expose that via hooks in any easy way :thinking_face: Checking the hooks docs I didn't find anything that could create a keyword node with a custom :reg c/c @U04V15CAJ

borkdude17:09:31

There is a hook function available api/reg-keyword! https://github.com/clj-kondo/clj-kondo/blob/f78375a589ea91a5d0aca779915a9b24577f0f45/src/clj_kondo/impl/hooks.clj#L22 We haven't documented this yet as the API wasn't that stable yet, perhaps, but feel free to try it out

borkdude17:09:32

you can use this in places like clojure.spec or re-frame where functions register "keywords" to mean something specific like a spec or event or so

borkdude17:09:57

the reg-by must be a fully qualified keyword of the function which registered it

ericdallo17:09:21

nice, I forgot about that function :) thanks!

borkdude17:09:27

oh look, it is documented: > :reg: can be added by :hooks using clj-kondo.hook-api/reg-keyword! to indicate a registered definition location for the keyword. It should be the fully qualified call that registered it.

lispers-anonymous17:09:18

So, just as an example, if I have a function that looked something like

(ns foo.bar)

(defn my-special-registrar [kw] ...)
And was called like so
(foo.bar/my-special-registrar ::important-keyword)
Then the value of reg-by would be :foo.bar/my-special-registrar , as a keyword, right?

ericdallo17:09:39

> oh look, it is documented: nice, I was looking on hooks.md, the most funny is that it was me that documented that 😂

ericdallo17:09:08

@UDVJE9RE3 can't you re-use re-frame hook for your case? since the signature looks the same

lispers-anonymous17:09:17

I probably could. In fact, the function in question wraps the re-frame registration events so it would be a very fitting match

ericdallo17:09:30

like this in your .clj-kondo/config.edn

{:hooks {:analyze-call {foo.bar/my-special-registrar re-frame.core/reg-event-db}}}

ericdallo17:09:58

actually I think this should work and it looks even easier:

{:lint-as {foo.bar/my-special-registrar re-frame.core/reg-event-db}}

lispers-anonymous17:09:22

Yeah, the lint-as was what I just tried and it works exactly as I expected.

lispers-anonymous17:09:12

Thank you both for your help. I'm constantly impressed by both clojure-lsp and clj-kondo. Incredible tools to work with.

lispers-anonymous17:09:24

The code lens references work too! That's really cool.

ericdallo17:09:23

Thank you! :)

🙏 2
Drew Verlee17:09:37

is lsp-find-reference capable of handling ns aliases e.g (:require [foo.bar :as cat] :cat/meow would = :foo.bar/meow, i feel like i saw this behavior working (which is amazing) and now i'm in a context where it isn't.

all-clear 2
ericdallo18:09:10

You probably need to use a aliased namespaced keyword ::cat/meow right?

ericdallo18:09:31

Otherwise :cat/meow means the namespace cat not foo.bar

Drew Verlee19:09:12

your right. My example was wrong. And now when i run lsp-find-references it correctly found it, so all is well.

👍 2
jkrasnay19:09:33

I have a macro that creates two functions in a do block using defn. I’ve also created an :analyze-call hook that reproduces the same structure. When I call one of the functions the linting works correctly (i.e. I don’t get an “Unresolved symbol” error), and I can find all references to either of the generated functions. However, when I try to go to the definition of one of the functions I don’t get sent to the macro call site as I expected. Should this work, and if so, any idea what I’m doing wrong?

ericdallo20:09:16

yes, it should work but you need to set the correct meta for the new generated nodes

ericdallo20:09:41

otherwise the new nodes wouldn't have the :row/:col meta, making clojure-lsp ignore those analysis

jkrasnay22:09:05

Hrm, tried that but still no joy. Would the fact it’s CLJS make a difference?

ericdallo22:09:03

not probably, can you share a repro where I could investigate? any change this code is open source?

jkrasnay22:09:44

No, unfortunately. I’ll try to create a small reproducer.

👍 2
jkrasnay19:09:37

And a related question: should “hover” show me the docstring and arglist for the generated functions?

ericdallo20:09:40

I'm not sure about this one, maybe related with the msising meta above?