Skip to content

Commit

Permalink
tidy up
Browse files Browse the repository at this point in the history
  • Loading branch information
aishfenton committed Jan 1, 2023
1 parent b716449 commit 38a068e
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 270 deletions.
6 changes: 3 additions & 3 deletions src/main/scala/afenton/bazel/bsp/BazelBspApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ object BazelBspApp
val program = for
errQ <- Queue.bounded[IO, String](100)
outQ <- Queue.bounded[IO, Message](100)
logger = new QueueLogger(errQ, verbose)
client = new MyBspClient(outQ, logger)
stateRef <- Ref.of[IO, ServerState](ServerState.default)
logger = Logger.toQueue(errQ, verbose)
client = BspClient.toQueue(outQ, logger)
stateRef <- Ref.of[IO, BazelBspServer.ServerState](BazelBspServer.defaultState)
server = new BazelBspServer(
client,
logger,
Expand Down
115 changes: 46 additions & 69 deletions src/main/scala/afenton/bazel/bsp/BazelBspServer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,26 @@ import afenton.bazel.bsp.jrpc.JRpcClient
import afenton.bazel.bsp.jrpc.Message
import afenton.bazel.bsp.jrpc.Notification
import afenton.bazel.bsp.protocol.*
import afenton.bazel.bsp.runner.BazelRunner
import afenton.bazel.bsp.runner.BazelLabel
import afenton.bazel.bsp.runner.BazelRunner
import cats.effect.IO
import cats.effect.kernel.Ref
import cats.effect.std.Queue
import cats.syntax.all._
import io.bazel.rules_scala.diagnostics.diagnostics.FileDiagnostics
import io.circe.Decoder
import io.circe.DecodingFailure
import io.circe.Json
import io.circe.syntax._

import java.net.URI
import java.nio.file.Path
import java.nio.file.Paths
import io.circe.Json
import io.circe.Decoder
import io.circe.DecodingFailure

case class ServerState(
targetSourceMap: TargetSourceMap,
currentErrors: List[FileDiagnostics],
workspaceRoot: Option[Path],
bazelRunner: Option[BazelRunner],
targets: List[BuildTarget]
)

object ServerState:
def default: ServerState = ServerState(TargetSourceMap.empty, Nil, None, None, Nil)

class BazelBspServer(
client: BspClient,
logger: Logger,
stateRef: Ref[IO, ServerState]
stateRef: Ref[IO, BazelBspServer.ServerState]
) extends BspServer(client):

private val version = "0.1"
Expand Down Expand Up @@ -78,7 +67,7 @@ class BazelBspServer(
state.bazelRunner.get,
ws.targets.map(_.id)
)
_ <- stateRef.update(s => s.copy(targetSourceMap = TargetSourceMap(ts)))
_ <- stateRef.update(s => s.copy(targetSourceMap = BazelBspServer.TargetSourceMap(ts)))
yield ()

def buildTargetInverseSources(
Expand Down Expand Up @@ -320,55 +309,43 @@ class BazelBspServer(

end BazelBspServer

class MyBspClient(stdOutQ: Queue[IO, Message], logger: Logger)
extends BspClient
with JRpcClient:

def sendNotification(n: Notification): IO[Unit] =
for
_ <- logger.info(n.method)
_ <- stdOutQ.offer(n)
yield ()

def publishDiagnostics(params: PublishDiagnosticsParams): IO[Unit] =
sendNotification("build/publishDiagnostics", params)

def buildTaskStart(params: TaskStartParams): IO[Unit] =
sendNotification("build/taskStart", params)

def buildTaskProgress(params: TaskProgressParams): IO[Unit] =
sendNotification("build/taskProgress", params)

def buildTaskFinished(params: TaskFinishParams): IO[Unit] =
sendNotification("build/taskFinish", params)

def buildShowMessage(params: ShowMessageParams): IO[Unit] =
sendNotification("build/showMessage", params)

case class TargetSourceMap(
val _targetSources: Map[BuildTargetIdentifier, List[
TextDocumentIdentifier
]]
):

private def invertMap[K, V](map: Map[K, List[V]]): Map[V, List[K]] =
map.toList
.flatMap((bt, ls) => ls.map(l => (l, bt)))
.groupMap(_._1)(_._2)

private val sourceTargets
: Map[TextDocumentIdentifier, List[BuildTargetIdentifier]] =
invertMap(_targetSources)

def sourcesForTarget(
bt: BuildTargetIdentifier
): List[TextDocumentIdentifier] =
_targetSources.get(bt).getOrElse(Nil)

def targetsForSource(
td: TextDocumentIdentifier
): List[BuildTargetIdentifier] =
sourceTargets.get(td).getOrElse(Nil)

object TargetSourceMap:
def empty: TargetSourceMap = TargetSourceMap(Map.empty)
object BazelBspServer:

case class ServerState(
targetSourceMap: BazelBspServer.TargetSourceMap,
currentErrors: List[FileDiagnostics],
workspaceRoot: Option[Path],
bazelRunner: Option[BazelRunner],
targets: List[BuildTarget]
)

def defaultState: ServerState =
ServerState(BazelBspServer.TargetSourceMap.empty, Nil, None, None, Nil)

protected case class TargetSourceMap(
val _targetSources: Map[BuildTargetIdentifier, List[
TextDocumentIdentifier
]]
):

private def invertMap[K, V](map: Map[K, List[V]]): Map[V, List[K]] =
map.toList
.flatMap((bt, ls) => ls.map(l => (l, bt)))
.groupMap(_._1)(_._2)

private val sourceTargets
: Map[TextDocumentIdentifier, List[BuildTargetIdentifier]] =
invertMap(_targetSources)

def sourcesForTarget(
bt: BuildTargetIdentifier
): List[TextDocumentIdentifier] =
_targetSources.get(bt).getOrElse(Nil)

def targetsForSource(
td: TextDocumentIdentifier
): List[BuildTargetIdentifier] =
sourceTargets.get(td).getOrElse(Nil)

object TargetSourceMap:
def empty: TargetSourceMap = TargetSourceMap(Map.empty)
17 changes: 9 additions & 8 deletions src/main/scala/afenton/bazel/bsp/FilesIO.scala
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package afenton.bazel.bsp

import cats.effect.IO
import java.nio.file.Path
import java.nio.file.Files
import scala.util.Try
import scala.jdk.CollectionConverters.*
import io.circe.Decoder
import java.nio.file.PathMatcher
import java.nio.file.FileVisitOption
import fs2.Stream
import java.nio.file.FileSystems
import io.circe.Decoder

import java.nio.file.FileSystem
import java.nio.file.FileSystems
import java.nio.file.FileVisitOption
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.PathMatcher
import scala.jdk.CollectionConverters.*
import scala.util.Try

object FilesIO:

Expand Down
42 changes: 23 additions & 19 deletions src/main/scala/afenton/bazel/bsp/Logger.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package afenton.bazel.bsp

import scala.io.AnsiColor
import cats.effect.IO
import cats.effect.std.Queue

import scala.io.AnsiColor

trait Logger:
def trace(msg: String*): IO[Unit]
def info(msg: String*): IO[Unit]
Expand All @@ -19,26 +20,29 @@ object Logger:
def error(msgs: String*): IO[Unit] = trace(msgs*)
}

class QueueLogger(stdErrQ: Queue[IO, String], verbose: Boolean) extends Logger:
private def format(level: Logger.Level, msgs: Seq[String]) =
def fmt(level: String, color: String, msgs: Seq[String]) =
val withVisibleLineEndings =
msgs.map(_.replace("\r\n", "[CRLF]\n")).mkString("\n")
def toQueue(errQ: Queue[IO, String], verbose: Boolean): Logger =
QueueLogger(errQ, verbose)

private class QueueLogger(errQ: Queue[IO, String], verbose: Boolean) extends Logger:
private def format(level: Logger.Level, msgs: Seq[String]) =
def fmt(level: String, color: String, msgs: Seq[String]) =
val withVisibleLineEndings =
msgs.map(_.replace("\r\n", "[CRLF]\n")).mkString("\n")

s"[${color}${level}${AnsiColor.RESET}] ${color}${withVisibleLineEndings}${AnsiColor.RESET}"
s"[${color}${level}${AnsiColor.RESET}] ${color}${withVisibleLineEndings}${AnsiColor.RESET}"

level match {
case Logger.Level.Trace => fmt("trace", AnsiColor.CYAN, msgs)
case Logger.Level.Info => fmt("info", AnsiColor.GREEN, msgs)
case Logger.Level.Error => fmt("error", AnsiColor.RED, msgs)
}
level match {
case Logger.Level.Trace => fmt("trace", AnsiColor.CYAN, msgs)
case Logger.Level.Info => fmt("info", AnsiColor.GREEN, msgs)
case Logger.Level.Error => fmt("error", AnsiColor.RED, msgs)
}

def trace(msgs: String*): IO[Unit] =
if verbose then stdErrQ.offer(format(Logger.Level.Trace, msgs))
else IO.unit
def trace(msgs: String*): IO[Unit] =
if verbose then errQ.offer(format(Logger.Level.Trace, msgs))
else IO.unit

def info(msgs: String*): IO[Unit] =
stdErrQ.offer(format(Logger.Level.Info, msgs))
def info(msgs: String*): IO[Unit] =
errQ.offer(format(Logger.Level.Info, msgs))

def error(msgs: String*): IO[Unit] =
stdErrQ.offer(format(Logger.Level.Error, msgs))
def error(msgs: String*): IO[Unit] =
errQ.offer(format(Logger.Level.Error, msgs))
9 changes: 5 additions & 4 deletions src/main/scala/afenton/bazel/bsp/jrpc/JRpc.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package afenton.bazel.bsp.jrpc

import afenton.bazel.bsp.Logger
import afenton.bazel.bsp.jrpc.PartialJson.JObject
import afenton.bazel.bsp.protocol.BspClient
import cats.data.NonEmptyList
import cats.effect.IO
import cats.parse.Rfc5234
Expand All @@ -10,12 +13,10 @@ import fs2.Pipe
import fs2.Pull
import fs2.Stream
import io.circe._
import io.circe.generic.semiauto.*
import io.circe.syntax.*
import afenton.bazel.bsp.jrpc.PartialJson.JObject
import afenton.bazel.bsp.Logger

import scala.reflect.TypeTest
import io.circe.generic.semiauto.*
import afenton.bazel.bsp.protocol.BspClient

sealed trait Message:
def jsonrpc: "2.0"
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/afenton/bazel/bsp/jrpc/PartialJson.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package afenton.bazel.bsp.jrpc

import cats.parse.{Parser => P, Parser0 => P0}
import cats.parse.{Parser => P}
import cats.parse.{Parser0 => P0}

sealed trait PartialJson:
def asString: String
Expand Down
35 changes: 35 additions & 0 deletions src/main/scala/afenton/bazel/bsp/protocol/BspClient.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,45 @@
package afenton.bazel.bsp.protocol

import afenton.bazel.bsp.Logger
import afenton.bazel.bsp.jrpc.JRpcClient
import afenton.bazel.bsp.jrpc.Message
import afenton.bazel.bsp.jrpc.Notification
import cats.effect.IO
import cats.effect.std.Queue

trait BspClient:
def publishDiagnostics(params: PublishDiagnosticsParams): IO[Unit]
def buildTaskStart(params: TaskStartParams): IO[Unit]
def buildTaskProgress(params: TaskProgressParams): IO[Unit]
def buildTaskFinished(params: TaskFinishParams): IO[Unit]
def buildShowMessage(params: ShowMessageParams): IO[Unit]

object BspClient:

def toQueue(outQ: Queue[IO, Message], logger: Logger): BspClient =
BspClientImpl(outQ, logger)

private class BspClientImpl(outQ: Queue[IO, Message], logger: Logger)
extends BspClient
with JRpcClient:

def sendNotification(n: Notification): IO[Unit] =
for
_ <- logger.info(n.method)
_ <- outQ.offer(n)
yield ()

def publishDiagnostics(params: PublishDiagnosticsParams): IO[Unit] =
sendNotification("build/publishDiagnostics", params)

def buildTaskStart(params: TaskStartParams): IO[Unit] =
sendNotification("build/taskStart", params)

def buildTaskProgress(params: TaskProgressParams): IO[Unit] =
sendNotification("build/taskProgress", params)

def buildTaskFinished(params: TaskFinishParams): IO[Unit] =
sendNotification("build/taskFinish", params)

def buildShowMessage(params: ShowMessageParams): IO[Unit] =
sendNotification("build/showMessage", params)
3 changes: 2 additions & 1 deletion src/main/scala/afenton/bazel/bsp/protocol/BspServer.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package afenton.bazel.bsp.protocol

import cats.effect.IO
import afenton.bazel.bsp.jrpc.RpcFunction
import cats.effect.IO

import java.net.URI

trait BspServer(client: BspClient):
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/afenton/bazel/bsp/protocol/Models.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import afenton.bazel.bsp.jrpc.Notification
import afenton.bazel.bsp.jrpc.RpcFunction
import afenton.bazel.bsp.jrpc.decodeIntOrString
import afenton.bazel.bsp.jrpc.encodeIntOrString
import afenton.bazel.bsp.runner.BazelLabel
import cats.effect.IO
import io.bazel.rules_scala.diagnostics.diagnostics.FileDiagnostics as ScalacDiagnostic
import io.bazel.rules_scala.diagnostics.diagnostics.Position as ScalacPosition
Expand All @@ -16,7 +17,6 @@ import io.circe.syntax._
import java.net.URI
import java.nio.file.Path
import java.nio.file.Paths
import afenton.bazel.bsp.runner.BazelLabel

object UriFactory:
def fileUri(path: Path): URI =
Expand Down
17 changes: 9 additions & 8 deletions src/main/scala/afenton/bazel/bsp/runner/BazelLabel.scala
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package afenton.bazel.bsp.runner

import java.nio.file.Path
import cats.parse.Parser as P
import cats.parse.Parser0 as P0
import cats.parse.Rfc5234
import java.nio.file.Paths
import afenton.bazel.bsp.protocol.BuildTargetIdentifier
import afenton.bazel.bsp.runner.BPath.BCons
import afenton.bazel.bsp.runner.BPath.BNil
import afenton.bazel.bsp.runner.BPath.Wildcard
import cats.effect.kernel.syntax.resource
import cats.instances.tailRec
import cats.parse.Rfc5234
import cats.parse.Parser as P
import cats.parse.Parser0 as P0

import java.nio.file.Path
import java.nio.file.Paths
import scala.annotation.tailrec
import afenton.bazel.bsp.runner.BPath.Wildcard
import afenton.bazel.bsp.runner.BPath.BCons
import afenton.bazel.bsp.runner.BPath.BNil

sealed trait BazelTarget:
def asString: String = this match
Expand Down
Loading

0 comments on commit 38a068e

Please sign in to comment.