lsp

:clojure-lsp: Clojure implementation of the Language Server Protocol: https://clojure-lsp.io/
practicalli-john 2021-03-13T00:08:39.024Z

The face configuration looks very useful, thank you.

😉 1
ericdallo 2021-03-13T01:09:31.026400Z

@brandon.ringe clojure-lsp used to pass the .clj-kondo/cache as cache dir but this was changed in december 2020, we don't pass any cache config to clj-kondo ATM, only the cache true that's why it uses the cache dir if available otherwise not, maybe we should always pass the project/.clj-kondo/.cache folder to clj-kondo @borkdude?

bringe 2021-03-13T01:15:09.026900Z

Oh I see. I think I was using an older version when I saw the two cache directories.

ericdallo 2021-03-13T01:19:48.027100Z

yes, probably 🙂

william 2021-03-13T13:09:17.030600Z

Hey, I'm using the call-hierarchy feature of lsp via the function lsp-treemacs-call-hierarchy in doom emacs. It works, giving me what the documentation calls the incoming call hierarchy (aka the functions that call the function I'm interested in). The documentation also says that I could call that function with a prefix argument, to yield the outgoing call hierarchy (aka the functions that are called by mine). But that results in an error:

Mar 13, 2021 5:27:17 AM org.eclipse.lsp4j.jsonrpc.RemoteEndpoint fallbackResponseError
SEVERE: Internal error: java.lang.reflect.InvocationTargetException
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0(GenericEndpoint.java:67)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.request(GenericEndpoint.java:120)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest(RemoteEndpoint.java:261)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:190)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
	at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0(GenericEndpoint.java:65)
	... 11 more
Caused by: java.lang.UnsupportedOperationException
	at org.eclipse.lsp4j.services.TextDocumentService.callHierarchyOutgoingCalls(TextDocumentService.java:534)
	... 16 more
And this happens both in clj and cljs projects. Am I missing anything? Is there another common way of getting the call graphs of functions in a clojure project?

william 2021-03-13T13:12:36.031500Z

oh, I see that in the documentation online it's mentioned that it's incoming only (I was thrown off by the elisp docs of that function)

william 2021-03-13T13:28:36.033200Z

Unrelated to that, I'd like to explore the codebase of lsp. One thing that I would really like to be able to do is walking through the code, like I do with cider-debug-defun-at-point, when a certain call is made from my client. Would there be a way to accomplish that?

william 2021-03-14T16:01:52.061700Z

thanks again @snoe! I'm still sorting out how to add cider-nrepl to this, but I posted that in the main conversation

ericdallo 2021-03-13T14:00:03.034100Z

Exactly @meditans, ATM we only support incoming call hierarchy, but I hope to add support to outgoing soon

ericdallo 2021-03-13T14:01:23.034200Z

You mean, debug the code only with LSP?

william 2021-03-13T14:02:15.034400Z

I mean, understand what the LSP code does, using the emacs debugger like I do usually in my code. Would that be possible?

william 2021-03-13T14:02:49.034600Z

In particular, triggering a command in one instance of emacs and seeing which command is called in lsp, and tracing down the execution with the debugger

ericdallo 2021-03-13T14:03:05.034800Z

There is a whole protocol for that called DAP (Debug Adapter Protocol), there are some LSP servers that support that as something more, like dart SDK, but clojure-lsp doesn't support that and it'd be really hard to implement the whole thing

ericdallo 2021-03-13T14:03:40.035Z

Yeah, what you want is debug a clojure function, you can accomplish that with cider only AFAIK as of now

william 2021-03-13T14:03:46.035200Z

thanks @ericdallo! It seems that it could be an easier thing to implement than the incoming one, and I could try my hand at doing that, if I can setup a good dev infrastructure like the one I was talking in the previous comment

ericdallo 2021-03-13T14:06:10.035400Z

I never used cider debug with clojure and with this setup: https://clojure-lsp.github.io/clojure-lsp/#development I can work really well

william 2021-03-13T14:06:12.035700Z

Yes, I plan to use the cider debugger, but here's my question: say that I'm using the repo A, and I have a local copy of clojure-lsp on which I'm hacking: 1. How do I convince the emacs instance that browses A to use my copy of clojure-lsp? 2. When I issue a command like call-hierarchy while working on A , I would be like to debug the call in my emacs instance that has clojure-lsp open

