Skip to content

Commit

Permalink
improvement: Ask to start http server if not running
Browse files Browse the repository at this point in the history
This will show up after indexing and users can start the server themselves or ignore it for the session.

Should help with scalameta#7072
  • Loading branch information
tgodzik committed Jan 3, 2025
1 parent 843d80f commit a5951fd
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ final class DismissedNotifications(conn: () => Connection, time: Time) {
val ScalaCliImportAuto = new Notification(14)
val BspErrors = new Notification(15)
val RequestTimeout = new Notification(16)
val ScalafixConfAmend = new Notification(16)
val ScalafixConfAmend = new Notification(17)

val all: List[Notification] = List(
Only212Navigation,
Expand All @@ -42,6 +42,8 @@ final class DismissedNotifications(conn: () => Connection, time: Time) {
ReconnectScalaCli,
ScalaCliImportAuto,
BspErrors,
RequestTimeout,
ScalafixConfAmend,
)

def resetAll(): Unit = {
Expand Down
22 changes: 22 additions & 0 deletions metals/src/main/scala/scala/meta/internal/metals/Messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,28 @@ object Messages {
}
}

object StartHttpServer {
def yes = new MessageActionItem("Start")

def notNow: MessageActionItem = Messages.notNow

def params(): ShowMessageRequestParams = {
val params = new ShowMessageRequestParams()
params.setMessage(
s"Http server is required for such features as Metals Doctor, do you want to start it now?"
)
params.setType(MessageType.Info)
params.setActions(
List(
yes,
notNow,
dontShowAgain,
).asJava
)
params
}
}

object GenerateBspAndConnect {
def yes = new MessageActionItem("Connect")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ class WorkspaceLspService(
private val cancelables = new MutableCancelable()
val fallbackIsInitialized: ju.concurrent.atomic.AtomicBoolean =
new ju.concurrent.atomic.AtomicBoolean(false)
var httpServer: Option[MetalsHttpServer] = None
@volatile var httpServer: HttpServerStatus = HttpServerOff

sealed trait HttpServerStatus
case object HttpServerOff extends HttpServerStatus
case object HttpServerIgnored extends HttpServerStatus
case class HttpServerOn(server: MetalsHttpServer) extends HttpServerStatus

private val clientConfig =
ClientConfiguration(
Expand Down Expand Up @@ -152,10 +157,32 @@ class WorkspaceLspService(

private val timerProvider: TimerProvider = new TimerProvider(time)

def getHttpServer(): Future[Option[MetalsHttpServer]] = {
httpServer match {
case HttpServerOff =>
languageClient
.showMessageRequest(Messages.StartHttpServer.params())
.asScala
.flatMap { item =>
if (item == Messages.StartHttpServer.yes) {
startHttpServer(force = true)
getHttpServer()
} else if (item == Messages.dontShowAgain) {
httpServer = HttpServerIgnored
Future.successful(None)
} else {
Future.successful(None)
}
}
case HttpServerOn(server) => Future.successful(Some(server))
case HttpServerIgnored => Future.successful(None)
}
}

val doctor: HeadDoctor =
new HeadDoctor(
() => folderServices.map(_.doctor) ++ optFallback.map(_.doctor),
() => httpServer,
getHttpServer,
clientConfig,
languageClient,
)
Expand Down Expand Up @@ -1268,8 +1295,8 @@ class WorkspaceLspService(
} yield ()
}

private def startHttpServer(): Unit = {
if (clientConfig.isHttpEnabled()) {
private def startHttpServer(force: Boolean = false): Unit = {
if (force || clientConfig.isHttpEnabled()) {
val host = "localhost"
val port = 5031
var url = s"http://$host:$port"
Expand All @@ -1288,7 +1315,7 @@ class WorkspaceLspService(
this,
)
)
httpServer = Some(server)
httpServer = HttpServerOn(server)
val newClient = new MetalsHttpClient(
folders.map(_.path),
() => url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package scala.meta.internal.metals.doctor

import java.util.concurrent.atomic.AtomicBoolean

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

import scala.meta.internal.metals.BuildInfo
import scala.meta.internal.metals.ClientCommands
import scala.meta.internal.metals.ClientConfiguration
Expand All @@ -14,10 +17,10 @@ import scala.meta.internal.metals.config.DoctorFormat

class HeadDoctor(
doctors: () => List[Doctor],
httpServer: () => Option[MetalsHttpServer],
httpServer: () => Future[Option[MetalsHttpServer]],
clientConfig: ClientConfiguration,
languageClient: MetalsLanguageClient,
) {
)(implicit ec: ExecutionContext) {
private val isVisible = new AtomicBoolean(false)

def onVisibilityDidChange(newState: Boolean): Unit = {
Expand Down Expand Up @@ -82,7 +85,7 @@ class HeadDoctor(
val params = clientCommand.toExecuteCommandParams(output)
languageClient.metalsExecuteClientCommand(params)
} else {
httpServer() match {
httpServer().map {
case Some(server) =>
onServer(server)
case None =>
Expand Down

0 comments on commit a5951fd

Please sign in to comment.