diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53e1db7d24..aa29f66e7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,9 +33,29 @@ jobs: - run: # for GitOps tests git config --global user.email "scalafmt@scalameta.org" && git config --global user.name "scalafmt" - - run: TEST="2.12" sbt ci-test + - run: TEST="2.12" sbt ci-test-jvm shell: bash - - run: TEST="2.13" sbt ci-test + - run: TEST="2.13" sbt ci-test-jvm + shell: bash + test-scala-native: + strategy: + fail-fast: false + matrix: + os: [macOS-latest, ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: olafurpg/setup-scala@v13 + with: + java-version: adopt@1.8 + - name: run tests + run: | + git fetch --tags -f + # for GitOps tests + git config --global user.email "scalafmt@scalameta.org" && git config --global user.name "scalafmt" + - run: TEST="2.12" sbt ci-test-native + shell: bash + - run: TEST="2.13" sbt ci-test-native shell: bash community-test: strategy: diff --git a/build.sbt b/build.sbt index 0320d8cf8b..dd07c94914 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,6 @@ import Dependencies._ import sbtcrossproject.CrossPlugin.autoImport.crossProject +import scala.scalanative.build._ def parseTagVersion: String = { import scala.sys.process._ @@ -30,8 +31,6 @@ inThisBuild(List( crossScalaVersions := List(scala213, scala212), resolvers ++= Resolver.sonatypeOssRepos("releases"), resolvers ++= Resolver.sonatypeOssRepos("snapshots"), - libraryDependencies ++= - List(munit.value % Test, scalacheck % Test, scalametaTestkit % Test), testFrameworks += new TestFramework("munit.Framework"), )) @@ -39,8 +38,9 @@ name := "scalafmtRoot" publish / skip := true addCommandAlias("native-image", "cli/nativeImage") +addCommandAlias("scala-native", "cliNative/compile;cliNative/nativeLink") -commands += Command.command("ci-test") { s => +commands += Command.command("ci-test-jvm") { s => val scalaVersion = sys.env.get("TEST") match { case Some("2.12") => scala212 case _ => scala213 @@ -50,23 +50,26 @@ commands += Command.command("ci-test") { s => docsTest :: s } -lazy val dynamic = project.in(file("scalafmt-dynamic")).settings( - moduleName := "scalafmt-dynamic", - description := "Implementation of scalafmt-interfaces", - buildInfoSettings, - buildInfoPackage := "org.scalafmt.dynamic", - buildInfoObject := "BuildInfo", - libraryDependencies ++= List( - "io.get-coursier" % "interface" % "0.0.17", - "com.typesafe" % "config" % "1.4.3", - munit.value % Test, - scalametaTestkit % Test, - ), - scalacOptions ++= scalacJvmOptions.value, -).dependsOn(interfaces, sysops.jvm).dependsOn(core.jvm % "test") +lazy val dynamic = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform) + .in(file("scalafmt-dynamic")).settings( + moduleName := "scalafmt-dynamic", + description := "Implementation of scalafmt-interfaces", + buildInfoSettings, + buildInfoPackage := "org.scalafmt.dynamic", + buildInfoObject := "BuildInfo", + libraryDependencies ++= List( + "io.get-coursier" % "interface" % "0.0.17", + "com.typesafe" % "config" % "1.4.3", + munit.value % Test, + scalametaTestkit.value % Test, + ), + scalacOptions ++= scalacJvmOptions.value, + ) + .dependsOn(interfaces, sysops) + .dependsOn(core % "test") .enablePlugins(BuildInfoPlugin) -lazy val interfaces = project.in(file("scalafmt-interfaces")).settings( +lazy val interfaces = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform).in(file("scalafmt-interfaces")).settings( moduleName := "scalafmt-interfaces", description := "Dependency-free, pure Java public interfaces to integrate with Scalafmt through a build tool or editor plugin.", @@ -82,7 +85,7 @@ lazy val interfaces = project.in(file("scalafmt-interfaces")).settings( }, ) -lazy val sysops = crossProject(JVMPlatform).withoutSuffixFor(JVMPlatform) +lazy val sysops = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform) .in(file("scalafmt-sysops")).settings( moduleName := "scalafmt-sysops", description := "Scalafmt systems operations", @@ -98,48 +101,67 @@ lazy val sysops = crossProject(JVMPlatform).withoutSuffixFor(JVMPlatform) }, ) -lazy val config = crossProject(JVMPlatform).withoutSuffixFor(JVMPlatform) +lazy val config = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform) .in(file("scalafmt-config")).settings( moduleName := "scalafmt-config", description := "Scalafmt config parsing", scalacOptions ++= scalacJvmOptions.value, libraryDependencies ++= Seq(metaconfig.value), - ).jvmSettings(libraryDependencies ++= Seq(metaconfigTypesafe.value)) + ) + .jvmSettings(libraryDependencies ++= Seq(metaconfigTypesafe.value)) + .nativeSettings( + libraryDependencies ++= Seq(metaconfigSconfig.value) + ) // .jsSettings( // libraryDependencies ++= Seq( // metaconfigHocon.value, // ) // ) -lazy val core = crossProject(JVMPlatform).in(file("scalafmt-core")).settings( - moduleName := "scalafmt-core", - buildInfoSettings, - scalacOptions ++= scalacJvmOptions.value, - libraryDependencies ++= Seq( - scalameta.value, - "org.scalameta" %% "mdoc-parser" % mdocV, - // scala-reflect is an undeclared dependency of fansi, see #1252. - // Scalafmt itself does not require scala-reflect. - "org.scala-lang" % "scala-reflect" % scalaVersion.value, - ), - libraryDependencies ++= { - CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 13)) => Seq() - case _ => Seq(compilerPlugin( - "org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full, - )) - } - }, -) +lazy val core = crossProject(JVMPlatform, NativePlatform) + .withoutSuffixFor(JVMPlatform) + .in(file("scalafmt-core")).settings( + moduleName := "scalafmt-core", + buildInfoSettings, + scalacOptions ++= scalacJvmOptions.value, + libraryDependencies ++= Seq( + scalameta.value, + "com.lihaoyi" %%% "fastparse" % "3.1.0", + "org.scalameta" %%% "mdoc-parser" % mdocV, + // scala-reflect is an undeclared dependency of fansi, see #1252. + "org.scala-lang" % "scala-reflect" % scalaVersion.value, + ), + libraryDependencies ++= { + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, 13)) => Seq() + case _ => Seq(compilerPlugin( + "org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full, + )) + } + }, + ) // .jsSettings( // libraryDependencies ++= List( // scalatest.value % Test // must be here for coreJS/test to run anything // ) // ) - .jvmSettings(Test / run / fork := true).dependsOn(sysops, config) + .jvmSettings(Test / run / fork := true) + .dependsOn(sysops, config, macros) .enablePlugins(BuildInfoPlugin) + lazy val coreJVM = core.jvm -// lazy val coreJS = core.js + +lazy val macros = crossProject(JVMPlatform, NativePlatform) + .withoutSuffixFor(JVMPlatform) + .in(file("scalafmt-macros")).settings( + moduleName := "scalafmt-macros", + buildInfoSettings, + scalacOptions ++= scalacJvmOptions.value, + libraryDependencies ++= Seq( + scalameta.value, + "org.scala-lang" % "scala-reflect" % scalaVersion.value, + ) + ) import sbtassembly.AssemblyPlugin.defaultUniversalScript @@ -156,7 +178,7 @@ val scalacJvmOptions = Def.setting { cross ++ unused } -lazy val cli = project.in(file("scalafmt-cli")).settings( +lazy val cli = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform).in(file("scalafmt-cli")).settings( moduleName := "scalafmt-cli", assembly / mainClass := Some("org.scalafmt.cli.Cli"), assembly / assemblyOption := (assembly / assemblyOption).value @@ -169,9 +191,9 @@ lazy val cli = project.in(file("scalafmt-cli")).settings( oldStrategy(x) }, libraryDependencies ++= Seq( - "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0", + "org.scalameta" %%% "munit-diff" % "1.0.2", "com.martiansoftware" % "nailgun-server" % "0.9.1", - "com.github.scopt" %% "scopt" % "4.1.0", + "com.github.scopt" %%% "scopt" % "4.1.0", ), scalacOptions ++= scalacJvmOptions.value, Compile / mainClass := Some("org.scalafmt.cli.Cli"), @@ -185,29 +207,37 @@ lazy val cli = project.in(file("scalafmt-cli")).settings( val isStatic = sys.env.get("NATIVE_IMAGE_STATIC").exists(_.toBoolean) if (isStatic) Seq("--static") else Nil }, -).dependsOn(coreJVM, dynamic).enablePlugins(NativeImagePlugin) +).nativeSettings(scalaNativeNativeConfig).dependsOn(core, dynamic).enablePlugins(NativeImagePlugin) + +lazy val tests = crossProject(JVMPlatform, NativePlatform) + .withoutSuffixFor(JVMPlatform) + .in(file("scalafmt-tests")) + .settings( + publish / skip := true, + libraryDependencies ++= Seq( + // Test dependencies + "com.lihaoyi" %%% "scalatags" % "0.13.1", + scalametaTestkit.value, + "org.scalameta" %%% "munit" % "1.0.0" % Test + ), + scalacOptions ++= scalacJvmOptions.value, + buildInfoPackage := "org.scalafmt.tests", + buildInfoKeys := + Seq[BuildInfoKey]("resourceDirectory" -> (baseDirectory.value / ".." / "shared" / "src" / "test" / "resources")), + ) + .enablePlugins(BuildInfoPlugin) + .jvmSettings( + javaOptions += "-Dfile.encoding=UTF8", + ) + .dependsOn(core, dynamic, cli) -lazy val tests = project.in(file("scalafmt-tests")).settings( - publish / skip := true, - libraryDependencies ++= Seq( - // Test dependencies - "com.lihaoyi" %% "scalatags" % "0.13.1", - scalametaTestkit, - munit.value, - ), - scalacOptions ++= scalacJvmOptions.value, - javaOptions += "-Dfile.encoding=UTF8", - buildInfoPackage := "org.scalafmt.tests", - buildInfoKeys := - Seq[BuildInfoKey]("resourceDirectory" -> (Test / resourceDirectory).value), -).enablePlugins(BuildInfoPlugin).dependsOn(coreJVM, dynamic, cli) lazy val communityTests = project.in(file("scalafmt-tests-community")).settings( publish / skip := true, libraryDependencies ++= Seq( // Test dependencies "com.lihaoyi" %% "scalatags" % "0.13.1", - scalametaTestkit, + scalametaTestkit.value, munit.value, ), scalacOptions ++= scalacJvmOptions.value, @@ -218,7 +248,7 @@ lazy val communityTests = project.in(file("scalafmt-tests-community")).settings( lazy val benchmarks = project.in(file("scalafmt-benchmarks")).settings( publish / skip := true, moduleName := "scalafmt-benchmarks", - libraryDependencies ++= Seq(scalametaTestkit), + libraryDependencies ++= Seq(scalametaTestkit.value), run / javaOptions ++= Seq( "-Djava.net.preferIPv4Stack=true", "-XX:+AggressiveOpts", @@ -235,13 +265,13 @@ lazy val benchmarks = project.in(file("scalafmt-benchmarks")).settings( "-Xmx2G", "-server", ), -).dependsOn(coreJVM).enablePlugins(JmhPlugin) +).dependsOn(core.jvm).enablePlugins(JmhPlugin) lazy val docs = project.in(file("scalafmt-docs")).settings( crossScalaVersions := List(scala212), publish / skip := true, mdoc := (Compile / run).evaluated, -).dependsOn(cli, dynamic).enablePlugins(DocusaurusPlugin) +).dependsOn(cli.jvm, dynamic.jvm).enablePlugins(DocusaurusPlugin) val V = "\\d+\\.\\d+\\.\\d+" val ReleaseCandidate = s"($V-RC\\d+).*".r @@ -270,3 +300,8 @@ lazy val buildInfoSettings: Seq[Def.Setting[_]] = Seq( buildInfoPackage := "org.scalafmt", buildInfoObject := "Versions", ) + +lazy val scalaNativeNativeConfig = + nativeConfig ~= { + _.withMode(Mode.releaseFull) + } \ No newline at end of file diff --git a/docs/contributing-scalafmt.md b/docs/contributing-scalafmt.md index 3eaf733247..1668390168 100644 --- a/docs/contributing-scalafmt.md +++ b/docs/contributing-scalafmt.md @@ -80,7 +80,7 @@ To build a native image of the command-line interface using - From the project root directory, - run `sbt cli/assembly` - - run `java -jar scalafmt-cli/target/scala-2.13/scalafmt.jar`, to execute recently built artifacts + - run `java -jar scalafmt-cli/jvm/target/scala-2.13/scalafmt.jar`, to execute recently built artifacts ## Random stuff diff --git a/docs/installation.md b/docs/installation.md index 77ea349899..35b6a6c176 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -502,7 +502,7 @@ handle parse and config errors. Here is an example how to extend `ScalafmtReporter`. -```scala mdoc:file:scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala +```scala mdoc:file:scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala ``` diff --git a/project/Dependencies.scala b/project/Dependencies.scala index a5560dc2cc..57bfdd900b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -12,7 +12,7 @@ object Dependencies { val scalacheckV = "1.18.0" val coursier = "2.1.10" val munitV = "1.0.1" - val mdocV = "2.5.4" + val mdocV = "2.6.0" val scalapb = Def.setting { ExclusionRule( @@ -21,7 +21,7 @@ object Dependencies { ) } - val scalametaTestkit = "org.scalameta" %% "testkit" % scalametaV + val scalametaTestkit = Def.setting("org.scalameta" %%% "testkit" % scalametaV) val scalacheck = "org.scalacheck" %% "scalacheck" % scalacheckV val munit = Def.setting("org.scalameta" %%% "munit" % munitV) @@ -32,5 +32,6 @@ object Dependencies { val metaconfigTypesafe = Def .setting("org.scalameta" %%% "metaconfig-typesafe-config" % metaconfigV) val metaconfigHocon = Def.setting("com.geirsson" %%% "metaconfig-hocon" % metaconfigV) + val metaconfigSconfig = Def.setting("org.scalameta" %%% "metaconfig-sconfig" % metaconfigV) } diff --git a/project/plugins.sbt b/project/plugins.sbt index f58ca6be10..2c65e1621b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -15,3 +15,5 @@ addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2") addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.4") addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.4") +addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.5") diff --git a/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/CliOptionsUtils.scala b/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/CliOptionsUtils.scala new file mode 100644 index 0000000000..c46513cb14 --- /dev/null +++ b/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/CliOptionsUtils.scala @@ -0,0 +1,13 @@ +package org.scalafmt.cli + +class CliOptionsUtils { + def makeOutputStreamOrWriter(parsed: CliOptions): Output.StreamOrWriter = { + val usesOut = parsed.stdIn || parsed.writeMode.usesOut + val cons = if (usesOut) System.console() else null + if (cons ne null) new Output.FromWriter(cons.writer()) + else new Output.FromStream( + if (parsed.noStdErr || !usesOut) parsed.common.out + else parsed.common.err, + ) + } +} diff --git a/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/CliUtils.scala b/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/CliUtils.scala new file mode 100644 index 0000000000..81a1a6da71 --- /dev/null +++ b/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/CliUtils.scala @@ -0,0 +1,34 @@ +package org.scalafmt.cli + +import com.martiansoftware.nailgun.NGContext +import org.scalafmt.sysops.AbsoluteFile + +trait CliUtils { + protected val isNative: Boolean = false + + def nailMain(nGContext: NGContext): Unit = { + val workingDirectory = AbsoluteFile.fromPathIfAbsolute( + nGContext.getWorkingDirectory, + ).getOrElse { + throw new IllegalStateException( + s"Expected absolute path, " + + s"obtained nGContext.getWorkingDirectory = ${nGContext.getWorkingDirectory}", + ) + } + val exit = Cli.mainWithOptions( + nGContext.getArgs, + CliOptions.default.copy(common = + CliOptions.default.common.copy( + cwd = Some(workingDirectory), + out = nGContext.out, + in = nGContext.in, + err = nGContext.err, + ), + ), + ) + nGContext.exit(exit.code) + } + + protected def returnDynamicRunner(): Either[String, ScalafmtRunner] = Right(ScalafmtDynamicRunner) + +} diff --git a/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/TermUtils.scala b/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/TermUtils.scala new file mode 100644 index 0000000000..12bae5c6eb --- /dev/null +++ b/scalafmt-cli/jvm/src/main/scala/org/scalafmt/cli/TermUtils.scala @@ -0,0 +1,13 @@ +package org.scalafmt.cli + +import java.sql.Timestamp + +trait TermUtils { + + // Copy/pasted over from coursier, but unused in scalafmt + private val format = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + protected def formatTimestamp(ts: Long): String = + format.format(new Timestamp(ts)) + + def noConsole = System.console() == null +} diff --git a/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/CliOptionsUtils.scala b/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/CliOptionsUtils.scala new file mode 100644 index 0000000000..b23a61a04d --- /dev/null +++ b/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/CliOptionsUtils.scala @@ -0,0 +1,11 @@ +package org.scalafmt.cli + +class CliOptionsUtils { + def makeOutputStreamOrWriter(parsed: CliOptions): Output.StreamOrWriter = { + val usesOut = parsed.stdIn || parsed.writeMode.usesOut + new Output.FromStream( + if (parsed.noStdErr || !usesOut) parsed.common.out + else parsed.common.err, + ) + } +} diff --git a/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/CliUtils.scala b/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/CliUtils.scala new file mode 100644 index 0000000000..7a60f0b9a3 --- /dev/null +++ b/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/CliUtils.scala @@ -0,0 +1,10 @@ +package org.scalafmt.cli + +trait CliUtils { + protected val isNative: Boolean = true + + protected def returnDynamicRunner(): Either[String, ScalafmtRunner] = { + assert(false, "Code path should be unreachable.") + ??? + } +} diff --git a/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/TermUtils.scala b/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/TermUtils.scala new file mode 100644 index 0000000000..de1a428e10 --- /dev/null +++ b/scalafmt-cli/native/src/main/scala/org/scalafmt/cli/TermUtils.scala @@ -0,0 +1,9 @@ +package org.scalafmt.cli + +trait TermUtils { + + // Copy/pasted over from coursier, but not used in scalafmt + protected def formatTimestamp(ts: Long): String = ??? + + def noConsole = false +} diff --git a/scalafmt-cli/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/native-image.properties b/scalafmt-cli/shared/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/native-image.properties similarity index 100% rename from scalafmt-cli/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/native-image.properties rename to scalafmt-cli/shared/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/native-image.properties diff --git a/scalafmt-cli/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/reflection.json b/scalafmt-cli/shared/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/reflection.json similarity index 100% rename from scalafmt-cli/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/reflection.json rename to scalafmt-cli/shared/src/main/resources/META-INF/native-image/org.scalafmt/scalafmt-cli/reflection.json diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/Cli.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/Cli.scala similarity index 86% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/Cli.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/Cli.scala index aae5e0f24b..d846034b33 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/Cli.scala +++ b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/Cli.scala @@ -1,7 +1,6 @@ package org.scalafmt.cli import org.scalafmt.Versions.{stable => stableVersion} -import org.scalafmt.sysops.AbsoluteFile import java.nio.file.Files import java.nio.file.Paths @@ -10,31 +9,7 @@ import scala.io.Source import scala.util.Using import scala.util.control.NoStackTrace -import com.martiansoftware.nailgun.NGContext - -object Cli { - def nailMain(nGContext: NGContext): Unit = { - val workingDirectory = AbsoluteFile.fromPathIfAbsolute( - nGContext.getWorkingDirectory, - ).getOrElse { - throw new IllegalStateException( - s"Expected absolute path, " + - s"obtained nGContext.getWorkingDirectory = ${nGContext.getWorkingDirectory}", - ) - } - val exit = mainWithOptions( - nGContext.getArgs, - CliOptions.default.copy(common = - CliOptions.default.common.copy( - cwd = Some(workingDirectory), - out = nGContext.out, - in = nGContext.in, - err = nGContext.err, - ), - ), - ) - nGContext.exit(exit.code) - } +object Cli extends CliUtils { private def throwIfError(exit: ExitCode): Unit = if (exit != ExitCode.Ok) throw new RuntimeException(exit.toString) with NoStackTrace @@ -125,7 +100,7 @@ object Cli { case Right(`stableVersion`) => options.common.debug.println(s"Using core runner [$stableVersion]") Right(ScalafmtCoreRunner) - case Right(v) if isNativeImage => + case Right(v) if isNativeImage || isNative => Left( s"""|error: invalid Scalafmt version. | @@ -142,7 +117,7 @@ object Cli { ) case Right(v) => options.common.debug.println(s"Using dynamic runner [$v]") - Right(ScalafmtDynamicRunner) + returnDynamicRunner() } } @@ -173,4 +148,4 @@ object Cli { ExitCode.Ok else exit } -} +} \ No newline at end of file diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/CliArgParser.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/CliArgParser.scala similarity index 100% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/CliArgParser.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/CliArgParser.scala diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/CliOptions.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/CliOptions.scala similarity index 94% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/CliOptions.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/CliOptions.scala index 3fd4a0e119..05a62c0a13 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/CliOptions.scala +++ b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/CliOptions.scala @@ -20,7 +20,7 @@ import scala.util.matching.Regex import metaconfig.Configured -object CliOptions { +object CliOptions extends CliOptionsUtils { val default = CliOptions() /** Tries to read configuration from @@ -38,15 +38,7 @@ object CliOptions { def auto(parsed: CliOptions): CliOptions = { val info: Output.StreamOrWriter = if (parsed.quiet) Output.NoopStream - else { - val usesOut = parsed.stdIn || parsed.writeMode.usesOut - val cons = if (usesOut) System.console() else null - if (cons ne null) new Output.FromWriter(cons.writer()) - else new Output.FromStream( - if (parsed.noStdErr || !usesOut) parsed.common.out - else parsed.common.err, - ) - } + else makeOutputStreamOrWriter(parsed) val common = parsed.common.copy( out = guardPrintStream(parsed.quiet && !parsed.stdIn)(parsed.common.out), info = info, diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ExitCode.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ExitCode.scala similarity index 93% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/ExitCode.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ExitCode.scala index 62815d7dc7..eae1cc7c61 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ExitCode.scala +++ b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ExitCode.scala @@ -1,6 +1,7 @@ package org.scalafmt.cli import scala.collection.mutable +import org.scalafmt.CompatCollections sealed abstract case class ExitCode(code: Int, name: String) { def isOk: Boolean = this == ExitCode.Ok @@ -13,7 +14,7 @@ object ExitCode { // for example how the name is calculated for merged exit codes. private var counter = 0 private val allInternal = mutable.ListBuffer.empty[ExitCode] - private val cache = new java.util.concurrent.ConcurrentHashMap[Int, ExitCode] + private val cache = CompatCollections.concurrentMap[Int, ExitCode] private def generateExitStatus(implicit name: sourcecode.Name) = { val code = counter counter = if (counter == 0) 1 else counter << 1 diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/FileFetchMode.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/FileFetchMode.scala similarity index 100% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/FileFetchMode.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/FileFetchMode.scala diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/InputMethod.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/InputMethod.scala similarity index 99% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/InputMethod.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/InputMethod.scala index f99caa84c4..2fbb6d22c1 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/InputMethod.scala +++ b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/InputMethod.scala @@ -8,6 +8,7 @@ import java.nio.file.Path import java.nio.file.Paths import scala.io.Source +import munit.{diff => difflib} sealed abstract class InputMethod { def readInput(options: CliOptions): String diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/Output.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/Output.scala similarity index 100% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/Output.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/Output.scala diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCliReporter.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtCliReporter.scala similarity index 100% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCliReporter.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtCliReporter.scala diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala similarity index 96% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala index 607a821250..de9646b833 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala +++ b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtCoreRunner.scala @@ -1,6 +1,6 @@ package org.scalafmt.cli -import org.scalafmt.CompatCollections.ParConverters._ +import org.scalafmt.CompatCollections.CompatParConverters._ import org.scalafmt.Error import org.scalafmt.Formatted import org.scalafmt.Scalafmt @@ -41,7 +41,7 @@ object ScalafmtCoreRunner extends ScalafmtRunner { val termDisplay = newTermDisplay(options, inputMethods, termDisplayMessage) val exitCode = new AtomicReference(ExitCode.Ok) Breaks.breakable { - inputMethods.par.foreach { inputMethod => + inputMethods.compatPar.foreach { inputMethod => val code = handleFile(inputMethod, options, adjustedScalafmtConf) exitCode.getAndUpdate(ExitCode.merge(code, _)) if (options.check && !code.isOk) Breaks.break diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtDynamicRunner.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtDynamicRunner.scala similarity index 95% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtDynamicRunner.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtDynamicRunner.scala index f37e36ea1c..115c67b895 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtDynamicRunner.scala +++ b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtDynamicRunner.scala @@ -1,6 +1,6 @@ package org.scalafmt.cli -import org.scalafmt.CompatCollections.ParConverters._ +import org.scalafmt.CompatCollections.CompatParConverters._ import org.scalafmt.Error import org.scalafmt.dynamic.ScalafmtDynamicError import org.scalafmt.interfaces.Scalafmt @@ -39,7 +39,7 @@ object ScalafmtDynamicRunner extends ScalafmtRunner { val exitCode = new AtomicReference(ExitCode.Ok) breakable { - inputMethods.par.foreach { inputMethod => + inputMethods.compatPar.foreach { inputMethod => try { val code = handleFile(inputMethod, session, options) exitCode.getAndUpdate(ExitCode.merge(code, _)) diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtRunner.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtRunner.scala similarity index 100% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/ScalafmtRunner.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/ScalafmtRunner.scala diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/TermDisplay.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/TermDisplay.scala similarity index 97% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/TermDisplay.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/TermDisplay.scala index 1cdb6246e1..715561d0b6 100644 --- a/scalafmt-cli/src/main/scala/org/scalafmt/cli/TermDisplay.scala +++ b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/TermDisplay.scala @@ -8,7 +8,6 @@ package org.scalafmt.cli */ import java.io.File import java.io.Writer -import java.sql.Timestamp import java.util.concurrent._ import scala.annotation.tailrec @@ -62,7 +61,7 @@ object Terminal { } -object TermDisplay { +object TermDisplay extends TermUtils { def defaultFallbackMode: Boolean = { val env0 = sys.env.get("COURSIER_PROGRESS").map(_.toLowerCase).collect { @@ -71,7 +70,7 @@ object TermDisplay { } def compatibilityEnv = sys.env.contains("COURSIER_NO_TERM") - def nonInteractive = System.console() == null + def nonInteractive = noConsole def insideEmacs = sys.env.contains("INSIDE_EMACS") def ci = sys.env.contains("CI") @@ -108,9 +107,6 @@ object TermDisplay { } } - private val format = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss") - private def formatTimestamp(ts: Long): String = format - .format(new Timestamp(ts)) private case class CheckUpdateInfo( currentTimeOpt: Option[Long], @@ -159,7 +155,7 @@ object TermDisplay { private var width = 80 private var currentHeight = 0 - private val q = new LinkedBlockingDeque[Message] + private val q = new LinkedBlockingQueue[Message] def update(): Unit = if (q.size() == 0) q.put(Message.Update) diff --git a/scalafmt-cli/src/main/scala/org/scalafmt/cli/WriteMode.scala b/scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/WriteMode.scala similarity index 100% rename from scalafmt-cli/src/main/scala/org/scalafmt/cli/WriteMode.scala rename to scalafmt-cli/shared/src/main/scala/org/scalafmt/cli/WriteMode.scala diff --git a/scalafmt-config/jvm/src/main/scala/org/scalafmt/config/PlatformConfig.scala b/scalafmt-config/jvm/src/main/scala/org/scalafmt/config/PlatformConfig.scala index f350693583..a438ea2162 100644 --- a/scalafmt-config/jvm/src/main/scala/org/scalafmt/config/PlatformConfig.scala +++ b/scalafmt-config/jvm/src/main/scala/org/scalafmt/config/PlatformConfig.scala @@ -3,6 +3,7 @@ package org.scalafmt.config import metaconfig.MetaconfigParser object PlatformConfig { + def isNative = false implicit val parser: MetaconfigParser = metaconfig.typesafeconfig.typesafeConfigMetaconfigParser } diff --git a/scalafmt-config/native/src/main/scala/org/scalafmt/config/PlatformConfig.scala b/scalafmt-config/native/src/main/scala/org/scalafmt/config/PlatformConfig.scala new file mode 100644 index 0000000000..4f07b376e4 --- /dev/null +++ b/scalafmt-config/native/src/main/scala/org/scalafmt/config/PlatformConfig.scala @@ -0,0 +1,9 @@ +package org.scalafmt.config + +import metaconfig.MetaconfigParser + +object PlatformConfig { + def isNative = true + implicit val parser: MetaconfigParser = + metaconfig.sconfig.sConfigMetaconfigParser +} diff --git a/scalafmt-config/shared/src/main/scala/org/scalafmt/config/ConfParsed.scala b/scalafmt-config/shared/src/main/scala/org/scalafmt/config/ConfParsed.scala index a861f36d36..b9eec9dc10 100644 --- a/scalafmt-config/shared/src/main/scala/org/scalafmt/config/ConfParsed.scala +++ b/scalafmt-config/shared/src/main/scala/org/scalafmt/config/ConfParsed.scala @@ -3,6 +3,7 @@ package org.scalafmt.config import org.scalafmt.config.PlatformConfig._ import java.nio.file.Path +import java.nio.file.Files import scala.io.Codec import scala.util.Try @@ -57,7 +58,14 @@ object ConfParsed { def fromString(input: String, path: Option[String] = None): ConfParsed = fromInput(Input.String(input), path) - def fromPath(input: Path, path: Option[String] = None): ConfParsed = - apply(Configured.fromExceptionThrowing(Input.File(input)), path) + def fromPath(input: Path, path: Option[String] = None): ConfParsed = { + if (isNative) { + val bytes = Files.readAllBytes(input) + val configStr = new String(bytes) + apply(Configured.fromExceptionThrowing(Input.String(configStr)), path) + } else { + apply(Configured.fromExceptionThrowing(Input.File(input)), path) + } + } } diff --git a/scalafmt-core/jvm/src/main/scala/org/scalafmt/internal/PlatformCompat.scala b/scalafmt-core/jvm/src/main/scala/org/scalafmt/internal/PlatformCompat.scala new file mode 100644 index 0000000000..ccad662d5f --- /dev/null +++ b/scalafmt-core/jvm/src/main/scala/org/scalafmt/internal/PlatformCompat.scala @@ -0,0 +1,10 @@ +package org.scalafmt.internal + +import metaconfig._ + +import java.io.File + +object PlatformCompat { + @inline def metaconfigInputFromFile(input: File) = + Input.File(input) +} diff --git a/scalafmt-core/jvm/src/main/scala/org/scalafmt/internal/RegexCompat.scala b/scalafmt-core/jvm/src/main/scala/org/scalafmt/internal/RegexCompat.scala new file mode 100644 index 0000000000..6312ef5001 --- /dev/null +++ b/scalafmt-core/jvm/src/main/scala/org/scalafmt/internal/RegexCompat.scala @@ -0,0 +1,105 @@ +package org.scalafmt.internal + +import java.util.regex.Pattern +import scala.util.matching.Regex + +object RegexCompat { + + @inline + val trailingSpace = + Pattern.compile("\\h++$", Pattern.MULTILINE) + + // "slc" stands for single-line comment + @inline + val srcLine = + Pattern.compile("^/\\/\\/*+\\h*+(.*?)\\h*+$") + + @inline + val slcDelim = Pattern.compile("\\h++") + + // "mlc" stands for multi-line comment + @inline + val mlcHeader = + Pattern.compile("^/\\*\\h*+(?:\n\\h*+[*]*+\\h*+)?") + + @inline + val mlcLineDelim = + Pattern.compile("\\h*+\n\\h*+[*]*+\\h*+") + + @inline + val mlcParagraphEnd = Pattern.compile("[.:!?=]$") + + @inline + val mlcParagraphBeg = Pattern.compile("^(?:[-*@=]|\\d++[.:])") + + @inline + val leadingAsteriskSpace = + Pattern.compile("(?<=\n)\\h*+(?=[*][^*])") + + @inline + val docstringLine = + Pattern.compile( + "^(?:\\h*+\\*)?(\\h*+)(.*?)\\h*+$", + Pattern.MULTILINE + ) + + @inline + val emptyLines = "\\h*+(\n\\h*+\\*?\\h*+)*" + + @inline + val emptyDocstring = Pattern.compile(s"^/\\*\\*$emptyLines\\*/$$") + + @inline + val onelineDocstring = { + val oneline = "[^*\n\\h](?:[^\n]*[^\n\\h])?" + Pattern.compile(s"^/\\*\\*$emptyLines($oneline)$emptyLines\\*/$$") + } + + @inline + val docstringLeadingSpace = Pattern.compile("^\\h++") + + @inline + def compileStripMarginPattern(pipe: Char) = + Pattern.compile(s"(?<=\n)\\h*+(?=\\${pipe})") + + @inline + def compileStripMarginPatternWithLineContent(pipe: Char) = + Pattern.compile(s"\n(\\h*+\\$pipe)?([^\n]*+)") + + // see: https://ammonite.io/#Save/LoadSession + @inline + private val ammonitePattern: Regex = "(?:\\s*\\n@(?=\\s))+".r + + @inline + val stripMarginPattern = compileStripMarginPattern('|') + val stripMarginPatternWithLineContent = compileStripMarginPatternWithLineContent('|') + // Pattern.compile("\n(\\h*+\\|)?([^\n]*+)") + + @inline + def replaceAllStripMargin( + stripMarginPattern: Pattern, + text: String, + spaces: String, + pipe: Char + ): String = + stripMarginPattern.matcher(text).replaceAll(spaces) + + @inline + def replaceAllLeadingAsterisk( + leadingAsteriskSpace: Pattern, + trimmed: String, + spaces: String + ): String = + leadingAsteriskSpace.matcher(trimmed).replaceAll(spaces) + + @inline + def splitByAmmonitePattern(code: String): Array[String] = + ammonitePattern.split(code) + + @inline + def splitByBeforeTextMatching( + baseText: String, + beforeText: String + ): Array[String] = + baseText.split(s"(?=${beforeText})") +} diff --git a/scalafmt-core/native/src/main/scala/org/scalafmt/internal/PlatformCompat.scala b/scalafmt-core/native/src/main/scala/org/scalafmt/internal/PlatformCompat.scala new file mode 100644 index 0000000000..94586ad6c0 --- /dev/null +++ b/scalafmt-core/native/src/main/scala/org/scalafmt/internal/PlatformCompat.scala @@ -0,0 +1,15 @@ +package org.scalafmt.internal + +import metaconfig._ +import scala.meta.internal.io.FileIO +import scala.meta.io.AbsolutePath + +import java.nio.charset.StandardCharsets +import java.io.File + +object PlatformCompat { + @inline def metaconfigInputFromFile(input: File) = + Input.String( + FileIO.slurp(AbsolutePath(input.toPath()), StandardCharsets.UTF_8) + ) +} diff --git a/scalafmt-core/native/src/main/scala/org/scalafmt/internal/RegexCompat.scala b/scalafmt-core/native/src/main/scala/org/scalafmt/internal/RegexCompat.scala new file mode 100644 index 0000000000..40c60b2298 --- /dev/null +++ b/scalafmt-core/native/src/main/scala/org/scalafmt/internal/RegexCompat.scala @@ -0,0 +1,265 @@ +package org.scalafmt.internal + +import scala.util.matching.Regex +import java.util.regex.Pattern + +/* Before text matching (?=re), after text matching (?<=re) + * and more are incompatible in Scala Native, so custom functions + * have to be used. + * Scala Native uses an implementation of: + * https://github.com/google/re2/wiki/Syntax + */ + +object RegexCompat { + + /* Replaces '\\h', which is incompatible in Scala Native. + * Does not check correctness of the input regex string. + */ + private def fixHorizontalSpaceInRegex(reg: String) = { + + @inline + val replacingInsideClass = + "\t \u00A0\u1680\u180E\u2000-\u200A\u202F\u205F\u3000" + + @inline + val replacingOutsideClass = + s"[$replacingInsideClass]" + + val sb = new StringBuilder() + var isInClass = false + var isEscaped = false + + for (char <- reg) { + char match { + case '\\' if !isEscaped => + isEscaped = true + case 'h' if isEscaped => + sb.append( + if (isInClass) replacingInsideClass + else replacingOutsideClass + ) + isEscaped = false + case '[' if !isEscaped => + sb.append('[') + isInClass = true + case ']' if !isEscaped => + sb.append(']') + isInClass = false + case other => + if (isEscaped) { + isEscaped = false + sb.append('\\') + } + sb.append(other) + } + } + sb.toString() + } + + @inline + val trailingSpace = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex("\\h+$"), + Pattern.MULTILINE + ) + + // "slc" stands for single-line comment + @inline + val srcLine = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex("^/\\/\\/*\\h*(.*?)\\h*$") + ) + + @inline + val slcDelim = + Pattern.compile(RegexCompat.fixHorizontalSpaceInRegex("\\h+")) + + // "mlc" stands for multi-line comment + @inline + val mlcHeader = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex("^/\\*\\h*(?:\n\\h*[*]*\\h*)?") + ) + + @inline + val mlcLineDelim = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex("\\h*\n\\h*[*]*\\h*") + ) + + @inline + val mlcParagraphEnd = Pattern.compile("[.:!?=]$") + + @inline + val mlcParagraphBeg = Pattern.compile("^(?:[-*@=]|\\d+[.:])") + + @inline + val leadingAsteriskSpace = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex("\n\\h*[*][^*]"), + Pattern.MULTILINE + ) + + @inline + val docstringLine = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex("^(?:\\h*\\*)?(\\h*)(.*?)\\h*$"), + Pattern.MULTILINE + ) + + @inline + val emptyLines = + RegexCompat.fixHorizontalSpaceInRegex("\\h*(\n\\h*\\*?\\h*)*") + + @inline + val emptyDocstring = Pattern.compile(s"^/\\*\\*$emptyLines\\*/$$") + + @inline + val onelineDocstring = { + val oneline = + RegexCompat.fixHorizontalSpaceInRegex("[^*\n\\h](?:[^\n]*[^\n\\h])?") + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex( + s"^/\\*\\*$emptyLines($oneline)$emptyLines\\*/$$" + ) + ) + } + + @inline + val docstringLeadingSpace = + Pattern.compile(RegexCompat.fixHorizontalSpaceInRegex("^\\h+")) + + @inline + def compileStripMarginPattern(pipe: Char) = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex(s"\n+\\h*?\\${pipe}"), + Pattern.MULTILINE + ) + + @inline + def compileStripMarginPatternWithLineContent(pipe: Char) = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex(s"\n(\\h*\\$pipe)?([^\n]*)"), + Pattern.MULTILINE + ) + + val stripMarginPatternWithLineContent = + compileStripMarginPatternWithLineContent('|') + + // see: https://ammonite.io/#Save/LoadSession + @inline + val ammonitePattern: Regex = + "(?:\\s*\\n@)".r + + @inline + val stripMarginPattern = + Pattern.compile( + RegexCompat.fixHorizontalSpaceInRegex("\n(\\h*\\|)?([^\n]*)"), + Pattern.MULTILINE + ) + + // startAfterPattern and endBeforePattern should be unique in basePattern + // basePattern = startAfterPattern + matched pattern + endBeforePattern + private def replaceAll( + basePattern: Pattern, + startAfterPattern: Pattern, + endBeforePattern: Pattern, + baseText: String, + replacingText: String + ): String = { + val sb = new StringBuilder() + val matcher = basePattern.matcher(baseText) + var currPosition = 0 + while (matcher.find()) { + val start = matcher.start() + val end = matcher.end() + + sb.append(baseText.substring(currPosition, start)) + + val subtext = baseText.substring(start, end) + val startAfterMatcher = startAfterPattern.matcher(subtext) + val endBeforeMatcher = endBeforePattern.matcher(subtext) + + startAfterMatcher.find() + endBeforeMatcher.find() + + sb.append(startAfterMatcher.group()) + sb.append(replacingText) + sb.append(endBeforeMatcher.group()) + + currPosition = end + } + + sb.append(baseText.substring(currPosition)) + sb.toString() + } + + def replaceAllStripMargin( + stripMarginPattern: Pattern, + text: String, + spaces: String, + pipe: Char + ): String = { + val startAfter = Pattern.compile("\n+") + val endBefore = Pattern.compile(s"\\${pipe}") + + replaceAll(stripMarginPattern, startAfter, endBefore, text, spaces) + } + + def replaceAllLeadingAsterisk( + leadingAsteriskSpace: Pattern, + trimmed: String, + spaces: String + ): String = { + val startAfter = Pattern.compile("\n") + val endBefore = Pattern.compile("([*][^*])") + + replaceAll(leadingAsteriskSpace, startAfter, endBefore, trimmed, spaces) + } + + def splitByAmmonitePattern(code: String): Array[String] = { + val whitespacePattern = Pattern.compile("\\s") + val actualMatches = ammonitePattern + .findAllMatchIn(code) + .filter(regexMatch => + regexMatch.end < code.length && whitespacePattern + .matcher(Character.toString(code.charAt(regexMatch.end))) + .find() + ) + .toArray + + val res = new scala.collection.mutable.ArrayBuffer[String]() + var currPosition = 0 + for (actualMatch <- actualMatches) { + if (currPosition != actualMatch.start) + res.append(code.substring(currPosition, actualMatch.start)) + currPosition = actualMatch.end + } + res.append(code.substring(currPosition)) + res.toArray + } + + // replaces baseText.split("(?={beforeText})") + def splitByBeforeTextMatching( + baseText: String, + beforeText: String + ): Array[String] = { + val beforeTextPattern = Pattern.compile(beforeText) + val matcher = beforeTextPattern + .matcher(baseText) + + val res = new scala.collection.mutable.ArrayBuffer[String]() + var currPosition = 0 + while (matcher.find()) { + val start = matcher.start() + // val end = matcher.end() + if (start != 0) + res.append(baseText.substring(currPosition, start)) + + currPosition = start + } + res.append(baseText.substring(currPosition, baseText.size)) + + res.toArray + } +} diff --git a/scalafmt-core/native/src/main/scala/org/scalafmt/internal/package.scala b/scalafmt-core/native/src/main/scala/org/scalafmt/internal/package.scala new file mode 100644 index 0000000000..97e0bcf34f --- /dev/null +++ b/scalafmt-core/native/src/main/scala/org/scalafmt/internal/package.scala @@ -0,0 +1,5 @@ +package org.scalafmt + +package object internal { + type PriorityQueue[T] = scala.collection.mutable.PriorityQueue[T] +} 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 785f85b798..729e969d11 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 @@ -45,7 +45,7 @@ object ProjectFiles { val defaultIncludePaths = Seq("glob:**.scala", "glob:**.sbt", "glob:**.sc") - private sealed abstract class PathMatcher { + sealed abstract class PathMatcher { def matches(path: file.Path): Boolean } diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtRunner.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtRunner.scala index e6dfee293c..b1353904f3 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtRunner.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtRunner.scala @@ -93,11 +93,8 @@ object ScalafmtRunner { implicit val encoder: ConfEncoder[ScalafmtRunner] = generic.deriveEncoder private def overrideDialect[T: ClassTag](d: Dialect, k: String, v: T) = { - import org.scalafmt.config.ReflectOps._ - val methodName = - if (k.isEmpty || k.startsWith("with")) k - else "with" + Character.toUpperCase(k.head) + k.tail - d.invokeAs[Dialect](methodName, v.asParam) + val map: Map[String,Any => Dialect] = DialectMacro.dialectMap(d) + map(k)(v) } implicit val decoder: ConfDecoderEx[ScalafmtRunner] = generic diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala index 24e2cc1382..3e8306231e 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatWriter.scala @@ -24,6 +24,8 @@ import scala.collection.AbstractIterator import scala.collection.mutable import scala.util.Try +import org.scalafmt.internal.RegexCompat._ + /** Produces formatted output from sequence of splits. */ class FormatWriter(formatOps: FormatOps) { @@ -583,7 +585,12 @@ class FormatWriter(formatOps: FormatOps) { } tupleOpt.fold(text) { case (pipe, indent) => val spaces = getIndentation(indent) - getStripMarginPattern(pipe).matcher(text).replaceAll(spaces) + RegexCompat.replaceAllStripMargin( + getStripMarginPattern(pipe), + text, + spaces, + pipe + ) } } @@ -794,7 +801,13 @@ class FormatWriter(formatOps: FormatOps) { terminateMlc(curlen, lines) } else { val trimmed = removeTrailingWhiteSpace(text) - sb.append(leadingAsteriskSpace.matcher(trimmed).replaceAll(spaces)) + sb.append( + RegexCompat.replaceAllLeadingAsterisk( + leadingAsteriskSpace, + trimmed, + spaces + ) + ) } private def appendLineBreak(): Unit = startNewLine(spaces).append('*') @@ -1905,41 +1918,18 @@ object FormatWriter { private def getIndentation(len: Int): String = if (len < indentations.length) indentations(len) else " " * len - private val trailingSpace = Pattern.compile("\\h++$", Pattern.MULTILINE) private def removeTrailingWhiteSpace(str: String): String = trailingSpace .matcher(str).replaceAll("") private def splitAsIterator(regex: Pattern)(value: String): Iterator[String] = regex.splitAsStream(value).iterator().asScala - // "slc" stands for single-line comment - private val slcDelim = Pattern.compile("\\h++") - // "mlc" stands for multi-line comment - private val mlcHeader = Pattern.compile("^/\\*\\h*+(?:\n\\h*+[*]*+\\h*+)?") - private val mlcLineDelim = Pattern.compile("\\h*+\n\\h*+[*]*+\\h*+") - private val mlcParagraphEnd = Pattern.compile("[.:!?=]$") - private val mlcParagraphBeg = Pattern.compile("^(?:[-*@=]|\\d++[.:])") - - private val leadingAsteriskSpace = Pattern.compile("(?<=\n)\\h*+(?=[*][^*])") - private val docstringLine = Pattern - .compile("^(?:\\h*+\\*)?(\\h*+)(.*?)\\h*+$", Pattern.MULTILINE) - private val emptyLines = "\\h*+(\n\\h*+\\*?\\h*+)*" - private val emptyDocstring = Pattern.compile(s"^/\\*\\*$emptyLines\\*/$$") - private val onelineDocstring = { - val oneline = "[^*\n\\h](?:[^\n]*[^\n\\h])?" - Pattern.compile(s"^/\\*\\*$emptyLines($oneline)$emptyLines\\*/$$") - } - private val docstringLeadingSpace = Pattern.compile("^\\h++") - @inline private def getStripMarginPattern(pipe: Char) = - if (pipe == '|') leadingPipeSpace else compileStripMarginPattern(pipe) - - @inline - private def compileStripMarginPattern(pipe: Char) = Pattern - .compile(s"(?<=\n)\\h*+(?=\\$pipe)") + if (pipe == '|') leadingPipeSpace + else RegexCompat.compileStripMarginPattern(pipe) - private val leadingPipeSpace = compileStripMarginPattern('|') + private val leadingPipeSpace = RegexCompat.compileStripMarginPattern('|') /** [[https://dotty.epfl.ch/docs/reference/other-new-features/indentation.html#the-end-marker]] */ diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala index 673db99e73..c6d288bd79 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala @@ -9,8 +9,6 @@ import org.scalafmt.util.TreeOps._ import scala.meta._ import scala.meta.tokens.Token -import java.util.regex.Pattern - import scala.annotation.tailrec /** A partial formatting solution up to splits.length number of tokens. @@ -371,16 +369,11 @@ object State { } @inline - private def compileStripMarginPattern(pipe: Char) = Pattern - .compile(s"\n(\\h*+\\$pipe)?([^\n]*+)") - - @inline - private def getStripMarginPattern(pipe: Char) = - if (pipe == '|') pipeStripMarginPattern else compileStripMarginPattern(pipe) - - private val pipeStripMarginPattern = compileStripMarginPattern('|') + private def getStripMarginPatternWithLineContent(pipe: Char) = + if (pipe == '|') RegexCompat.stripMarginPatternWithLineContent + else RegexCompat.compileStripMarginPatternWithLineContent(pipe) - private val slcLine = Pattern.compile("^/\\/\\/*+\\h*+(.*?)\\h*+$") + private val slcLine = RegexCompat.srcLine def getColumns(ft: FormatToken, indent: Int, column: Int)(implicit style: ScalafmtConfig, @@ -457,7 +450,7 @@ object State { adjustMargin: Int => Int, firstLength: Int, ): (Int, Int) = { - val matcher = getStripMarginPattern(pipe).matcher(syntax) + val matcher = getStripMarginPatternWithLineContent(pipe).matcher(syntax) matcher.region(firstNL, syntax.length) if (!matcher.find()) (firstLength, firstLength) else { diff --git a/scalafmt-dynamic/src/main/resources/META-INF/services/org.scalafmt.interfaces.Scalafmt b/scalafmt-dynamic/jvm/src/main/resources/META-INF/services/org.scalafmt.interfaces.Scalafmt similarity index 100% rename from scalafmt-dynamic/src/main/resources/META-INF/services/org.scalafmt.interfaces.Scalafmt rename to scalafmt-dynamic/jvm/src/main/resources/META-INF/services/org.scalafmt.interfaces.Scalafmt diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/Dependency.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/Dependency.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/Dependency.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/Dependency.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/DependencyDownloader.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/DependencyDownloader.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/DependencyDownloader.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/DependencyDownloader.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtConfigLoader.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtConfigLoader.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtConfigLoader.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtConfigLoader.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicSession.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicSession.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicSession.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicSession.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtModuleLoader.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtModuleLoader.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtModuleLoader.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtModuleLoader.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtReflect.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtReflect.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtReflect.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtReflect.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtReflectConfig.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtReflectConfig.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtReflectConfig.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/ScalafmtReflectConfig.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/PositionExceptionImpl.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/PositionExceptionImpl.scala similarity index 65% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/PositionExceptionImpl.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/PositionExceptionImpl.scala index 40162766a4..5dc8849635 100644 --- a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/PositionExceptionImpl.scala +++ b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/PositionExceptionImpl.scala @@ -14,8 +14,8 @@ case class PositionExceptionImpl( ) extends PositionException(longMessage, cause) { def start: Int = pos.start def end: Int = pos.end - override def startLine: Int = pos.startLine - override def startCharacter: Int = pos.startCharacter - override def endLine: Int = pos.endLine - override def endCharacter: Int = pos.endCharacter + override def startLine(): Int = pos.startLine + override def startCharacter(): Int = pos.startCharacter + override def endLine(): Int = pos.endLine + override def endCharacter(): Int = pos.endCharacter } diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/RangePosition.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/RangePosition.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/RangePosition.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/RangePosition.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/ReflectionException.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/ReflectionException.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/ReflectionException.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/ReflectionException.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/VersionMismatch.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/VersionMismatch.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/VersionMismatch.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/exceptions/VersionMismatch.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/package.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/package.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/package.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/package.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/utils/ReentrantCache.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/utils/ReentrantCache.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/utils/ReentrantCache.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/utils/ReentrantCache.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/utils/ReflectUtils.scala b/scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/utils/ReflectUtils.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/utils/ReflectUtils.scala rename to scalafmt-dynamic/jvm/src/main/scala/org/scalafmt/dynamic/utils/ReflectUtils.scala diff --git a/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala b/scalafmt-dynamic/jvm/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala similarity index 99% rename from scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala rename to scalafmt-dynamic/jvm/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala index 4126345ac3..e787c348dd 100644 --- a/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala +++ b/scalafmt-dynamic/jvm/src/test/scala/org/scalafmt/dynamic/DynamicSuite.scala @@ -592,7 +592,7 @@ class DynamicSuite extends FunSuite { assertEquals(cfg.indentMain, Some(2)) assertEquals(cfg.indentCallSite, Some(3)) assertEquals(cfg.indentDefnSite, Some(5)) - } + } } } diff --git a/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/PositionSyntax.scala b/scalafmt-dynamic/jvm/src/test/scala/org/scalafmt/dynamic/PositionSyntax.scala similarity index 100% rename from scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/PositionSyntax.scala rename to scalafmt-dynamic/jvm/src/test/scala/org/scalafmt/dynamic/PositionSyntax.scala diff --git a/scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/ScalafmtVersionSuite.scala b/scalafmt-dynamic/jvm/src/test/scala/org/scalafmt/dynamic/ScalafmtVersionSuite.scala similarity index 100% rename from scalafmt-dynamic/src/test/scala/org/scalafmt/dynamic/ScalafmtVersionSuite.scala rename to scalafmt-dynamic/jvm/src/test/scala/org/scalafmt/dynamic/ScalafmtVersionSuite.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicError.scala b/scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicError.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicError.scala rename to scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamicError.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtVersion.scala b/scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/ScalafmtVersion.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtVersion.scala rename to scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/ScalafmtVersion.scala diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/ScalafmtException.scala b/scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/exception/ScalafmtException.scala similarity index 100% rename from scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/exceptions/ScalafmtException.scala rename to scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/exception/ScalafmtException.scala diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/PositionException.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/PositionException.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/PositionException.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/PositionException.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/Scalafmt.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/Scalafmt.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/Scalafmt.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/Scalafmt.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtClassLoader.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtClassLoader.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtClassLoader.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtClassLoader.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtException.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtException.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtException.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtException.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtReporter.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtReporter.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtReporter.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtReporter.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtResult.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtResult.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtResult.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtResult.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtSession.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtSession.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtSession.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtSession.java diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtSessionFactory.java b/scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtSessionFactory.java similarity index 100% rename from scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/ScalafmtSessionFactory.java rename to scalafmt-interfaces/jvm/src/main/java/org/scalafmt/interfaces/ScalafmtSessionFactory.java diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/PositionException.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/PositionException.scala new file mode 100644 index 0000000000..d5812edb11 --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/PositionException.scala @@ -0,0 +1,39 @@ +package org.scalafmt.interfaces + +import java.nio.file.Path + +/** An exception that happened at a position in a source file such as a parse + * error. + */ +abstract class PositionException(message: String, cause: Throwable) + extends Exception(message, cause) { + + override def fillInStackTrace(): Throwable = synchronized { + return this; + } + + /** @return + * The file where the error occurred. + */ + def file(): Path; + + /** @return + * The text contents of the file being formatted. + */ + def code(): String; + + /** @return + * The fully formatted error message including line content and caret. + */ + def longMessage(): String + + /** @return + * Only the error message itself without line content and caret. + */ + def shortMessage(): String + + def startLine(): Int + def startCharacter(): Int + def endLine(): Int + def endCharacter(): Int +} diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/RepositoryCredential.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/RepositoryCredential.scala new file mode 100644 index 0000000000..ee92a8fe8d --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/RepositoryCredential.scala @@ -0,0 +1,9 @@ +package org.scalafmt.interfaces; + +final class RepositoryCredential(val host: String, val username: String, val password: String) + +object RepositoryCredential { + trait ScalafmtExtension { + def withRepositoryCredentials(credentials: RepositoryCredential*): Scalafmt + } +} \ No newline at end of file diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/Scalafmt.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/Scalafmt.scala new file mode 100644 index 0000000000..cccc4a5e42 --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/Scalafmt.scala @@ -0,0 +1,111 @@ +package org.scalafmt.interfaces + +import java.nio.file.Path +import java.util +import java.util.NoSuchElementException +import java.util.ServiceLoader + +/** A stable public interface to run Scalafmt. + * + * This interface is designed for integrations such as editor plugins and build + * tools. An implementation of this interface is available in the module + * 'scalafmt-dynamic'. + * + * It is recommended to use this interface over the org.scalafmt.Scalafmt + * object for several reasons: + * + * - this API is guaranteed to be binary compatible with all future versions + * of Scalafmt. + * - it downloads the Scalafmt version matching the 'version' setting in + * .scalafmt.conf. All versions down to v1.2.0 are supported. + * - it respects the 'project.{excludeFilters,includeFilters}' setting in + * .scalafmt.conf. + * - it uses the correct parser for `*.sbt` and `*.sc` files. + * - it automatically caches parsing of configuration files avoiding + * redundant work when possible. + * - it has two external library dependencies (com.geirsson:coursier-small + * and com.typesafe:config), which is a smaller dependency footprint + * compared to scalafmt-core. + */ + +trait Scalafmt { + + /** Format a single file with the given .scalafmt.conf configuration. + * + * @param config + * the absolute path to the configuration file. This file must exist or an + * exception will be thrown. + * @param file + * relative or absolute path to the file being formatted. Used only for the + * path name, the file does not have to exist on disk. + * @param code + * the text contents to format. + * @return + * the formatted contents if formatting was successful, otherwise the + * original text contents. + */ + def format(config: Path, file: Path, code: String): String + + /** Whether to respect the 'project.{excludeFilters,includeFilters}' setting + * in .scalafmt.conf. + * + * @param respectExcludeFilters + * If true (default), returns the original file contents when formatting a + * file that does not matches the project settings in .scalafmt.conf. If + * false, formats every file that is passed to the {@link #format(Path, + * Path, String)} method regardless of .scalafmt.conf settings. + */ + def withRespectProjectFilters(respectExcludeFilters: Boolean): Scalafmt + + /** Whether to respect the 'version' setting in .scalafmt.conf. + * + * @param respectVersion + * If true (default), refuses to format files when the 'version' setting is + * missing in .scalafmt.conf and users must update .scalafmt.conf to format + * files. If false, falls back to the default version provided via {@link + * #withDefaultVersion(String)}. + */ + def withRespectVersion(respectVersion: Boolean): Scalafmt + + /** The fallback Scalafmt version to use when there is no 'version' setting in + * .scalafmt.conf. + * + * The default version is ignored when {@link #withRespectVersion(boolean)} + * is true. + */ + def withDefaultVersion(defaultVersion: String): Scalafmt + + /** Use this reporter to report errors and information messages. + */ + def withReporter(reporter: ScalafmtReporter): Scalafmt + + /** Use this repositories to resolve dependencies. + */ + def withMavenRepositories(repositories: String*): Scalafmt + + /** Clear internal caches such as classloaded Scalafmt instances. + */ + def clear(): Unit + + /** + * Create a ScalafmtSession to format a batch of files using fixed configuration. + * @param config location of the configuration file + * @return a new session instance + */ + def createSession(config: Path): ScalafmtSession +} + +object Scalafmt { + + /** Classload a new instance of this Scalafmt instance. + * + * @param loader + * the classloader containing the 'scalafmt-dynamic' module. + * + * @throws NoSuchElementException + * if the classloader does not have the 'scalafmt-dynamic' module. + */ + def create(loader: ClassLoader): Scalafmt = throw new Exception( + "Can't use different version for native CLI" + ) +} diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtClassLoader.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtClassLoader.scala new file mode 100644 index 0000000000..2b796f3c0c --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtClassLoader.scala @@ -0,0 +1,17 @@ +package org.scalafmt.interfaces + +/** A classloader that shares only scalafmt-interfaces classes from the parent + * classloader. + * + * This classloader is intended to be used as a parent when class-loading + * scalafmt-dynamic. By using this classloader as a parent, it's possible to + * cast runtime instances from the scalafmt-dynamic classloader into + * `org.scalafmt.interfaces.Scalafmt` from this classloader. + */ +class ScalafmtClassLoader(var parent: ClassLoader) extends ClassLoader(null) { + @throws[ClassNotFoundException] + override protected def findClass(name: String) = if ( + name.startsWith("org.scalafmt.interfaces") + ) parent.loadClass(name) + else super.findClass(name) +} diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtReporter.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtReporter.scala new file mode 100644 index 0000000000..f36eb444f3 --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtReporter.scala @@ -0,0 +1,78 @@ +package org.scalafmt.interfaces + +import java.io.OutputStreamWriter +import java.io.PrintWriter +import java.nio.file.Path + +/** A reporter to handle error and information messages from Scalafmt. + */ +trait ScalafmtReporter { + + /** An error occurred while trying to process this file. + * + * @param file + * can be either a Scala source file or .scalafmt.conf. + * @param message + * the error message. + */ + def error(file: Path, message: String): Unit + + /** An exception occurred while trying to process this file. + * + * @param file + * can be either a Scala source file or .scalafmt.conf. + * @param e + * the exception that occurred, has type {@link PositionException} when the + * error appeared as a position. + */ + def error(file: Path, e: Throwable): Unit + + /** An exception occurred while trying to process this file. + * + * @param file + * can be either a Scala source file or .scalafmt.conf. + * @param message + * additional error message + * @param e + * the exception that occurred, has type {@link PositionException} when the + * error appeared as a position. + */ + def error(file: Path, message: String, e: Throwable): Unit = + error(file, new RuntimeException(message, e)) + + /** This file was not formatted because it's excluded by project settings from + * .scalafmt.conf. + * + * @param file + * the file path that was not formatted. + */ + def excluded(file: Path): Unit + + /** This .scalafmt.conf file is missing the 'version' setting. + * + * @param config + * the .scalafmt.conf file. + * @param defaultVersion + * the configured default Scalafmt version. + */ + def missingVersion(config: Path, defaultVersion: String): Unit = { + val message = String.format( + "missing setting 'version'. To fix this problem, add the following line to .scalafmt.conf: 'version=%s'.", + defaultVersion + ) + error(config, message) + } + + /** The .scalafmt.conf file was parsed with the given Scalafmt version. + */ + def parsedConfig(config: Path, scalafmtVersion: String): Unit + + /** Use {@link #downloadOutputStreamWriter} instead. + */ + @deprecated def downloadWriter(): PrintWriter + + /** Use this writer for printing progress while downloading new Scalafmt + * versions. + */ + def downloadOutputStreamWriter(): OutputStreamWriter +} diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtResult.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtResult.scala new file mode 100644 index 0000000000..3a1e87a23a --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtResult.scala @@ -0,0 +1,6 @@ +package org.scalafmt.interfaces; + +final class ScalafmtResult(val value: String, val exception: Throwable) { + def this(value: String) = this(value, null) + def this(exception: Throwable) = this(null, exception) +} diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtSession.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtSession.scala new file mode 100644 index 0000000000..57a0f927b2 --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtSession.scala @@ -0,0 +1,44 @@ +package org.scalafmt.interfaces; + +import java.nio.file.Path; + +/** + * A session based on a fixed configuration. + */ +trait ScalafmtSession { + + /** + * Format a single file with the given configuration. + * + * @param file relative or absolute path to the file being formatted. Used only for the path + * name, the file does not have to exist on disk. + * @param code the text contents to format. + * @return the formatted contents if formatting was successful, otherwise the original text + * contents. + */ + def format(file: Path, code: String): String + + + /** + * Format a single file with the given configuration. + * + * @param file relative or absolute path to the file being formatted. Used only for the path + * name, the file does not have to exist on disk. + * @param code the text contents to format. + * @return the formatted contents if formatting was successful, otherwise an error. + */ + def formatOrError(file: Path, code: String): ScalafmtResult + + /** + * Whether the path matches the 'project.{excludeFilters,includeFilters}' setting. + * @param file path to match + * @return true if the path matched the filters + */ + def matchesProjectFilters(file: Path): Boolean; + + /** + * Whether this configuration intends to limit files to those managed by git. + */ + def isGitOnly: Boolean + +} diff --git a/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtSessionFactory.scala b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtSessionFactory.scala new file mode 100644 index 0000000000..327f35c805 --- /dev/null +++ b/scalafmt-interfaces/native/src/main/scala/org/scalafmt/interfaces/ScalafmtSessionFactory.scala @@ -0,0 +1,11 @@ +package org.scalafmt.interfaces + +import java.nio.file.Path + +trait ScalafmtSessionFactory { + + /** Create a ScalafmtSession to format a batch of files using fixed + * configuration. + */ + def createSession(config: Path): ScalafmtSession +} diff --git a/scalafmt-macros/shared/src/main/scala/org/scalafmt/config/DialectMacro.scala b/scalafmt-macros/shared/src/main/scala/org/scalafmt/config/DialectMacro.scala new file mode 100644 index 0000000000..34c9cfdc0e --- /dev/null +++ b/scalafmt-macros/shared/src/main/scala/org/scalafmt/config/DialectMacro.scala @@ -0,0 +1,28 @@ +package org.scalafmt.config + +import scala.reflect.macros.blackbox +import scala.language.experimental.macros + +import scala.meta.Dialect + +// Builds a map between string and dialect method application +object DialectMacro { + def dialectMap(dialect: Dialect): Map[String, (Any => Dialect)] = macro dialectMap_impl + + def dialectMap_impl(c: blackbox.Context)(dialect: c.Tree): c.Expr[Map[String, (Any => Dialect)]] = { + import c.universe._ + val mapElements = typeOf[Dialect].members.flatMap { + case v: TermSymbol if v.isVal => + val valName = v.name.decodedName.toString().strip() + val tpe = v.typeSignature + val methodName = TermName("with" + Character.toUpperCase(valName.head) + valName.tail.strip()) + if (typeOf[Dialect].members.exists(_.name.decodedName == methodName)) + Some(q"""$valName -> ((v: Any) => $dialect.$methodName(v.asInstanceOf[$tpe]))""") + else None + case _ => None + } + c.Expr[Map[String, (Any => Dialect)]]( + q"""scala.collection.immutable.Map(..$mapElements)""" + ) + } +} diff --git a/scalafmt-sysops/shared/src/main/scala-2.12/org/scalafmt/CompatCollections.scala b/scalafmt-sysops/jvm/src/main/scala-2.12/org/scalafmt/CompatCollections.scala similarity index 62% rename from scalafmt-sysops/shared/src/main/scala-2.12/org/scalafmt/CompatCollections.scala rename to scalafmt-sysops/jvm/src/main/scala-2.12/org/scalafmt/CompatCollections.scala index 84094035db..7fe9f2f4af 100644 --- a/scalafmt-sysops/shared/src/main/scala-2.12/org/scalafmt/CompatCollections.scala +++ b/scalafmt-sysops/jvm/src/main/scala-2.12/org/scalafmt/CompatCollections.scala @@ -1,6 +1,9 @@ package org.scalafmt +import java.util.concurrent._ + private[scalafmt] object CompatCollections { val JavaConverters = scala.collection.JavaConverters object ParConverters + def concurrentMap[K, V] = new ConcurrentHashMap[K, V] } diff --git a/scalafmt-sysops/jvm/src/main/scala-2.13/org/scalafmt/CompatCollections.scala b/scalafmt-sysops/jvm/src/main/scala-2.13/org/scalafmt/CompatCollections.scala new file mode 100644 index 0000000000..30bda19a8a --- /dev/null +++ b/scalafmt-sysops/jvm/src/main/scala-2.13/org/scalafmt/CompatCollections.scala @@ -0,0 +1,14 @@ +package org.scalafmt + +import java.util.concurrent._ +import scala.collection.parallel.CollectionConverters._ + +private[scalafmt] object CompatCollections { + val JavaConverters = scala.jdk.CollectionConverters + object CompatParConverters { + implicit class XIterable[T](val col: Iterable[T]) extends AnyVal { + def compatPar = col.par + } + } + def concurrentMap[K, V] = new ConcurrentHashMap[K, V] +} \ No newline at end of file diff --git a/scalafmt-sysops/jvm/src/main/scala/org/scalafmt/PlatformConfig.scala b/scalafmt-sysops/jvm/src/main/scala/org/scalafmt/PlatformConfig.scala new file mode 100644 index 0000000000..4eb84b814f --- /dev/null +++ b/scalafmt-sysops/jvm/src/main/scala/org/scalafmt/PlatformConfig.scala @@ -0,0 +1,5 @@ +package org.scalafmt + +object PlatformConfig { + def isNative = false +} diff --git a/scalafmt-sysops/native/src/main/scala-2.12/org/scalafmt/CompatCollections.scala b/scalafmt-sysops/native/src/main/scala-2.12/org/scalafmt/CompatCollections.scala new file mode 100644 index 0000000000..835630a69b --- /dev/null +++ b/scalafmt-sysops/native/src/main/scala-2.12/org/scalafmt/CompatCollections.scala @@ -0,0 +1,22 @@ +package org.scalafmt + +import java.util.HashMap + +object CompatCollections { + val JavaConverters = scala.jdk.CollectionConverters + + // Scala Native does not include ParallelConverters + object CompatParConverters { + implicit class XIterable[T](val col: Iterable[T]) extends AnyVal { + def compatPar = col + } + } + + class ConcurrentMap[K, V] extends HashMap[K, V] { + def contains(key: K): Boolean = { + super.containsKey(key) + } + } + def concurrentMap[K, V] = new ConcurrentMap[K, V] + +} diff --git a/scalafmt-sysops/native/src/main/scala-2.13/org/scalafmt/CompatCollections.scala b/scalafmt-sysops/native/src/main/scala-2.13/org/scalafmt/CompatCollections.scala new file mode 100644 index 0000000000..835630a69b --- /dev/null +++ b/scalafmt-sysops/native/src/main/scala-2.13/org/scalafmt/CompatCollections.scala @@ -0,0 +1,22 @@ +package org.scalafmt + +import java.util.HashMap + +object CompatCollections { + val JavaConverters = scala.jdk.CollectionConverters + + // Scala Native does not include ParallelConverters + object CompatParConverters { + implicit class XIterable[T](val col: Iterable[T]) extends AnyVal { + def compatPar = col + } + } + + class ConcurrentMap[K, V] extends HashMap[K, V] { + def contains(key: K): Boolean = { + super.containsKey(key) + } + } + def concurrentMap[K, V] = new ConcurrentMap[K, V] + +} diff --git a/scalafmt-sysops/native/src/main/scala/org/scalafmt/PlatformConfig.scala b/scalafmt-sysops/native/src/main/scala/org/scalafmt/PlatformConfig.scala new file mode 100644 index 0000000000..9ac63bcc32 --- /dev/null +++ b/scalafmt-sysops/native/src/main/scala/org/scalafmt/PlatformConfig.scala @@ -0,0 +1,5 @@ +package org.scalafmt + +object PlatformConfig { + def isNative = true +} diff --git a/scalafmt-sysops/shared/src/main/scala-2.13/org/scalafmt/CompatCollections.scala b/scalafmt-sysops/shared/src/main/scala-2.13/org/scalafmt/CompatCollections.scala deleted file mode 100644 index 392588673e..0000000000 --- a/scalafmt-sysops/shared/src/main/scala-2.13/org/scalafmt/CompatCollections.scala +++ /dev/null @@ -1,6 +0,0 @@ -package org.scalafmt - -private[scalafmt] object CompatCollections { - val JavaConverters = scala.jdk.CollectionConverters - val ParConverters = scala.collection.parallel.CollectionConverters -} diff --git a/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/FileOps.scala b/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/FileOps.scala index c08cf05ad7..3d727fafdd 100644 --- a/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/FileOps.scala +++ b/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/FileOps.scala @@ -17,6 +17,7 @@ import scala.util.Failure import scala.util.Success import scala.util.Try import scala.util.Using +import org.scalafmt.PlatformConfig object FileOps { @@ -76,9 +77,13 @@ object FileOps { /** Reads file from file system or from http url */ def readFile(filename: String)(implicit codec: Codec): String = - Try(new URL(filename)) match { - case Success(url) => readFile(url) - case _ => readFile(getFile(filename)) + if (PlatformConfig.isNative) { + readFile(getFile(filename)) + } else { + Try(new URL(filename)) match { + case Success(url) => readFile(url) + case _ => readFile(getFile(filename)) + } } def readFile(url: URL)(implicit codec: Codec): String = { diff --git a/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/GitOps.scala b/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/GitOps.scala index 7f97bf225d..749cd821e6 100644 --- a/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/GitOps.scala +++ b/scalafmt-sysops/shared/src/main/scala/org/scalafmt/sysops/GitOps.scala @@ -3,11 +3,14 @@ package org.scalafmt.sysops import java.nio.file.InvalidPathException import java.nio.file.Path -import scala.sys.process.ProcessLogger import scala.util.Failure import scala.util.Success import scala.util.Try +import java.io.BufferedReader +import java.io.InputStreamReader +import org.scalafmt.sysops.{AbsoluteFile, FileOps} + object GitOps { trait Factory { @@ -55,13 +58,35 @@ private class GitOpsImpl(val workingDirectory: AbsoluteFile) extends GitOps { .linesIterator.toSeq private def tryExec(cmd: Seq[String]): Try[String] = { - val errors = Seq.newBuilder[String] + val errorsString = new StringBuilder Try { - val swallowStderr = ProcessLogger(_ => (), errors += _) - sys.process.Process(cmd, workingDirectory.jfile).!!(swallowStderr) + val processBuilder = new ProcessBuilder() + processBuilder.directory(workingDirectory.jfile) + val out = new StringBuilder + processBuilder.command(cmd: _*); + val process = processBuilder.start() + + val outputReader = + new BufferedReader(new InputStreamReader(process.getInputStream())) + + val errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())) + + def pipe(src: BufferedReader, dst: StringBuilder): Unit = { + var line = outputReader.readLine() + while (line != null) { + out.append(line + "\n") + line = outputReader.readLine() + } + } + + pipe(outputReader, out) + pipe(errorReader, errorsString) + + out.toString } match { case Failure(e) => - val err = errors.result().mkString("\n> ", "\n> ", "\n") + val err = errorsString.toString.split('\n').mkString("\n> ", "\n> ", "\n") val msg = s"Failed to run command ${cmd.mkString(" ")}. Error:$err" Failure(new IllegalStateException(msg, e)) case Success(x) => Success(x.trim) diff --git a/scalafmt-tests-community/src/test/scala/org/scalafmt/community/TestHelpers.scala b/scalafmt-tests-community/src/test/scala/org/scalafmt/community/TestHelpers.scala index c7baf44c12..19654b3919 100644 --- a/scalafmt-tests-community/src/test/scala/org/scalafmt/community/TestHelpers.scala +++ b/scalafmt-tests-community/src/test/scala/org/scalafmt/community/TestHelpers.scala @@ -1,7 +1,7 @@ package org.scalafmt.community import org.scalafmt.CompatCollections.JavaConverters._ -import org.scalafmt.CompatCollections.ParConverters._ +import org.scalafmt.CompatCollections.CompatParConverters._ import org.scalafmt.Formatted import org.scalafmt.Scalafmt import org.scalafmt.config._ @@ -99,13 +99,13 @@ object TestHelpers { val (dirs, files) = try ds.iterator().asScala.toList.partition(Files.isDirectory(_)) finally ds.close() - val fileStats = files.par.flatMap { x => + val fileStats = files.compatPar.flatMap { x => val fileStr = x.toString if (fileStr.endsWith(".scala") && !excluded(fileStr)) Some(runFile(styleName, x, fileStr)) else None }.reduceLeftOption(TestStats.merge) - val dirStats = dirs.par.flatMap(checkFilesRecursive(styleName, _)) + val dirStats = dirs.compatPar.flatMap(checkFilesRecursive(styleName, _)) .reduceLeftOption(TestStats.merge) fileStats.fold(dirStats)(x => dirStats.map(TestStats.merge(_, x)).orElse(fileStats), diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/ScalafmtProps.scala b/scalafmt-tests/jvm/src/test/scala/org/scalafmt/ScalafmtProps.scala similarity index 97% rename from scalafmt-tests/src/test/scala/org/scalafmt/ScalafmtProps.scala rename to scalafmt-tests/jvm/src/test/scala/org/scalafmt/ScalafmtProps.scala index 74b3e5d427..197c11c6c3 100644 --- a/scalafmt-tests/src/test/scala/org/scalafmt/ScalafmtProps.scala +++ b/scalafmt-tests/jvm/src/test/scala/org/scalafmt/ScalafmtProps.scala @@ -1,6 +1,6 @@ package org.scalafmt -import org.scalafmt.CompatCollections.ParConverters._ +import org.scalafmt.CompatCollections.CompatParConverters._ import org.scalafmt.config.ScalafmtConfig import org.scalafmt.sysops.AbsoluteFile import org.scalafmt.util.FormatAssertions @@ -24,7 +24,7 @@ class ScalafmtProps extends FunSuite with FormatAssertions { // TODO(olafur) remove once testkit 1.7 is out Corpus.fastparse .copy(Corpus.fastparse.url.replace("olafurpg", "scalameta")), - ).take(count).toBuffer.par + ).take(count).toBuffer.compatPar SyntaxAnalysis.run[Observation[Bug]](corpus) { file => val code = file.read try Scalafmt.format(code, config) match { diff --git a/scalafmt-tests/jvm/src/test/scala/org/scalafmt/cli/CliOptionsJVMTest.scala b/scalafmt-tests/jvm/src/test/scala/org/scalafmt/cli/CliOptionsJVMTest.scala new file mode 100644 index 0000000000..e9d72c4c91 --- /dev/null +++ b/scalafmt-tests/jvm/src/test/scala/org/scalafmt/cli/CliOptionsJVMTest.scala @@ -0,0 +1,25 @@ +package org.scalafmt.cli + +import munit.FunSuite +import FileTestOps._ + +class CliOptionsJVMTest extends FunSuite { + + private val baseCliOptionsWithOut = baseCliOptions + .copy(common = baseCliOptions.common.copy(out = System.out)) + + Seq("--stdin", "--stdout").foreach { arg => + test(s"don't write info when using $arg") { + val options = Cli.getConfig(Array(arg), baseCliOptionsWithOut).get + val cons = System.console() + if (cons ne null) options.common.info match { + case x: Output.FromWriter if x.obj eq cons.writer() => + case x => fail(s"info should be writing to console: $x") + } + else options.common.info match { + case x: Output.FromStream if x.obj eq Output.NoopStream.printStream => + case x => fail(s"info should be writing to NoopStream: $x") + } + } + } +} \ No newline at end of file diff --git a/scalafmt-tests/jvm/src/test/scala/org/scalafmt/sysops/FileOpsJVMTest.scala b/scalafmt-tests/jvm/src/test/scala/org/scalafmt/sysops/FileOpsJVMTest.scala new file mode 100644 index 0000000000..4152c93824 --- /dev/null +++ b/scalafmt-tests/jvm/src/test/scala/org/scalafmt/sysops/FileOpsJVMTest.scala @@ -0,0 +1,14 @@ +package org.scalafmt.sysops + +class FileOpsJVMTest extends munit.FunSuite { + test("readFile with URL") { + val url = getClass.getResource("/readme.md") + val contents = FileOps.readFile(url.toString) + val expectedFirstLine = "# scalafmt tests\n" + val firstLine = contents.substring(0, expectedFirstLine.length) + assertEquals(firstLine, expectedFirstLine) + + assertEquals(FileOps.readFile(url), contents) + assertEquals(FileOps.readAsURL(url), contents) + } +} \ No newline at end of file diff --git a/scalafmt-tests/src/test/resources/Test.manual b/scalafmt-tests/shared/src/test/resources/Test.manual similarity index 100% rename from scalafmt-tests/src/test/resources/Test.manual rename to scalafmt-tests/shared/src/test/resources/Test.manual diff --git a/scalafmt-tests/src/test/resources/align/AlignByRightName.stat b/scalafmt-tests/shared/src/test/resources/align/AlignByRightName.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/AlignByRightName.stat rename to scalafmt-tests/shared/src/test/resources/align/AlignByRightName.stat diff --git a/scalafmt-tests/src/test/resources/align/ArrowEnumeratorGenerator.stat b/scalafmt-tests/shared/src/test/resources/align/ArrowEnumeratorGenerator.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/ArrowEnumeratorGenerator.stat rename to scalafmt-tests/shared/src/test/resources/align/ArrowEnumeratorGenerator.stat diff --git a/scalafmt-tests/src/test/resources/align/BeforeCommentWithinMethodChain.stat b/scalafmt-tests/shared/src/test/resources/align/BeforeCommentWithinMethodChain.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/BeforeCommentWithinMethodChain.stat rename to scalafmt-tests/shared/src/test/resources/align/BeforeCommentWithinMethodChain.stat diff --git a/scalafmt-tests/src/test/resources/align/DefaultWithAlign.stat b/scalafmt-tests/shared/src/test/resources/align/DefaultWithAlign.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/DefaultWithAlign.stat rename to scalafmt-tests/shared/src/test/resources/align/DefaultWithAlign.stat diff --git a/scalafmt-tests/src/test/resources/align/MixedTokens.stat b/scalafmt-tests/shared/src/test/resources/align/MixedTokens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/MixedTokens.stat rename to scalafmt-tests/shared/src/test/resources/align/MixedTokens.stat diff --git a/scalafmt-tests/src/test/resources/align/NoSpace.stat b/scalafmt-tests/shared/src/test/resources/align/NoSpace.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/NoSpace.stat rename to scalafmt-tests/shared/src/test/resources/align/NoSpace.stat diff --git a/scalafmt-tests/src/test/resources/align/TrollAlignment.stat b/scalafmt-tests/shared/src/test/resources/align/TrollAlignment.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/TrollAlignment.stat rename to scalafmt-tests/shared/src/test/resources/align/TrollAlignment.stat diff --git a/scalafmt-tests/src/test/resources/align/addSbtPlugin.source b/scalafmt-tests/shared/src/test/resources/align/addSbtPlugin.source similarity index 100% rename from scalafmt-tests/src/test/resources/align/addSbtPlugin.source rename to scalafmt-tests/shared/src/test/resources/align/addSbtPlugin.source diff --git a/scalafmt-tests/src/test/resources/align/comment-wrapping.source b/scalafmt-tests/shared/src/test/resources/align/comment-wrapping.source similarity index 100% rename from scalafmt-tests/src/test/resources/align/comment-wrapping.source rename to scalafmt-tests/shared/src/test/resources/align/comment-wrapping.source diff --git a/scalafmt-tests/src/test/resources/align/defaultTokenOwners.stat b/scalafmt-tests/shared/src/test/resources/align/defaultTokenOwners.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/defaultTokenOwners.stat rename to scalafmt-tests/shared/src/test/resources/align/defaultTokenOwners.stat diff --git a/scalafmt-tests/src/test/resources/align/duplicateAlign.stat b/scalafmt-tests/shared/src/test/resources/align/duplicateAlign.stat similarity index 100% rename from scalafmt-tests/src/test/resources/align/duplicateAlign.stat rename to scalafmt-tests/shared/src/test/resources/align/duplicateAlign.stat diff --git a/scalafmt-tests/src/test/resources/binPack/LambdaParameterFalse.stat b/scalafmt-tests/shared/src/test/resources/binPack/LambdaParameterFalse.stat similarity index 100% rename from scalafmt-tests/src/test/resources/binPack/LambdaParameterFalse.stat rename to scalafmt-tests/shared/src/test/resources/binPack/LambdaParameterFalse.stat diff --git a/scalafmt-tests/src/test/resources/binPack/LiteralList.stat b/scalafmt-tests/shared/src/test/resources/binPack/LiteralList.stat similarity index 100% rename from scalafmt-tests/src/test/resources/binPack/LiteralList.stat rename to scalafmt-tests/shared/src/test/resources/binPack/LiteralList.stat diff --git a/scalafmt-tests/src/test/resources/binPack/LiteralListNoByte.stat b/scalafmt-tests/shared/src/test/resources/binPack/LiteralListNoByte.stat similarity index 100% rename from scalafmt-tests/src/test/resources/binPack/LiteralListNoByte.stat rename to scalafmt-tests/shared/src/test/resources/binPack/LiteralListNoByte.stat diff --git a/scalafmt-tests/src/test/resources/binPack/ParentConstructors.stat b/scalafmt-tests/shared/src/test/resources/binPack/ParentConstructors.stat similarity index 100% rename from scalafmt-tests/src/test/resources/binPack/ParentConstructors.stat rename to scalafmt-tests/shared/src/test/resources/binPack/ParentConstructors.stat diff --git a/scalafmt-tests/shared/src/test/resources/binPack/TermNameList b/scalafmt-tests/shared/src/test/resources/binPack/TermNameList new file mode 100644 index 0000000000..4f9a81bb75 --- /dev/null +++ b/scalafmt-tests/shared/src/test/resources/binPack/TermNameList @@ -0,0 +1,8 @@ +binPack.literalArgumentLists = true +binPack.literalsExclude = ["String"] +<<< ONLY basic +val secret: List[Bit] = List(aaaaa, aaaaa, bbbbbbb, bbbbbbb, bbbbbbb, aaaaa, bbbbbbb, aaaaa, bbbbbbb, bbbbbbb, bbbbbbb, aaaaa, aaaaa, bbbbbbb, bbbbbbb, aaaaa, bbbbbbb, + aaaaa, aaaaa, bbbbbbb, bbbbbbb, aaaaa, bbbbbbb, aaaaa, bbbbbbb, bbbbbbb, aaaaa, aaaaa, bbbbbbb, bbbbbbb, bbbbbbb, bbbbbbb, bbbbbbb, aaaaa, bbbbbbb, aaaaa, bbbbbbb, bbbbbbb, aaaaa, aaaaa, aaaaa, aaaaa, bbbbbbb, + aaaaa, bbbbbbb, bbbbbbb, bbbbbbb, aaaaa, aaaaa, bbbbbbb, aaaaa, aaaaa, bbbbbbb, aaaaa, aaaaa, aaaaa, bbbbbbb, aaaaa, aaaaa, aaaaa, bbbbbbb, aaaaa, bbbbbbb) +>>> +x diff --git a/scalafmt-tests/src/test/resources/binPack/TermNameList.stat b/scalafmt-tests/shared/src/test/resources/binPack/TermNameList.stat similarity index 100% rename from scalafmt-tests/src/test/resources/binPack/TermNameList.stat rename to scalafmt-tests/shared/src/test/resources/binPack/TermNameList.stat diff --git a/scalafmt-tests/src/test/resources/default/Advanced.stat b/scalafmt-tests/shared/src/test/resources/default/Advanced.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Advanced.stat rename to scalafmt-tests/shared/src/test/resources/default/Advanced.stat diff --git a/scalafmt-tests/src/test/resources/default/Apply.stat b/scalafmt-tests/shared/src/test/resources/default/Apply.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Apply.stat rename to scalafmt-tests/shared/src/test/resources/default/Apply.stat diff --git a/scalafmt-tests/src/test/resources/default/ApplyInfix.stat b/scalafmt-tests/shared/src/test/resources/default/ApplyInfix.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/ApplyInfix.stat rename to scalafmt-tests/shared/src/test/resources/default/ApplyInfix.stat diff --git a/scalafmt-tests/src/test/resources/default/Case.case b/scalafmt-tests/shared/src/test/resources/default/Case.case similarity index 100% rename from scalafmt-tests/src/test/resources/default/Case.case rename to scalafmt-tests/shared/src/test/resources/default/Case.case diff --git a/scalafmt-tests/src/test/resources/default/Case.stat b/scalafmt-tests/shared/src/test/resources/default/Case.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Case.stat rename to scalafmt-tests/shared/src/test/resources/default/Case.stat diff --git a/scalafmt-tests/src/test/resources/default/Class.stat b/scalafmt-tests/shared/src/test/resources/default/Class.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Class.stat rename to scalafmt-tests/shared/src/test/resources/default/Class.stat diff --git a/scalafmt-tests/src/test/resources/default/Comment.stat b/scalafmt-tests/shared/src/test/resources/default/Comment.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Comment.stat rename to scalafmt-tests/shared/src/test/resources/default/Comment.stat diff --git a/scalafmt-tests/src/test/resources/default/DefDef.stat b/scalafmt-tests/shared/src/test/resources/default/DefDef.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/DefDef.stat rename to scalafmt-tests/shared/src/test/resources/default/DefDef.stat diff --git a/scalafmt-tests/src/test/resources/default/Fidelity.source b/scalafmt-tests/shared/src/test/resources/default/Fidelity.source similarity index 100% rename from scalafmt-tests/src/test/resources/default/Fidelity.source rename to scalafmt-tests/shared/src/test/resources/default/Fidelity.source diff --git a/scalafmt-tests/src/test/resources/default/Fidelity.stat b/scalafmt-tests/shared/src/test/resources/default/Fidelity.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Fidelity.stat rename to scalafmt-tests/shared/src/test/resources/default/Fidelity.stat diff --git a/scalafmt-tests/src/test/resources/default/For.stat b/scalafmt-tests/shared/src/test/resources/default/For.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/For.stat rename to scalafmt-tests/shared/src/test/resources/default/For.stat diff --git a/scalafmt-tests/src/test/resources/default/Idempotency.stat b/scalafmt-tests/shared/src/test/resources/default/Idempotency.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Idempotency.stat rename to scalafmt-tests/shared/src/test/resources/default/Idempotency.stat diff --git a/scalafmt-tests/src/test/resources/default/If.stat b/scalafmt-tests/shared/src/test/resources/default/If.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/If.stat rename to scalafmt-tests/shared/src/test/resources/default/If.stat diff --git a/scalafmt-tests/src/test/resources/default/Lambda.stat b/scalafmt-tests/shared/src/test/resources/default/Lambda.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Lambda.stat rename to scalafmt-tests/shared/src/test/resources/default/Lambda.stat diff --git a/scalafmt-tests/src/test/resources/default/SearchState.stat b/scalafmt-tests/shared/src/test/resources/default/SearchState.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/SearchState.stat rename to scalafmt-tests/shared/src/test/resources/default/SearchState.stat diff --git a/scalafmt-tests/src/test/resources/default/Select.stat b/scalafmt-tests/shared/src/test/resources/default/Select.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Select.stat rename to scalafmt-tests/shared/src/test/resources/default/Select.stat diff --git a/scalafmt-tests/src/test/resources/default/Semicolon.stat b/scalafmt-tests/shared/src/test/resources/default/Semicolon.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Semicolon.stat rename to scalafmt-tests/shared/src/test/resources/default/Semicolon.stat diff --git a/scalafmt-tests/src/test/resources/default/String.stat b/scalafmt-tests/shared/src/test/resources/default/String.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/String.stat rename to scalafmt-tests/shared/src/test/resources/default/String.stat diff --git a/scalafmt-tests/src/test/resources/default/Super.stat b/scalafmt-tests/shared/src/test/resources/default/Super.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Super.stat rename to scalafmt-tests/shared/src/test/resources/default/Super.stat diff --git a/scalafmt-tests/src/test/resources/default/TermParam.stat b/scalafmt-tests/shared/src/test/resources/default/TermParam.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/TermParam.stat rename to scalafmt-tests/shared/src/test/resources/default/TermParam.stat diff --git a/scalafmt-tests/src/test/resources/default/TestingClassNameDoNotEdit.scalafmt b/scalafmt-tests/shared/src/test/resources/default/TestingClassNameDoNotEdit.scalafmt similarity index 100% rename from scalafmt-tests/src/test/resources/default/TestingClassNameDoNotEdit.scalafmt rename to scalafmt-tests/shared/src/test/resources/default/TestingClassNameDoNotEdit.scalafmt diff --git a/scalafmt-tests/src/test/resources/default/Trait.stat b/scalafmt-tests/shared/src/test/resources/default/Trait.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Trait.stat rename to scalafmt-tests/shared/src/test/resources/default/Trait.stat diff --git a/scalafmt-tests/src/test/resources/default/Try.stat b/scalafmt-tests/shared/src/test/resources/default/Try.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Try.stat rename to scalafmt-tests/shared/src/test/resources/default/Try.stat diff --git a/scalafmt-tests/src/test/resources/default/TypeArguments.stat b/scalafmt-tests/shared/src/test/resources/default/TypeArguments.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/TypeArguments.stat rename to scalafmt-tests/shared/src/test/resources/default/TypeArguments.stat diff --git a/scalafmt-tests/src/test/resources/default/TypeWith.stat b/scalafmt-tests/shared/src/test/resources/default/TypeWith.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/TypeWith.stat rename to scalafmt-tests/shared/src/test/resources/default/TypeWith.stat diff --git a/scalafmt-tests/src/test/resources/default/Unicode.stat b/scalafmt-tests/shared/src/test/resources/default/Unicode.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Unicode.stat rename to scalafmt-tests/shared/src/test/resources/default/Unicode.stat diff --git a/scalafmt-tests/src/test/resources/default/Unindent.stat b/scalafmt-tests/shared/src/test/resources/default/Unindent.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Unindent.stat rename to scalafmt-tests/shared/src/test/resources/default/Unindent.stat diff --git a/scalafmt-tests/src/test/resources/default/Val.stat b/scalafmt-tests/shared/src/test/resources/default/Val.stat similarity index 100% rename from scalafmt-tests/src/test/resources/default/Val.stat rename to scalafmt-tests/shared/src/test/resources/default/Val.stat diff --git a/scalafmt-tests/src/test/resources/literals/Double.stat b/scalafmt-tests/shared/src/test/resources/literals/Double.stat similarity index 100% rename from scalafmt-tests/src/test/resources/literals/Double.stat rename to scalafmt-tests/shared/src/test/resources/literals/Double.stat diff --git a/scalafmt-tests/src/test/resources/literals/Float.stat b/scalafmt-tests/shared/src/test/resources/literals/Float.stat similarity index 100% rename from scalafmt-tests/src/test/resources/literals/Float.stat rename to scalafmt-tests/shared/src/test/resources/literals/Float.stat diff --git a/scalafmt-tests/src/test/resources/literals/Long.stat b/scalafmt-tests/shared/src/test/resources/literals/Long.stat similarity index 100% rename from scalafmt-tests/src/test/resources/literals/Long.stat rename to scalafmt-tests/shared/src/test/resources/literals/Long.stat diff --git a/scalafmt-tests/src/test/resources/literals/Unchanged.stat b/scalafmt-tests/shared/src/test/resources/literals/Unchanged.stat similarity index 100% rename from scalafmt-tests/src/test/resources/literals/Unchanged.stat rename to scalafmt-tests/shared/src/test/resources/literals/Unchanged.stat diff --git a/scalafmt-tests/src/test/resources/literals/binary.stat b/scalafmt-tests/shared/src/test/resources/literals/binary.stat similarity index 100% rename from scalafmt-tests/src/test/resources/literals/binary.stat rename to scalafmt-tests/shared/src/test/resources/literals/binary.stat diff --git a/scalafmt-tests/src/test/resources/literals/hex.stat b/scalafmt-tests/shared/src/test/resources/literals/hex.stat similarity index 100% rename from scalafmt-tests/src/test/resources/literals/hex.stat rename to scalafmt-tests/shared/src/test/resources/literals/hex.stat diff --git a/scalafmt-tests/src/test/resources/literals/scientific.stat b/scalafmt-tests/shared/src/test/resources/literals/scientific.stat similarity index 100% rename from scalafmt-tests/src/test/resources/literals/scientific.stat rename to scalafmt-tests/shared/src/test/resources/literals/scientific.stat diff --git a/scalafmt-tests/src/test/resources/newdefault/CaseNoAlign.stat b/scalafmt-tests/shared/src/test/resources/newdefault/CaseNoAlign.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newdefault/CaseNoAlign.stat rename to scalafmt-tests/shared/src/test/resources/newdefault/CaseNoAlign.stat diff --git a/scalafmt-tests/src/test/resources/newdefault/ColumnWidth.stat b/scalafmt-tests/shared/src/test/resources/newdefault/ColumnWidth.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newdefault/ColumnWidth.stat rename to scalafmt-tests/shared/src/test/resources/newdefault/ColumnWidth.stat diff --git a/scalafmt-tests/src/test/resources/newdefault/SearchState.stat b/scalafmt-tests/shared/src/test/resources/newdefault/SearchState.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newdefault/SearchState.stat rename to scalafmt-tests/shared/src/test/resources/newdefault/SearchState.stat diff --git a/scalafmt-tests/src/test/resources/newlines/AlwaysBeforeCurlyBraceLambdaParams.stat b/scalafmt-tests/shared/src/test/resources/newlines/AlwaysBeforeCurlyBraceLambdaParams.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/AlwaysBeforeCurlyBraceLambdaParams.stat rename to scalafmt-tests/shared/src/test/resources/newlines/AlwaysBeforeCurlyBraceLambdaParams.stat diff --git a/scalafmt-tests/src/test/resources/newlines/OffByOneParameterlessMethod.stat b/scalafmt-tests/shared/src/test/resources/newlines/OffByOneParameterlessMethod.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/OffByOneParameterlessMethod.stat rename to scalafmt-tests/shared/src/test/resources/newlines/OffByOneParameterlessMethod.stat diff --git a/scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaAlways.stat b/scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaAlways.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaAlways.stat rename to scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaAlways.stat diff --git a/scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaNever.stat b/scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaNever.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaNever.stat rename to scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaNever.stat diff --git a/scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaPreserve.stat b/scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaPreserve.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaPreserve.stat rename to scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaPreserve.stat diff --git a/scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaSquash.stat b/scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaSquash.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/afterCurlyLambdaSquash.stat rename to scalafmt-tests/shared/src/test/resources/newlines/afterCurlyLambdaSquash.stat diff --git a/scalafmt-tests/src/test/resources/newlines/alwaysBeforeElseAfterCurlyIf.stat b/scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeElseAfterCurlyIf.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/alwaysBeforeElseAfterCurlyIf.stat rename to scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeElseAfterCurlyIf.stat diff --git a/scalafmt-tests/src/test/resources/newlines/alwaysBeforeMultilineDef.stat b/scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeMultilineDef.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/alwaysBeforeMultilineDef.stat rename to scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeMultilineDef.stat diff --git a/scalafmt-tests/src/test/resources/newlines/alwaysBeforeTopLevelStatements.source b/scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeTopLevelStatements.source similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/alwaysBeforeTopLevelStatements.source rename to scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeTopLevelStatements.source diff --git a/scalafmt-tests/src/test/resources/newlines/alwaysBeforeTopLevelStatements.stat b/scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeTopLevelStatements.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/alwaysBeforeTopLevelStatements.stat rename to scalafmt-tests/shared/src/test/resources/newlines/alwaysBeforeTopLevelStatements.stat diff --git a/scalafmt-tests/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingF.stat b/scalafmt-tests/shared/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingF.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingF.stat rename to scalafmt-tests/shared/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingF.stat diff --git a/scalafmt-tests/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingT.stat b/scalafmt-tests/shared/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingT.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingT.stat rename to scalafmt-tests/shared/src/test/resources/newlines/beforeConfigSingleArgParenLambdaParamsF_danglingT.stat diff --git a/scalafmt-tests/src/test/resources/newlines/newlineBetweenCurlyAndCatchFinally.stat b/scalafmt-tests/shared/src/test/resources/newlines/newlineBetweenCurlyAndCatchFinally.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/newlineBetweenCurlyAndCatchFinally.stat rename to scalafmt-tests/shared/src/test/resources/newlines/newlineBetweenCurlyAndCatchFinally.stat diff --git a/scalafmt-tests/src/test/resources/newlines/source.source b/scalafmt-tests/shared/src/test/resources/newlines/source.source similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/source.source rename to scalafmt-tests/shared/src/test/resources/newlines/source.source diff --git a/scalafmt-tests/src/test/resources/newlines/source_classic.stat b/scalafmt-tests/shared/src/test/resources/newlines/source_classic.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/source_classic.stat rename to scalafmt-tests/shared/src/test/resources/newlines/source_classic.stat diff --git a/scalafmt-tests/src/test/resources/newlines/source_fold.stat b/scalafmt-tests/shared/src/test/resources/newlines/source_fold.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/source_fold.stat rename to scalafmt-tests/shared/src/test/resources/newlines/source_fold.stat diff --git a/scalafmt-tests/src/test/resources/newlines/source_keep.stat b/scalafmt-tests/shared/src/test/resources/newlines/source_keep.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/source_keep.stat rename to scalafmt-tests/shared/src/test/resources/newlines/source_keep.stat diff --git a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat b/scalafmt-tests/shared/src/test/resources/newlines/source_unfold.stat similarity index 100% rename from scalafmt-tests/src/test/resources/newlines/source_unfold.stat rename to scalafmt-tests/shared/src/test/resources/newlines/source_unfold.stat diff --git a/scalafmt-tests/src/test/resources/optIn/Annotation.stat b/scalafmt-tests/shared/src/test/resources/optIn/Annotation.stat similarity index 100% rename from scalafmt-tests/src/test/resources/optIn/Annotation.stat rename to scalafmt-tests/shared/src/test/resources/optIn/Annotation.stat diff --git a/scalafmt-tests/src/test/resources/optIn/AnnotationParam.stat b/scalafmt-tests/shared/src/test/resources/optIn/AnnotationParam.stat similarity index 100% rename from scalafmt-tests/src/test/resources/optIn/AnnotationParam.stat rename to scalafmt-tests/shared/src/test/resources/optIn/AnnotationParam.stat diff --git a/scalafmt-tests/src/test/resources/optIn/BreakChainOnFirstMethodDot.stat b/scalafmt-tests/shared/src/test/resources/optIn/BreakChainOnFirstMethodDot.stat similarity index 100% rename from scalafmt-tests/src/test/resources/optIn/BreakChainOnFirstMethodDot.stat rename to scalafmt-tests/shared/src/test/resources/optIn/BreakChainOnFirstMethodDot.stat diff --git a/scalafmt-tests/src/test/resources/optIn/SelectChain.stat b/scalafmt-tests/shared/src/test/resources/optIn/SelectChain.stat similarity index 100% rename from scalafmt-tests/src/test/resources/optIn/SelectChain.stat rename to scalafmt-tests/shared/src/test/resources/optIn/SelectChain.stat diff --git a/scalafmt-tests/src/test/resources/optIn/SelectChains.stat b/scalafmt-tests/shared/src/test/resources/optIn/SelectChains.stat similarity index 100% rename from scalafmt-tests/src/test/resources/optIn/SelectChains.stat rename to scalafmt-tests/shared/src/test/resources/optIn/SelectChains.stat diff --git a/scalafmt-tests/src/test/resources/optIn/SelfAnnotation.stat b/scalafmt-tests/shared/src/test/resources/optIn/SelfAnnotation.stat similarity index 100% rename from scalafmt-tests/src/test/resources/optIn/SelfAnnotation.stat rename to scalafmt-tests/shared/src/test/resources/optIn/SelfAnnotation.stat diff --git a/scalafmt-tests/src/test/resources/optIn/forceBlankLineBeforeDocstring.stat b/scalafmt-tests/shared/src/test/resources/optIn/forceBlankLineBeforeDocstring.stat similarity index 100% rename from scalafmt-tests/src/test/resources/optIn/forceBlankLineBeforeDocstring.stat rename to scalafmt-tests/shared/src/test/resources/optIn/forceBlankLineBeforeDocstring.stat diff --git a/scalafmt-tests/src/test/resources/readme.md b/scalafmt-tests/shared/src/test/resources/readme.md similarity index 100% rename from scalafmt-tests/src/test/resources/readme.md rename to scalafmt-tests/shared/src/test/resources/readme.md diff --git a/scalafmt-tests/src/test/resources/rewrite/AsciiSortImports.stat b/scalafmt-tests/shared/src/test/resources/rewrite/AsciiSortImports.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/AsciiSortImports.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/AsciiSortImports.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/AvoidInfix.stat b/scalafmt-tests/shared/src/test/resources/rewrite/AvoidInfix.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/AvoidInfix.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/AvoidInfix.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/AvoidInfix2.stat b/scalafmt-tests/shared/src/test/resources/rewrite/AvoidInfix2.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/AvoidInfix2.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/AvoidInfix2.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/AvoidInfix3.stat b/scalafmt-tests/shared/src/test/resources/rewrite/AvoidInfix3.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/AvoidInfix3.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/AvoidInfix3.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/ExpandImportSelectors.stat b/scalafmt-tests/shared/src/test/resources/rewrite/ExpandImportSelectors.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/ExpandImportSelectors.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/ExpandImportSelectors.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/Imports.source b/scalafmt-tests/shared/src/test/resources/rewrite/Imports.source similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/Imports.source rename to scalafmt-tests/shared/src/test/resources/rewrite/Imports.source diff --git a/scalafmt-tests/src/test/resources/rewrite/PreferCurlyForYields.stat b/scalafmt-tests/shared/src/test/resources/rewrite/PreferCurlyForYields.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/PreferCurlyForYields.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/PreferCurlyForYields.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/PreferCurlyFors.stat b/scalafmt-tests/shared/src/test/resources/rewrite/PreferCurlyFors.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/PreferCurlyFors.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/PreferCurlyFors.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBraces-ParenLambdas.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-ParenLambdas.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBraces-ParenLambdas.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-ParenLambdas.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBraces-case.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-case.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBraces-case.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-case.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBraces-if.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-if.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBraces-if.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-if.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBraces-precedence.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-precedence.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBraces-precedence.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces-precedence.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBraces.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBraces.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBraces2.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces2.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBraces2.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces2.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBraces748.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces748.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBraces748.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBraces748.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantBracesStrInterpolation.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantBracesStrInterpolation.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantBracesStrInterpolation.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantBracesStrInterpolation.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/RedundantParens.stat b/scalafmt-tests/shared/src/test/resources/rewrite/RedundantParens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/RedundantParens.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/RedundantParens.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/SortImports.stat b/scalafmt-tests/shared/src/test/resources/rewrite/SortImports.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortImports.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/SortImports.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/SortModifiers.stat b/scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortModifiers.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/SortModifiers1.source b/scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers1.source similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortModifiers1.source rename to scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers1.source diff --git a/scalafmt-tests/src/test/resources/rewrite/SortModifiersScala3.stat b/scalafmt-tests/shared/src/test/resources/rewrite/SortModifiersScala3.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortModifiersScala3.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/SortModifiersScala3.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/SortModifiers_Default.source b/scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_Default.source similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortModifiers_Default.source rename to scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_Default.source diff --git a/scalafmt-tests/src/test/resources/rewrite/SortModifiers_Mod_With_No_Token.source b/scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_Mod_With_No_Token.source similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortModifiers_Mod_With_No_Token.source rename to scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_Mod_With_No_Token.source diff --git a/scalafmt-tests/src/test/resources/rewrite/SortModifiers_bug_1148.stat b/scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_bug_1148.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortModifiers_bug_1148.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_bug_1148.stat diff --git a/scalafmt-tests/src/test/resources/rewrite/SortModifiers_bug_1148_implicit_first_in_order.stat b/scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_bug_1148_implicit_first_in_order.stat similarity index 100% rename from scalafmt-tests/src/test/resources/rewrite/SortModifiers_bug_1148_implicit_first_in_order.stat rename to scalafmt-tests/shared/src/test/resources/rewrite/SortModifiers_bug_1148_implicit_first_in_order.stat diff --git a/scalafmt-tests/src/test/resources/scala3/ContextFunction.stat b/scalafmt-tests/shared/src/test/resources/scala3/ContextFunction.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/ContextFunction.stat rename to scalafmt-tests/shared/src/test/resources/scala3/ContextFunction.stat diff --git a/scalafmt-tests/src/test/resources/scala3/DependentFunction.stat b/scalafmt-tests/shared/src/test/resources/scala3/DependentFunction.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/DependentFunction.stat rename to scalafmt-tests/shared/src/test/resources/scala3/DependentFunction.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Derives.stat b/scalafmt-tests/shared/src/test/resources/scala3/Derives.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Derives.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Derives.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Dialect.stat b/scalafmt-tests/shared/src/test/resources/scala3/Dialect.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Dialect.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Dialect.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Enum.stat b/scalafmt-tests/shared/src/test/resources/scala3/Enum.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Enum.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Enum.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Export.stat b/scalafmt-tests/shared/src/test/resources/scala3/Export.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Export.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Export.stat diff --git a/scalafmt-tests/src/test/resources/scala3/ExportGivens.stat b/scalafmt-tests/shared/src/test/resources/scala3/ExportGivens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/ExportGivens.stat rename to scalafmt-tests/shared/src/test/resources/scala3/ExportGivens.stat diff --git a/scalafmt-tests/src/test/resources/scala3/ExtendsComma.stat b/scalafmt-tests/shared/src/test/resources/scala3/ExtendsComma.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/ExtendsComma.stat rename to scalafmt-tests/shared/src/test/resources/scala3/ExtendsComma.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Extension.stat b/scalafmt-tests/shared/src/test/resources/scala3/Extension.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Extension.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Extension.stat diff --git a/scalafmt-tests/src/test/resources/scala3/FewerBraces.stat b/scalafmt-tests/shared/src/test/resources/scala3/FewerBraces.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/FewerBraces.stat rename to scalafmt-tests/shared/src/test/resources/scala3/FewerBraces.stat diff --git a/scalafmt-tests/src/test/resources/scala3/FewerBraces_fold.stat b/scalafmt-tests/shared/src/test/resources/scala3/FewerBraces_fold.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/FewerBraces_fold.stat rename to scalafmt-tests/shared/src/test/resources/scala3/FewerBraces_fold.stat diff --git a/scalafmt-tests/src/test/resources/scala3/FewerBraces_keep.stat b/scalafmt-tests/shared/src/test/resources/scala3/FewerBraces_keep.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/FewerBraces_keep.stat rename to scalafmt-tests/shared/src/test/resources/scala3/FewerBraces_keep.stat diff --git a/scalafmt-tests/src/test/resources/scala3/FewerBraces_unfold.stat b/scalafmt-tests/shared/src/test/resources/scala3/FewerBraces_unfold.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/FewerBraces_unfold.stat rename to scalafmt-tests/shared/src/test/resources/scala3/FewerBraces_unfold.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Given.stat b/scalafmt-tests/shared/src/test/resources/scala3/Given.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Given.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Given.stat diff --git a/scalafmt-tests/src/test/resources/scala3/GivenPatterns.stat b/scalafmt-tests/shared/src/test/resources/scala3/GivenPatterns.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/GivenPatterns.stat rename to scalafmt-tests/shared/src/test/resources/scala3/GivenPatterns.stat diff --git a/scalafmt-tests/src/test/resources/scala3/ImportingGivens.stat b/scalafmt-tests/shared/src/test/resources/scala3/ImportingGivens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/ImportingGivens.stat rename to scalafmt-tests/shared/src/test/resources/scala3/ImportingGivens.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Infix.stat b/scalafmt-tests/shared/src/test/resources/scala3/Infix.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Infix.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Infix.stat diff --git a/scalafmt-tests/src/test/resources/scala3/InlineTransparent.stat b/scalafmt-tests/shared/src/test/resources/scala3/InlineTransparent.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/InlineTransparent.stat rename to scalafmt-tests/shared/src/test/resources/scala3/InlineTransparent.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Issues.stat b/scalafmt-tests/shared/src/test/resources/scala3/Issues.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Issues.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Issues.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Macro.stat b/scalafmt-tests/shared/src/test/resources/scala3/Macro.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Macro.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Macro.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Match.stat b/scalafmt-tests/shared/src/test/resources/scala3/Match.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Match.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Match.stat diff --git a/scalafmt-tests/src/test/resources/scala3/MatchType.stat b/scalafmt-tests/shared/src/test/resources/scala3/MatchType.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/MatchType.stat rename to scalafmt-tests/shared/src/test/resources/scala3/MatchType.stat diff --git a/scalafmt-tests/src/test/resources/scala3/OpaqueType.stat b/scalafmt-tests/shared/src/test/resources/scala3/OpaqueType.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/OpaqueType.stat rename to scalafmt-tests/shared/src/test/resources/scala3/OpaqueType.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Open.stat b/scalafmt-tests/shared/src/test/resources/scala3/Open.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Open.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Open.stat diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat b/scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat rename to scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces.stat diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat b/scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces_fold.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat rename to scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces_fold.stat diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat b/scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces_keep.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat rename to scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces_keep.stat diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat b/scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces_unfold.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat rename to scalafmt-tests/shared/src/test/resources/scala3/OptionalBraces_unfold.stat diff --git a/scalafmt-tests/src/test/resources/scala3/PolyFunction.stat b/scalafmt-tests/shared/src/test/resources/scala3/PolyFunction.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/PolyFunction.stat rename to scalafmt-tests/shared/src/test/resources/scala3/PolyFunction.stat diff --git a/scalafmt-tests/src/test/resources/scala3/RenameImportExport.stat b/scalafmt-tests/shared/src/test/resources/scala3/RenameImportExport.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/RenameImportExport.stat rename to scalafmt-tests/shared/src/test/resources/scala3/RenameImportExport.stat diff --git a/scalafmt-tests/src/test/resources/scala3/StarImport.stat b/scalafmt-tests/shared/src/test/resources/scala3/StarImport.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/StarImport.stat rename to scalafmt-tests/shared/src/test/resources/scala3/StarImport.stat diff --git a/scalafmt-tests/src/test/resources/scala3/TraitParams.stat b/scalafmt-tests/shared/src/test/resources/scala3/TraitParams.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/TraitParams.stat rename to scalafmt-tests/shared/src/test/resources/scala3/TraitParams.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Type.stat b/scalafmt-tests/shared/src/test/resources/scala3/Type.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Type.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Type.stat diff --git a/scalafmt-tests/src/test/resources/scala3/TypeLambda.stat b/scalafmt-tests/shared/src/test/resources/scala3/TypeLambda.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/TypeLambda.stat rename to scalafmt-tests/shared/src/test/resources/scala3/TypeLambda.stat diff --git a/scalafmt-tests/src/test/resources/scala3/UnionIntersectionType.stat b/scalafmt-tests/shared/src/test/resources/scala3/UnionIntersectionType.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/UnionIntersectionType.stat rename to scalafmt-tests/shared/src/test/resources/scala3/UnionIntersectionType.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Using.stat b/scalafmt-tests/shared/src/test/resources/scala3/Using.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Using.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Using.stat diff --git a/scalafmt-tests/src/test/resources/scala3/Vararg.stat b/scalafmt-tests/shared/src/test/resources/scala3/Vararg.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scala3/Vararg.stat rename to scalafmt-tests/shared/src/test/resources/scala3/Vararg.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/Advanced.stat b/scalafmt-tests/shared/src/test/resources/scalajs/Advanced.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/Advanced.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/Advanced.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/Apply.stat b/scalafmt-tests/shared/src/test/resources/scalajs/Apply.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/Apply.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/Apply.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/Class.stat b/scalafmt-tests/shared/src/test/resources/scalajs/Class.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/Class.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/Class.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/DefDef.stat b/scalafmt-tests/shared/src/test/resources/scalajs/DefDef.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/DefDef.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/DefDef.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/For.stat b/scalafmt-tests/shared/src/test/resources/scalajs/For.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/For.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/For.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/If.stat b/scalafmt-tests/shared/src/test/resources/scalajs/If.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/If.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/If.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/Import.source b/scalafmt-tests/shared/src/test/resources/scalajs/Import.source similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/Import.source rename to scalafmt-tests/shared/src/test/resources/scalajs/Import.source diff --git a/scalafmt-tests/src/test/resources/scalajs/TermApply.stat b/scalafmt-tests/shared/src/test/resources/scalajs/TermApply.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/TermApply.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/TermApply.stat diff --git a/scalafmt-tests/src/test/resources/scalajs/Type.stat b/scalafmt-tests/shared/src/test/resources/scalajs/Type.stat similarity index 100% rename from scalafmt-tests/src/test/resources/scalajs/Type.stat rename to scalafmt-tests/shared/src/test/resources/scalajs/Type.stat diff --git a/scalafmt-tests/src/test/resources/spaces/AfterKeywordBeforeParen.stat b/scalafmt-tests/shared/src/test/resources/spaces/AfterKeywordBeforeParen.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/AfterKeywordBeforeParen.stat rename to scalafmt-tests/shared/src/test/resources/spaces/AfterKeywordBeforeParen.stat diff --git a/scalafmt-tests/src/test/resources/spaces/AfterSymbolicDefs.stat b/scalafmt-tests/shared/src/test/resources/spaces/AfterSymbolicDefs.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/AfterSymbolicDefs.stat rename to scalafmt-tests/shared/src/test/resources/spaces/AfterSymbolicDefs.stat diff --git a/scalafmt-tests/src/test/resources/spaces/BeforeContextBoundColonIfMultipleBounds.stat b/scalafmt-tests/shared/src/test/resources/spaces/BeforeContextBoundColonIfMultipleBounds.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/BeforeContextBoundColonIfMultipleBounds.stat rename to scalafmt-tests/shared/src/test/resources/spaces/BeforeContextBoundColonIfMultipleBounds.stat diff --git a/scalafmt-tests/src/test/resources/spaces/BeforeContextBoundColonTrue.stat b/scalafmt-tests/shared/src/test/resources/spaces/BeforeContextBoundColonTrue.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/BeforeContextBoundColonTrue.stat rename to scalafmt-tests/shared/src/test/resources/spaces/BeforeContextBoundColonTrue.stat diff --git a/scalafmt-tests/src/test/resources/spaces/Constructor.stat b/scalafmt-tests/shared/src/test/resources/spaces/Constructor.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/Constructor.stat rename to scalafmt-tests/shared/src/test/resources/spaces/Constructor.stat diff --git a/scalafmt-tests/src/test/resources/spaces/Hacking.stat b/scalafmt-tests/shared/src/test/resources/spaces/Hacking.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/Hacking.stat rename to scalafmt-tests/shared/src/test/resources/spaces/Hacking.stat diff --git a/scalafmt-tests/src/test/resources/spaces/ImportCurlyBraces.source b/scalafmt-tests/shared/src/test/resources/spaces/ImportCurlyBraces.source similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/ImportCurlyBraces.source rename to scalafmt-tests/shared/src/test/resources/spaces/ImportCurlyBraces.source diff --git a/scalafmt-tests/src/test/resources/spaces/InByNameTypes.stat b/scalafmt-tests/shared/src/test/resources/spaces/InByNameTypes.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/InByNameTypes.stat rename to scalafmt-tests/shared/src/test/resources/spaces/InByNameTypes.stat diff --git a/scalafmt-tests/src/test/resources/spaces/InParentheses.stat b/scalafmt-tests/shared/src/test/resources/spaces/InParentheses.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/InParentheses.stat rename to scalafmt-tests/shared/src/test/resources/spaces/InParentheses.stat diff --git a/scalafmt-tests/src/test/resources/spaces/InterpolatedStringCurlyBraces.stat b/scalafmt-tests/shared/src/test/resources/spaces/InterpolatedStringCurlyBraces.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/InterpolatedStringCurlyBraces.stat rename to scalafmt-tests/shared/src/test/resources/spaces/InterpolatedStringCurlyBraces.stat diff --git a/scalafmt-tests/src/test/resources/spaces/NeverAroundInfixTypes.stat b/scalafmt-tests/shared/src/test/resources/spaces/NeverAroundInfixTypes.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/NeverAroundInfixTypes.stat rename to scalafmt-tests/shared/src/test/resources/spaces/NeverAroundInfixTypes.stat diff --git a/scalafmt-tests/src/test/resources/spaces/Scalatest.stat b/scalafmt-tests/shared/src/test/resources/spaces/Scalatest.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/Scalatest.stat rename to scalafmt-tests/shared/src/test/resources/spaces/Scalatest.stat diff --git a/scalafmt-tests/src/test/resources/spaces/TrailingWhiteSpace.stat b/scalafmt-tests/shared/src/test/resources/spaces/TrailingWhiteSpace.stat similarity index 100% rename from scalafmt-tests/src/test/resources/spaces/TrailingWhiteSpace.stat rename to scalafmt-tests/shared/src/test/resources/spaces/TrailingWhiteSpace.stat diff --git a/scalafmt-tests/src/test/resources/test/BlocksInSingleArg.stat b/scalafmt-tests/shared/src/test/resources/test/BlocksInSingleArg.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/BlocksInSingleArg.stat rename to scalafmt-tests/shared/src/test/resources/test/BlocksInSingleArg.stat diff --git a/scalafmt-tests/src/test/resources/test/Class.stat b/scalafmt-tests/shared/src/test/resources/test/Class.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/Class.stat rename to scalafmt-tests/shared/src/test/resources/test/Class.stat diff --git a/scalafmt-tests/src/test/resources/test/ContinuationIndent.stat b/scalafmt-tests/shared/src/test/resources/test/ContinuationIndent.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/ContinuationIndent.stat rename to scalafmt-tests/shared/src/test/resources/test/ContinuationIndent.stat diff --git a/scalafmt-tests/src/test/resources/test/ContinuationIndentCaseSite0.stat b/scalafmt-tests/shared/src/test/resources/test/ContinuationIndentCaseSite0.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/ContinuationIndentCaseSite0.stat rename to scalafmt-tests/shared/src/test/resources/test/ContinuationIndentCaseSite0.stat diff --git a/scalafmt-tests/src/test/resources/test/ContinuationIndentCaseSite1.stat b/scalafmt-tests/shared/src/test/resources/test/ContinuationIndentCaseSite1.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/ContinuationIndentCaseSite1.stat rename to scalafmt-tests/shared/src/test/resources/test/ContinuationIndentCaseSite1.stat diff --git a/scalafmt-tests/src/test/resources/test/ContinuationIndentCaseSite5.stat b/scalafmt-tests/shared/src/test/resources/test/ContinuationIndentCaseSite5.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/ContinuationIndentCaseSite5.stat rename to scalafmt-tests/shared/src/test/resources/test/ContinuationIndentCaseSite5.stat diff --git a/scalafmt-tests/src/test/resources/test/ContinuationIndentHalfDanglingParens.stat b/scalafmt-tests/shared/src/test/resources/test/ContinuationIndentHalfDanglingParens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/ContinuationIndentHalfDanglingParens.stat rename to scalafmt-tests/shared/src/test/resources/test/ContinuationIndentHalfDanglingParens.stat diff --git a/scalafmt-tests/src/test/resources/test/ContinuationIndentNoDanglingParens.stat b/scalafmt-tests/shared/src/test/resources/test/ContinuationIndentNoDanglingParens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/ContinuationIndentNoDanglingParens.stat rename to scalafmt-tests/shared/src/test/resources/test/ContinuationIndentNoDanglingParens.stat diff --git a/scalafmt-tests/src/test/resources/test/Dangling.stat b/scalafmt-tests/shared/src/test/resources/test/Dangling.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/Dangling.stat rename to scalafmt-tests/shared/src/test/resources/test/Dangling.stat diff --git a/scalafmt-tests/src/test/resources/test/Dialect.source b/scalafmt-tests/shared/src/test/resources/test/Dialect.source similarity index 100% rename from scalafmt-tests/src/test/resources/test/Dialect.source rename to scalafmt-tests/shared/src/test/resources/test/Dialect.source diff --git a/scalafmt-tests/src/test/resources/test/DynamicStyle.stat b/scalafmt-tests/shared/src/test/resources/test/DynamicStyle.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/DynamicStyle.stat rename to scalafmt-tests/shared/src/test/resources/test/DynamicStyle.stat diff --git a/scalafmt-tests/src/test/resources/test/ImportSingleLine.source b/scalafmt-tests/shared/src/test/resources/test/ImportSingleLine.source similarity index 100% rename from scalafmt-tests/src/test/resources/test/ImportSingleLine.source rename to scalafmt-tests/shared/src/test/resources/test/ImportSingleLine.source diff --git a/scalafmt-tests/src/test/resources/test/IndentOperator.stat b/scalafmt-tests/shared/src/test/resources/test/IndentOperator.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/IndentOperator.stat rename to scalafmt-tests/shared/src/test/resources/test/IndentOperator.stat diff --git a/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat b/scalafmt-tests/shared/src/test/resources/test/IndentOperatorFormatInfix.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat rename to scalafmt-tests/shared/src/test/resources/test/IndentOperatorFormatInfix.stat diff --git a/scalafmt-tests/src/test/resources/test/IndentYieldKeyword.stat b/scalafmt-tests/shared/src/test/resources/test/IndentYieldKeyword.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/IndentYieldKeyword.stat rename to scalafmt-tests/shared/src/test/resources/test/IndentYieldKeyword.stat diff --git a/scalafmt-tests/src/test/resources/test/Issue1509.stat b/scalafmt-tests/shared/src/test/resources/test/Issue1509.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/Issue1509.stat rename to scalafmt-tests/shared/src/test/resources/test/Issue1509.stat diff --git a/scalafmt-tests/src/test/resources/test/JavaDoc.stat b/scalafmt-tests/shared/src/test/resources/test/JavaDoc.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/JavaDoc.stat rename to scalafmt-tests/shared/src/test/resources/test/JavaDoc.stat diff --git a/scalafmt-tests/src/test/resources/test/NoAlign.stat b/scalafmt-tests/shared/src/test/resources/test/NoAlign.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/NoAlign.stat rename to scalafmt-tests/shared/src/test/resources/test/NoAlign.stat diff --git a/scalafmt-tests/src/test/resources/test/OperatorSpray.stat b/scalafmt-tests/shared/src/test/resources/test/OperatorSpray.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/OperatorSpray.stat rename to scalafmt-tests/shared/src/test/resources/test/OperatorSpray.stat diff --git a/scalafmt-tests/src/test/resources/test/StripMargin.stat b/scalafmt-tests/shared/src/test/resources/test/StripMargin.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/StripMargin.stat rename to scalafmt-tests/shared/src/test/resources/test/StripMargin.stat diff --git a/scalafmt-tests/src/test/resources/test/Type747.stat b/scalafmt-tests/shared/src/test/resources/test/Type747.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/Type747.stat rename to scalafmt-tests/shared/src/test/resources/test/Type747.stat diff --git a/scalafmt-tests/src/test/resources/test/Unicode.stat b/scalafmt-tests/shared/src/test/resources/test/Unicode.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/Unicode.stat rename to scalafmt-tests/shared/src/test/resources/test/Unicode.stat diff --git a/scalafmt-tests/src/test/resources/test/UnindentTopLevelOperatorsOperatorSpray.stat b/scalafmt-tests/shared/src/test/resources/test/UnindentTopLevelOperatorsOperatorSpray.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/UnindentTopLevelOperatorsOperatorSpray.stat rename to scalafmt-tests/shared/src/test/resources/test/UnindentTopLevelOperatorsOperatorSpray.stat diff --git a/scalafmt-tests/src/test/resources/test/arityThreshold.source b/scalafmt-tests/shared/src/test/resources/test/arityThreshold.source similarity index 100% rename from scalafmt-tests/src/test/resources/test/arityThreshold.source rename to scalafmt-tests/shared/src/test/resources/test/arityThreshold.source diff --git a/scalafmt-tests/src/test/resources/test/i1116.stat b/scalafmt-tests/shared/src/test/resources/test/i1116.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/i1116.stat rename to scalafmt-tests/shared/src/test/resources/test/i1116.stat diff --git a/scalafmt-tests/src/test/resources/test/i1245.stat b/scalafmt-tests/shared/src/test/resources/test/i1245.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/i1245.stat rename to scalafmt-tests/shared/src/test/resources/test/i1245.stat diff --git a/scalafmt-tests/src/test/resources/test/i1300.stat b/scalafmt-tests/shared/src/test/resources/test/i1300.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/i1300.stat rename to scalafmt-tests/shared/src/test/resources/test/i1300.stat diff --git a/scalafmt-tests/src/test/resources/test/i1439.stat b/scalafmt-tests/shared/src/test/resources/test/i1439.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/i1439.stat rename to scalafmt-tests/shared/src/test/resources/test/i1439.stat diff --git a/scalafmt-tests/src/test/resources/test/i1527.stat b/scalafmt-tests/shared/src/test/resources/test/i1527.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/i1527.stat rename to scalafmt-tests/shared/src/test/resources/test/i1527.stat diff --git a/scalafmt-tests/src/test/resources/test/includeNoParensInSelectChains.stat b/scalafmt-tests/shared/src/test/resources/test/includeNoParensInSelectChains.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/includeNoParensInSelectChains.stat rename to scalafmt-tests/shared/src/test/resources/test/includeNoParensInSelectChains.stat diff --git a/scalafmt-tests/src/test/resources/test/poorMansTrailingCommasInConfigStyle.stat b/scalafmt-tests/shared/src/test/resources/test/poorMansTrailingCommasInConfigStyle.stat similarity index 100% rename from scalafmt-tests/src/test/resources/test/poorMansTrailingCommasInConfigStyle.stat rename to scalafmt-tests/shared/src/test/resources/test/poorMansTrailingCommasInConfigStyle.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlways.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlways.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlways.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlways.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysAlignMore.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysAlignMore.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysAlignMore.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysAlignMore.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysComments.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysComments.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysComments.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysComments.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysDanglingParens.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysDanglingParens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysDanglingParens.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysDanglingParens.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysOwners.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysOwners.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysOwners.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysOwners.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysSingleLine.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysSingleLine.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysSingleLine.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysSingleLine.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysVerticalMultilineAtDefnSite.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysVerticalMultilineAtDefnSite.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasAlwaysVerticalMultilineAtDefnSite.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasAlwaysVerticalMultilineAtDefnSite.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultiple.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultiple.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultiple.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultiple.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultipleAlignMore.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultipleAlignMore.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultipleAlignMore.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultipleAlignMore.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultipleComments.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultipleComments.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultipleComments.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultipleComments.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultipleDanglingParens.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultipleDanglingParens.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasMultipleDanglingParens.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasMultipleDanglingParens.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNever.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNever.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNever.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNever.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNeverComments.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNeverComments.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNeverComments.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNeverComments.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNeverCommentsAlignMore.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNeverCommentsAlignMore.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNeverCommentsAlignMore.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNeverCommentsAlignMore.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNeverSingleLine.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNeverSingleLine.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasNeverSingleLine.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasNeverSingleLine.stat diff --git a/scalafmt-tests/src/test/resources/trailing-commas/trailingCommasPreserve.stat b/scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasPreserve.stat similarity index 100% rename from scalafmt-tests/src/test/resources/trailing-commas/trailingCommasPreserve.stat rename to scalafmt-tests/shared/src/test/resources/trailing-commas/trailingCommasPreserve.stat diff --git a/scalafmt-tests/src/test/resources/unit/Advanced.source b/scalafmt-tests/shared/src/test/resources/unit/Advanced.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Advanced.source rename to scalafmt-tests/shared/src/test/resources/unit/Advanced.source diff --git a/scalafmt-tests/src/test/resources/unit/Annotations.stat b/scalafmt-tests/shared/src/test/resources/unit/Annotations.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Annotations.stat rename to scalafmt-tests/shared/src/test/resources/unit/Annotations.stat diff --git a/scalafmt-tests/src/test/resources/unit/Apply.stat b/scalafmt-tests/shared/src/test/resources/unit/Apply.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Apply.stat rename to scalafmt-tests/shared/src/test/resources/unit/Apply.stat diff --git a/scalafmt-tests/src/test/resources/unit/ApplyInfix.stat b/scalafmt-tests/shared/src/test/resources/unit/ApplyInfix.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/ApplyInfix.stat rename to scalafmt-tests/shared/src/test/resources/unit/ApplyInfix.stat diff --git a/scalafmt-tests/src/test/resources/unit/Argument.source b/scalafmt-tests/shared/src/test/resources/unit/Argument.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Argument.source rename to scalafmt-tests/shared/src/test/resources/unit/Argument.source diff --git a/scalafmt-tests/src/test/resources/unit/Basic.source b/scalafmt-tests/shared/src/test/resources/unit/Basic.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Basic.source rename to scalafmt-tests/shared/src/test/resources/unit/Basic.source diff --git a/scalafmt-tests/src/test/resources/unit/Case.case b/scalafmt-tests/shared/src/test/resources/unit/Case.case similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Case.case rename to scalafmt-tests/shared/src/test/resources/unit/Case.case diff --git a/scalafmt-tests/src/test/resources/unit/Case.stat b/scalafmt-tests/shared/src/test/resources/unit/Case.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Case.stat rename to scalafmt-tests/shared/src/test/resources/unit/Case.stat diff --git a/scalafmt-tests/src/test/resources/unit/ColumnWidth.source b/scalafmt-tests/shared/src/test/resources/unit/ColumnWidth.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/ColumnWidth.source rename to scalafmt-tests/shared/src/test/resources/unit/ColumnWidth.source diff --git a/scalafmt-tests/src/test/resources/unit/Comment.stat b/scalafmt-tests/shared/src/test/resources/unit/Comment.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Comment.stat rename to scalafmt-tests/shared/src/test/resources/unit/Comment.stat diff --git a/scalafmt-tests/src/test/resources/unit/Cond.stat b/scalafmt-tests/shared/src/test/resources/unit/Cond.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Cond.stat rename to scalafmt-tests/shared/src/test/resources/unit/Cond.stat diff --git a/scalafmt-tests/src/test/resources/unit/DefDef.stat b/scalafmt-tests/shared/src/test/resources/unit/DefDef.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/DefDef.stat rename to scalafmt-tests/shared/src/test/resources/unit/DefDef.stat diff --git a/scalafmt-tests/src/test/resources/unit/Dialect.stat b/scalafmt-tests/shared/src/test/resources/unit/Dialect.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Dialect.stat rename to scalafmt-tests/shared/src/test/resources/unit/Dialect.stat diff --git a/scalafmt-tests/src/test/resources/unit/For.stat b/scalafmt-tests/shared/src/test/resources/unit/For.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/For.stat rename to scalafmt-tests/shared/src/test/resources/unit/For.stat diff --git a/scalafmt-tests/src/test/resources/unit/FormatOff.stat b/scalafmt-tests/shared/src/test/resources/unit/FormatOff.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/FormatOff.stat rename to scalafmt-tests/shared/src/test/resources/unit/FormatOff.stat diff --git a/scalafmt-tests/src/test/resources/unit/If.stat b/scalafmt-tests/shared/src/test/resources/unit/If.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/If.stat rename to scalafmt-tests/shared/src/test/resources/unit/If.stat diff --git a/scalafmt-tests/src/test/resources/unit/Import.source b/scalafmt-tests/shared/src/test/resources/unit/Import.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Import.source rename to scalafmt-tests/shared/src/test/resources/unit/Import.source diff --git a/scalafmt-tests/src/test/resources/unit/Interpolate.stat b/scalafmt-tests/shared/src/test/resources/unit/Interpolate.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Interpolate.stat rename to scalafmt-tests/shared/src/test/resources/unit/Interpolate.stat diff --git a/scalafmt-tests/src/test/resources/unit/Lambda.stat b/scalafmt-tests/shared/src/test/resources/unit/Lambda.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Lambda.stat rename to scalafmt-tests/shared/src/test/resources/unit/Lambda.stat diff --git a/scalafmt-tests/src/test/resources/unit/Lit.stat b/scalafmt-tests/shared/src/test/resources/unit/Lit.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Lit.stat rename to scalafmt-tests/shared/src/test/resources/unit/Lit.stat diff --git a/scalafmt-tests/src/test/resources/unit/Markdown.source b/scalafmt-tests/shared/src/test/resources/unit/Markdown.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Markdown.source rename to scalafmt-tests/shared/src/test/resources/unit/Markdown.source diff --git a/scalafmt-tests/src/test/resources/unit/Mod.stat b/scalafmt-tests/shared/src/test/resources/unit/Mod.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Mod.stat rename to scalafmt-tests/shared/src/test/resources/unit/Mod.stat diff --git a/scalafmt-tests/src/test/resources/unit/Package.source b/scalafmt-tests/shared/src/test/resources/unit/Package.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Package.source rename to scalafmt-tests/shared/src/test/resources/unit/Package.source diff --git a/scalafmt-tests/src/test/resources/unit/Symbol.stat b/scalafmt-tests/shared/src/test/resources/unit/Symbol.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Symbol.stat rename to scalafmt-tests/shared/src/test/resources/unit/Symbol.stat diff --git a/scalafmt-tests/src/test/resources/unit/Template.source b/scalafmt-tests/shared/src/test/resources/unit/Template.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Template.source rename to scalafmt-tests/shared/src/test/resources/unit/Template.source diff --git a/scalafmt-tests/src/test/resources/unit/TermApply.stat b/scalafmt-tests/shared/src/test/resources/unit/TermApply.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/TermApply.stat rename to scalafmt-tests/shared/src/test/resources/unit/TermApply.stat diff --git a/scalafmt-tests/src/test/resources/unit/TermUpdate.stat b/scalafmt-tests/shared/src/test/resources/unit/TermUpdate.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/TermUpdate.stat rename to scalafmt-tests/shared/src/test/resources/unit/TermUpdate.stat diff --git a/scalafmt-tests/src/test/resources/unit/Trait.source b/scalafmt-tests/shared/src/test/resources/unit/Trait.source similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Trait.source rename to scalafmt-tests/shared/src/test/resources/unit/Trait.source diff --git a/scalafmt-tests/src/test/resources/unit/Type.stat b/scalafmt-tests/shared/src/test/resources/unit/Type.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Type.stat rename to scalafmt-tests/shared/src/test/resources/unit/Type.stat diff --git a/scalafmt-tests/src/test/resources/unit/TypeArgument.stat b/scalafmt-tests/shared/src/test/resources/unit/TypeArgument.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/TypeArgument.stat rename to scalafmt-tests/shared/src/test/resources/unit/TypeArgument.stat diff --git a/scalafmt-tests/src/test/resources/unit/UnaryApply.stat b/scalafmt-tests/shared/src/test/resources/unit/UnaryApply.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/UnaryApply.stat rename to scalafmt-tests/shared/src/test/resources/unit/UnaryApply.stat diff --git a/scalafmt-tests/src/test/resources/unit/Val.stat b/scalafmt-tests/shared/src/test/resources/unit/Val.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Val.stat rename to scalafmt-tests/shared/src/test/resources/unit/Val.stat diff --git a/scalafmt-tests/src/test/resources/unit/Xml.stat b/scalafmt-tests/shared/src/test/resources/unit/Xml.stat similarity index 100% rename from scalafmt-tests/src/test/resources/unit/Xml.stat rename to scalafmt-tests/shared/src/test/resources/unit/Xml.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/VerticalMultilineDefnSite.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/VerticalMultilineDefnSite.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/VerticalMultilineDefnSite.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/VerticalMultilineDefnSite.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/afterImplicitKW.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/afterImplicitKW.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/afterImplicitKW.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/afterImplicitKW.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/beforeImplicitKW.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/beforeImplicitKW.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/beforeImplicitKW.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/beforeImplicitKW.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/excludeDanglingInDef.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/excludeDanglingInDef.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/excludeDanglingInDef.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/excludeDanglingInDef.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/newlineAfterOpenParen.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/newlineAfterOpenParen.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/newlineAfterOpenParen.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/newlineAfterOpenParen.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/verticalAlignMultilineOperators.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalAlignMultilineOperators.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/verticalAlignMultilineOperators.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalAlignMultilineOperators.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/verticalMultiline.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalMultiline.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/verticalMultiline.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalMultiline.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/verticalMultilineDangling.source b/scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalMultilineDangling.source similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/verticalMultilineDangling.source rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalMultilineDangling.source diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/verticalMultilineDefnSiteNoDangling.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalMultilineDefnSiteNoDangling.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/verticalMultilineDefnSiteNoDangling.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/verticalMultilineDefnSiteNoDangling.stat diff --git a/scalafmt-tests/src/test/resources/vertical-multiline/withSpacesInParentheses.stat b/scalafmt-tests/shared/src/test/resources/vertical-multiline/withSpacesInParentheses.stat similarity index 100% rename from scalafmt-tests/src/test/resources/vertical-multiline/withSpacesInParentheses.stat rename to scalafmt-tests/shared/src/test/resources/vertical-multiline/withSpacesInParentheses.stat diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/CommentTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/CommentTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/CommentTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/CommentTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/CustomStructureTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/CustomStructureTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/CustomStructureTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/CustomStructureTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/Debug.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/Debug.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/Debug.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/Debug.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/EmptyFileTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/EmptyFileTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/EmptyFileTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/EmptyFileTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/FidelityTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/FidelityTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/FidelityTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/FidelityTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/FormatTests.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/FormatTests.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/FormatTests.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/FormatTests.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/LineEndingsTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/LineEndingsTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/LineEndingsTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/LineEndingsTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/ManualTests.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/ManualTests.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/ManualTests.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/ManualTests.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/RangeTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/RangeTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/RangeTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/RangeTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/ScalafmtRunnerTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/ScalafmtRunnerTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/ScalafmtRunnerTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/ScalafmtRunnerTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/ScalafmtTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/ScalafmtTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/ScalafmtTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/ScalafmtTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/UnitTests.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/UnitTests.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/UnitTests.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/UnitTests.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliOptionsTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/CliOptionsTest.scala similarity index 85% rename from scalafmt-tests/src/test/scala/org/scalafmt/cli/CliOptionsTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/CliOptionsTest.scala index a1f0423671..2a9653c4e8 100644 --- a/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliOptionsTest.scala +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/CliOptionsTest.scala @@ -11,6 +11,7 @@ import java.nio.file.Paths import FileTestOps._ import metaconfig.Configured import munit.FunSuite +import java.io.FileNotFoundException class CliOptionsTest extends FunSuite { @@ -96,7 +97,13 @@ class CliOptionsTest extends FunSuite { val opt = baseCliOptions.copy(config = Some(configPath)) assert(opt.scalafmtConfig.isInstanceOf[Configured.NotOk]) val confError = opt.scalafmtConfig.asInstanceOf[Configured.NotOk].error - assert(confError.cause.exists(_.isInstanceOf[NoSuchFileException])) + // native - FileNotFoundException, JVM - NoSuchFileException + assert( + confError.cause.exists(err => + err.isInstanceOf[NoSuchFileException] || err + .isInstanceOf[FileNotFoundException] + ) + ) } test(".scalafmtConfig returns Configured.NotOk for invalid configuration") { @@ -111,19 +118,4 @@ class CliOptionsTest extends FunSuite { assertEquals(options.common.info.printStream, System.out) } - Seq("--stdin", "--stdout").foreach { arg => - test(s"don't write info when using $arg") { - val options = Cli.getConfig(Array(arg), baseCliOptionsWithOut).get - val cons = System.console() - if (cons ne null) options.common.info match { - case x: Output.FromWriter if x.obj eq cons.writer() => - case x => fail(s"info should be writing to console: $x") - } - else options.common.info match { - case x: Output.FromStream if x.obj eq Output.NoopStream.printStream => - case x => fail(s"info should be writing to NoopStream: $x") - } - } - } - } diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/CliTest.scala similarity index 97% rename from scalafmt-tests/src/test/scala/org/scalafmt/cli/CliTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/CliTest.scala index 7a773da67d..885a0d3dab 100644 --- a/scalafmt-tests/src/test/scala/org/scalafmt/cli/CliTest.scala +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/CliTest.scala @@ -5,6 +5,7 @@ import org.scalafmt.Versions.{stable => stableVersion} import org.scalafmt.cli.FileTestOps._ import org.scalafmt.config.ProjectFiles import org.scalafmt.config.ScalafmtConfig +import org.scalafmt.config.PlatformConfig import org.scalafmt.sysops.AbsoluteFile import org.scalafmt.sysops.FileOps import org.scalafmt.sysops.OsSpecific._ @@ -104,7 +105,13 @@ trait CliTestBehavior { val isCore = version == stableVersion val label = if (isCore) "core" else "dynamic" val dialectError = if (isCore) " [dialect default]" else "" + def assumeNotDynamicOnNative(): Unit = + assume( + isCore || !PlatformConfig.isNative, + "Dynamic module is incompatible with Scala Native" + ) test(s"scalafmt tmpFile tmpFile2: $label") { + assumeNotDynamicOnNative() val originalTmpFile = Files.createTempFile("prefix", ".scala") val originalTmpFile2 = Files.createTempFile("prefix2", ".scala") val scalafmtConfig = Files.createTempFile("scalafmtConfig", ".scala") @@ -130,6 +137,7 @@ trait CliTestBehavior { } test(s"scalafmt --stdout tmpFile prints to stdout: $label") { + assumeNotDynamicOnNative() val originalTmpFile = Files.createTempFile("prefix", ".scala") Files.write(originalTmpFile, unformatted.getBytes) val args = Array( @@ -149,6 +157,7 @@ trait CliTestBehavior { } test(s"scalafmt --stdin --assume-filename: $label") { + assumeNotDynamicOnNative() val scalafmtConfig = Files.createTempFile(".scalafmt", ".conf") val config = s"""| |version="$version" @@ -176,6 +185,7 @@ trait CliTestBehavior { } test(s"scalafmt --test tmpFile is left unformatted: $label") { + assumeNotDynamicOnNative() val tmpFile = Files.createTempFile("prefix", ".scala") Files.write(tmpFile, unformatted.getBytes) val args = Array( @@ -189,6 +199,7 @@ trait CliTestBehavior { assertNoDiff(str, unformatted) } test(s"scalafmt --test fails with non zero exit code $label") { + assumeNotDynamicOnNative() val tmpFile = Files.createTempFile("prefix", ".scala") Files.write(tmpFile, unformatted.getBytes) val args = Array( @@ -201,6 +212,7 @@ trait CliTestBehavior { } test(s"scalafmt foo.randomsuffix is formatted: $label") { + assumeNotDynamicOnNative() val tmpFile = Files.createTempFile("prefix", "randomsuffix") Files.write(tmpFile, unformatted.getBytes) val args = Array( @@ -215,6 +227,7 @@ trait CliTestBehavior { } test(s"handles .scala, .sbt, and .sc files: $label") { + assumeNotDynamicOnNative() val input = string2dir( s"""|/foobar.scala |object A { } @@ -243,6 +256,7 @@ trait CliTestBehavior { } test(s"excludefilters are respected: $label") { + assumeNotDynamicOnNative() val input = string2dir( s"""|/foo.sbt |lazy val x = project @@ -289,6 +303,7 @@ trait CliTestBehavior { } test(s"scalafmt doesnotexist.scala throws error: $label") { + assumeNotDynamicOnNative() def check(filename: String): Unit = { val args = Array( s"$filename.scala".asFilename, @@ -304,6 +319,7 @@ trait CliTestBehavior { } test(s"scalafmt (no matching files) throws error: $label") { + assumeNotDynamicOnNative() val scalafmtConfig: Path = Files.createTempFile(".scalafmt", ".conf") val config: String = s"""| |version="$version" @@ -314,6 +330,7 @@ trait CliTestBehavior { } test(s"scalafmt (no matching files) is okay with --mode diff and --stdin: $label") { + assumeNotDynamicOnNative() runArgs(Array( "--mode", "diff", @@ -329,6 +346,7 @@ trait CliTestBehavior { } test(s"scalafmt (no arg) read config from git repo: $label") { + assumeNotDynamicOnNative() val input = string2dir( s"""|/foo.scala |object FormatMe { @@ -362,6 +380,7 @@ trait CliTestBehavior { } test(s"scalafmt (no arg, no config): $label") { + assumeNotDynamicOnNative() noArgTest( string2dir( """|/foo.scala @@ -381,6 +400,7 @@ trait CliTestBehavior { } test(s"config is read even from nested dir: $label") { + assumeNotDynamicOnNative() val original = "object a { val x = 1 }" val expected = """|object a { | val x = @@ -406,6 +426,7 @@ trait CliTestBehavior { } test(s"if project.includeFilters isn't modified (and files aren't passed manually), it should ONLY accept scala and sbt files: $label") { + assumeNotDynamicOnNative() val root = string2dir( s"""| |/scalafmt.conf @@ -435,6 +456,7 @@ trait CliTestBehavior { } test(s"includeFilters are ignored for full paths but NOT test for passed directories: $label") { + assumeNotDynamicOnNative() val root = string2dir( s"""| |/inner1/file1.scala @@ -463,6 +485,7 @@ trait CliTestBehavior { } test(s"includeFilters are respected for full paths but NOT test for passed directories: $label") { + assumeNotDynamicOnNative() val root = string2dir( s"""| |/inner1/file1.scala @@ -493,6 +516,7 @@ trait CliTestBehavior { } test(s"--config accepts absolute paths: $label") { + assumeNotDynamicOnNative() val root = string2dir( s"""|/scalafmt.conf |version = "$version" @@ -511,6 +535,7 @@ trait CliTestBehavior { // These are tests for deprecated flags test(s"scalafmt -i -f file1,file2,file3 should still work: $label") { + assumeNotDynamicOnNative() val file1 = Files.createTempFile("prefix", ".scala") val file2 = Files.createTempFile("prefix2", ".scala") val file3 = Files.createTempFile("prefix3", ".scala") @@ -535,6 +560,7 @@ trait CliTestBehavior { } test(s"parse error is formatted nicely: $label") { + assumeNotDynamicOnNative() val input = """|/foo.scala |object A { foo( } |""".stripMargin @@ -555,6 +581,7 @@ trait CliTestBehavior { } test(s"command line argument error: $label") { + assumeNotDynamicOnNative() val exit = Console.withErr(Output.NoopStream.printStream) { Cli.mainWithOptions( Array("--foobar"), @@ -565,6 +592,7 @@ trait CliTestBehavior { } test(s"--test failure prints out unified diff: $label") { + assumeNotDynamicOnNative() val fooFile = "foo.scala" val input = s"""|/.scalafmt.conf |onTestFailure = "To fix this ..." @@ -594,6 +622,7 @@ trait CliTestBehavior { } test(s"--test succeeds even with parse error: $label") { + assumeNotDynamicOnNative() val input = """|/foo.scala |object A { |""".stripMargin @@ -611,6 +640,7 @@ trait CliTestBehavior { } test(s"--test fails with parse error if fatalWarnings=true: $label") { + assumeNotDynamicOnNative() val input = s"""|/.scalafmt.conf |runner.fatalWarnings = true |version = "$version" @@ -632,6 +662,7 @@ trait CliTestBehavior { } test(s"exception is thrown on invalid .scalafmt.conf: $label") { + assumeNotDynamicOnNative() val input = s"""/.scalafmt.conf |version="$version" |blah = intellij @@ -653,6 +684,7 @@ trait CliTestBehavior { } test(s"eof: $label") { + assumeNotDynamicOnNative() val in = Files.createTempFile("scalafmt", "Foo.scala") Files.write(in, "object A".getBytes(StandardCharsets.UTF_8)) val args = Array("--config-str", s"""{version="$version"}""", in.toString) @@ -663,6 +695,7 @@ trait CliTestBehavior { } test(s"--config-str should be used if it is specified: $label") { + assumeNotDynamicOnNative() val expected = "This message should be shown" val unexpected = "This message should not be shown" val input = s"""|/.scalafmt.conf @@ -687,6 +720,7 @@ trait CliTestBehavior { } test(s"--list enable scalafmt to output a list of unformatted files with ExitCode.TestError: $label") { + assumeNotDynamicOnNative() val input = s"""|/.scalafmt.conf |version = "$version" | diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/cli/FakeGitOps.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/FakeGitOps.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/cli/FakeGitOps.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/FakeGitOps.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/cli/FileTestOps.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/FileTestOps.scala similarity index 94% rename from scalafmt-tests/src/test/scala/org/scalafmt/cli/FileTestOps.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/FileTestOps.scala index b7279bd4cb..a680a0d3fe 100644 --- a/scalafmt-tests/src/test/scala/org/scalafmt/cli/FileTestOps.scala +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/cli/FileTestOps.scala @@ -3,6 +3,7 @@ package org.scalafmt.cli import org.scalafmt.config.ScalafmtConfig import org.scalafmt.sysops.AbsoluteFile import org.scalafmt.sysops.FileOps +import org.scalafmt.internal.RegexCompat import java.io.File import java.io.PrintStream @@ -15,7 +16,7 @@ object FileTestOps { */ def string2dir(layout: String): AbsoluteFile = { val root = AbsoluteFile(Files.createTempDirectory("root")) - layout.split("(?=\n/)").foreach { row => + RegexCompat.splitByBeforeTextMatching(layout, "\n/").foreach { row => val path :: contents :: Nil = row.stripPrefix("\n").split("\n", 2).toList val file = root / path.stripPrefix("/") file.parent.mkdirs() diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/config/AvoidInfixSettingsTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/config/AvoidInfixSettingsTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/config/AvoidInfixSettingsTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/config/AvoidInfixSettingsTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/config/ScalafmtConfigTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/config/ScalafmtConfigTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/config/ScalafmtConfigTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/config/ScalafmtConfigTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/config/StandardProjectLayoutTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/config/StandardProjectLayoutTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/config/StandardProjectLayoutTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/config/StandardProjectLayoutTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/stats/GitInfo.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/GitInfo.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/stats/GitInfo.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/GitInfo.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/stats/JavaInfo.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/JavaInfo.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/stats/JavaInfo.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/JavaInfo.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/stats/MachineStats.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/MachineStats.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/stats/MachineStats.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/MachineStats.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/stats/OsInfo.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/OsInfo.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/stats/OsInfo.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/OsInfo.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/stats/RuntimeInfo.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/RuntimeInfo.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/stats/RuntimeInfo.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/RuntimeInfo.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/stats/TestStats.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/TestStats.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/stats/TestStats.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/stats/TestStats.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/sysops/FileOpsTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/sysops/FileOpsTest.scala similarity index 78% rename from scalafmt-tests/src/test/scala/org/scalafmt/sysops/FileOpsTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/sysops/FileOpsTest.scala index 7b1bb7ef7f..08108c0a9d 100644 --- a/scalafmt-tests/src/test/scala/org/scalafmt/sysops/FileOpsTest.scala +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/sysops/FileOpsTest.scala @@ -45,17 +45,6 @@ class FileOpsTest extends munit.FunSuite { assertEquals(FileOps.listFiles(subsubfile), Seq(subsubfile)) } - test("readFile with URL") { - val url = getClass.getResource("/readme.md") - val contents = FileOps.readFile(url.toString) - val expectedFirstLine = "# scalafmt tests\n" - val firstLine = contents.substring(0, expectedFirstLine.length) - assertEquals(firstLine, expectedFirstLine) - - assertEquals(FileOps.readFile(url), contents) - assertEquals(FileOps.readAsURL(url), contents) - } - } object FileOpsTest { diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/sysops/GitOpsTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/sysops/GitOpsTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/sysops/GitOpsTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/sysops/GitOpsTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/CanRunTests.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/CanRunTests.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/CanRunTests.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/CanRunTests.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/DeleteTree.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/DeleteTree.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/DeleteTree.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/DeleteTree.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/DiffTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/DiffTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/DiffTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/DiffTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/ErrorTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/ErrorTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/ErrorTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/ErrorTest.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/FormatAssertions.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/FormatAssertions.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/FormatAssertions.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/FormatAssertions.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/FormatException.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/FormatException.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/FormatException.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/FormatException.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/FormatOutput.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/FormatOutput.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/FormatOutput.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/FormatOutput.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/HasTests.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/HasTests.scala similarity index 96% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/HasTests.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/HasTests.scala index 2ce23a591f..384e816fee 100644 --- a/scalafmt-tests/src/test/scala/org/scalafmt/util/HasTests.scala +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/HasTests.scala @@ -68,11 +68,12 @@ trait HasTests extends FormatAssertions { def extension(filename: String): String = filename.replaceAll(".*\\.", "") def parseDiffTests(filename: String): Seq[DiffTest] = { + val absFilename = Paths.get(filename).normalize().toString() val content = FileOps.readFile(filename) val sep = if (content.contains(System.lineSeparator)) System.lineSeparator else "\n" - val spec = BuildInfo.resourceDirectory.toPath - .relativize(Paths.get(filename)).getName(0).toString + val spec = BuildInfo.resourceDirectory.toPath.normalize() + .relativize(Paths.get(absFilename)).getName(0).toString val split = content.split(s"(?:^|$sep)<<< ") if (split.length <= 1) return Seq.empty // RETURNING!!! @@ -84,7 +85,7 @@ trait HasTests extends FormatAssertions { def loadStyle(cfg: String, base: ScalafmtConfig, ln: Int): ScalafmtConfig = ScalafmtConfig.fromHoconString(cfg, base).getOrRecover { c => throw new IllegalArgumentException( - s"""|Failed to parse line=$ln filename $filename: + s"""|Failed to parse line=$ln filename $absFilename: |$cfg |$c""".stripMargin, ) diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/Report.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/Report.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/Report.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/Report.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/Result.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/Result.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/Result.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/Result.scala diff --git a/scalafmt-tests/src/test/scala/org/scalafmt/util/StyleMapTest.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/StyleMapTest.scala similarity index 100% rename from scalafmt-tests/src/test/scala/org/scalafmt/util/StyleMapTest.scala rename to scalafmt-tests/shared/src/test/scala/org/scalafmt/util/StyleMapTest.scala diff --git a/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/Tabulator.scala b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/Tabulator.scala new file mode 100644 index 0000000000..b417927cc6 --- /dev/null +++ b/scalafmt-tests/shared/src/test/scala/org/scalafmt/util/Tabulator.scala @@ -0,0 +1,39 @@ +package org.scalafmt.util + +/** Shamelessly copied from: http://stackoverflow.com/a/7542476 + */ +object Tabulator { + + def csv(table: Seq[Seq[Any]]) = table.map(_.mkString(",")).mkString("\n") + + def format(table: Seq[Seq[Any]]) = + table match { + case Seq() => "" + case _ => + val sizes = + for (row <- table) + yield (for (cell <- row) + yield + if (cell == null) 0 + else cell.toString.length) + val colSizes = for (col <- sizes.transpose) yield col.max + val rows = for (row <- table) yield formatRow(row, colSizes) + formatRows(rowSeparator(colSizes), rows) + } + + def formatRows(rowSeparator: String, rows: Seq[String]): String = + (rowSeparator :: rows.head :: rowSeparator :: rows.tail.toList ::: rowSeparator :: List( + )).mkString("\n") + + def formatRow(row: Seq[Any], colSizes: Seq[Int]) = { + val cells = + (for ((item, size) <- row.zip(colSizes)) + yield + if (size == 0) "" + else ("%" + size + "s").format(item)) + cells.mkString("|", "|", "|") + } + + def rowSeparator(colSizes: Seq[Int]) = + colSizes.map(size => "-" * size).mkString("+", "+", "+") +}