diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 000000000..0d5990db2 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,18 @@ +maxColumn = 100 +project.git = true +project.excludeFilters = [ /sbt-test/, /input_sources/, /contraband-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/.travis.yml b/.travis.yml index ff0899634..535d8f33c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ scala: - 2.12.1 script: - - sbt -Dfile.encoding=UTF8 -J-XX:ReservedCodeCacheSize=256M "++$TRAVIS_SCALA_VERSION test" + - sbt -Dfile.encoding=UTF8 -J-XX:ReservedCodeCacheSize=256M ";++$TRAVIS_SCALA_VERSION test;scalafmtCheck" jdk: - oraclejdk8 diff --git a/build.sbt b/build.sbt index b5e89d6c4..1571c04bb 100644 --- a/build.sbt +++ b/build.sbt @@ -18,11 +18,19 @@ def commonSettings: Seq[Setting[_]] = Seq( scalacOptions += "-Ywarn-unused", mimaPreviousArtifacts := Set(), // Some(organization.value %% moduleName.value % "1.0.0"), publishArtifact in Compile := true, - publishArtifact in Test := false + publishArtifact in Test := false, + commands += Command.command("scalafmtCheck") { state => + sys.process.Process("git diff --name-only --exit-code").! match { + case 0 => // ok + case x => sys.error("git diff detected! Did you compile before committing?") + } + state + } ) lazy val lmRoot = (project in file(".")). aggregate(lm). + disablePlugins(com.typesafe.sbt.SbtScalariform). settings( inThisBuild(Seq( homepage := Some(url("https://github.com/sbt/librarymanagement")), @@ -41,6 +49,7 @@ lazy val lmRoot = (project in file(".")). ) lazy val lm = (project in file("librarymanagement")). + disablePlugins(com.typesafe.sbt.SbtScalariform). settings( commonSettings, name := "librarymanagement", diff --git a/project/AutomateScalafmtPlugin.scala b/project/AutomateScalafmtPlugin.scala new file mode 100644 index 000000000..f066d0567 --- /dev/null +++ b/project/AutomateScalafmtPlugin.scala @@ -0,0 +1,66 @@ +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/plugins.sbt b/project/plugins.sbt index 767bccb53..6d069c96c 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,5 +2,6 @@ addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.2") addSbtPlugin("com.eed3si9n" % "sbt-doge" % "0.1.3") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0-M4") addSbtPlugin("me.lessis" % "bintray-sbt" % "0.3.0") +addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.6.8") scalacOptions += "-language:postfixOps"