@@ -9,17 +9,43 @@ import java.io.File
9
9
import java.nio.file.Files
10
10
import java.nio.file.Path
11
11
import java.nio.file.Paths
12
+ import org.simpleframework.xml.Attribute
13
+ import org.simpleframework.xml.ElementList
14
+ import org.simpleframework.xml.Root
15
+ import org.simpleframework.xml.Serializer
16
+ import org.simpleframework.xml.core.Persister
17
+ import kotlin.io.path.notExists
18
+ import kotlin.io.path.readText
19
+
20
+
21
+ @Root(strict = false )
22
+ class XmlClasspathEntry {
23
+ @field:Attribute(name = " kind" , required = true )
24
+ lateinit var kind: String
25
+
26
+ @field:Attribute(name = " path" , required = false )
27
+ var path: String? = null
28
+
29
+ @field:Attribute(name = " sourcepath" , required = false )
30
+ var sourcepath: String? = null
31
+ }
32
+
33
+ @Root(strict = false , name = " classpath" )
34
+ class XmlClasspath {
35
+ @field:ElementList(required = false , entry = " classpathentry" , inline = true )
36
+ lateinit var entries: List <XmlClasspathEntry >
37
+ }
12
38
13
39
internal class GradleClassPathResolver (private val path : Path , private val includeKotlinDSL : Boolean ): ClassPathResolver {
14
40
override val resolverType: String = " Gradle"
15
41
private val projectDirectory: Path get() = path.getParent()
16
42
override val classpath: Set <ClassPathEntry > get() {
17
- val scripts = listOf (" projectClassPathFinder.gradle" )
18
- val tasks = listOf (" kotlinLSPProjectDeps" )
43
+ val scripts = listOf (" projectEclipseClassPathFinder.gradle" )
44
+ val tasks = listOf (" eclipseClasspath" )
45
+
46
+ executeGradleScript(projectDirectory, scripts, tasks)
19
47
20
- return readDependenciesViaGradleCLI(projectDirectory, scripts, tasks)
21
- .apply { if (isNotEmpty()) LOG .info(" Successfully resolved dependencies for '${projectDirectory.fileName} ' using Gradle" ) }
22
- .map { ClassPathEntry (it, null ) }.toSet()
48
+ return parseDotClasspath(projectDirectory)
23
49
}
24
50
override val buildScriptClasspath: Set <Path > get() {
25
51
return if (includeKotlinDSL) {
@@ -70,25 +96,33 @@ private fun getGradleCommand(workspace: Path): Path {
70
96
}
71
97
}
72
98
73
- private fun readDependenciesViaGradleCLI (projectDirectory : Path , gradleScripts : List <String >, gradleTasks : List <String >): Set < Path > {
99
+ private fun executeGradleScript (projectDirectory : Path , gradleScripts : List <String >, gradleTasks : List <String >): Pair < String , String > {
74
100
LOG .info(" Resolving dependencies for '{}' through Gradle's CLI using tasks {}..." , projectDirectory.fileName, gradleTasks)
75
101
76
102
val tmpScripts = gradleScripts.map { gradleScriptToTempFile(it, deleteOnExit = false ).toPath().toAbsolutePath() }
77
103
val gradle = getGradleCommand(projectDirectory)
78
104
79
105
val command = listOf (gradle.toString()) + tmpScripts.flatMap { listOf (" -I" , it.toString()) } + gradleTasks + listOf (" --console=plain" )
80
- val dependencies = findGradleCLIDependencies(command, projectDirectory)
106
+ LOG .debug(" Running command: $command " )
107
+ val ret = execAndReadStdoutAndStderr(command, projectDirectory)
108
+ tmpScripts.forEach(Files ::delete)
109
+ return ret
110
+ }
111
+
112
+ private fun readDependenciesViaGradleCLI (projectDirectory : Path , gradleScripts : List <String >, gradleTasks : List <String >): Set <Path > {
113
+ val (result, errors) = executeGradleScript(projectDirectory, gradleScripts, gradleTasks)
114
+
115
+ val dependencies = findGradleCLIDependencies(result, errors)
81
116
?.also { LOG .debug(" Classpath for task {}" , it) }
82
117
.orEmpty()
83
118
.filter { it.toString().lowercase().endsWith(" .jar" ) || Files .isDirectory(it) } // Some Gradle plugins seem to cause this to output POMs, therefore filter JARs
84
119
.toSet()
85
120
86
- tmpScripts.forEach( Files ::delete)
121
+
87
122
return dependencies
88
123
}
89
124
90
- private fun findGradleCLIDependencies (command : List <String >, projectDirectory : Path ): Set <Path >? {
91
- val (result, errors) = execAndReadStdoutAndStderr(command, projectDirectory)
125
+ private fun findGradleCLIDependencies (result : String , errors : String ): Set <Path >? {
92
126
if (" FAILURE: Build failed" in errors) {
93
127
LOG .warn(" Gradle task failed: {}" , errors)
94
128
} else {
@@ -111,3 +145,27 @@ private fun parseGradleCLIDependencies(output: String): Set<Path>? {
111
145
.filterNotNull()
112
146
return artifacts.toSet()
113
147
}
148
+
149
+ private fun parseDotClasspath (projectDirectory : Path ) : Set <ClassPathEntry > {
150
+ val dotClasspath = projectDirectory.resolve(" .classpath" )
151
+ if (dotClasspath.notExists()){
152
+ return emptySet()
153
+ }
154
+ val xmlToParse = dotClasspath.readText()
155
+ val serializer: Serializer = Persister ()
156
+ val classpath = serializer.read(XmlClasspath ::class .java, xmlToParse)
157
+ val ret =
158
+ classpath
159
+ .entries
160
+ .map {
161
+ ClassPathEntry (Path .of(it.path ? : " " ), Path .of(it.sourcepath ? : " " ))
162
+ }
163
+ .toSet()
164
+
165
+ if (ret.isNotEmpty()) {
166
+ LOG .info(" Using classpath from .classpath" )
167
+ }
168
+ dotClasspath.toFile().delete()
169
+ return ret
170
+
171
+ }
0 commit comments