lsp

:clojure-lsp: Clojure implementation of the Language Server Protocol: https://clojure-lsp.io/
anonimitoraf 2021-03-20T12:19:27.031500Z

Weird, I always get this:

LSP :: keys.cljs not in project or it is blacklisted.
when I load a (doom) emacs session that my clojure project is in. Possible race condition between (doom) emacs session loading and LSP initialization? When I open the project directly (via projectile), it's fine

anonimitoraf 2021-03-20T12:19:57.031900Z

I can make a repro project tomorrow, if necessary. So essentially all I do is: • Open a project, add it to LSP known projects • Save session as "blah" • Close emacs • Load session "blah" • I get asked this:

anonimitoraf 2021-03-21T07:54:05.054300Z

Update on this: I found the cause: • I had treemacs sync mode on • In treemacs I had an inner folder registered as a project. Treemacs doesn't allow projects that overlap. • Removed it, now works fine

anonimitoraf 2021-03-20T12:24:33.032300Z

ericdallo 2021-03-20T12:45:36.032800Z

I use doom-emacs but never saw this, but yeah, it could be some race condition, I'd suggest asking for help on lsp-mode or doom discord as @yyoncho is more familiar with that than me

👍 1
anonimitoraf 2021-03-20T13:36:14.033100Z

Thanks, I'll try those

anonimitoraf 2021-03-20T13:36:42.033300Z

Oh, just FYI, this only started happening recently

anonimitoraf 2021-03-20T13:36:55.033500Z

So maybe I'll look at recent emacs lsp commits too

ericdallo 2021-03-20T15:36:19.034Z

Hum, yeah, good start

ericdallo 2021-03-20T17:26:10.035400Z

So, I'd like to give a try later on implementing https://cursive-ide.com/userguide/macros.html#customising-symbol-resolution on clojure-lsp 🧵

ericdallo 2021-03-21T17:11:28.066200Z

Still need some corner cases fixes though, but it's working nice 🙂

borkdude 2021-03-21T17:12:18.066600Z

you might also want to add clj-kondo.lint-as/def-catch-all to this list

borkdude 2021-03-21T17:12:26.066800Z

which works for weirder def-like macros

ericdallo 2021-03-21T17:12:42.067Z

yes!

borkdude 2021-03-21T17:12:55.067200Z

and I would probably remove -> since I have almost never encountered this in lint-as

borkdude 2021-03-21T17:13:08.067400Z

oh you have, well, then leave it :)

ericdallo 2021-03-21T17:13:22.067600Z

Cursive thas that, I don't see any harm keep it, right?

borkdude 2021-03-21T17:13:33.067900Z

no harm. good job!

ericdallo 2021-03-21T17:13:44.068100Z

Thank you for the help! I'm glad this worked 🙂

borkdude 2021-03-21T17:15:25.068300Z

LSP is quickly becoming the most complete IDE after Cursive

borkdude 2021-03-21T17:15:45.068500Z

I hope you get funding by CT

☝️ 1
ericdallo 2021-03-21T17:16:22.068700Z

Yeah 😄 That'd be really good 🙂

borkdude 2021-03-21T17:17:29.068900Z

Was there a survey announcement recently? Haven't seen one

ericdallo 2021-03-21T17:17:51.069100Z

No, I think they will start the voting on april

ericdallo 2021-03-21T17:18:25.069300Z

they were closing the members register this month

borkdude 2021-03-21T17:18:35.069500Z

So how did it end with the incremental diffing? reverted it?

borkdude 2021-03-21T17:18:51.069700Z

yeah, but usually they send out a survey to the sponsors before this

borkdude 2021-03-21T17:19:19.070Z

to see which projects should get funded by the opinion of the sponsors

borkdude 2021-03-21T17:20:31.070200Z

I will ask Daniel

ericdallo 2021-03-21T17:21:31.070400Z

> So how did it end with the incremental diffing? reverted it? I still need to find the out-of-sync corner case issue, it's behind a feature-flag

ericdallo 2021-03-21T17:21:47.070600Z

Oh, got it

borkdude 2021-03-21T17:22:22.070800Z

I was thinking, maybe generative testing could be used to find this corner case

ericdallo 2021-03-21T17:23:34.071Z

yes, it could help indeed, I think we could improve the integration tests to be able to do that

ericdallo 2021-03-21T17:23:46.071200Z

the clojure-lsp integration tests base is working good

