Fork me on GitHub

@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?


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


yes, probably šŸ™‚


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.RemoteEndpoint.handleRequest(
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(
	at java.base/java.util.concurrent.Executors$
	at java.base/
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(
	at java.base/java.util.concurrent.ThreadPoolExecutor$
	at java.base/
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(
	at java.base/java.lang.reflect.Method.invoke(
	... 11 more
Caused by: java.lang.UnsupportedOperationException
	... 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?


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)


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?


You mean, debug the code only with LSP?


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


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


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


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


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


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


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"))


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


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


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


only ./target/clojure-lsp


$ ./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


it's a java version problem, let me understand who's who here šŸ˜‚


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


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


that's because 59.0 is jdk15?


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


that's expected


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


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


at /tmp/clojure-lsp.*.out


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


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


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


and lsp-workspace-restart


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


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:
which is the position of the executable


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


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


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


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


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].


Is that the correct project root?


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


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


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


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


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


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.util.concurrent.ThreadPoolExecutor$    630
                                      java.util.concurrent.ThreadPoolExecutor.runWorker   1130
                                    java.util.concurrent.Executors$             515
                            org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen   94
                     org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage  194
                                       org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume        190
                                 org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest        261
             $null$0        65
                               jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke   43
                                   jdk.internal.reflect.NativeMethodAccessorImpl.invoke   64
                                                                 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         189
                                                   java.sql.DriverManager.getConnection         677
                                                                org.sqlite.JDBC.connect                   90


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


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


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


Never saw that error before


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


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


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


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


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


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


I use jdk11 and 8 and both works


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


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


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


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


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



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


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


so I could do:

and then execute lein with-profile :debug bin


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


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 šŸ˜‚


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


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


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


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


awesome: see, it just uses the jdk that it finds in the package-set, that for nixos-unstable is openjdk-15


trying lsp-clojure-server-info


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


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


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


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


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


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


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


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 (
    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) (
    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) ( (
Caused by: clojure.lang.LispReader$ReaderException: java.lang.RuntimeException: No reader function for tag dbg


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


thanks! I'll ask in #cider now šŸ˜‚

šŸ‘ 3

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

šŸ‘ 3

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


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


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


thanks @UKFSJSM38! 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


I never used cider debug with clojure and with this setup: I can work really well


I use CIDER a lot though