diff --git a/frontend/src/main/scala/bloop/Project.scala b/frontend/src/main/scala/bloop/Project.scala index d63ec85b04..6cfa1311c3 100644 --- a/frontend/src/main/scala/bloop/Project.scala +++ b/frontend/src/main/scala/bloop/Project.scala @@ -8,9 +8,10 @@ import bloop.exec.JavaEnv import bloop.io.{AbsolutePath, Paths} import bloop.io.Timer.timed import bloop.logging.Logger - import xsbti.compile.ClasspathOptions +import scala.util.control.NoStackTrace + case class Project(name: String, baseDirectory: AbsolutePath, dependencies: Array[String], @@ -89,6 +90,13 @@ object Project { fromProperties(properties, config, logger) } + private class MissingFieldError(fieldName: String, config: AbsolutePath) + extends Exception( + s"""The field '$fieldName' is missing in '${config.syntax}'. + |Please export your project again from your build tool (e.g. `bloopInstall`). + |Check the installation page for further information: https://scalacenter.github.io/bloop/docs/installation""".stripMargin + ) with NoStackTrace + def fromProperties(properties: Properties, config: AbsolutePath, logger: Logger): Project = { def toPaths(line: String) = line.split(",").map(toPath) def toPath(line: String) = AbsolutePath(NioPaths.get(line)) @@ -105,10 +113,15 @@ object Project { val classpath = toPaths(properties.getProperty("classpath")) val classesDir = toPath(properties.getProperty("classesDir")) val classpathOptions = { - val values = properties.getProperty("classpathOptions").split(",") - val Array(bootLibrary, compiler, extra, autoBoot, filterLibrary) = - values.map(java.lang.Boolean.parseBoolean) - ClasspathOptions.of(bootLibrary, compiler, extra, autoBoot, filterLibrary) + val opts = properties.getProperty("classpathOptions") + // Protecting our users from breaking changes in the configuration file format. + if (opts == null) throw new MissingFieldError("classpathOptions", config) + else { + val values = opts.split(",") + val Array(bootLibrary, compiler, extra, autoBoot, filterLibrary) = + values.map(java.lang.Boolean.parseBoolean) + ClasspathOptions.of(bootLibrary, compiler, extra, autoBoot, filterLibrary) + } } val scalacOptions = properties.getProperty("scalacOptions").split(";").filterNot(_.isEmpty) diff --git a/frontend/src/test/scala/bloop/logging/RecordingLogger.scala b/frontend/src/test/scala/bloop/logging/RecordingLogger.scala index 65107e3c28..2a6e92154b 100644 --- a/frontend/src/test/scala/bloop/logging/RecordingLogger.scala +++ b/frontend/src/test/scala/bloop/logging/RecordingLogger.scala @@ -9,7 +9,9 @@ class RecordingLogger extends AbstractLogger { def clear(): Unit = messages.clear() def getMessages(): List[(String, String)] = messages.iterator.asScala.toList.map { // Remove trailing '\r' so that we don't have to special case for Windows - case (category, msg) => (category, msg.stripSuffix("\r")) + case (category, msg0) => + val msg = if (msg0 == null) "" else msg0 + (category, msg.stripSuffix("\r")) } override val name: String = "RecordingLogger" diff --git a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala index 1c872134f7..209a8a365f 100644 --- a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala +++ b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala @@ -117,6 +117,7 @@ object PluginImplementation { val configuration = Keys.configuration.value val projectName = makeName(project.id, configuration) val baseDirectory = Keys.baseDirectory.value.getAbsoluteFile + val buildBaseDirectory = Keys.baseDirectory.in(ThisBuild).value.getAbsoluteFile // In the test configuration, add a dependency on the base project val baseProjectDependency = if (configuration == Test) List(project.id) else Nil @@ -184,7 +185,7 @@ object PluginImplementation { sbt.IO.createDirectory(bloopConfigDir) config.writeTo(outFile) logger.debug(s"Bloop wrote the configuration of project '$projectName' to '$outFile'.") - val relativeConfigPath = outFile.relativeTo(baseDirectory).getOrElse(outFile) + val relativeConfigPath = outFile.relativeTo(buildBaseDirectory).getOrElse(outFile) logger.success(s"Generated $relativeConfigPath") // format: ON }