Skip to content

Commit 8105c61

Browse files
committed
Compose inputs in SetupIde, add fixes to Bsp initial configuration
1 parent 319eb45 commit 8105c61

File tree

3 files changed

+69
-59
lines changed

3 files changed

+69
-59
lines changed

modules/build/src/main/scala/scala/build/input/InputsComposer.scala

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,36 @@ import scala.collection.mutable
1313

1414
object InputsComposer {
1515

16+
// TODO errors on corner cases
17+
def findModuleConfig(
18+
args: Seq[String],
19+
cwd: os.Path
20+
): Either[ModuleConfigurationError, Option[os.Path]] = {
21+
def moduleConfigDirectlyFromArgs = {
22+
val moduleConfigPathOpt = args
23+
.map(arg => os.Path(arg, cwd))
24+
.find(_.endsWith(os.RelPath(Constants.moduleConfigFileName)))
25+
26+
moduleConfigPathOpt match {
27+
case Some(path) if os.exists(path) => Right(Some(path))
28+
case Some(path) => Left(ModuleConfigurationError(
29+
s"""File does not exist:
30+
| - $path
31+
|""".stripMargin
32+
))
33+
case None => Right(None)
34+
}
35+
}
36+
37+
def moduleConfigFromCwd =
38+
Right(os.walk(cwd).find(p => p.endsWith(os.RelPath(Constants.moduleConfigFileName))))
39+
40+
for {
41+
fromArgs <- moduleConfigDirectlyFromArgs
42+
fromCwd <- moduleConfigFromCwd
43+
} yield fromArgs.orElse(fromCwd)
44+
}
45+
1646
private[input] object Keys {
1747
val modules = "modules"
1848
val roots = "roots"
@@ -107,7 +137,7 @@ final case class InputsComposer(
107137

108138
def getModuleInputs: Either[BuildException, Seq[ModuleInputs]] =
109139
if allowForbiddenFeatures then
110-
findModuleConfig match {
140+
findModuleConfig(args, cwd) match {
111141
case Right(Some(moduleConfigPath)) =>
112142
val configText = os.read(moduleConfigPath)
113143
for {
@@ -129,33 +159,6 @@ final case class InputsComposer(
129159
// case _ => Left("scalaVersion must be a string")
130160
// }
131161

132-
// TODO errors on corner cases
133-
private def findModuleConfig: Either[ModuleConfigurationError, Option[os.Path]] = {
134-
def moduleConfigDirectlyFromArgs = {
135-
val moduleConfigPathOpt = args
136-
.map(arg => os.Path(arg, cwd))
137-
.find(_.endsWith(os.RelPath(Constants.moduleConfigFileName)))
138-
139-
moduleConfigPathOpt match {
140-
case Some(path) if os.exists(path) => Right(Some(path))
141-
case Some(path) => Left(ModuleConfigurationError(
142-
s"""File does not exist:
143-
| - $path
144-
|""".stripMargin
145-
))
146-
case None => Right(None)
147-
}
148-
}
149-
150-
def moduleConfigFromCwd =
151-
Right(os.walk(cwd).find(p => p.endsWith(os.RelPath(Constants.moduleConfigFileName))))
152-
153-
for {
154-
fromArgs <- moduleConfigDirectlyFromArgs
155-
fromCwd <- moduleConfigFromCwd
156-
} yield fromArgs.orElse(fromCwd)
157-
}
158-
159162
private def checkForCycles(modules: Seq[ModuleDefinition])
160163
: Either[ModuleConfigurationError, Unit] = either {
161164
val lookup = Map.from(modules.map(module => module.name -> module))
@@ -195,10 +198,12 @@ final case class InputsComposer(
195198
modules: Seq[ModuleDefinition],
196199
moduleConfigPath: os.Path
197200
): Either[BuildException, Seq[ModuleInputs]] = either {
201+
val workspacePath = moduleConfigPath / os.up
198202
val moduleInputsInfo = modules.map { m =>
199-
val moduleName = ProjectName(m.name)
200-
val moduleInputs = inputsFromArgs(m.roots, Some(moduleName))
201-
m -> value(moduleInputs)
203+
val moduleName = ProjectName(m.name)
204+
val argsWithWorkspace = m.roots.map(r => os.Path(r, workspacePath).toString)
205+
val moduleInputs = inputsFromArgs(argsWithWorkspace, Some(moduleName))
206+
m -> value(moduleInputs).copy(mayAppendHash = false)
202207
}
203208

204209
val projectNameMap: Map[String, ProjectName] =
@@ -208,7 +213,8 @@ final case class InputsComposer(
208213
val moduleDeps: Seq[ProjectName] = moduleDef.dependsOn.map(projectNameMap)
209214

210215
inputs.dependsOn(moduleDeps)
211-
.withForcedWorkspace(moduleConfigPath / os.up)
216+
.withForcedWorkspace(workspacePath)
217+
.copy(mayAppendHash = false)
212218
}
213219

214220
moduleInputs

modules/cli/src/main/scala/scala/cli/commands/bsp/Bsp.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ object Bsp extends ScalaCommand[BspOptions] {
8686
val preprocessInputs: Seq[String] => Either[BuildException, Seq[(ModuleInputs, BuildOptions)]] =
8787
argsSeq =>
8888
either {
89-
val sharedOptions = getSharedOptions()
89+
val sharedOptions = getSharedOptions()
9090
val launcherOptions = getLauncherOptions()
9191
val envs = getEnvsFromFile()
9292

@@ -136,9 +136,13 @@ object Bsp extends ScalaCommand[BspOptions] {
136136
val inputsAndBuildOptions = preprocessInputs(args.all).orExit(logger)
137137

138138
// TODO reported override option values
139+
// FIXME Only some options need to be unified for the whole project, like scala version, JVM
139140
val finalBuildOptions = inputsAndBuildOptions.map(_._2).reduceLeft(_ orElse _)
140141
val inputs = inputsAndBuildOptions.map(_._1)
141142

143+
if (options.shared.logging.verbosity >= 3)
144+
pprint.err.log(finalBuildOptions)
145+
142146
/** values used for launching the bsp, especially for launching the bloop server, they do not
143147
* include options extracted from sources, except in bloopRifleConfig - it's needed for
144148
* correctly launching the bloop server

modules/cli/src/main/scala/scala/cli/commands/setupide/SetupIde.scala

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker
77
import com.google.gson.GsonBuilder
88

99
import java.nio.charset.{Charset, StandardCharsets}
10-
1110
import scala.build.EitherCps.{either, value}
1211
import scala.build.*
1312
import scala.build.bsp.IdeInputs
1413
import scala.build.errors.{BuildException, WorkspaceError}
15-
import scala.build.input.{ModuleInputs, OnDisk, Virtual, WorkspaceOrigin}
14+
import scala.build.input.{InputsComposer, ModuleInputs, OnDisk, Virtual, WorkspaceOrigin}
1615
import scala.build.internal.Constants
1716
import scala.build.internals.EnvVar
1817
import scala.build.options.{BuildOptions, Scope}
@@ -68,12 +67,12 @@ object SetupIde extends ScalaCommand[SetupIdeOptions] {
6867

6968
override def runCommand(options: SetupIdeOptions, args: RemainingArgs, logger: Logger): Unit = {
7069
val buildOptions = buildOptionsOrExit(options)
71-
val inputs = options.shared.inputs(args.all).orExit(logger)
72-
CurrentParams.workspaceOpt = Some(inputs.workspace)
70+
val moduleInputs = options.shared.composeInputs(args.all).orExit(logger)
71+
CurrentParams.workspaceOpt = Some(moduleInputs.head.workspace)
7372

7473
val bspPath = writeBspConfiguration(
7574
options,
76-
inputs,
75+
moduleInputs,
7776
buildOptions,
7877
previousCommandName = None,
7978
args = args.all
@@ -92,7 +91,7 @@ object SetupIde extends ScalaCommand[SetupIdeOptions] {
9291
): Unit =
9392
writeBspConfiguration(
9493
SetupIdeOptions(shared = options),
95-
inputs,
94+
Seq(inputs),
9695
buildOptions,
9796
previousCommandName,
9897
args
@@ -106,13 +105,13 @@ object SetupIde extends ScalaCommand[SetupIdeOptions] {
106105

107106
private def writeBspConfiguration(
108107
options: SetupIdeOptions,
109-
inputs: ModuleInputs,
108+
moduleInputs: Seq[ModuleInputs],
110109
buildOptions: BuildOptions,
111110
previousCommandName: Option[String],
112111
args: Seq[String]
113112
): Either[BuildException, Option[os.Path]] = either {
114113

115-
val virtualInputs = inputs.elements.collect {
114+
val virtualInputs = moduleInputs.flatMap(_.elements).collect {
116115
case v: Virtual => v
117116
}
118117
if (virtualInputs.nonEmpty)
@@ -125,23 +124,24 @@ object SetupIde extends ScalaCommand[SetupIdeOptions] {
125124
val logger = options.shared.logger
126125

127126
if (buildOptions.classPathOptions.allExtraDependencies.toSeq.nonEmpty)
128-
value(downloadDeps(
129-
inputs,
130-
buildOptions,
131-
logger
132-
))
133-
134-
val (bspName, bspJsonDestination) = bspDetails(inputs.workspace, options.bspFile)
135-
val scalaCliBspJsonDestination =
136-
inputs.workspace / Constants.workspaceDirName / "ide-options-v2.json"
137-
val scalaCliBspLauncherOptsJsonDestination =
138-
inputs.workspace / Constants.workspaceDirName / "ide-launcher-options.json"
139-
val scalaCliBspInputsJsonDestination =
140-
inputs.workspace / Constants.workspaceDirName / "ide-inputs.json"
141-
val scalaCliBspEnvsJsonDestination =
142-
inputs.workspace / Constants.workspaceDirName / "ide-envs.json"
143-
144-
val inputArgs = inputs.elements.collect { case d: OnDisk => d.path.toString }
127+
for (module <- moduleInputs) do value(downloadDeps(module, buildOptions, logger))
128+
129+
val workspace = moduleInputs.head.workspace
130+
131+
val (bspName, bspJsonDestination) = bspDetails(workspace, options.bspFile)
132+
val scalaCliBspJsonDestination = workspace / Constants.workspaceDirName / "ide-options-v2.json"
133+
val scalaCliBspLauncherOptsJsonDestination = workspace / Constants.workspaceDirName / "ide-launcher-options.json"
134+
val scalaCliBspInputsJsonDestination = workspace / Constants.workspaceDirName / "ide-inputs.json"
135+
val scalaCliBspEnvsJsonDestination = workspace / Constants.workspaceDirName / "ide-envs.json"
136+
137+
// FIXME single modules can also be defined with module config toml file
138+
val inputArgs = if moduleInputs.size > 1 then
139+
InputsComposer.findModuleConfig(args, Os.pwd)
140+
.orExit(logger)
141+
.fold(args)(p => Seq(p.toString))
142+
else
143+
moduleInputs.head.elements
144+
.collect { case d: OnDisk => d.path.toString }
145145

146146
val ideInputs = IdeInputs(
147147
options.shared.validateInputArgs(args)
@@ -189,7 +189,7 @@ object SetupIde extends ScalaCommand[SetupIdeOptions] {
189189
val envsForBsp = sys.env.filter((key, _) => EnvVar.allBsp.map(_.name).contains(key))
190190
val scalaCliBspEnvsJson = writeToArray(envsForBsp)
191191

192-
if (inputs.workspaceOrigin.contains(WorkspaceOrigin.HomeDir))
192+
if (moduleInputs.head.workspaceOrigin.contains(WorkspaceOrigin.HomeDir))
193193
value(Left(new WorkspaceError(
194194
s"""$baseRunnerName can not determine where to write its BSP configuration.
195195
|Set an explicit BSP directory path via `--bsp-directory`.

0 commit comments

Comments
 (0)