borkdude 2021-03-21T17:24:13.071400Z

is it a problem with the async stuff, or with the diff function?

ericdallo 2021-03-21T17:24:42.071600Z

Probably the async stuff

ericdallo 2021-03-21T17:24:54.071800Z

the diff function seems to work good

ericdallo 2021-03-21T17:25:15.072Z

also it seems to happen with medium/big buffers

borkdude 2021-03-21T17:25:48.072200Z

Maybe you can test it by putting some random Thread/sleeps into the async handlers

ericdallo 2021-03-21T17:26:00.072400Z

hum, good idea indeed

borkdude 2021-03-21T17:54:12.072600Z

Btw, I will probably make a new clj-kondo release tonight with a bunch of bug fixes in it

ericdallo 2021-03-21T17:54:51.072800Z

good to know! I'll include in this feature release if don't find any issues with that bump 🤞

ericdallo 2021-03-21T17:55:08.073Z

thanks for telling me

borkdude 2021-03-21T17:56:20.073200Z

I will push one more fix to master within the next two hours

👍 1
borkdude 2021-03-21T18:55:19.073500Z

Pushing 2021.03.21, will be on clojars in a few minutes hopefully

ericdallo 2021-03-21T18:58:51.073800Z

Nice, I'm finishing the resolve macro as, then I'll bump clj-kondo, if everything goes fine, I'll release it later tonight

ericdallo 2021-03-21T19:12:30.074Z

I love this bot 🙂 https://github.com/clojure-lsp/clojure-lsp/pull/375

borkdude 2021-03-21T19:44:28.074300Z

Hmm, I found one more edge. I will do another release tonight

ericdallo 2021-03-21T19:47:53.074500Z

👍 , I'll wait for clojure-lsp release so

ericdallo 2021-03-20T17:33:55.035600Z

This is the only one big feature I see it's missing from non-cursive IDEs, and if we could add that, it'd improve a lot the UX. it could be really nice for other editors as well like Calva (c/c @brandon.ringe) I was discussing with @yyoncho (lsp-mode maintainer) and we could do that via code actions, like: 1. clojure-lsp detect a unresolved macro and return a code action "Resolve macro as..." 2. LS client (for now, lsp-mode), wrap that code action asking to user how it should resolve, for now we can show only the common clojure ones: def , defn , let -> etc 3. clojure-lsp receive that and somehow update user/project clj-kondo config lint-as . @borkdude I'd like you opinion/suggestion on how we can achieve the 3 step. In a ideal world, clojure-lsp could call a clj-kondo function to update the user config and clojure-lsp trigger a re-lint of that file. Or clojure-lsp could ask to clj-kondo the clj-kondo config-path and change that itself manually, WDYT?

👍 1
borkdude 2021-03-20T18:28:42.035800Z

@ericdallo That seems good to me. You can use https://github.com/borkdude/rewrite-edn or just rewrite-clj to update the clj-kondo config.

ericdallo 2021-03-20T18:48:12.036200Z

Nice, any suggestion if this logic should be on clj-kondo side or clojure-lsp? I think that on clj-kondo we could use existing functions to know what is the user clj-kondo config

borkdude 2021-03-20T18:48:52.036400Z

clj-kondo has only a forked version of rewrite-clj currently, so it isn't able to do any code editing

borkdude 2021-03-20T18:49:20.036600Z

is there something in the response of clj-kondo/run! that points at the config dir?

ericdallo 2021-03-20T18:49:43.036800Z

Not that I recall

borkdude 2021-03-20T18:50:51.037Z

I'll take a look

borkdude 2021-03-20T18:51:58.037200Z

we can add a core function for this

borkdude 2021-03-20T18:52:06.037400Z

in clj-kondo.core

ericdallo 2021-03-20T18:52:55.037600Z

Yeah, that would help :)

borkdude 2021-03-20T18:53:50.037800Z

but it also depends on the :config-dir argument to clj-kondo/run! so it's call-dependent

borkdude 2021-03-20T18:54:08.038Z

can users configure this in lsp?

borkdude 2021-03-20T18:54:29.038200Z

I think 99% of the time the config is in .clj-kondo/config.edn but maybe not in monorepo projects

ericdallo 2021-03-20T18:54:34.038400Z

No, only if it's available via the .clj-kondo/config.edn file

ericdallo 2021-03-20T18:55:00.038600Z

Yeah, I thought we could use the same logic clj-kondo use to find the config

