diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala b/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala index 11e4f7511b..834fa397fa 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala +++ b/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala @@ -6,6 +6,7 @@ import util.control.Breaks import org.scalafmt.Error import org.scalafmt.{Formatted, Scalafmt, Versions} import org.scalafmt.config.{ProjectFiles, ScalafmtConfig} +import org.scalafmt.config.ScalafmtConfigException import org.scalafmt.CompatCollections.ParConverters._ import scala.meta.parsers.ParseException @@ -21,10 +22,18 @@ object ScalafmtCoreRunner extends ScalafmtRunner { ExitCode.UnexpectedError } { scalafmtConf => options.common.debug.println(s"parsed config (v${Versions.version})") - val filterMatcher = ProjectFiles.FileMatcher( - scalafmtConf.project, - options.customExcludes - ) + val filterMatcher = + try { + ProjectFiles.FileMatcher( + scalafmtConf.project, + options.customExcludes + ) + } catch { + case e: ScalafmtConfigException => + options.common.err.println(e.getMessage()) + return ExitCode.UnexpectedError // RETURNING EARLY! + } + val inputMethods = getInputMethods(options, filterMatcher.matchesPath) val termDisplay = diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ProjectFiles.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ProjectFiles.scala index 666c29358f..a7f18cf0d3 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ProjectFiles.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ProjectFiles.scala @@ -70,11 +70,27 @@ object ProjectFiles { private def regex(seq: Seq[String]) = create(seq, new Regex(_)) private final class Nio(pattern: String) extends PathMatcher { - private val matcher = fs.getPathMatcher(pattern) + private val matcher = + try { fs.getPathMatcher(pattern) } + catch { + case _: IllegalArgumentException => + throw new ScalafmtConfigException( + s"Illegal pattern in configuration: $pattern" + ) + } def matches(path: file.Path): Boolean = matcher.matches(path) } private final class Regex(regex: String) extends PathMatcher { - private val pattern = java.util.regex.Pattern.compile(regex) + private val pattern = + try { java.util.regex.Pattern.compile(regex) } + catch { + case e: java.util.regex.PatternSyntaxException => + throw new ScalafmtConfigException( + s"""|Illegal regex in configuration: $regex + |reason: ${e.getMessage()}""".stripMargin + ) + } + def matches(path: file.Path): Boolean = pattern.matcher(path.toString).find() } diff --git a/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala b/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala index c38d0b505b..c80e22c0f8 100644 --- a/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala +++ b/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala @@ -286,6 +286,37 @@ class DynamicSuite extends FunSuite { ) } + check("regex-error") { f => + f.setConfig(s"""|version = "$nightly" + |runner.dialect = "scala212" + |project.excludeFilters = [ + | ".*foo(" + |] + |""".stripMargin) + val err = f.assertThrows[ScalafmtDynamicError.ConfigParseError]().getMessage + assertNoDiff( + err.takeRight(120), + """|Invalid config: Illegal regex in configuration: .*foo( + |reason: Unclosed group near index 6 + |.*foo( + |""".stripMargin + ) + } + + check("path-error") { f => + f.setConfig(s"""|version = "$nightly" + |runner.dialect = "scala212" + |project.excludePaths = [ + | "foo.scala" + |] + |""".stripMargin) + val err = f.assertThrows[ScalafmtDynamicError.ConfigParseError]().getMessage + assertNoDiff( + err.takeRight(120), + "Invalid config: Illegal pattern in configuration: foo.scala" + ) + } + check("config-cache") { f => f.setVersion(latest, "scala211") f.assertFormat() diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliTest.scala b/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliTest.scala index aebd34f6b7..85775ec359 100644 --- a/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliTest.scala +++ b/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliTest.scala @@ -798,6 +798,64 @@ class CliTest extends AbstractCliTest with CliTestBehavior { testCli("1.6.0-RC4") // test for runDynamic testCli(stableVersion) // test for runScalafmt + test(s"path-error") { + val input = + s"""|/.scalafmt.conf + |version = "${stableVersion}" + |project.excludePaths = [ + | "glob:**/src/main/scala/besom/rpc/**.scala", + | "foo.scala" + |] + |/foo.scala + |object A { foo( } + |""".stripMargin + + noArgTest( + string2dir(input), + input, + Seq(Array("--test")), + ExitCode.UnexpectedError, + assertOut = out => { + assertContains( + out, + s"""Illegal pattern in configuration: foo.scala""".stripMargin + ) + }, + Some(ExitCode.UnexpectedError) + ) + + } + + test(s"regex-error") { + val input = + s"""|/.scalafmt.conf + |version = "${stableVersion}" + |project.excludeFilters = [ + | ".*foo(" + |] + |/foo.scala + |object A { foo( } + |""".stripMargin + + noArgTest( + string2dir(input), + input, + Seq(Array("--test")), + ExitCode.UnexpectedError, + assertOut = out => { + assertContains( + out, + """|Illegal regex in configuration: .*foo( + |reason: Unclosed group near index 6 + |.*foo( + |""".stripMargin + ) + }, + Some(ExitCode.UnexpectedError) + ) + + } + test("Fail if .scalafmt.conf is missing.") { val input = s"""|/foo.scala