Fork me on GitHub
#lsp
<
2024-06-03
>
lassemaatta05:06:27

(perhaps this has been discussed before) Is it possible to navigate to the original Java sources from .clj files when doing interop?

lassemaatta05:06:49

Background: • Using leiningen • Have [some.lib "1.0"] and [some.lib "1.0" :classifier "sources"] in project.clj • Tried both eglot and lsp-mode

lassemaatta05:06:28

With cider, I can e.g. cider-doc when over a Java class name to open a doc buffer, which shows the original javadoc descriptions. This buffer also includes a link to the original (non-decompiled) sources under ~/.m2/.. , which allows me to browse the original java sources

lassemaatta05:06:37

But when I try something similar with LSP (e.g. xref-find-definitions): I get a buffer with decompiled Java sources ("Decompiled with CFR 0.152.")

lassemaatta05:06:33

I tried setting :java {:decompile-jar-as-project? false} in my config, but it does not seem to have any effect

lassemaatta06:06:32

Actually, it seems like sometimes navigation to sources works as expected :thinking_face: If I open a project (or restart eglot/lsp-mode), navigating to a class from a (let [^SomeClass foo (get-foo)] .. seems to work fine and I get the sources for SomeClass. However, if later in the code I try the same for (SomeClass/staticMethod) then I get the decompiled sources. And if I go back to the earlier line (the let example) then that now also links to the decompiled sources.

lassemaatta06:06:08

So it feels like sometimes some references trigger the decompilation and once that happens, the original sources are no longer available and the decompiled sources are preferred

ericdallo12:06:15

if we have the original java source code, we should not decompile, it's probably a bug I'm interested in solving if it's happening

ericdallo12:06:41

any chance you make a repro in https://github.com/ericdallo/clojure-sample in a branch or any other public repo?

lassemaatta12:06:37

Sure, I’ll try to create a repro later

👍 1
lassemaatta14:06:05

I was lazy so I just published this very WIP project I'm working on: https://github.com/lassemaatta/murmeli/blob/master/project.clj

lassemaatta14:06:30

I also included the .lsp/config.edn

ericdallo14:06:26

thanks, I'll try to check it soon

lassemaatta14:06:49

In summary (at least on my machine): • xref-find-definitions on something like ^MongoClients -> Opens the proper java sources ◦ Under ~/.emacs.d/workspace/.cache/com.mongodb.client.MongoClients.java (in lsp-mode) ◦ Under ~/.m2/repository/org/mongodb-driver-sync/.../MongoClients.java (in eglot) • xref-find-definitions on something like ServerApiVersion/V1 (or (ServerApi/builder)) -> Opens the decompiled sources ◦ Under .lsp/.cache/java/decompiled/com/mongodb/client/MongoClients.java

ericdallo16:06:03

BTW as a fun fact: there is a lsp-mode command I created called lsp-clojure-cursor-info , which will tell what's the token at cursor and its definition, pretty useful to debug if analysis are correct for that buffer

ericdallo16:06:54

with that, we can see that we have java source analysis for com.mongodb.client package but not for com.mongodb , that's why we decompile it. Is the classes of that package also available?

ericdallo16:06:15

Checking the jar, I can only see java source classes for com.mongodb.client indeed

lassemaatta17:06:39

that's what I get for lsp-clojure-cursor-info, yet I get the decompiled sources when I navigate to it

ericdallo20:06:04

hum, it works for me, it goes to the source MongoClients/create :thinking_face:

{:node
 {:value MongoClients/create,
  :string-value "MongoClients/create",
  :map-qualifier nil},
 :elements
 [{:element
   {:end-row 29,
    :name-end-col 45,
    :external? false,
    :name-end-row 29,
    :call true,
    :method-name "create",
    :name-row 29,
    :lang :clj,
    :col 25,
    :class "com.mongodb.client.MongoClients",
    :name-col 26,
    :uri
    "file:///home/greg/dev/clojure-lsp-java-source-issue/src/murmeli/core.clj",
    :end-col 55,
    :bucket :java-class-usages,
    :row 29},
   :definition
   {:end-row 41,
    :name-end-col 0,
    :external? true,
    :name-end-row 0,
    :name-row 0,
    :return-type "MongoClient",
    :name "create",
    :col 5,
    :class "com.mongodb.client.MongoClients",
    :name-col 0,
    :uri
    "jar:file:///home/greg/.m2/repository/org/mongodb/mongodb-driver-sync/5.1.0/mongodb-driver-sync-5.1.0-sources.jar!/com/mongodb/client/MongoClients.java",
    :end-col 5,
    :flags #{:method :public :static},
    :doc
    "/**\n     * Creates a new client with the default connection string \"\".\n     *\n     * @return the client\n     */",
    :parameters [],
    :bucket :java-member-definitions,
    :row 39},
   :semantic-tokens [{:token-type :class, :token-modifier []}]}]} 

ericdallo00:06:42

Mine is happening because of https://github.com/clojure-lsp/clojure-lsp/blob/8ac7b42f6e4e8afb34bb7b669891f96a38653cb0/lib/src/clojure_lsp/queries.clj#L342, the only thing I can think is that for some reason, there are no java-class-definitions or java-member-definitions for your project when starting it, can you try to clean the .lsp/.cache to see if it changes anything?