-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use eclipse gradle plugin to get classpath with sources #439
base: main
Are you sure you want to change the base?
Conversation
Thanks for looking into this! That's a neat idea, though generating files in the user's project directory is something I'm trying to use sparingly. Ideally we could use the Gradle tooling API to get the dependencies from Gradle directly, see The tooling API offers an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat idea! Left a comment :)
@fwcd thanks for the link and context! I agree with your assessment on the other thread... it seems like a lot of work to create a whole new IDE plugin for LSP. I imagine most of what is needed to generate the classpath can be obtained from the I did think about the files in the user project, which is why I delete the |
2c76412
to
0c30db1
Compare
@fwcd figured out how to use the There are 2 major problems I'm still having (happy to create issues if needed) with go-to-definition. I'm currentyl using
|
Nice! What I had in mind would be to go a step further and resolve the |
@fwcd so I've been playing around a bit with the Tooling API. It's pretty straightforward to get the EclipseProject and the classes from that, but I haven't found how to get Here's a function showing how to get the sources using the tooling api:
|
Its been a 2+ years since I last used the eclipse model, but I remember back when using it with https://github.com/sourcegraph/scip-java that it was pretty suboptimal and often missed things when tested across a number of repositories across github (at one point i took the union of the eclipse + IDEA models + an init script from this repo as they both missed some that the other didnt). We're currently using this custom task, id be interested in knowing whether you know of how this compares to it off-hand (from my experience it worked better than the eclipse model, but again its been a long while so my memory may be very fuzzy) |
@Strum355 Interesting! honestly I have no idea how it compares. I've just started using Kotlin at work in the past 6 months and hate using IntelliJ; I've been trying to use Emacs but I can't seem to get anywhere near the ability to explore dependencies using the language server so I figured I'd take a stab at this. I don't really get much time to mess around with it though. I've been trying to find Do you think it would make sense for |
@@ -19,15 +19,18 @@ internal class GradleClassPathResolver(private val path: Path, private val inclu | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than building string commands, invoking the build and parsing the string output, line by line, I think that this whole file could just become a single call to the classpath, using the Eclipse model from the Gradle project connection. There's more information on the third party tooling web doc. They say that to find examples of calling Gradle's API from Java, you need to go through the JavaDoc, starting at the GradleConnector.
This could simplify the class a fair bit and improve the time it takes for the server to spin up. What do you think @aiguofer?
package org.javacs.kt.classpath
import org.gradle.tooling.GradleConnector
import org.gradle.tooling.model.eclipse.EclipseProject
import java.io.File
import java.nio.file.Path
internal class GradleClassPathResolver(private val path: Path) : ClassPathResolver {
override val resolverType: String = "Gradle"
private val projectDirectory: Path get() = path.parent
override val classpath: Set<ClassPathEntry> = GradleConnector
.newConnector()
.forProjectDirectory(File(projectDirectory.toString()))
.connect()
.use { connector ->
val model = connector.getModel(EclipseProject::class.java)
model.classpath.map {
ClassPathEntry(
compiledJar = it.source.toPath(),
sourceJar = null,
)
}.toSet()
}
}
cc @themkat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main issue is that apparently the EclipseProject
doesn't catch all the dependencies, especially for android dependencies. @Strum355 mentioned above that for SCIP they had to use a combination of EclipseProject
, IdeaProject
, and a gradle task that also builds some strings and passes them in to be parsed. I currently have a locally working branch that does it similarly, but the gradle task with string parsing definitely makes it slower.
When I have some time I'll try to make some comparisons of the outputs of each.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great, thanks @aiguofer! Strum's comment now makes much more sense!
I should've pinned the link to a specific commit, our gradle work just underwent some changes that Im not a part of 😬 we're not using init scripts anymore, but rather a gradle plugin itself |
ahh thanks @Strum355! One of the issues is that we're trying to get the source jars to add to the classpath entries, but only the |
I had originally created #410. The ability to navigate to sources is pretty crucial for me. This PR uses the built in Eclipse Gradle plugin to generate the Classpath with sources. The plugin creates a
.classpath
file, which we read and parse to generate the set ofClassPathEntry
for Gradle.This PR would still need some cleanup, but figured I'd put it out to see what others think of it.
There is still an issue when you navigate to a source where it tries to load it as a kotlin script and fails with something like: