fwcd / kotlin-language-server

Kotlin code completion, diagnostics and more for any editor/IDE using the Language Server Protocol
MIT License
1.67k stars 210 forks source link

Go-to-definition not working for external java jar #410

Closed aiguofer closed 1 year ago

aiguofer commented 1 year ago

I'm pretty new to Kotlin dev and I'm trying to see if I can use Emacs with lsp instead of IntelliJ. Go to def is working fine for objects in my project, but when I try to go to def for some of the external libs it seems to fail.

Here's an example of what I see in lsp logs:

async2    Found declaration descriptor Lazy Java class org.apache.arrow.flight.FlightServer
async2    Finished in 11 ms
The following file kls:file:///Users/aiguofer/.gradle/caches/modules-2/files-2.1/org.apache.arrow/flight-core/10.0.1/626dcd8fb0f467cb93ca17e8fcfee1bb383b96d3/flight-core-10.0.1.jar!/org/apache/arrow/flight/FlightServer.kt is missing, ignoring from the results.

Interestingly, when I go to definition within IntelliJ, it actually opens up FlightServer.java instead of FlightServer.kt. Not sure why it's trying to open the file using the wrong extension.

aiguofer commented 1 year ago

Nvm, after looking more into docs I found the following settings: lsp-kotlin-external-sources-auto-convert-to-kotlin and lsp-kotlin-external-sources-use-kls-scheme. Playing around with these got it working. Other lines I saw in logs were:

async2    J2K can not convert Keyword yet
async2    J2K can not convert ClassObjectAccessExpression yet

My guess is it tried to convert the Java file to Kotlin and failed, and that's why it didn't exist. I'll leave the conversion turned off until it gets better.

daplf commented 1 year ago

Hey @aiguofer

It seems that you are using Gradle. Go to definition for Gradle currently relies solely on decompiling the external dependencies. On top of that, we also have the J2K mechanism in place, which is still missing some features.

If you can use Maven instead of Gradle, you will have access to source JARs, which make things much easier.

aiguofer commented 1 year ago

Thanks for the info @daplf! unfortunately my team already decided on Gradle so I don't have much of a choice. It looks like if I disable convert to kotlin and use kls scheme it decompiles the class object into a temp buffer which works well enough. My guess is that's exactly what IntelliJ is doing? or maybe they go and fetch all the source jars themselves...

daplf commented 1 year ago

@aiguofer Intellij can fetch source jars. I don't know if it does so automatically though.

aiguofer commented 1 year ago

@daplf So I've been getting a better understanding of Gradle. It looks like there's a Gradle plugin for Eclipse that can download the source jars and create a .classpath file including the path to those sources. It seems like it'd be pretty easy to implement a ClassPathResolver that reads that file if it's present.

Alternatively, there could be a gradle task that does something similar and gets called by the MavenClassPathResolver.

Thoughts?