Skip to content

Commit

Permalink
try to propagate cancel
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Dec 12, 2024
1 parent 30643c4 commit 044cc69
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import scala.util.control.NonFatal
import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.builds.BuildServerProvider
import scala.meta.internal.builds.ShellRunner
import scala.meta.internal.metals.CancelableFuture
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.Messages.BspProvider
import scala.meta.internal.metals.MetalsEnrichments._
Expand All @@ -31,7 +32,7 @@ final class BspConfigGenerator(
def runUnconditionally(
buildTool: BuildServerProvider,
args: List[String],
): Future[BspConfigGenerationStatus] =
): CancelableFuture[BspConfigGenerationStatus] =
shellRunner
.run(
s"${buildTool.buildServerName} bspConfig",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class BspConnector(
args => bspConfigGenerator.runUnconditionally(bsp, args),
statusBar,
)
.future
.flatMap { _ =>
connect(
projectRoot,
Expand Down
28 changes: 17 additions & 11 deletions metals/src/main/scala/scala/meta/internal/builds/BloopInstall.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import java.util.concurrent.TimeUnit

import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.Promise

import scala.meta.internal.builds.Digest.Status
import scala.meta.internal.metals.BuildInfo
import scala.meta.internal.metals.CancelSwitch
import scala.meta.internal.metals.CancelableFuture
import scala.meta.internal.metals.Confirmation
import scala.meta.internal.metals.Interruptable
import scala.meta.internal.metals.Interruptable._
import scala.meta.internal.metals.Messages._
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.Tables
Expand Down Expand Up @@ -37,14 +42,14 @@ final class BloopInstall(

def runUnconditionally(
buildTool: BloopInstallProvider
): Future[WorkspaceLoadedStatus] = {
): CancelableFuture[WorkspaceLoadedStatus] = {
buildTool.bloopInstall(
workspace,
args => {
scribe.info(s"running '${args.mkString(" ")}'")
val process =
runArgumentsUnconditionally(buildTool, args, userConfig().javaHome)
process.foreach { e =>
process.future.foreach { e =>
if (e.isFailed) {
// Record the exact command that failed to help troubleshooting.
scribe.error(s"$buildTool command failed: ${args.mkString(" ")}")
Expand All @@ -59,7 +64,7 @@ final class BloopInstall(
buildTool: BloopInstallProvider,
args: List[String],
javaHome: Option[String],
): Future[WorkspaceLoadedStatus] = {
): CancelableFuture[WorkspaceLoadedStatus] = {
persistChecksumStatus(Status.Started, buildTool)
val processFuture = shellRunner
.run(
Expand All @@ -81,7 +86,7 @@ final class BloopInstall(
case ExitCodes.Cancel => WorkspaceLoadedStatus.Cancelled
case result => WorkspaceLoadedStatus.Failed(result)
}
processFuture.foreach { result =>
processFuture.future.foreach { result =>
try result.toChecksumStatus.foreach(persistChecksumStatus(_, buildTool))
catch {
case _: InterruptedException =>
Expand Down Expand Up @@ -112,35 +117,36 @@ final class BloopInstall(
def runIfApproved(
buildTool: BloopInstallProvider,
digest: String,
): Future[WorkspaceLoadedStatus] =
): CancelableFuture[WorkspaceLoadedStatus] =
synchronized {
oldInstallResult(digest) match {
case Some(result)
if result != WorkspaceLoadedStatus.Duplicate(Status.Requested) =>
scribe.info(s"skipping build import with status '${result.name}'")
Future.successful(result)
CancelableFuture.successful(result)
case _ =>
if (userConfig().shouldAutoImportNewProject) {
runUnconditionally(buildTool)
} else {
scribe.debug("Awaiting user response...")
for {
implicit val cancelSwitch = CancelSwitch(Promise[Unit]())
(for {
userResponse <- requestImport(
buildTools,
buildTool,
languageClient,
digest,
)
).withInterrupt
installResult <- {
if (userResponse.isYes) {
runUnconditionally(buildTool)
runUnconditionally(buildTool).withInterrupt
} else {
// Don't spam the user with requests during rapid build changes.
notification.dismiss(2, TimeUnit.MINUTES)
Future.successful(WorkspaceLoadedStatus.Rejected)
Interruptable.successful(WorkspaceLoadedStatus.Rejected)
}
}
} yield installResult
} yield installResult).toCancellable
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ package scala.meta.internal.builds
import java.io.IOException
import java.nio.file.Files

import scala.concurrent.Future

import scala.meta.internal.metals.CancelableFuture
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.io.AbsolutePath

Expand All @@ -18,8 +17,8 @@ trait BloopInstallProvider extends BuildTool {
*/
def bloopInstall(
workspace: AbsolutePath,
systemProcess: List[String] => Future[WorkspaceLoadedStatus],
): Future[WorkspaceLoadedStatus] = {
systemProcess: List[String] => CancelableFuture[WorkspaceLoadedStatus],
): CancelableFuture[WorkspaceLoadedStatus] = {
cleanupStaleConfig()
systemProcess(bloopInstallArgs(workspace))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import scala.annotation.nowarn
import scala.concurrent.Future

import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.metals.CancelableFuture
import scala.meta.internal.metals.Messages
import scala.meta.internal.metals.StatusBar
import scala.meta.io.AbsolutePath
Expand All @@ -20,12 +21,16 @@ trait BuildServerProvider extends BuildTool {
@nowarn("msg=parameter statusBar in method generateBspConfig is never used")
def generateBspConfig(
workspace: AbsolutePath,
systemProcess: List[String] => Future[BspConfigGenerationStatus],
systemProcess: List[String] => CancelableFuture[
BspConfigGenerationStatus
],
statusBar: StatusBar,
): Future[BspConfigGenerationStatus] =
): CancelableFuture[BspConfigGenerationStatus] =
createBspFileArgs(workspace).map(systemProcess).getOrElse {
Future.successful(
Failed(Right(Messages.NoBspSupport.toString()))
CancelableFuture(
Future.successful(
Failed(Right(Messages.NoBspSupport.toString()))
)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class NewProjectProvider(
javaHome,
javaOptsMap = javaOpts,
)
.future
.flatMap {
case ExitCodes.Success =>
askForWindow(projectPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ case class SbtBuildTool(

def shutdownBspServer(
shellRunner: ShellRunner
): Future[Int] = {
): CancelableFuture[Int] = {
val shutdownArgs =
composeArgs(List("--client", "shutdown"), projectRoot, projectRoot.toNIO)
scribe.info(s"running ${shutdownArgs.mkString(" ")}")
Expand Down Expand Up @@ -242,7 +242,7 @@ case class SbtBuildTool(
if (promise.isCompleted) {
// executes when user chooses `restart` after the timeout
restartSbtBuildServer()
} else shutdownBspServer(shellRunner).ignoreValue
} else shutdownBspServer(shellRunner).future.ignoreValue
case _ =>
promise.trySuccess(())
Future.successful(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package scala.meta.internal.builds

import java.security.MessageDigest

import scala.concurrent.Future

import scala.meta.internal.bsp.BspConfigGenerationStatus._
import scala.meta.internal.metals.BuildInfo
import scala.meta.internal.metals.CancelableFuture
import scala.meta.internal.metals.Directories
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.StatusBar
Expand All @@ -26,9 +25,11 @@ case class ScalaCliBuildTool(

override def generateBspConfig(
workspace: AbsolutePath,
systemProcess: List[String] => Future[BspConfigGenerationStatus],
systemProcess: List[String] => CancelableFuture[
BspConfigGenerationStatus
],
statusBar: StatusBar,
): Future[BspConfigGenerationStatus] =
): CancelableFuture[BspConfigGenerationStatus] =
createBspFileArgs(workspace).map(systemProcess).getOrElse {
// fallback to creating `.bsp/scala-cli.json` that starts JVM launcher
val bspConfig =
Expand All @@ -37,7 +38,7 @@ case class ScalaCliBuildTool(
bspConfig.writeText(
ScalaCli.scalaCliBspJsonContent(projectRoot = projectRoot.toString())
)
Future.successful(Generated)
CancelableFuture.successful(Generated)
}

override def createBspFileArgs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import java.io.File

import scala.concurrent.Await
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.Promise
import scala.concurrent.duration.DurationInt
import scala.language.postfixOps
import scala.util.Properties

import scala.meta.internal.metals.Cancelable
import scala.meta.internal.metals.CancelableFuture
import scala.meta.internal.metals.JavaBinary
import scala.meta.internal.metals.JdkSources
import scala.meta.internal.metals.MetalsEnrichments._
Expand Down Expand Up @@ -45,7 +45,7 @@ class ShellRunner(time: Time, workDoneProvider: WorkDoneProgress)(implicit
processErr: String => Unit = scribe.error(_),
propagateError: Boolean = false,
javaOptsMap: Map[String, String] = Map.empty,
): Future[Int] = {
): CancelableFuture[Int] = {

val classpathSeparator = if (Properties.isWin) ";" else ":"
val classpath = Fetch
Expand Down Expand Up @@ -92,7 +92,7 @@ class ShellRunner(time: Time, workDoneProvider: WorkDoneProgress)(implicit
processErr: String => Unit = scribe.error(_),
propagateError: Boolean = false,
logInfo: Boolean = true,
): Future[Int] = {
): CancelableFuture[Int] = {
val elapsed = new Timer(time)
val env = additionalEnv ++ JdkSources.envVariables(javaHome)
val ps = SystemProcess.run(
Expand Down Expand Up @@ -125,7 +125,7 @@ class ShellRunner(time: Time, workDoneProvider: WorkDoneProgress)(implicit
result.trySuccess(code)
}
result.future.onComplete(_ => cancelables.remove(newCancelable))
result.future
CancelableFuture(result.future, newCancelable)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.util.Try

case class CancelableFuture[T](
case class CancelableFuture[+T](
future: Future[T],
cancelable: Cancelable = Cancelable.empty,
) extends Cancelable {
Expand Down
Loading

0 comments on commit 044cc69

Please sign in to comment.