Skip to content

Commit

Permalink
Use the EclipseModel directly to fetch dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
aiguofer committed Mar 15, 2023
1 parent 4bdd672 commit 0c30db1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@ internal class GradleClassPathResolver(private val path: Path, private val inclu

return readDependenciesViaGradleCLI(projectDirectory, scripts, tasks)
.apply { if (isNotEmpty()) LOG.info("Successfully resolved dependencies for '${projectDirectory.fileName}' using Gradle") }
.map { ClassPathEntry(it, null) }.toSet()
}
override val buildScriptClasspath: Set<Path> get() {
override val buildScriptClasspath: Set<Path>
get() {
return if (includeKotlinDSL) {
val scripts = listOf("kotlinDSLClassPathFinder.gradle")
val tasks = listOf("kotlinLSPKotlinDSLDeps")

return readDependenciesViaGradleCLI(projectDirectory, scripts, tasks)
.apply { if (isNotEmpty()) LOG.info("Successfully resolved build script dependencies for '${projectDirectory.fileName}' using Gradle") }
.map {
it.compiledJar
}.toSet()
} else {
emptySet()
}
Expand Down Expand Up @@ -70,24 +73,20 @@ private fun getGradleCommand(workspace: Path): Path {
}
}

private fun readDependenciesViaGradleCLI(projectDirectory: Path, gradleScripts: List<String>, gradleTasks: List<String>): Set<Path> {
private fun readDependenciesViaGradleCLI(projectDirectory: Path, gradleScripts: List<String>, gradleTasks: List<String>): Set<ClassPathEntry> {
LOG.info("Resolving dependencies for '{}' through Gradle's CLI using tasks {}...", projectDirectory.fileName, gradleTasks)

val tmpScripts = gradleScripts.map { gradleScriptToTempFile(it, deleteOnExit = false).toPath().toAbsolutePath() }
val gradle = getGradleCommand(projectDirectory)

val command = listOf(gradle.toString()) + tmpScripts.flatMap { listOf("-I", it.toString()) } + gradleTasks + listOf("--console=plain")
val dependencies = findGradleCLIDependencies(command, projectDirectory)
?.also { LOG.debug("Classpath for task {}", it) }
.orEmpty()
.filter { it.toString().lowercase().endsWith(".jar") || Files.isDirectory(it) } // Some Gradle plugins seem to cause this to output POMs, therefore filter JARs
.toSet()

tmpScripts.forEach(Files::delete)
return dependencies
}

private fun findGradleCLIDependencies(command: List<String>, projectDirectory: Path): Set<Path>? {
private fun findGradleCLIDependencies(command: List<String>, projectDirectory: Path): Set<ClassPathEntry> {
val (result, errors) = execAndReadStdoutAndStderr(command, projectDirectory)
if ("FAILURE: Build failed" in errors) {
LOG.warn("Gradle task failed: {}", errors)
Expand All @@ -101,13 +100,22 @@ private fun findGradleCLIDependencies(command: List<String>, projectDirectory: P
return parseGradleCLIDependencies(result)
}

private val artifactPattern by lazy { "kotlin-lsp-gradle (.+)(?:\r?\n)".toRegex() }
private val artifactPattern by lazy { "kotlin-lsp-gradle path:(.+) source:(.+)".toRegex() }
private val gradleErrorWherePattern by lazy { "\\*\\s+Where:[\r\n]+(\\S\\.*)".toRegex() }

private fun parseGradleCLIDependencies(output: String): Set<Path>? {
private fun parseGradleCLIDependencies(output: String): Set<ClassPathEntry> {
LOG.debug(output)
val artifacts = artifactPattern.findAll(output)
.mapNotNull { Paths.get(it.groups[1]?.value) }
.filterNotNull()
.map {
val path = it.groups[1]?.value
val source = it.groups[2]?.value
val jarPath = if (path == "null" || path == null) null else Path.of(path)
val sourceJarPath = if (source == "null" || source == null) null else Path.of(source)
if (jarPath != null && (path!!.lowercase().endsWith(".jar") || Files.isDirectory(jarPath))) {
LOG.debug { "Adding path:$jarPath source: $sourceJarPath to classpath" }
return@map ClassPathEntry(jarPath, sourceJarPath)
} else return@map null
}.filterNotNull()

return artifacts.toSet()
}
37 changes: 30 additions & 7 deletions shared/src/main/resources/projectClassPathFinder.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry
import org.gradle.plugins.ide.eclipse.model.EclipseModel
import org.gradle.plugins.ide.eclipse.model.Library

allprojects { project ->
apply plugin: "eclipse"

task kotlinLSPProjectDeps { task ->
doLast {
def classpaths = new HashMap()
System.out.println ""
System.out.println "gradle-version $gradleVersion"
System.out.println "kotlin-lsp-project ${project.name}"
Expand Down Expand Up @@ -28,33 +35,35 @@ allprojects { project ->
File.separator + variantBase +
File.separator + "classes"

System.out.println "kotlin-lsp-gradle $buildClasses"
classpaths[buildClasses.toString()] = null

def userClasses = project.getBuildDir().absolutePath +
File.separator + "intermediates" +
File.separator + "javac" +
File.separator + variantBase +
File.separator + "compile" + variantBase.capitalize() + "JavaWithJavac" + File.separator + "classes"

System.out.println "kotlin-lsp-gradle $userClasses"
classpaths[userClasses.toString()] = null

def userVariantClasses = project.getBuildDir().absolutePath +
File.separator + "intermediates" +
File.separator + "javac" +
File.separator + variantBase +
File.separator + "classes"

System.out.println "kotlin-lsp-gradle $userVariantClasses"
classpaths[userVariantClasses.toString()] = null

variant.getCompileClasspath().each {
System.out.println "kotlin-lsp-gradle $it"
classpaths[it.toString()] = null
}
}


} else if (project.hasProperty('sourceSets')) {
// Print the list of all dependencies jar files.
sourceSets.forEach {
it.compileClasspath.forEach {
System.out.println "kotlin-lsp-gradle $it"
classpaths[it.toString()] = null
}
}
}
Expand All @@ -69,18 +78,32 @@ allprojects { project ->
kotlinExtension.targets.names.each {
def classpath = configurations["${it}CompileClasspath"]
classpath.files.each {
System.out.println "kotlin-lsp-gradle $it"
classpaths[it.toString()] = null
}
}
}

EclipseModel eclipseModel = project.extensions.getByType(EclipseModel.class)

for (ClasspathEntry dep : (eclipseModel.getClasspath().resolveDependencies())) {
if (dep instanceof Library) {
if (classpaths.get(dep.getPath()) == null){
classpaths[dep.getPath()] = dep.getSourcePath()?.getPath()
}
}
}

for (e in classpaths) {
System.out.println "kotlin-lsp-gradle path:$e.key source:$e.value"
}
}
}

task kotlinLSPAllGradleDeps {
doLast {
fileTree("$gradle.gradleHomeDir/lib")
.findAll { it.toString().endsWith '.jar' }
.forEach { System.out.println "kotlin-lsp-gradle $it" }
.forEach { System.out.println "kotlin-lsp-gradle path:$it source:null" }
}
}
}

0 comments on commit 0c30db1

Please sign in to comment.