ericdallo 2021-03-20T18:55:19.038800Z

The core function would just call that logic I imagine

borkdude 2021-03-20T18:55:21.039Z

I think what you should do is look up from the current file towards the first .clj-kondo dir and pick the config.edn from there

ericdallo 2021-03-20T18:55:58.039200Z

So, On clojure-lsp side?

borkdude 2021-03-20T18:56:08.039400Z

I have this function in clj-kondo.impl.core:

(defn config-dir
  ([] (config-dir
       (io/file
        (System/getProperty "user.dir"))))
  ([start]
   (let [start (io/file start)
         ;; NOTE: .getParentFile doesn't work on relative files
         start (.getAbsoluteFile start)
         start (if (.isFile start)
                 (.getParentFile start)
                 start)]
     (when start
       (loop [dir start]
         (let [cfg-dir (io/file dir ".clj-kondo")]
           (if (.exists cfg-dir)
             (if (.isDirectory cfg-dir)
               cfg-dir
               (throw (Exception. (str cfg-dir " must be a directory"))))
             (when-let [parent (.getParentFile dir)]
               (recur parent)))))))))

borkdude 2021-03-20T18:56:30.039600Z

so I think you can call that one, but we should maybe make it public

ericdallo 2021-03-20T18:56:42.039800Z

Yes, that makes sense

borkdude 2021-03-20T18:57:01.040Z

feel free to make a PR to make a public wrapper around it

borkdude 2021-03-20T18:57:25.040200Z

but first you can call it from impl.core

borkdude 2021-03-20T18:57:29.040400Z

just for testing

ericdallo 2021-03-20T18:58:19.040600Z

Sure! Thanks for the guide, I'll make that later today

ericdallo 2021-03-20T20:47:29.040800Z

@borkdude it seems that function almost always will return the project .clj-kondo since clj-kondo creates it for the .clj-kondo/.cache

ericdallo 2021-03-20T20:47:52.041Z

maybe clojure-lsp should check if there is a config.edn file from the return of that function?

ericdallo 2021-03-20T20:48:27.041200Z

still it'd be logic to check the home dir on clojure-lsp side, it'd be better if clj-kondo return the project .clj-kondo only if there is a config.edn file there

ericdallo 2021-03-20T20:51:34.041500Z

but user may have no config.edn on ~/.clj-kondo as well :thinking_face:

borkdude 2021-03-20T21:00:23.041700Z

@ericdallo clj-kondo never creates a .clj-kondo directory

borkdude 2021-03-20T21:00:58.041900Z

I think it may be better to show the user a list of possible candidates

ericdallo 2021-03-20T21:01:42.042100Z

I see, presenting from the current folder until home I suppose

borkdude 2021-03-20T21:02:22.042300Z

candidate config.edn files

ericdallo 2021-03-20T21:02:23.042500Z

like:

- /home/user/mono-repo/project-a/.clj-kondo/config.edn
- /home/user/mono-repo/.clj-kondo/config.edn
- /home/user/.clj-kondo/config.edn

borkdude 2021-03-20T21:02:29.042700Z

yeah

borkdude 2021-03-20T21:02:46.042900Z

well, in that example on the first and last are relevant

ericdallo 2021-03-20T21:02:52.043100Z

it seems better indeed, so we don't need to use the clj-kondo config-dir, right?

borkdude 2021-03-20T21:03:04.043400Z

since clj-kondo doesn't reach the middle one when it encounters the top one

borkdude 2021-03-20T21:03:28.043600Z

I think in most cases people want to use it to the project config (the top one)

borkdude 2021-03-20T21:03:38.043800Z

since it fixes it for their teammates as well

ericdallo 2021-03-20T21:03:47.044Z

I see, so I think we can present either the home one or the project, right?

borkdude 2021-03-20T21:04:03.044200Z

yes

ericdallo 2021-03-20T21:04:30.044400Z

ok, so we don't need to touch clj-kondo code I think

borkdude 2021-03-20T21:04:46.044600Z

alright

ericdallo 2021-03-20T21:04:48.044800Z

I'll check if we are missing anything, but looks good to me

ericdallo 2021-03-20T22:33:03.045400Z

@borkdude I realized that when we have a unknown macro, we don't necessarily have a lint/diagnostics on the macro, but on other places inside the macro usage that may be because of a unknown macro

ericdallo 2021-03-20T22:33:31.045600Z

The only way I see that working is clj-kondo return in the analysis if that macro is known or not

