Skip to content

Commit 037c9df

Browse files
fix: use existing async executor
1 parent 61619b3 commit 037c9df

File tree

1 file changed

+96
-58
lines changed

1 file changed

+96
-58
lines changed

server/src/main/kotlin/org/javacs/kt/CompilerClassPath.kt

Lines changed: 96 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
package org.javacs.kt
22

3-
import org.javacs.kt.classpath.ClassPathEntry
4-
import org.javacs.kt.classpath.defaultClassPathResolver
5-
import org.javacs.kt.compiler.Compiler
6-
import org.javacs.kt.database.DatabaseService
7-
import org.javacs.kt.util.AsyncExecutor
83
import java.io.Closeable
94
import java.io.File
105
import java.nio.file.FileSystems
116
import java.nio.file.Files
127
import java.nio.file.Path
138
import java.util.concurrent.CompletableFuture
9+
import org.javacs.kt.classpath.ClassPathEntry
10+
import org.javacs.kt.classpath.ClassPathResolver
11+
import org.javacs.kt.classpath.defaultClassPathResolver
12+
import org.javacs.kt.compiler.Compiler
13+
import org.javacs.kt.database.DatabaseService
14+
import org.javacs.kt.util.AsyncExecutor
1415

1516
/**
16-
* Manages the class path (compiled JARs, etc), the Java source path
17-
* and the compiler. Note that Kotlin sources are stored in SourcePath.
17+
* Manages the class path (compiled JARs, etc), the Java source path and the compiler. Note that
18+
* Kotlin sources are stored in SourcePath.
1819
*/
1920
class CompilerClassPath(
2021
private val config: CompilerConfiguration,
2122
private val scriptsConfig: ScriptsConfiguration,
2223
private val codegenConfig: CodegenConfiguration,
23-
private val databaseService: DatabaseService
24+
private val databaseService: DatabaseService,
2425
) : Closeable {
2526
val workspaceRoots = mutableSetOf<Path>()
2627

@@ -30,14 +31,15 @@ class CompilerClassPath(
3031
val outputDirectory: File = Files.createTempDirectory("klsBuildOutput").toFile()
3132
val javaHome: String? = System.getProperty("java.home", null)
3233

33-
var compiler = Compiler(
34-
javaSourcePath,
35-
classPath.map { it.compiledJar }.toSet(),
36-
buildScriptClassPath,
37-
scriptsConfig,
38-
codegenConfig,
39-
outputDirectory
40-
)
34+
var compiler =
35+
Compiler(
36+
javaSourcePath,
37+
classPath.map { it.compiledJar }.toSet(),
38+
buildScriptClassPath,
39+
scriptsConfig,
40+
codegenConfig,
41+
outputDirectory,
42+
)
4143
private set
4244

4345
private val async = AsyncExecutor()
@@ -50,65 +52,94 @@ class CompilerClassPath(
5052
private fun refresh(
5153
updateClassPath: Boolean = true,
5254
updateBuildScriptClassPath: Boolean = true,
53-
updateJavaSourcePath: Boolean = true
55+
updateJavaSourcePath: Boolean = true,
5456
): Boolean {
5557
val resolver = defaultClassPathResolver(workspaceRoots, databaseService.db)
5658
var refreshCompiler = updateJavaSourcePath
57-
val asyncExecutor = AsyncExecutor()
58-
59-
val classPathFuture = if (updateClassPath) {
60-
asyncExecutor.compute {
61-
val newClassPath = resolver.classpathOrEmpty
62-
if (newClassPath != classPath) {
63-
synchronized(classPath) {
64-
syncPaths(classPath, newClassPath, "class path") { it.compiledJar }
65-
}
66-
refreshCompiler = true
67-
}
6859

69-
asyncExecutor.compute {
70-
val newClassPathWithSources = resolver.classpathWithSources
71-
synchronized(classPath) {
72-
syncPaths(classPath, newClassPathWithSources, "class path with sources") { it.compiledJar }
73-
}
74-
}
60+
val classPathFuture =
61+
if (updateClassPath) {
62+
updateClassPathAsync(resolver)
63+
} else {
64+
CompletableFuture.completedFuture(false)
7565
}
76-
} else {
77-
CompletableFuture.completedFuture(null)
78-
}
7966

80-
val buildScriptClassPathFuture = if (updateBuildScriptClassPath) {
81-
asyncExecutor.compute {
82-
LOG.info("Update build script path")
83-
val newBuildScriptClassPath = resolver.buildScriptClasspathOrEmpty
84-
if (newBuildScriptClassPath != buildScriptClassPath) {
85-
syncPaths(buildScriptClassPath, newBuildScriptClassPath, "build script class path") { it }
86-
refreshCompiler = true
87-
}
67+
val buildScriptClassPathFuture =
68+
if (updateBuildScriptClassPath) {
69+
updateBuildScriptClassPathAsync(resolver)
70+
} else {
71+
CompletableFuture.completedFuture(false)
8872
}
89-
} else {
90-
CompletableFuture.completedFuture(null)
91-
}
9273

74+
// Wait for both futures to complete
9375
CompletableFuture.allOf(classPathFuture, buildScriptClassPathFuture).join()
9476

77+
// Update refreshCompiler based on the results of the futures
78+
refreshCompiler =
79+
refreshCompiler || classPathFuture.get() || buildScriptClassPathFuture.get()
80+
9581
if (refreshCompiler) {
9682
LOG.info("Reinstantiating compiler")
9783
compiler.close()
98-
compiler = Compiler(
99-
javaSourcePath,
100-
classPath.map { it.compiledJar }.toSet(),
101-
buildScriptClassPath,
102-
scriptsConfig,
103-
codegenConfig,
104-
outputDirectory
105-
)
84+
compiler =
85+
Compiler(
86+
javaSourcePath,
87+
classPath.map { it.compiledJar }.toSet(),
88+
buildScriptClassPath,
89+
scriptsConfig,
90+
codegenConfig,
91+
outputDirectory,
92+
)
10693
updateCompilerConfiguration()
10794
}
10895

10996
return refreshCompiler
11097
}
11198

99+
private fun updateClassPathAsync(resolver: ClassPathResolver): CompletableFuture<Boolean> {
100+
return async.compute {
101+
var updated = false
102+
val newClassPath = resolver.classpathOrEmpty
103+
if (newClassPath != classPath) {
104+
synchronized(classPath) {
105+
syncPaths(classPath, newClassPath, "class path") { it.compiledJar }
106+
}
107+
updated = true
108+
}
109+
110+
val newClassPathWithSources = resolver.classpathWithSources
111+
synchronized(classPath) {
112+
syncPaths(classPath, newClassPathWithSources, "class path with sources") {
113+
it.compiledJar
114+
}
115+
}
116+
117+
updated
118+
}
119+
}
120+
121+
private fun updateBuildScriptClassPathAsync(
122+
resolver: ClassPathResolver
123+
): CompletableFuture<Boolean> {
124+
return async.compute {
125+
var updated = false
126+
LOG.info("Update build script path")
127+
val newBuildScriptClassPath = resolver.buildScriptClasspathOrEmpty
128+
if (newBuildScriptClassPath != buildScriptClassPath) {
129+
synchronized(buildScriptClassPath) {
130+
syncPaths(
131+
buildScriptClassPath,
132+
newBuildScriptClassPath,
133+
"build script class path",
134+
) {
135+
it
136+
}
137+
}
138+
updated = true
139+
}
140+
updated
141+
}
142+
}
112143

113144
/** Synchronizes the given two path sets and logs the differences. */
114145
private fun <T> syncPaths(dest: MutableSet<T>, new: Set<T>, name: String, toPath: (T) -> Path) {
@@ -162,15 +193,22 @@ class CompilerClassPath(
162193
val buildScript = isBuildScript(file)
163194
val javaSource = isJavaSource(file)
164195
if (buildScript || javaSource) {
165-
return refresh(updateClassPath = buildScript, updateBuildScriptClassPath = false, updateJavaSourcePath = javaSource)
196+
return refresh(
197+
updateClassPath = buildScript,
198+
updateBuildScriptClassPath = false,
199+
updateJavaSourcePath = javaSource,
200+
)
166201
} else {
167202
return false
168203
}
169204
}
170205

171206
private fun isJavaSource(file: Path): Boolean = file.fileName.toString().endsWith(".java")
172207

173-
private fun isBuildScript(file: Path): Boolean = file.fileName.toString().let { it == "pom.xml" || it == "build.gradle" || it == "build.gradle.kts" }
208+
private fun isBuildScript(file: Path): Boolean =
209+
file.fileName.toString().let {
210+
it == "pom.xml" || it == "build.gradle" || it == "build.gradle.kts"
211+
}
174212

175213
private fun findJavaSourceFiles(root: Path): Set<Path> {
176214
val sourceMatcher = FileSystems.getDefault().getPathMatcher("glob:*.java")

0 commit comments

Comments
 (0)