From 9d87e6b3d411c38300d1151354aa2308b6e2befa Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 19 Apr 2017 19:56:35 -0400 Subject: [PATCH] Add Scalafmt --- .scalafmt.conf | 18 ++++++++ build.sbt | 5 +-- project/AutomateScalafmtPlugin.scala | 67 ++++++++++++++++++++++++++++ project/Formatting.scala | 40 ----------------- project/plugins.sbt | 2 +- 5 files changed, 88 insertions(+), 44 deletions(-) create mode 100644 .scalafmt.conf create mode 100644 project/AutomateScalafmtPlugin.scala delete mode 100644 project/Formatting.scala diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 000000000..4c32a4aed --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,18 @@ +maxColumn = 100 +project.git = true +project.excludeFilters = [ /sbt-test/, /input_sources/, /contraband-scala/, /Keys.scala ] + +# http://docs.scala-lang.org/style/scaladoc.html recommends the JavaDoc style. +# scala/scala is written that way too https://github.com/scala/scala/blob/v2.12.2/src/library/scala/Predef.scala +docstrings = JavaDoc + +# This also seems more idiomatic to include whitespace in import x.{ yyy } +spaces.inImportCurlyBraces = true + +# This works around sequence wildcard (`_*`) turning into `_ *` +spaces.beforeSeqWildcard = true + +# Vertical alignment only => for pattern matching +align.tokens.add = [ + { code = "=>", owner = "Case" } +] diff --git a/build.sbt b/build.sbt index 79bd12670..9e29538bf 100644 --- a/build.sbt +++ b/build.sbt @@ -58,7 +58,7 @@ def minimalSettings: Seq[Setting[_]] = publishPomSettings ++ Release.javaVersionCheckSettings def baseSettings: Seq[Setting[_]] = - minimalSettings ++ Seq(projectComponent) ++ baseScalacOptions ++ Licensed.settings ++ Formatting.settings + minimalSettings ++ Seq(projectComponent) ++ baseScalacOptions ++ Licensed.settings def testedBaseSettings: Seq[Setting[_]] = baseSettings ++ testDependencies @@ -221,7 +221,6 @@ lazy val mainSettingsProj = (project in file("main-settings")). // The main integration project for sbt. It brings all of the projects together, configures them, and provides for overriding conventions. lazy val mainProj = (project in file("main")). dependsOn(actionsProj, mainSettingsProj, runProj, commandProj). - disablePlugins(SbtScalariform). settings( testedBaseSettings, name := "Main", @@ -277,7 +276,7 @@ def projectsWithMyProvided = allProjects.map(p => p.copy(configurations = (p.con lazy val nonRoots = projectsWithMyProvided.map(p => LocalProject(p.id)) def rootSettings = fullDocSettings ++ - Util.publishPomSettings ++ otherRootSettings ++ Formatting.sbtFilesSettings ++ + Util.publishPomSettings ++ otherRootSettings ++ Transform.conscriptSettings(bundledLauncherProj) def otherRootSettings = Seq( scripted := scriptedTask.evaluated, diff --git a/project/AutomateScalafmtPlugin.scala b/project/AutomateScalafmtPlugin.scala new file mode 100644 index 000000000..01d8af03c --- /dev/null +++ b/project/AutomateScalafmtPlugin.scala @@ -0,0 +1,67 @@ +import org.scalafmt.bootstrap.ScalafmtBootstrap +import org.scalafmt.sbt.ScalafmtPlugin +import sbt._ +import sbt.Keys._ +import sbt.inc.Analysis + +// Taken from https://github.com/akka/alpakka/blob/master/project/AutomateScalafmtPlugin.scala +object AutomateScalafmtPlugin extends AutoPlugin { + + object autoImport { + def automateScalafmtFor(configurations: Configuration*): Seq[Setting[_]] = + configurations.flatMap { c => + inConfig(c)( + Seq( + compileInputs.in(compile) := { + scalafmtInc.value + compileInputs.in(compile).value + }, + sourceDirectories.in(scalafmtInc) := Seq(scalaSource.value), + scalafmtInc := { + val cache = streams.value.cacheDirectory / "scalafmt" + val include = includeFilter.in(scalafmtInc).value + val exclude = excludeFilter.in(scalafmtInc).value + val sources = + sourceDirectories + .in(scalafmtInc) + .value + .descendantsExcept(include, exclude) + .get + .toSet + def format(handler: Set[File] => Unit, msg: String) = { + def update(handler: Set[File] => Unit, msg: String)(in: ChangeReport[File], + out: ChangeReport[File]) = { + val label = Reference.display(thisProjectRef.value) + val files = in.modified -- in.removed + Analysis + .counted("Scala source", "", "s", files.size) + .foreach(count => streams.value.log.info(s"$msg $count in $label ...")) + handler(files) + files + } + FileFunction.cached(cache)(FilesInfo.hash, FilesInfo.exists)(update(handler, msg))( + sources + ) + } + def formattingHandler(files: Set[File]) = + if (files.nonEmpty) { + val filesArg = files.map(_.getAbsolutePath).mkString(",") + ScalafmtBootstrap.main(List("--quiet", "-i", "-f", filesArg)) + } + format(formattingHandler, "Formatting") + format(_ => (), "Reformatted") // Recalculate the cache + } + ) + ) + } + } + + private val scalafmtInc = taskKey[Unit]("Incrementally format modified sources") + + override def requires = ScalafmtPlugin + + override def trigger = allRequirements + + override def projectSettings = + (includeFilter.in(scalafmtInc) := "*.scala") +: autoImport.automateScalafmtFor(Compile, Test) +} diff --git a/project/Formatting.scala b/project/Formatting.scala deleted file mode 100644 index 30259e009..000000000 --- a/project/Formatting.scala +++ /dev/null @@ -1,40 +0,0 @@ -import sbt._, Keys._ -import com.typesafe.sbt.SbtScalariform._, autoImport._ - -object Formatting { - val BuildConfig = config("build") extend Compile - val BuildSbtConfig = config("buildsbt") extend Compile - - val scalariformCheck = taskKey[Unit]("Checks that the existing code is formatted, via git diff") - - private val prefs: Seq[Setting[_]] = { - import scalariform.formatter.preferences._ - Seq( - scalariformPreferences ~= (_ - .setPreference(AlignSingleLineCaseStatements, true) - .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 100) - .setPreference(DanglingCloseParenthesis, Force) - ) - ) - } - - val settings: Seq[Setting[_]] = Seq() ++ prefs - val sbtFilesSettings: Seq[Setting[_]] = Seq() ++ prefs ++ - inConfig(BuildConfig)(configScalariformSettings) ++ - inConfig(BuildSbtConfig)(configScalariformSettings) ++ - Seq( - scalaSource in BuildConfig := baseDirectory.value / "project", - scalaSource in BuildSbtConfig := baseDirectory.value / "project", - includeFilter in (BuildConfig, scalariformFormat) := ("*.scala": FileFilter), - includeFilter in (BuildSbtConfig, scalariformFormat) := ("*.sbt": FileFilter), - scalariformFormat in Compile := { - val x = (scalariformFormat in BuildSbtConfig).value - val y = (scalariformFormat in BuildConfig).value - (scalariformFormat in Compile).value - }, - scalariformCheck := { - val diff = "git diff".!! - if (diff.nonEmpty) sys.error("Working directory is dirty!\n" + diff) - } - ) -} diff --git a/project/plugins.sbt b/project/plugins.sbt index 27d89b44e..3edebabca 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,7 +6,7 @@ addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.11") addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.4") addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.8.5") addSbtPlugin("com.typesafe.sbt" % "sbt-javaversioncheck" % "0.1.0") -addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.6.0") +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.6.8") addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.8.2") addSbtPlugin("me.lessis" % "bintray-sbt" % "0.3.0") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0-M4")