ericdallo 2021-03-13T14:06:19.035900Z

I use CIDER a lot though

ericdallo 2021-03-13T14:07:22.036100Z

oh got it

ericdallo 2021-03-13T14:07:51.036300Z

Usinghttps://clojure-lsp.github.io/clojure-lsp/#development is quite easy to achive that

william 2021-03-13T14:08:51.036500Z

amazing! let me try to setup that now then, so I can ask questions (I'm relatively new to clojure tooling)

ericdallo 2021-03-13T14:10:47.036700Z

np, in the beginning I use to lein bin to generate a new clojure-lsp target and use that instead of the installed one pointing to it with (setq lsp-clojure-custom-server-command '("path/to/clojure-lsp/target/clojure-lsp"))

ericdallo 2021-03-13T14:11:05.036900Z

but NREPL helps a lot to connect to a running instance of clojure-lsp and eval/test things

william 2021-03-13T14:17:00.037100Z

ok, so, I: 1. cloned the project 2. run lein with-profile :debug bin , which compiled some executables in clojure-lsp/target 3. I try to run the executables, like java -jar target/clojure-lsp-2021.03.06-17.05.35-standalone.jar or java -jar target/clojure-lsp-2021.03.06-17.05.35.jar, and get an error in both cases

ericdallo 2021-03-13T14:17:33.037300Z

you should use the target/clojure-lsp that already run as java

ericdallo 2021-03-13T14:17:40.037500Z

only ./target/clojure-lsp

ericdallo 2021-03-13T14:18:42.037700Z

Also check if the error is expected, like here: https://clojure-lsp.github.io/clojure-lsp/troubleshooting/#server-is-not-initializing

william 2021-03-13T14:19:19.038100Z

$ ./target/clojure-lsp
Exception in thread "main" java.lang.UnsupportedClassVersionError: clojure_lsp/ClojureExtensions has been compiled by a more recent version of the Java Runtime (class file version 59.0), this version of the Java Runtime only recognizes class file versions up to 55.0

william 2021-03-13T14:19:47.038300Z

it's a java version problem, let me understand who's who here 😂

ericdallo 2021-03-13T14:20:41.038500Z

yep, you should compile with java 11 or 8 I think

ericdallo 2021-03-13T14:21:09.038700Z

actually, you compiled with jdk15 and is running with java 11

william 2021-03-13T14:21:39.038900Z

that's because 59.0 is jdk15?

ericdallo 2021-03-13T14:29:39.039100Z

yep

william 2021-03-13T14:34:16.039300Z

ok, I should be using jdk15 everywhere now, and I recompiled for good measure, when I do ./target/clojure-lsp I get no error, but no output either

ericdallo 2021-03-13T14:34:40.039500Z

that's expected

ericdallo 2021-03-13T14:35:01.039700Z

Do this check to see if it's running: https://clojure-lsp.github.io/clojure-lsp/troubleshooting/#server-is-not-initializing

william 2021-03-13T14:36:30.040Z

yep, it's working! Now I guess I have to find the port on which this is running

ericdallo 2021-03-13T14:37:23.040200Z

yes! but you should run from you editor first, not via terminal

william 2021-03-13T14:37:39.040400Z

at /tmp/clojure-lsp.*.out

william 2021-03-13T14:37:41.040600Z

oh

ericdallo 2021-03-13T14:38:05.040800Z

yes, if you run via terminal, you'd need to send the json manually, too hard to do that

ericdallo 2021-03-13T14:38:15.041Z

via editor, the LSP client already do that, like lsp-mode

ericdallo 2021-03-13T14:38:36.041200Z

so you just need to (setq lsp-clojure-custom-server-command '("path/to/clojure-lsp/target/clojure-lsp"))

ericdallo 2021-03-13T14:38:52.041400Z

and lsp-workspace-restart

ericdallo 2021-03-13T14:39:24.041600Z

then lsp-clojure-server-info should print the port or you can get it via the log file /tmp/clojure-lsp-*.out

william 2021-03-13T14:46:47.041800Z

I guess the server is not properly restarting, because I get:

Process clojure-lsp stderr finished
/run/current-system/sw/bin/emacs: /home/carlo/code/clojure/clojure-lsp/target/clojure-lsp: Exec format error
the value of that variable is correctly set to:
("/home/carlo/code/clojure/clojure-lsp/target/clojure-lsp")
which is the position of the executable

ericdallo 2021-03-13T14:50:28.042Z

try setting the variable to: '("bash" "-c" "/path/to/clojure-lsp-executable")

william 2021-03-13T14:58:23.042200Z

yes, this seems to have worked, and I think I should have a server at -[-] clojure-lsp:28753 , but interestingly lsp-clojure-server-info didn't work, and most of the feature don't seem to work. I mostly get:

helm-M-x-execute-command: The connected server(s) does not support method textDocument/definition.
To find out what capabilities support your server use 'M-x lsp-describe-session'
and expand the capabilities section
I don't seem to have any capability

william 2021-03-13T14:58:54.042400Z

I have to run for two hours but I'd really like to resume from here when I'm back, or when you have some time

ericdallo 2021-03-13T15:17:47.042600Z

it seems the lsp-mode didn't connect corretly to the server, try to lsp-workspace-restart or force lsp start in a buffer with lsp

william 2021-03-13T16:27:12.042800Z

if I do lsp-disconnect and then lsp it seems stuck on initialization:

LSP :: Guessed project root is ~/code/clojure/scratch.pad
LSP :: Connected to [clojure-lsp:30631/starting].

ericdallo 2021-03-13T16:28:22.043Z

Is that the correct project root?

william 2021-03-13T16:30:57.043200Z

yes, it is the directory in which I have the project

william 2021-03-13T16:31:22.043400Z

I'm fairly sure that I don't need anything else to be there because the canonical version of clojure-lsp works

ericdallo 2021-03-13T16:31:30.043600Z

Check /tmp/clojure-lsp.*.out log if there is anything

ericdallo 2021-03-13T16:32:46.043800Z

Did you change any code that can break clojure-lsp? Try with the master branch

william 2021-03-13T16:34:18.044Z

I didn't change any code (just master), but I have something in /tmp/clojure-lsp...:

william 2021-03-13T16:34:18.044200Z

2021-03-13T16:32:58.651Z h2 INFO [clojure-lsp.main:383] - Starting server...
2021-03-13T16:32:59.407Z h2 INFO [clojure-lsp.nrepl:21] - ====== LSP nrepl server started on port 46467
2021-03-13T16:32:59.433Z h2 INFO [clojure-lsp.main:288] - Initializing...
2021-03-13T16:32:59.552Z h2 WARN [clojure-lsp.db:55] - Could not load db org.sqlite.core.NativeDB
2021-03-13T16:32:59.560Z h2 INFO [clojure-lsp.crawler:83] - Analyzing 9 paths with clj-kondo with batch size of 1 ...
2021-03-13T16:33:02.517Z h2 INFO [clojure-lsp.crawler:158] - Paths analyzed, took 2.9574838 secs. Caching for next startups...
2021-03-13T16:33:02.695Z h2 INFO [clojure-lsp.crawler:187] - Manual GC after classpath scan took 0.11909454 seconds
2021-03-13T16:33:02.723Z h2 ERROR [clojure-lsp.main:?] - 
                                                                   java.lang.Thread.run                        Thread.java:  845
                                     java.util.concurrent.ThreadPoolExecutor$Worker.run            ThreadPoolExecutor.java:  630
                                      java.util.concurrent.ThreadPoolExecutor.runWorker            ThreadPoolExecutor.java: 1130
                                                    java.util.concurrent.FutureTask.run                    FutureTask.java:  264
                                    java.util.concurrent.Executors$RunnableAdapter.call                     Executors.java:  515
                          org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run    ConcurrentMessageProcessor.java:  113
                            org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen         StreamMessageProducer.java:   94
                     org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage         StreamMessageProducer.java:  194
                                       org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume                RemoteEndpoint.java:  190
                                 org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest                RemoteEndpoint.java:  261
                             org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.request               GenericEndpoint.java:  120
 org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint$$Lambda$58/0x00000000516b6468.apply                                         
                       org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0               GenericEndpoint.java:   65
                                                                                    ...                                         
                               jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke  DelegatingMethodAccessorImpl.java:   43
                                   jdk.internal.reflect.NativeMethodAccessorImpl.invoke      NativeMethodAccessorImpl.java:   64
                                  jdk.internal.reflect.NativeMethodAccessorImpl.invoke0       NativeMethodAccessorImpl.java     
clojure_lsp.main.proxy$clojure_lsp.ClojureExtensions$LanguageServer$c8d5825a.initialize                                         
                                                                 clojure-lsp.main/fn/fn                           main.clj:  289
                                                                                    ...                                         
                                                        clojure-lsp.handlers/initialize                       handlers.clj:   40
                                                 clojure-lsp.crawler/initialize-project                        crawler.clj:  211
                                                    clojure-lsp.crawler/analyze-project                        crawler.clj:  194
                                                  clojure-lsp.crawler/analyze-classpath                        crawler.clj:  188
                                                               clojure-lsp.db/save-deps                             db.clj:   34
                                                               next.jdbc/get-connection                           jdbc.clj:  158
                                                               next.jdbc.protocols/fn/G                      protocols.clj:   24
                                                                next.jdbc.connection/fn                     connection.clj:  415
                                                               next.jdbc.protocols/fn/G                      protocols.clj:   24
                                                                next.jdbc.connection/fn                     connection.clj:  408
                                                   next.jdbc.connection/make-connection                     connection.clj:  385
                                       next.jdbc.connection/url+etc/reify/getConnection                     connection.clj:  359
                                             next.jdbc.connection/get-driver-connection                     connection.clj:  141
                                                   java.sql.DriverManager.getConnection                 DriverManager.java:  189
                                                   java.sql.DriverManager.getConnection                 DriverManager.java:  677
                                                                org.sqlite.JDBC.connect                          JDBC.java:   90

william 2021-03-13T16:34:34.044400Z

it seems this is the problem:

2021-03-13T16:32:59.552Z h2 WARN [clojure-lsp.db:55] - Could not load db org.sqlite.core.NativeDB

william 2021-03-13T16:34:49.044600Z

but it's just a WARN so I don't know

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

No, that warning is expected, but that exception is not, it seems is not being able to persist the analysis in the .lsp/sqlite.db file

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

Never saw that error before

ericdallo 2021-03-13T17:22:35.045200Z

Really odd, what do you have on .lsp folder?

william 2021-03-13T17:32:14.045700Z

I had only a sqlite.db file. I nuked that, just to be sure, and it seems that I'm not able to recreate another one. I'm sure that the error is that one though, because I have

| java.lang.ClassNotFoundException: org.sqlite.core.NativeDB
│   java.lang.NoClassDefFoundError: org.sqlite.core.NativeDB
at the end of my /tmp/...log file

ericdallo 2021-03-13T17:34:06.045900Z

Really weird, and this only happens with a local clojure-lsp compiled? If so, what version of jdk you used to compile? probably the sqlite lib we use don't have support for jdk 15 or something

william 2021-03-13T17:35:29.046100Z

right, let me see what happens if I use jdk8 (? or jdk9)?

william 2021-03-13T17:35:56.046300Z

and also what happens with the usual version of clojure-lsp

william 2021-03-13T17:37:12.046500Z

ok the usual version of clojure-lsp just works (creates the right folder etc). Now I'll recompile with jdk9

ericdallo 2021-03-13T17:41:40.046700Z

I use jdk11 and 8 and both works

william 2021-03-13T17:54:52.046900Z

I have jdk11 now, and I think we're getting closer. Now, the usual lsp still works fine, and when I try to start the custom one I get:

Exception in thread "main" java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version; class=clojure_lsp/ClojureExtensions, offset=6

ericdallo 2021-03-13T17:56:00.047100Z

Hahaha another weird error, the java version you are running is the same from the compiled clojure-lsp jdk?

william 2021-03-13T17:56:28.047300Z

no, but I don't how to control that one, let me recompile and see if it's magically solved 😂

ericdallo 2021-03-13T17:57:10.047500Z

Yeah, you should use the same versions otherwise you will face those errors

william 2021-03-13T17:58:38.047700Z

how do I control which version clojure-lsp is using?

william 2021-03-13T17:59:46.047900Z

still

Exception in thread "main" java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version; class=clojure_lsp/ClojureExtensions, offset=6
after recompiling, that probably means that I'm not yet using the right version

ericdallo 2021-03-13T18:14:25.048100Z

When you lein bin, lein will use the jdk version from JAVA_PATH if I recall correctly, and you need to check what is the java being used when running, via your java command

william 2021-03-13T18:16:33.048300Z

so I could do:

JAVA_PATH=/nix/store/52ynjxkdx8swmmkdvl27blw9bd77gxxr-adoptopenjdk-openj9-bin-11.0.9/bin/
and then execute lein with-profile :debug bin

william 2021-03-13T18:24:35.048500Z

awesome! It works now @ericdallo, I understood and fixed the incongruence

william 2021-03-13T18:26:00.048700Z

it was because, due to how my system works, lein was using openjdk-15 while I was using adoptopenjdk-15 , so the version wasn't the problem, the two incompatible jdks were 😂

william 2021-03-13T18:26:21.048900Z

now, how would I proceed with the rest of the setup?

ericdallo 2021-03-13T18:30:19.049100Z

Oh, good to see another nix user here :) Yeah, sometimes nix is tricky

ericdallo 2021-03-13T18:30:56.049400Z

So you have your compiled clojure-lsp up and running, you can get the port via lsp-clojure-server-info

ericdallo 2021-03-13T18:31:12.049600Z

And them connect your cider to that running session with cider-connect

william 2021-03-13T18:31:24.049800Z

awesome: see, https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/development/tools/build-managers/leiningen/default.nix#L48 it just uses the jdk that it finds in the package-set, that for nixos-unstable is openjdk-15

william 2021-03-13T18:31:45.050100Z

trying lsp-clojure-server-info

william 2021-03-13T18:33:38.050700Z

ok, I should be connected into it, how do I make sure?

william 2021-03-13T18:34:24.051300Z

and generally, what do I do now? Open another emacs with the clojure-lsp code? I don't get how the new emacs can know which function I'm using

ericdallo 2021-03-13T18:37:05.051900Z

You can use that same section, basically it's a repl on a running code, any code that you eval will affect the running clojure-lsp

ericdallo 2021-03-13T18:37:23.052100Z

So if you change a function, you can eval and next time that function is called will use your code

ericdallo 2021-03-13T18:38:05.052300Z

You can code on clojure-lsp and eval the functions that way, or change the code, and recompile a new clijure-lsp with lein bin

william 2021-03-13T18:42:37.053Z

just to be sure that this is what you're suggesting: I should connect with my other emacs instance to the same server/same port, and at that point I can just send commands from both places

william 2021-03-13T18:44:18.053200Z

but that doesn't seem to do what I expect: I connected, then issued on the element-by-uri->call-hierarchy-item function the command cider-debug-defun-at-point

william 2021-03-13T18:44:43.053400Z

and I got an error:

clojure.lang.ExceptionInfo: null
#:clojure.error{:phase :read-source}
 at clojure.main$repl$read_eval_print__9110$fn__9111.invoke (main.clj:433)
    clojure.main$repl$read_eval_print__9110.invoke (main.clj:432)
    clojure.main$repl$fn__9119.invoke (main.clj:458)
    clojure.main$repl.invokeStatic (main.clj:458)
    clojure.main$repl.doInvoke (main.clj:368)
    clojure.lang.RestFn.invoke (RestFn.java:1523)
    nrepl.middleware.interruptible_eval$evaluate.invokeStatic (interruptible_eval.clj:84)
    nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)
    nrepl.middleware.interruptible_eval$interruptible_eval$fn__980$fn__984.invoke (interruptible_eval.clj:152)
    clojure.lang.AFn.run (AFn.java:22)
    nrepl.middleware.session$session_exec$main_loop__1048$fn__1052.invoke (session.clj:202)
    nrepl.middleware.session$session_exec$main_loop__1048.invoke (session.clj:201)
    clojure.lang.AFn.run (AFn.java:22)
    java.lang.Thread.run (Thread.java:832)
Caused by: clojure.lang.LispReader$ReaderException: java.lang.RuntimeException: No reader function for tag dbg

ericdallo 2021-03-13T18:46:54.053600Z

I never used cider debug and I'm not sure this is the way it should be used, so I can't help you with that, you can hack and code using default cider repl connected though

william 2021-03-13T18:50:53.053800Z

thanks! I'll ask in #cider now 😂

👍 1
snoe 2021-03-13T19:20:23.054500Z

it's a bit weird to me to be trying to debug the binary, if you have your editor launch lein run instead of the compile target it might help

👍 1
william 2021-03-13T23:57:12.055800Z

@snoe thanks! Could you be a bit more specific on how and where should I launch lein run?