@@ -6,12 +6,13 @@ import bsp.BuildTarget.BuildTargetScalaBuildTarget
66import bsp .CompileParams
77import bsp .InverseSourcesParams
88import cats .effect .kernel .Ref
9- import cats .effect .std .MapRef
9+ import cats .effect .std .AtomicCell
1010import cats .effect .IO
1111import langoustine .lsp .*
1212import langoustine .lsp .structures .*
1313import org .scala .abusers .pc .ScalaVersion
14- import org .scala .abusers .sls .LspNioConverter .asNio
14+ import org .scala .abusers .sls .NioConverter .asNio
15+ import org .scala .abusers .sls .LoggingUtils .*
1516
1617import java .net .URI
1718
@@ -34,7 +35,7 @@ object BspStateManager {
3435 def instance (bspServer : BuildServer ): IO [BspStateManager ] =
3536 // We should track this in progress bar. Think of this as `Import Build`
3637 for {
37- sourcesToTargets <- MapRef .ofScalaConcurrentTrieMap [IO , URI , ScalaBuildTargetInformation ]
38+ sourcesToTargets <- AtomicCell [IO ].of( Map [ URI , ScalaBuildTargetInformation ]())
3839 buildTargets <- Ref .of[IO , Set [ScalaBuildTargetInformation ]](Set .empty)
3940 } yield BspStateManager (bspServer, sourcesToTargets, buildTargets)
4041}
@@ -47,24 +48,26 @@ object BspStateManager {
4748 */
4849class BspStateManager (
4950 val bspServer : BuildServer ,
50- sourcesToTargets : MapRef [IO , URI , Option [ ScalaBuildTargetInformation ]],
51+ sourcesToTargets : AtomicCell [IO , Map [ URI , ScalaBuildTargetInformation ]],
5152 targets : Ref [IO , Set [ScalaBuildTargetInformation ]],
5253) {
5354 import ScalaBuildTargetInformation .*
5455
55- def importBuild =
56+ def importBuild ( back : Communicate [ IO ]) =
5657 for {
58+ _ <- back.logMessage(" Starting build import." ) // in the future this should be a task with progress
5759 importedBuild <- getBuildInformation(bspServer)
5860 _ <- bspServer.generic.buildTargetCompile(CompileParams (targets = importedBuild.map(_.buildTarget.id).toList))
5961 _ <- targets.set(importedBuild)
62+ _ <- back.logMessage(" Build import finished." )
6063 } yield ()
6164
62- val byScalaVersion : Ordering [ScalaBuildTargetInformation ] = new Ordering [ScalaBuildTargetInformation ] {
65+ private val byScalaVersion : Ordering [ScalaBuildTargetInformation ] = new Ordering [ScalaBuildTargetInformation ] {
6366 override def compare (x : ScalaBuildTargetInformation , y : ScalaBuildTargetInformation ): Int =
6467 Ordering [ScalaVersion ].compare(x.scalaVersion, y.scalaVersion)
6568 }
6669
67- def getBuildInformation (bspServer : BuildServer ): IO [Set [ScalaBuildTargetInformation ]] =
70+ private def getBuildInformation (bspServer : BuildServer ): IO [Set [ScalaBuildTargetInformation ]] =
6871 for {
6972 workspaceBuildTargets <- bspServer.generic.workspaceBuildTargets()
7073 scalacOptions <- bspServer.scala.buildTargetScalacOptions(
@@ -75,7 +78,7 @@ class BspStateManager(
7578 .values
7679 .toSet
7780
78- def buildTargetInverseSources (uri : URI ): IO [List [bsp.BuildTargetIdentifier ]] =
81+ private def buildTargetInverseSources (uri : URI ): IO [List [bsp.BuildTargetIdentifier ]] =
7982 for inverseSources <- bspServer.generic
8083 .buildTargetInverseSources(
8184 InverseSourcesParams (
@@ -108,19 +111,21 @@ class BspStateManager(
108111 * We want to fail fast if this is not the case because it is a way bigger problem that we may hide
109112 */
110113 def get (uri : URI ): IO [ScalaBuildTargetInformation ] =
111- sourcesToTargets(uri) .get.map(
112- _ .getOrElse(throw new IllegalStateException (" Get should always be called after didOpen" ))
113- )
114+ sourcesToTargets.get.map { state =>
115+ state .getOrElse(uri, throw new IllegalStateException (" Get should always be called after didOpen" ))
116+ }
114117
115118 def didOpen (in : Invocation [DidOpenTextDocumentParams , IO ]): IO [Unit ] = {
116119 val uri = in.params.textDocument.uri.asNio
117- for {
118- possibleIds <- buildTargetInverseSources(uri)
119- targets0 <- targets.get
120- possibleBuildTargets = possibleIds.flatMap(id => targets0.find(_.buildTarget.id == id))
121- bestBuildTarget = possibleBuildTargets.maxBy(_.buildTarget.project.scala.map(_.data.scalaVersion))
122- _ <- sourcesToTargets(uri).set(Some (bestBuildTarget)) // lets assume we will always update it
123- } yield ()
120+ sourcesToTargets.evalUpdate(state =>
121+ for {
122+ possibleIds <- buildTargetInverseSources(uri)
123+ targets0 <- targets.get
124+ possibleBuildTargets = possibleIds.flatMap(id => targets0.find(_.buildTarget.id == id))
125+ bestBuildTarget = possibleBuildTargets.maxBy(_.buildTarget.project.scala.map(_.data.scalaVersion))
126+ _ <- in.toClient.logDebug(s " Best build target for $uri is ${bestBuildTarget.toString}" )
127+ } yield state.updated(uri, bestBuildTarget)
128+ )
124129 }
125130}
126131
0 commit comments