Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional settings for error handling #178

Merged
merged 1 commit into from
Dec 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ inThisBuild(
onLoadMessage := s"Welcome to sbt-scalafmt ${version.value}"
skip in publish := true

val scalafmtVersion = "3.2.0"
val scalafmtVersion = "3.2.1"
lazy val plugin = project
.enablePlugins(SbtPlugin)
.settings(
Expand Down
7 changes: 7 additions & 0 deletions plugin/src/main/scala/org/scalafmt/sbt/ErrorHandling.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.scalafmt.sbt

private[sbt] class ErrorHandling(
val logOnEachError: Boolean,
val failOnErrors: Boolean,
val detailedErrorEnabled: Boolean
)
42 changes: 34 additions & 8 deletions plugin/src/main/scala/org/scalafmt/sbt/ScalafmtPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ object ScalafmtPlugin extends AutoPlugin {
val scalafmtFilter = settingKey[String](
"File filtering mode when running scalafmt."
)
val scalafmtLogOnEachError = settingKey[Boolean](
"Enables logging on an error."
)
val scalafmtFailOnErrors = settingKey[Boolean](
"Controls whether to fail in case of formatting errors."
)
}

import autoImport._
Expand Down Expand Up @@ -127,13 +133,13 @@ object ScalafmtPlugin extends AutoPlugin {
resolvers: Seq[Resolver],
currentProject: ResolvedProject,
filterMode: String,
detailedErrorEnabled: Boolean
errorHandling: ErrorHandling
) {
private val log = taskStreams.log
private val reporter = new ScalafmtSbtReporter(
log,
new OutputStreamWriter(taskStreams.binary()),
detailedErrorEnabled
errorHandling
)

private val scalafmtSession = {
Expand Down Expand Up @@ -179,18 +185,28 @@ object ScalafmtPlugin extends AutoPlugin {

private def withFormattedSources[T](sources: Seq[File])(
onFormat: (File, Input, Output) => T
): Seq[Option[T]] =
sources.map { file =>
): Seq[Option[T]] = {
val res = sources.map { file =>
val path = file.toPath.toAbsolutePath
Try(IO.read(file)) match {
case Failure(x) =>
reporter.error(path, "Failed to read", x)
None
case Success(x) =>
val output = scalafmtSession.format(path, x)
Some(onFormat(file, x, output))
val output = scalafmtSession.formatOrError(path, x)
/* no need to report on exception since for all errors
* reporter.error would have been called already */
Option(output.value).map(o => onFormat(file, x, o))
}
}
val bad = res.count(_ eq None)
if (bad != 0) {
val err = s"scalafmt: failed for $bad sources"
if (errorHandling.failOnErrors) throw new MessageOnlyException(err)
log.error(err)
}
res
}

def formatTrackedSources(
cacheStoreFactory: CacheStoreFactory,
Expand Down Expand Up @@ -413,7 +429,11 @@ object ScalafmtPlugin extends AutoPlugin {
fullResolvers.value,
thisProject.value,
scalafmtFilter.value,
scalafmtDetailedError.value
new ErrorHandling(
scalafmtLogOnEachError.value,
scalafmtFailOnErrors.value,
scalafmtDetailedError.value
)
)
func(files, session)
}
Expand Down Expand Up @@ -453,7 +473,11 @@ object ScalafmtPlugin extends AutoPlugin {
fullResolvers.value,
thisProject.value,
"",
scalafmtDetailedError.value
new ErrorHandling(
scalafmtLogOnEachError.value,
scalafmtFailOnErrors.value,
scalafmtDetailedError.value
)
).formatSources(absFiles)
}
)
Expand All @@ -480,6 +504,8 @@ object ScalafmtPlugin extends AutoPlugin {
Seq(
scalafmtFilter := "",
scalafmtOnCompile := false,
scalafmtLogOnEachError := false,
scalafmtFailOnErrors := true,
scalafmtDetailedError := false
)

Expand Down
32 changes: 19 additions & 13 deletions plugin/src/main/scala/org/scalafmt/sbt/ScalafmtSbtReporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import org.scalafmt.interfaces.ScalafmtReporter
class ScalafmtSbtReporter(
log: Logger,
out: OutputStreamWriter,
detailedErrorEnabled: Boolean
errorHandling: ErrorHandling
) extends ScalafmtReporter {
import ScalafmtSbtReporter._

Expand All @@ -23,25 +23,31 @@ class ScalafmtSbtReporter(
error(file, null, e)

override def error(file: Path, message: String, e: Throwable): Unit = {
def getMessage() = {
def getMessage(toThrow: Boolean) = {
val res = new StringWriter()
res.write("scalafmt: ")
res.write(Option(message).getOrElse("failed"))
if (toThrow) res.write("scalafmt: ")
val nestedMessage = if (e == null) None else Option(e.getMessage)
val messageOpt = Option(message).orElse(nestedMessage)
res.write(messageOpt.getOrElse("failed"))
res.write(" [")
res.write(file.toString)
res.write(']')
if (null != e) {
if (!detailedErrorEnabled)
Option(e.getMessage).foreach { x =>
res.write(" ")
res.write(x)
}
if (null != e && !toThrow) {
if (errorHandling.detailedErrorEnabled)
e.printStackTrace(new PrintWriter(res))
else if (messageOpt ne nestedMessage) nestedMessage.foreach { x =>
res.write(": ")
res.write(x)
}
}
res.toString
}

val cause = if (detailedErrorEnabled) e else null
throw new ScalafmtSbtError(getMessage(), cause)
if (errorHandling.logOnEachError) log.error(getMessage(false))
else if (errorHandling.failOnErrors) {
val cause = if (errorHandling.detailedErrorEnabled) e else null
throw new ScalafmtSbtError(getMessage(true), cause)
}
}

override def excluded(file: Path): Unit =
Expand All @@ -57,6 +63,6 @@ class ScalafmtSbtReporter(
object ScalafmtSbtReporter {

private class ScalafmtSbtError(message: String, cause: Throwable)
extends RuntimeException(message, cause)
extends RuntimeException(message, cause, true, cause != null)

}
3 changes: 3 additions & 0 deletions plugin/src/sbt-test/scalafmt-sbt/sbt/changes/invalid.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object Test {
foo(a, b // ) invalid
}
10 changes: 10 additions & 0 deletions plugin/src/sbt-test/scalafmt-sbt/sbt/test
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ $ exec git -C p17 add "src/main/scala/TestBad2.scala"
# now commit it, no longer modified
$ exec git -C p17 commit -m 'added TestBad2.scala'
> p17/scalafmtCheck
# don't filter but fail after all errors
> set p17/scalafmtFilter := ("")
$ copy-file changes/invalid.scala p17/src/main/scala/TestInvalid1.scala
$ copy-file changes/invalid.scala p17/src/main/scala/TestInvalid2.scala
-> p17/scalafmt
# fail after all errors
> set p17/scalafmtLogOnEachError := true
-> p17/scalafmt
> set p17/scalafmtFailOnErrors := false
> p17/scalafmt

$ copy-file changes/target/managed.scala project/target/managed.scala
$ copy-file changes/x/Something.scala project/x/Something.scala
Expand Down