Fork me on GitHub
#lsp
<
2021-03-13
>
ericdallo01:03:31

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

bringe01:03:09

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

ericdallo01:03:48

yes, probably šŸ™‚

william13:03:17

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?

william13:03:36

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)

william13:03:36

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?

ericdallo14:03:23

You mean, debug the code only with LSP?

william14:03:15

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

william14:03:49

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

ericdallo14:03:05

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

ericdallo14:03:40

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

william14:03:12

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

william14:03:51

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

ericdallo14:03:47

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

ericdallo14:03:05

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

william14:03:00

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

ericdallo14:03:33

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

ericdallo14:03:40

only ./target/clojure-lsp

william14:03:19

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

william14:03:47

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

ericdallo14:03:41

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

ericdallo14:03:09

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

william14:03:39

that's because 59.0 is jdk15?

william14:03:16

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

ericdallo14:03:40

that's expected

william14:03:30

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

ericdallo14:03:23

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

william14:03:39

at /tmp/clojure-lsp.*.out

ericdallo14:03:05

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

ericdallo14:03:15

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

ericdallo14:03:36

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

ericdallo14:03:52

and lsp-workspace-restart

ericdallo14:03:24

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

william14:03:47

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

ericdallo14:03:28

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

william14:03:23

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

william14:03:54

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

ericdallo15:03:47

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

william16:03:12

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

ericdallo16:03:22

Is that the correct project root?

william16:03:57

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

william16:03:22

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

ericdallo16:03:30

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

ericdallo16:03:46

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

william16:03:18

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

william16:03:18

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

william16:03:34

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

william16:03:49

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

ericdallo17:03:49

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

ericdallo17:03:59

Never saw that error before

ericdallo17:03:35

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

william17:03:14

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

ericdallo17:03:06

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

william17:03:29

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

william17:03:56

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

william17:03:12

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

ericdallo17:03:40

I use jdk11 and 8 and both works

william17:03:52

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

ericdallo17:03:00

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

william17:03:28

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

ericdallo17:03:10

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

william17:03:38

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

william17:03:46

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

ericdallo18:03:25

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

william18:03:33

so I could do:

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

william18:03:35

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

william18:03:00

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

william18:03:21

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

ericdallo18:03:19

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

ericdallo18:03:56

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

ericdallo18:03:12

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

william18:03:24

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

william18:03:45

trying lsp-clojure-server-info

william18:03:38

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

william18:03:24

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

ericdallo18:03:05

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

ericdallo18:03:23

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

ericdallo18:03:05

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

william18:03:37

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

william18:03:18

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

william18:03:43

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

ericdallo18:03:54

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

william18:03:53

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

šŸ‘ 3
snoe19:03:23

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
william23:03:12

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

william16:03:52

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

ericdallo14:03:03

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

william14:03:46

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

ericdallo14:03:10

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

ericdallo14:03:19

I use CIDER a lot though