Use daemon if available for parsing files in JPS

Original commit: 6f59b6da8e
This commit is contained in:
Alexey Tsvetkov
2018-04-03 21:09:29 +03:00
parent 88c4f73e3c
commit a47d5434f3
3 changed files with 46 additions and 20 deletions
@@ -101,8 +101,8 @@ object CompilerRunnerUtil {
} }
fun invokeClassesFqNames( fun invokeClassesFqNames(
files: Set<File>, environment: JpsCompilerEnvironment,
environment: JpsCompilerEnvironment files: Set<File>
): Set<String> = withCompilerClassloader(environment) { classLoader -> ): Set<String> = withCompilerClassloader(environment) { classLoader ->
val klass = Class.forName("org.jetbrains.kotlin.parsing.util.ParseFileUtilsKt", true, classLoader) val klass = Class.forName("org.jetbrains.kotlin.parsing.util.ParseFileUtilsKt", true, classLoader)
val method = klass.getMethod("classesFqNames", Set::class.java) val method = klass.getMethod("classesFqNames", Set::class.java)
@@ -72,6 +72,20 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
const val FAIL_ON_FALLBACK_PROPERTY = "test.kotlin.jps.compiler.runner.fail.on.fallback" const val FAIL_ON_FALLBACK_PROPERTY = "test.kotlin.jps.compiler.runner.fail.on.fallback"
} }
fun classesFqNamesByFiles(
environment: JpsCompilerEnvironment,
files: Set<File>
): Set<String> = withDaemonOrFallback(
withDaemon = {
doWithDaemon(environment) { sessionId, daemon ->
daemon.classesFqNamesByFiles(sessionId, files)
}
},
fallback = {
CompilerRunnerUtil.invokeClassesFqNames(environment, files)
}
)
fun runK2JvmCompiler( fun runK2JvmCompiler(
commonArguments: CommonCompilerArguments, commonArguments: CommonCompilerArguments,
k2jvmArguments: K2JVMCompilerArguments, k2jvmArguments: K2JVMCompilerArguments,
@@ -122,12 +136,10 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
): ExitCode { ): ExitCode {
log.debug("Using kotlin-home = " + environment.kotlinPaths.homePath) log.debug("Using kotlin-home = " + environment.kotlinPaths.homePath)
return if (isDaemonEnabled()) { return withDaemonOrFallback(
val daemonExitCode = compileWithDaemon(compilerClassName, compilerArgs, environment) withDaemon = { compileWithDaemon(compilerClassName, compilerArgs, environment) },
daemonExitCode ?: fallbackCompileStrategy(compilerArgs, compilerClassName, environment) fallback = { fallbackCompileStrategy(compilerArgs, compilerClassName, environment) }
} else { )
fallbackCompileStrategy(compilerArgs, compilerClassName, environment)
}
} }
override fun compileWithDaemon( override fun compileWithDaemon(
@@ -141,15 +153,6 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
K2METADATA_COMPILER -> CompileService.TargetPlatform.METADATA K2METADATA_COMPILER -> CompileService.TargetPlatform.METADATA
else -> throw IllegalArgumentException("Unknown compiler type $compilerClassName") else -> throw IllegalArgumentException("Unknown compiler type $compilerClassName")
} }
log.debug("Try to connect to daemon")
val connection = getDaemonConnection(environment)
if (connection == null) {
log.info("Could not connect to daemon")
return null
}
val (daemon, sessionId) = connection
val compilerMode = CompilerMode.JPS_COMPILER val compilerMode = CompilerMode.JPS_COMPILER
val verbose = compilerArgs.verbose val verbose = compilerArgs.verbose
val options = CompilationOptions( val options = CompilationOptions(
@@ -159,10 +162,33 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
reportSeverity(verbose), reportSeverity(verbose),
requestedCompilationResults = emptyArray() requestedCompilationResults = emptyArray()
) )
val res = return doWithDaemon(environment) { sessionId, daemon ->
daemon.compile(sessionId, withAdditionalCompilerArgs(compilerArgs), options, JpsCompilerServicesFacadeImpl(environment), null) daemon.compile(sessionId, withAdditionalCompilerArgs(compilerArgs), options, JpsCompilerServicesFacadeImpl(environment), null)
}?.let { exitCodeFromProcessExitCode(it) }
}
private fun <T> withDaemonOrFallback(withDaemon: () -> T?, fallback: () -> T): T =
if (isDaemonEnabled()) {
withDaemon() ?: fallback()
} else {
fallback()
}
private fun <T> doWithDaemon(
environment: JpsCompilerEnvironment,
fn: (sessionId: Int, daemon: CompileService) -> CompileService.CallResult<T>
): T? {
log.debug("Try to connect to daemon")
val connection = getDaemonConnection(environment)
if (connection == null) {
log.info("Could not connect to daemon")
return null
}
val (daemon, sessionId) = connection
val res = fn(sessionId, daemon)
// TODO: consider implementing connection retry, instead of fallback here // TODO: consider implementing connection retry, instead of fallback here
return res.takeUnless { it is CompileService.CallResult.Dying }?.let { exitCodeFromProcessExitCode(it.get()) } return res.takeUnless { it is CompileService.CallResult.Dying }?.get()
} }
private fun withAdditionalCompilerArgs(compilerArgs: CommonCompilerArguments): Array<String> { private fun withAdditionalCompilerArgs(compilerArgs: CommonCompilerArguments): Array<String> {
@@ -190,7 +190,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val dirtyFiles = chunkDirtyFiles[target] val dirtyFiles = chunkDirtyFiles[target]
val removedFiles = chunkRemovedFiles[target] ?: emptyList() val removedFiles = chunkRemovedFiles[target] ?: emptyList()
val existingClasses = CompilerRunnerUtil.invokeClassesFqNames(dirtyFiles.toHashSet(), environment) val existingClasses = JpsKotlinCompilerRunner().classesFqNamesByFiles(environment, dirtyFiles.toHashSet())
val previousClasses = cache.classesBySources(dirtyFiles + removedFiles) val previousClasses = cache.classesBySources(dirtyFiles + removedFiles)
for (jvmClassName in previousClasses) { for (jvmClassName in previousClasses) {
val fqName = jvmClassName.fqNameForClassNameWithoutDollars.asString() val fqName = jvmClassName.fqNameForClassNameWithoutDollars.asString()