The face configuration looks very useful, thank you.
@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?
https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/config.clj#L16-L33
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.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?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?
thanks again @snoe! 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
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
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
I never used cider debug with clojure and with this setup: https://clojure-lsp.github.io/clojure-lsp/#development I can work really well
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
I use CIDER a lot though
oh got it
Usinghttps://clojure-lsp.github.io/clojure-lsp/#development is quite easy to achive that
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
Also check if the error is expected, like here: https://clojure-lsp.github.io/clojure-lsp/troubleshooting/#server-is-not-initializing
$ ./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?
yep
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
Do this check to see if it's running: https://clojure-lsp.github.io/clojure-lsp/troubleshooting/#server-is-not-initializing
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
oh
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:
("/home/carlo/code/clojure/clojure-lsp/target/clojure-lsp")
which is the position of the executabletry 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 capabilityI 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.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
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
fileReally 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?
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 versionWhen 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:
JAVA_PATH=/nix/store/52ynjxkdx8swmmkdvl27blw9bd77gxxr-adoptopenjdk-openj9-bin-11.0.9/bin/
and then execute lein with-profile :debug bin
awesome! It works now @ericdallo, 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, 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
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 (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
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 😂
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
@snoe thanks! Could you be a bit more specific on how and where should I launch lein run
?