ericdallo 2021-03-20T22:34:05.045800Z

otherwise I can't see clojure-lsp suggesting correctly a Resolve macro as code action

borkdude 2021-03-20T22:34:39.046Z

clj-kondo does report whether a var is a macro

ericdallo 2021-03-20T22:35:19.046200Z

yes, but it reports if that macro is known? like is defined via lint-as or some common macros that are coded on clj-kondo?

ericdallo 2021-03-20T22:36:04.046400Z

for example, it should not return a unknown macro for defflow if I have it correctly configured with hooks etc

ericdallo 2021-03-20T22:36:26.046600Z

only specifying as :macro true is not enough

borkdude 2021-03-20T22:36:49.046800Z

"known macro" is not a thing since not all macros use syntax that gives problems

ericdallo 2021-03-20T22:37:09.047Z

yeah, I wonder how cursive handles that

borkdude 2021-03-20T22:38:11.047200Z

where does cursive give this hint?

ericdallo 2021-03-20T22:39:06.047400Z

good question

ericdallo 2021-03-20T22:39:51.047600Z

but when you resolve it, Cursive save that config to not ask later again, so the way we handle that should consider that as well

borkdude 2021-03-20T22:41:02.047800Z

I think cursive just shows this when you are on the macro call name: https://cursive-ide.com/userguide/macros.html

borkdude 2021-03-20T22:41:16.048100Z

and from the analysis you can infer you are calling a macro, so maybe you could do the same

borkdude 2021-03-20T22:41:54.048300Z

I'm not sure if cursive always suggests this or only in the presence of warnings, but this you can also check, since you know the start and end location

ericdallo 2021-03-20T22:42:28.048500Z

ok, we can suggest it if it's a macro, but how we'd know if it was already resolved as before?

borkdude 2021-03-20T22:43:04.048700Z

by looking at the config in :lint-as maybe?

borkdude 2021-03-20T22:43:40.048900Z

I guess that part doesn't have to be that intelligent

ericdallo 2021-03-20T22:43:40.049100Z

yeah, that would not be totally reliable as I imagine there is some common macros clj-kondo support by default?

borkdude 2021-03-20T22:43:49.049300Z

the user can think for himself when changing this

ericdallo 2021-03-20T22:44:08.049500Z

Hum, yeah, it could be a start

borkdude 2021-03-20T22:44:18.049700Z

yeah, but for supported macros the user would probably not reach for this

ericdallo 2021-03-20T22:44:35.049900Z

So I can always return the code action if cursor is inside a macro function

borkdude 2021-03-20T22:44:56.050100Z

on the macro name I would say?

borkdude 2021-03-20T22:45:17.050300Z

this is how Cursive seems to do it from the screenshot in the docs

borkdude 2021-03-20T22:45:29.050500Z

have you got a running version of Cursive?

ericdallo 2021-03-20T22:45:37.050700Z

it'd be now warnings/lints on the macro definition, it may not be clear to user that there is a action only when hovering the macro name I think

ericdallo 2021-03-20T22:46:04.050900Z

> have you got a running version of Cursive? Nope, only saw teammates using

borkdude 2021-03-20T22:46:31.051100Z

I do have an intellij license, for free, open source

borkdude 2021-03-20T22:46:46.051300Z

you can request it from jetbrains, but you can even run cursive with the CE free edition

borkdude 2021-03-20T22:47:00.051500Z

and cursive also has open source licenses

ericdallo 2021-03-20T22:47:20.051700Z

good to know, I'll setup it later so

borkdude 2021-03-20T22:47:38.051900Z

maybe also ask some feedback from other people in the channel

borkdude 2021-03-20T22:47:55.052100Z

I don't have strong feelings about this, as I'm likely to edit the config manually

👍 1
borkdude 2021-03-20T22:48:19.052400Z

but maybe people don't know this option exists, so it would be good to have it

☝️ 1
ericdallo 2021-03-20T22:48:58.052700Z

I know it's something commonly used by cursive users

ericdallo 2021-03-20T23:03:38.052900Z

I got to install and repro:

ericdallo 2021-03-20T23:04:34.053300Z

so, cursive always show as a code action only when on macro name indeed

ericdallo 2021-03-20T23:05:49.053500Z

and always show the code action, even if you already chose one before, exactly as you said @borkdude 🙂

ericdallo 2021-03-20T23:05:55.053700Z

So I think we can do the same