Skip to content

Commit

Permalink
ConfParsed: don't mask parsing/retrieval errors
Browse files Browse the repository at this point in the history
  • Loading branch information
kitbellew committed Nov 5, 2023
1 parent 630322d commit f3fe546
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 38 deletions.
45 changes: 24 additions & 21 deletions scalafmt-cli/src/main/scala/org/scalafmt/cli/Cli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,36 +98,39 @@ object Cli {
private def getProposedConfigVersion(options: CliOptions): String =
s"version = $stableVersion"

private type MaybeRunner = Either[String, ScalafmtRunner]

private def findRunner(
options: CliOptions
): Either[String, ScalafmtRunner] = {
): MaybeRunner = options.hoconOpt.fold[MaybeRunner] {
Left(s"""error: missing Scalafmt configuration file.
|Consider creating '${options.getProposedConfigFile}' with the following:
|${getProposedConfigVersion(options)}
|""".stripMargin)
} {
// Run format using
// - `scalafmt-dynamic` if the specified `version` setting doesn't match build version.
// - `scalafmt-core` if the specified `version` setting match with build version
// (or if the `version` is not specified).
val versionOpt = options.hoconOpt.map(x => Right(x.version)).getOrElse {
Left(s"""error: missing Scalafmt configuration file.
|Consider creating '${options.getProposedConfigFile}' with the following:
_.version.fold[MaybeRunner] {
val where = options.configStr match {
case None =>
options.canonicalConfigFile
.fold(options.getProposedConfigFile)(_.get)
.toString
case _ => "--config-str option"
}
Left(s"""error: missing Scalafmt version.
|Consider adding the following to $where:
|${getProposedConfigVersion(options)}
|""".stripMargin)
}
versionOpt.flatMap {
case None =>
val where = options.configStr match {
case None =>
options.canonicalConfigFile
.fold(options.getProposedConfigFile)(_.get)
.toString
case _ => "--config-str option"
}
Left(s"""error: missing Scalafmt version.
|Consider adding the following to $where:
|${getProposedConfigVersion(options)}
|""".stripMargin)
case Some(`stableVersion`) =>
} {
case Left(error) =>
Left(s"error: invalid configuration: ${error}")
case Right(`stableVersion`) =>
options.common.debug.println(s"Using core runner [$stableVersion]")
Right(ScalafmtCoreRunner)
case Some(v) if isNativeImage =>
case Right(v) if isNativeImage =>
Left(
s"""error: invalid Scalafmt version.
|
Expand All @@ -141,7 +144,7 @@ object Cli {
|Scalafmt automatically installs and invokes the correct version of Scalafmt when running on the JVM.
|""".stripMargin
)
case Some(v) =>
case Right(v) =>
options.common.debug.println(s"Using dynamic runner [$v]")
Right(ScalafmtDynamicRunner)
}
Expand Down
16 changes: 12 additions & 4 deletions scalafmt-cli/src/main/scala/org/scalafmt/cli/CliOptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.io.{InputStream, OutputStream, PrintStream}
import java.nio.file.{Files, NoSuchFileException, Path}

import metaconfig.Configured
import org.scalafmt.config.{ConfParsed, ScalafmtConfig}
import org.scalafmt.config.{ConfParsed, ScalafmtConfig, ScalafmtConfigException}
import org.scalafmt.sysops.{AbsoluteFile, GitOps, OsSpecific}

import scala.io.Codec
Expand Down Expand Up @@ -182,10 +182,18 @@ case class CliOptions(
case _ => filters.mkString("(", "|", ")").r
}

private def getHoconValueOpt[A](f: ConfParsed => Option[A]): Option[A] =
hoconOpt.flatMap(f)
private def getHoconValueOpt[A](
f: ConfParsed => Option[Either[String, A]]
): Option[A] =
hoconOpt.flatMap(f).map {
case Right(x) => x
case Left(x) => throw new ScalafmtConfigException(x)
}

private def getHoconValue[A](default: A, f: ConfParsed => Option[A]): A =
private def getHoconValue[A](
default: A,
f: ConfParsed => Option[Either[String, A]]
): A =
getHoconValueOpt[A](f).getOrElse(default)

private[cli] def isGit: Boolean =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,31 @@ class ConfParsed(val conf: Configured[Conf]) extends AnyVal {

def getHoconValueOpt[A](
path: String*
)(implicit ev: ConfDecoderEx[A]): Option[A] = {
val nestedConf = conf.andThen(_.getNestedConf(path: _*))
nestedConf.andThen(ev.read(None, _)).map(Some(_)).getOrElse(None)
)(implicit ev: ConfDecoderEx[A]): Option[Either[String, A]] = {
val res = conf.andThen(_.getNestedConf(path: _*)).andThen(ev.read(None, _))
res.fold[Option[Either[String, A]]](x =>
if (x.isMissingField) None else Some(Left(x.msg))
)(x => Some(Right(x)))
}

def getHoconValue[A: ConfDecoderEx](default: A, path: String*): A =
getHoconValueOpt[A](path: _*).getOrElse(default)

def isGit: Option[Boolean] =
def isGit: Option[Either[String, Boolean]] =
getHoconValueOpt[Boolean]("project", "git")

def fatalWarnings: Option[Boolean] =
def fatalWarnings: Option[Either[String, Boolean]] =
getHoconValueOpt[Boolean]("runner", "fatalWarnings")

def ignoreWarnings: Option[Boolean] =
def ignoreWarnings: Option[Either[String, Boolean]] =
getHoconValueOpt[Boolean]("runner", "ignoreWarnings")

def onTestFailure: Option[String] =
def onTestFailure: Option[Either[String, String]] =
getHoconValueOpt[String]("onTestFailure")

def encoding: Option[Codec] =
getHoconValueOpt[String]("encoding").flatMap(x => Try(Codec(x)).toOption)
def encoding: Option[Either[String, Codec]] =
getHoconValueOpt[String]("encoding").map {
_.flatMap(x => Try(Codec(x)).toEither.left.map(_.getMessage))
}

def version: Option[String] =
def version: Option[Either[String, String]] =
getHoconValueOpt[String]("version")

}
Expand Down

0 comments on commit f3fe546

Please sign in to comment.