@@ -20,6 +20,14 @@ import ch.epfl.scala.bsp
20
20
import ch .epfl .scala .bsp .BuildTargetIdentifier
21
21
import ch .epfl .scala .bsp .MessageType
22
22
import ch .epfl .scala .bsp .ShowMessageParams
23
+ import ch .epfl .scala .bsp .CompileResult
24
+ import ch .epfl .scala .bsp .StatusCode
25
+ import ch .epfl .scala .bsp .Uri
26
+ import ch .epfl .scala .bsp .endpoints
27
+ import ch .epfl .scala .bsp .CompileResult
28
+ import ch .epfl .scala .bsp .MessageType
29
+ import ch .epfl .scala .bsp .ShowMessageParams
30
+ import ch .epfl .scala .bsp .StatusCode
23
31
import ch .epfl .scala .bsp .Uri
24
32
import ch .epfl .scala .bsp .endpoints
25
33
import ch .epfl .scala .debugadapter .DebugServer
@@ -302,7 +310,7 @@ final class BloopBspServices(
302
310
compileProvider = Some (BloopBspServices .DefaultCompileProvider ),
303
311
testProvider = Some (BloopBspServices .DefaultTestProvider ),
304
312
runProvider = Some (BloopBspServices .DefaultRunProvider ),
305
- debugProvider = None , // todo kpodsiad
313
+ debugProvider = Some ( BloopBspServices . DefaultDebugProvider ),
306
314
inverseSourcesProvider = Some (true ),
307
315
dependencySourcesProvider = Some (true ),
308
316
dependencyModulesProvider = None ,
@@ -689,10 +697,7 @@ final class BloopBspServices(
689
697
}
690
698
691
699
def test (params : bsp.TestParams ): BspEndpointResponse [bsp.TestResult ] = {
692
- def test (
693
- project : Project ,
694
- state : State
695
- ): Task [State ] = {
700
+ def test (project : Project , state : State ): Task [Tasks .TestRuns ] = {
696
701
val testFilter = TestInternals .parseFilters(Nil ) // Don't support test only for now
697
702
val handler = new LoggingEventHandler (state.logger)
698
703
Tasks .test(
@@ -717,25 +722,35 @@ final class BloopBspServices(
717
722
val args = params.arguments.getOrElse(Nil )
718
723
val logger = logger0.asBspServerVerbose
719
724
compileProjects(mappings, state, args, originId, logger).flatMap {
720
- case (newState, compileResult) =>
721
- compileResult match {
722
- case Right (_) =>
723
- val sequentialTestExecution = mappings.foldLeft(Task .now(newState)) {
724
- case (taskState, (_, p)) => taskState.flatMap(state => test(p, state))
725
- }
726
-
727
- sequentialTestExecution.materialize.map(_.toEither).map {
728
- case Right (newState) =>
725
+ case (newState, Right (CompileResult (_, StatusCode .Ok , _, _))) =>
726
+ val sequentialTestExecution : Task [Seq [Tasks .TestRuns ]] =
727
+ Task .sequence(mappings.map { case (_, p) => test(p, state) })
728
+
729
+ sequentialTestExecution.materialize.map {
730
+ case Success (testRunsSeq) =>
731
+ testRunsSeq.reduceOption(_ ++ _) match {
732
+ case None =>
729
733
(newState, Right (bsp.TestResult (originId, bsp.StatusCode .Ok , None , None )))
730
- case Left (e) =>
731
- // (newState, Right(bsp.TestResult(None, bsp.StatusCode.Error, None)))
732
- val errorMessage =
733
- Response .internalError(s " Failed test execution: ${e.getMessage}" )
734
- (newState, Left (errorMessage))
734
+ case Some (testRuns) =>
735
+ val status = testRuns.status
736
+ val bspStatus =
737
+ if (status == ExitStatus .Ok ) bsp.StatusCode .Ok else bsp.StatusCode .Error
738
+ (
739
+ newState.mergeStatus(status),
740
+ Right (bsp.TestResult (originId, bspStatus, None , None ))
741
+ )
735
742
}
736
-
737
- case Left (error) => Task .now((newState, Left (error)))
743
+ case Failure (e) =>
744
+ val errorMessage =
745
+ Response .internalError(s " Failed test execution: ${e.getMessage}" )
746
+ (newState, Left (errorMessage))
738
747
}
748
+
749
+ case (newState, Right (CompileResult (_, errorCode, _, _))) =>
750
+ Task .now((newState, Right (bsp.TestResult (originId, errorCode, None , None ))))
751
+
752
+ case (newState, Left (error)) =>
753
+ Task .now((newState, Left (error)))
739
754
}
740
755
}
741
756
}
@@ -1026,7 +1041,8 @@ final class BloopBspServices(
1026
1041
val capabilities = bsp.BuildTargetCapabilities (
1027
1042
canCompile = true ,
1028
1043
canTest = true ,
1029
- canRun = true
1044
+ canRun = true ,
1045
+ canDebug = true
1030
1046
)
1031
1047
val isJavaOnly = p.scalaInstance.isEmpty
1032
1048
val languageIds =
@@ -1064,29 +1080,49 @@ final class BloopBspServices(
1064
1080
projects : Seq [ProjectMapping ],
1065
1081
state : State
1066
1082
): BspResult [bsp.SourcesResult ] = {
1067
- val sourcesItems = projects.iterator.map {
1068
- case (target, project) =>
1069
- project.allSourceFilesAndDirectories.map { sources =>
1070
- val items = sources.map { s =>
1071
- import bsp .SourceItemKind ._
1072
- val uri = s.underlying.toUri()
1073
- val (bspUri, kind) = if (s.exists) {
1074
- (uri, if (s.isFile) File else Directory )
1075
- } else {
1076
- val fileMatcher = FileSystems .getDefault.getPathMatcher(" glob:*.{scala, java}" )
1077
- if (fileMatcher.matches(s.underlying.getFileName)) (uri, File )
1078
- // If path doesn't exist and its name doesn't look like a file, assume it's a dir
1079
- else (new URI (uri.toString + " /" ), Directory )
1080
- }
1081
- // TODO(jvican): Don't default on false for generated, add this info to JSON fields
1082
- bsp.SourceItem (bsp.Uri (bspUri), kind, false )
1083
- }
1083
+ def sourceItem (s : AbsolutePath , isGenerated : Boolean ): bsp.SourceItem = {
1084
+ import bsp .SourceItemKind ._
1085
+ val uri = s.underlying.toUri()
1086
+ val (bspUri, kind) = if (s.exists) {
1087
+ (uri, if (s.isFile) File else Directory )
1088
+ } else {
1089
+ val fileMatcher = FileSystems .getDefault.getPathMatcher(" glob:*.{scala, java}" )
1090
+ if (fileMatcher.matches(s.underlying.getFileName)) (uri, File )
1091
+ // If path doesn't exist and its name doesn't look like a file, assume it's a dir
1092
+ else (new URI (uri.toString + " /" ), Directory )
1093
+ }
1094
+ bsp.SourceItem (bsp.Uri (bspUri), kind, isGenerated)
1095
+ }
1096
+
1097
+ val dag = Aggregate (projects.map(p => state.build.getDagFor(p._2)).toList)
1098
+
1099
+ // Collect the projects' sources following the projects topological sorting, so that
1100
+ // source generators that depend on other source generators' outputs can run correctly.
1101
+ val collectSourcesTasks = Dag .topologicalSort(dag).map { project =>
1102
+ val unmanagedSources = project.allUnmanagedSourceFilesAndDirectories.map { sources =>
1103
+ sources.map(sourceItem(_, isGenerated = false ))
1104
+ }
1105
+
1106
+ val managedSources = {
1107
+ val tasks = project.sourceGenerators
1108
+ .map(state.sourceGeneratorCache.update(_, state.logger, state.commonOptions))
1109
+ Task .gatherUnordered(tasks).map(_.flatten.map(sourceItem(_, isGenerated = true )))
1110
+ }
1111
+
1112
+ for {
1113
+ unmanaged <- unmanagedSources
1114
+ managed <- managedSources
1115
+ } yield (project, unmanaged ++ managed)
1116
+ }
1117
+
1118
+ val projectToTarget = projects.map { case (target, project) => project -> target }.toMap
1119
+ Task .sequence(collectSourcesTasks).map { results =>
1120
+ val items = results.flatMap {
1121
+ case (project, items) =>
1084
1122
val roots = project.sourceRoots.map(_.map(p => bsp.Uri (p.toBspUri)))
1085
- bsp.SourcesItem (target, items, roots)
1086
- }
1087
- }.toList
1123
+ projectToTarget.get(project).map(bsp.SourcesItem (_, items, roots))
1124
+ }
1088
1125
1089
- Task .sequence(sourcesItems).map { items =>
1090
1126
(state, Right (bsp.SourcesResult (items)))
1091
1127
}
1092
1128
}
@@ -1309,4 +1345,5 @@ object BloopBspServices {
1309
1345
private [bloop] val DefaultCompileProvider = bsp.CompileProvider (DefaultLanguages )
1310
1346
private [bloop] val DefaultTestProvider = bsp.TestProvider (DefaultLanguages )
1311
1347
private [bloop] val DefaultRunProvider = bsp.RunProvider (DefaultLanguages )
1348
+ private [bloop] val DefaultDebugProvider = bsp.DebugProvider (DefaultLanguages )
1312
1349
}
0 commit comments