From 3fe59139ae40acd158a2411d1be499da193aa5a0 Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Tue, 1 May 2018 01:12:59 +0300 Subject: [PATCH 1/9] add scalafmt module, that formats all sources files on every run --- .../scalalib/scalafmt/ScalafmtModule.scala | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala new file mode 100644 index 00000000000..0291e3dc993 --- /dev/null +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala @@ -0,0 +1,36 @@ +package mill.scalalib.scalafmt + +import ammonite.ops.{exists, ls} +import mill._ +import mill.define.Command +import mill.modules.Jvm +import mill.scalalib._ + +trait ScalafmtModule extends JavaModule { + + def reformat(): Command[Unit] = T.command { + val files = filesToFormat(sources()) + T.ctx().log.info(s"Formatting ${files.size} Scala sources") + + Jvm.subprocess( + "org.scalafmt.cli.Cli", + scalafmtDeps().map(_.path), + mainArgs = files.map(_.toString) + ) + () + } + + def scalafmtVersion: T[String] = "1.5.1" + + def scalafmtDeps = resolveDeps( + T { Agg(ivy"com.geirsson::scalafmt-cli:${scalafmtVersion()}") } + ) + + private def filesToFormat(sources: Seq[PathRef]) = { + for { + pathRef <- sources if exists(pathRef.path) + file <- ls.rec(pathRef.path) if file.isFile && file.ext == "scala" + } yield file + } + +} From 73f04d9cd0328c6c850b63ad0d8e223dba46a56f Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Tue, 1 May 2018 02:47:34 +0300 Subject: [PATCH 2/9] scalafmt worker that internally chaches reformatted files --- .../scalalib/scalafmt/ScalafmtModule.scala | 24 +++++------ .../scalalib/scalafmt/ScalafmtWorker.scala | 42 +++++++++++++++++++ 2 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala index 0291e3dc993..206c65915c3 100644 --- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala @@ -1,36 +1,36 @@ package mill.scalalib.scalafmt -import ammonite.ops.{exists, ls} +import ammonite.ops._ import mill._ -import mill.define.Command -import mill.modules.Jvm +import mill.define.{Command, Sources, Worker} import mill.scalalib._ trait ScalafmtModule extends JavaModule { def reformat(): Command[Unit] = T.command { - val files = filesToFormat(sources()) - T.ctx().log.info(s"Formatting ${files.size} Scala sources") - - Jvm.subprocess( - "org.scalafmt.cli.Cli", - scalafmtDeps().map(_.path), - mainArgs = files.map(_.toString) + worker().reformat( + filesToFormat(sources()), + scalafmtConfig().head, + scalafmtDeps().map(_.path) ) - () } def scalafmtVersion: T[String] = "1.5.1" + def scalafmtConfig: Sources = T.sources(pwd / ".scalafmt.conf") + def scalafmtDeps = resolveDeps( T { Agg(ivy"com.geirsson::scalafmt-cli:${scalafmtVersion()}") } ) + def worker: Worker[ScalafmtWorker] = T.worker { new ScalafmtWorker() } + private def filesToFormat(sources: Seq[PathRef]) = { for { pathRef <- sources if exists(pathRef.path) file <- ls.rec(pathRef.path) if file.isFile && file.ext == "scala" - } yield file + } yield PathRef(file) } + } diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala new file mode 100644 index 00000000000..a9d2bd31353 --- /dev/null +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala @@ -0,0 +1,42 @@ +package mill.scalalib.scalafmt + +import ammonite.ops.Path +import mill.{Agg, PathRef} +import mill.modules.Jvm +import mill.util.Ctx + +import scala.collection.mutable + +private[scalafmt] class ScalafmtWorker { + private val reformatted: mutable.Map[Path, Int] = mutable.Map.empty + private var configSig: Int = 0 + + def reformat(input: Seq[PathRef], + scalafmtConfig: PathRef, + scalafmtClasspath: Agg[Path])(implicit ctx: Ctx): Unit = { + val toFormat = + if (scalafmtConfig.sig != configSig) input + else + input.filterNot(ref => reformatted.get(ref.path).contains(ref.sig)) + + if (toFormat.nonEmpty) { + ctx.log.info(s"Formatting ${toFormat.size} Scala sources") + + Jvm.subprocess( + "org.scalafmt.cli.Cli", + scalafmtClasspath, + mainArgs = toFormat + .map(_.path.toString) ++ Seq("--config", scalafmtConfig.path.toString) + ) + + reformatted ++= toFormat.map { ref => + val updRef = PathRef(ref.path) + updRef.path -> updRef.sig + } + configSig = scalafmtConfig.sig + } else { + ctx.log.info(s"Everything is formatted already") + } + + } +} From ac36673d0aa782428da48d3b64fbb6e0fc274053 Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Tue, 1 May 2018 02:54:30 +0300 Subject: [PATCH 3/9] move jvm process call to helper method --- .../scalalib/scalafmt/ScalafmtWorker.scala | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala index a9d2bd31353..a110d91757a 100644 --- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala @@ -21,14 +21,9 @@ private[scalafmt] class ScalafmtWorker { if (toFormat.nonEmpty) { ctx.log.info(s"Formatting ${toFormat.size} Scala sources") - - Jvm.subprocess( - "org.scalafmt.cli.Cli", - scalafmtClasspath, - mainArgs = toFormat - .map(_.path.toString) ++ Seq("--config", scalafmtConfig.path.toString) - ) - + reformatAction(toFormat.map(_.path), + scalafmtConfig.path, + scalafmtClasspath) reformatted ++= toFormat.map { ref => val updRef = PathRef(ref.path) updRef.path -> updRef.sig @@ -37,6 +32,15 @@ private[scalafmt] class ScalafmtWorker { } else { ctx.log.info(s"Everything is formatted already") } - } + + private def reformatAction(toFormat: Seq[Path], + config: Path, + classpath: Agg[Path])(implicit ctx: Ctx) = + Jvm.subprocess( + "org.scalafmt.cli.Cli", + classpath, + mainArgs = toFormat.map(_.toString) ++ Seq("--config", config.toString) + ) + } From 0da6bcd9123e33387585ce12c86b8acfabfd8ae0 Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Tue, 1 May 2018 22:14:45 +0300 Subject: [PATCH 4/9] use scala 2.12.4 to resolve scalafmt deps; check for config file existence; add quiet flags to scalafmt CLI --- .../src/mill/scalalib/scalafmt/ScalafmtModule.scala | 13 ++++++++----- .../src/mill/scalalib/scalafmt/ScalafmtWorker.scala | 11 ++++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala index 206c65915c3..21b580b8ec0 100644 --- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala @@ -5,7 +5,7 @@ import mill._ import mill.define.{Command, Sources, Worker} import mill.scalalib._ -trait ScalafmtModule extends JavaModule { +trait ScalafmtModule extends ScalaModule { def reformat(): Command[Unit] = T.command { worker().reformat( @@ -19,9 +19,13 @@ trait ScalafmtModule extends JavaModule { def scalafmtConfig: Sources = T.sources(pwd / ".scalafmt.conf") - def scalafmtDeps = resolveDeps( - T { Agg(ivy"com.geirsson::scalafmt-cli:${scalafmtVersion()}") } - ) + def scalafmtDeps: T[Agg[PathRef]] = T { + Lib.resolveDependencies( + scalaWorker.repositories, + Lib.depToDependency(_, "2.12.4"), + Seq(ivy"com.geirsson::scalafmt-cli:${scalafmtVersion()}") + ) + } def worker: Worker[ScalafmtWorker] = T.worker { new ScalafmtWorker() } @@ -32,5 +36,4 @@ trait ScalafmtModule extends JavaModule { } yield PathRef(file) } - } diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala index a110d91757a..9e156e34bdb 100644 --- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala @@ -1,6 +1,6 @@ package mill.scalalib.scalafmt -import ammonite.ops.Path +import ammonite.ops.{Path, exists} import mill.{Agg, PathRef} import mill.modules.Jvm import mill.util.Ctx @@ -34,13 +34,18 @@ private[scalafmt] class ScalafmtWorker { } } + private val cliFlags = Seq("--non-interactive", "--quiet") + private def reformatAction(toFormat: Seq[Path], config: Path, - classpath: Agg[Path])(implicit ctx: Ctx) = + classpath: Agg[Path])(implicit ctx: Ctx) = { + val configFlags = + if (exists(config)) Seq("--config", config.toString) else Seq.empty Jvm.subprocess( "org.scalafmt.cli.Cli", classpath, - mainArgs = toFormat.map(_.toString) ++ Seq("--config", config.toString) + mainArgs = toFormat.map(_.toString) ++ configFlags ++ cliFlags ) + } } From 34587b991a54b387de6868276cf0b26efbdce8d6 Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Wed, 2 May 2018 14:48:04 +0300 Subject: [PATCH 5/9] make a scalafmt worker a singleton --- .../mill/scalalib/scalafmt/ScalafmtModule.scala | 16 ++++++++-------- .../mill/scalalib/scalafmt/ScalafmtWorker.scala | 9 ++++++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala index 21b580b8ec0..abfd4a496c2 100644 --- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala @@ -2,17 +2,19 @@ package mill.scalalib.scalafmt import ammonite.ops._ import mill._ -import mill.define.{Command, Sources, Worker} +import mill.define.{Command, Sources} import mill.scalalib._ trait ScalafmtModule extends ScalaModule { def reformat(): Command[Unit] = T.command { - worker().reformat( - filesToFormat(sources()), - scalafmtConfig().head, - scalafmtDeps().map(_.path) - ) + ScalafmtWorkerModule + .worker() + .reformat( + filesToFormat(sources()), + scalafmtConfig().head, + scalafmtDeps().map(_.path) + ) } def scalafmtVersion: T[String] = "1.5.1" @@ -27,8 +29,6 @@ trait ScalafmtModule extends ScalaModule { ) } - def worker: Worker[ScalafmtWorker] = T.worker { new ScalafmtWorker() } - private def filesToFormat(sources: Seq[PathRef]) = { for { pathRef <- sources if exists(pathRef.path) diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala index 9e156e34bdb..d9921e9dd42 100644 --- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala @@ -1,12 +1,19 @@ package mill.scalalib.scalafmt import ammonite.ops.{Path, exists} -import mill.{Agg, PathRef} +import mill._ +import mill.define.{Discover, ExternalModule, Worker} import mill.modules.Jvm import mill.util.Ctx import scala.collection.mutable +object ScalafmtWorkerModule extends ExternalModule { + def worker: Worker[ScalafmtWorker] = T.worker { new ScalafmtWorker() } + + lazy val millDiscover = Discover[this.type] +} + private[scalafmt] class ScalafmtWorker { private val reformatted: mutable.Map[Path, Int] = mutable.Map.empty private var configSig: Int = 0 From fef9051e94ac071f886d67097b09416c57bb6290 Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Sat, 5 May 2018 16:02:31 +0300 Subject: [PATCH 6/9] add tests for scalafmt module --- .../scalafmt/core/resources/application.conf | 1 + .../resources/scalafmt/core/src/Main.scala | 7 ++ .../resources/scalafmt/core/src/Person.scala | 12 +++ .../scalalib/scalafmt/ScalafmtTests.scala | 98 +++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 scalalib/test/resources/scalafmt/core/resources/application.conf create mode 100644 scalalib/test/resources/scalafmt/core/src/Main.scala create mode 100644 scalalib/test/resources/scalafmt/core/src/Person.scala create mode 100644 scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala diff --git a/scalalib/test/resources/scalafmt/core/resources/application.conf b/scalalib/test/resources/scalafmt/core/resources/application.conf new file mode 100644 index 00000000000..f5f8925704f --- /dev/null +++ b/scalalib/test/resources/scalafmt/core/resources/application.conf @@ -0,0 +1 @@ +foo.bar = 2 diff --git a/scalalib/test/resources/scalafmt/core/src/Main.scala b/scalalib/test/resources/scalafmt/core/src/Main.scala new file mode 100644 index 00000000000..a5c7423590f --- /dev/null +++ b/scalalib/test/resources/scalafmt/core/src/Main.scala @@ -0,0 +1,7 @@ + +object Main extends App{ + val person = Person.fromString("rockjam:25") + val greeting = s"hello ${person.name}, your age is: ${person.age}" + println(greeting) +} + diff --git a/scalalib/test/resources/scalafmt/core/src/Person.scala b/scalalib/test/resources/scalafmt/core/src/Person.scala new file mode 100644 index 00000000000..b296cf85fca --- /dev/null +++ b/scalalib/test/resources/scalafmt/core/src/Person.scala @@ -0,0 +1,12 @@ +object Person { + def fromString(s: String): Person = { + val Array(name, age) = s.split(":") + Person( + name, + age.toInt) + } +} + + + +case class Person(name: String, age: Int) diff --git a/scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala b/scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala new file mode 100644 index 00000000000..2d4e5fd676b --- /dev/null +++ b/scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala @@ -0,0 +1,98 @@ +package mill.scalalib.scalafmt + +import ammonite.ops._ +import mill.scalalib.ScalaModule +import mill.util.{TestEvaluator, TestUtil} +import utest._ +import utest.framework.TestPath + +object ScalafmtTests extends TestSuite { + + trait TestBase extends TestUtil.BaseModule { + def millSourcePath = + TestUtil.getSrcPathBase() / millOuterCtx.enclosing.split('.') + } + + object ScalafmtTestModule extends TestBase { + object core extends ScalaModule with ScalafmtModule { + def scalaVersion = "2.12.4" + } + } + + val resourcePath = pwd / 'scalalib / 'test / 'resources / 'scalafmt + + def workspaceTest[T, M <: TestUtil.BaseModule]( + m: M, + resourcePath: Path = resourcePath)(t: TestEvaluator[M] => T)( + implicit tp: TestPath): T = { + val eval = new TestEvaluator(m) + rm(m.millSourcePath) + rm(eval.outPath) + mkdir(m.millSourcePath / up) + cp(resourcePath, m.millSourcePath) + t(eval) + } + + def tests: Tests = Tests { + 'reformat - workspaceTest(ScalafmtTestModule) { eval => + val before = getProjectFiles(ScalafmtTestModule.core, eval) + + // first reformat + val Right(_) = eval.apply(ScalafmtTestModule.core.reformat()) + + val firstReformat = getProjectFiles(ScalafmtTestModule.core, eval) + + assert( + firstReformat("Main.scala").modifyTime > before("Main.scala").modifyTime, + firstReformat("Main.scala").content != before("Main.scala").content, + + firstReformat("Person.scala").modifyTime > before("Person.scala").modifyTime, + firstReformat("Person.scala").content != before("Person.scala").content, + + // resources files aren't modified + firstReformat("application.conf").modifyTime == before( + "application.conf").modifyTime + ) + + // cached reformat + val Right(_) = eval.apply(ScalafmtTestModule.core.reformat()) + + val cached = getProjectFiles(ScalafmtTestModule.core, eval) + + assert( + cached("Main.scala").modifyTime == firstReformat("Main.scala").modifyTime, + cached("Person.scala").modifyTime == firstReformat("Person.scala").modifyTime, + cached("application.conf").modifyTime == firstReformat( + "application.conf").modifyTime + ) + + // reformat after change + write.over(cached("Main.scala").path, + cached("Main.scala").content + "\n object Foo") + + val Right(_) = eval.apply(ScalafmtTestModule.core.reformat()) + + val afterChange = getProjectFiles(ScalafmtTestModule.core, eval) + + assert( + afterChange("Main.scala").modifyTime > cached("Main.scala").modifyTime, + afterChange("Person.scala").modifyTime == cached("Person.scala").modifyTime, + afterChange("application.conf").modifyTime == cached("application.conf").modifyTime + ) + } + } + + case class FileInfo(content: String, modifyTime: Long, path: Path) + + def getProjectFiles(m: ScalaModule, eval: TestEvaluator[_]) = { + val Right((sources, _)) = eval.apply(m.sources) + val Right((resources, _)) = eval.apply(m.resources) + + val sourcesFiles = sources.flatMap(p => ls.rec(p.path)) + val resourcesFiles = resources.flatMap(p => ls.rec(p.path)) + (sourcesFiles ++ resourcesFiles).map { p => + p.name -> FileInfo(read(p), p.mtime.toMillis, p) + }.toMap + } + +} From c6be48d1422139e9c849167155936f1012e2ecfd Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Sat, 5 May 2018 23:38:08 +0300 Subject: [PATCH 7/9] add reformatAll command --- .../scalalib/scalafmt/ScalafmtModule.scala | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala index abfd4a496c2..3b325b4c7d0 100644 --- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala +++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala @@ -1,11 +1,11 @@ package mill.scalalib.scalafmt -import ammonite.ops._ +import ammonite.ops.{exists, ls, pwd} import mill._ -import mill.define.{Command, Sources} +import mill.define._ import mill.scalalib._ -trait ScalafmtModule extends ScalaModule { +trait ScalafmtModule extends JavaModule { def reformat(): Command[Unit] = T.command { ScalafmtWorkerModule @@ -23,13 +23,13 @@ trait ScalafmtModule extends ScalaModule { def scalafmtDeps: T[Agg[PathRef]] = T { Lib.resolveDependencies( - scalaWorker.repositories, + ScalaWorkerModule.repositories, Lib.depToDependency(_, "2.12.4"), Seq(ivy"com.geirsson::scalafmt-cli:${scalafmtVersion()}") ) } - private def filesToFormat(sources: Seq[PathRef]) = { + protected def filesToFormat(sources: Seq[PathRef]) = { for { pathRef <- sources if exists(pathRef.path) file <- ls.rec(pathRef.path) if file.isFile && file.ext == "scala" @@ -37,3 +37,22 @@ trait ScalafmtModule extends ScalaModule { } } + +object ScalafmtModule extends ExternalModule with ScalafmtModule { + + def reformatAll(sources: mill.main.Tasks[Seq[PathRef]]): Command[Unit] = + T.command { + val files = Task.sequence(sources.value)().flatMap(filesToFormat) + ScalafmtWorkerModule + .worker() + .reformat( + files, + scalafmtConfig().head, + scalafmtDeps().map(_.path) + ) + } + + implicit def millScoptTargetReads[T] = new mill.main.Tasks.Scopt[T]() + + lazy val millDiscover = Discover[this.type] +} From bfbbb6da60a4de9d87d78b1c0e933c1b7e05ba74 Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Sat, 5 May 2018 23:50:46 +0300 Subject: [PATCH 8/9] tests for reformatAll command --- .../scalalib/scalafmt/ScalafmtTests.scala | 97 ++++++++++--------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala b/scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala index 2d4e5fd676b..fcff52a33ce 100644 --- a/scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala +++ b/scalalib/test/src/mill/scalalib/scalafmt/ScalafmtTests.scala @@ -1,6 +1,7 @@ package mill.scalalib.scalafmt import ammonite.ops._ +import mill.main.Tasks import mill.scalalib.ScalaModule import mill.util.{TestEvaluator, TestUtil} import utest._ @@ -34,51 +35,57 @@ object ScalafmtTests extends TestSuite { } def tests: Tests = Tests { - 'reformat - workspaceTest(ScalafmtTestModule) { eval => - val before = getProjectFiles(ScalafmtTestModule.core, eval) - - // first reformat - val Right(_) = eval.apply(ScalafmtTestModule.core.reformat()) - - val firstReformat = getProjectFiles(ScalafmtTestModule.core, eval) - - assert( - firstReformat("Main.scala").modifyTime > before("Main.scala").modifyTime, - firstReformat("Main.scala").content != before("Main.scala").content, - - firstReformat("Person.scala").modifyTime > before("Person.scala").modifyTime, - firstReformat("Person.scala").content != before("Person.scala").content, - - // resources files aren't modified - firstReformat("application.conf").modifyTime == before( - "application.conf").modifyTime - ) - - // cached reformat - val Right(_) = eval.apply(ScalafmtTestModule.core.reformat()) - - val cached = getProjectFiles(ScalafmtTestModule.core, eval) - - assert( - cached("Main.scala").modifyTime == firstReformat("Main.scala").modifyTime, - cached("Person.scala").modifyTime == firstReformat("Person.scala").modifyTime, - cached("application.conf").modifyTime == firstReformat( - "application.conf").modifyTime - ) - - // reformat after change - write.over(cached("Main.scala").path, - cached("Main.scala").content + "\n object Foo") - - val Right(_) = eval.apply(ScalafmtTestModule.core.reformat()) - - val afterChange = getProjectFiles(ScalafmtTestModule.core, eval) - - assert( - afterChange("Main.scala").modifyTime > cached("Main.scala").modifyTime, - afterChange("Person.scala").modifyTime == cached("Person.scala").modifyTime, - afterChange("application.conf").modifyTime == cached("application.conf").modifyTime - ) + 'scalafmt - { + def checkReformat(reformatCommand: mill.define.Command[Unit]) = + workspaceTest(ScalafmtTestModule) { eval => + val before = getProjectFiles(ScalafmtTestModule.core, eval) + + // first reformat + val Right(_) = eval.apply(reformatCommand) + + val firstReformat = getProjectFiles(ScalafmtTestModule.core, eval) + + assert( + firstReformat("Main.scala").modifyTime > before("Main.scala").modifyTime, + firstReformat("Main.scala").content != before("Main.scala").content, + firstReformat("Person.scala").modifyTime > before("Person.scala").modifyTime, + firstReformat("Person.scala").content != before("Person.scala").content, + // resources files aren't modified + firstReformat("application.conf").modifyTime == before( + "application.conf").modifyTime + ) + + // cached reformat + val Right(_) = eval.apply(reformatCommand) + + val cached = getProjectFiles(ScalafmtTestModule.core, eval) + + assert( + cached("Main.scala").modifyTime == firstReformat("Main.scala").modifyTime, + cached("Person.scala").modifyTime == firstReformat("Person.scala").modifyTime, + cached("application.conf").modifyTime == firstReformat( + "application.conf").modifyTime + ) + + // reformat after change + write.over(cached("Main.scala").path, + cached("Main.scala").content + "\n object Foo") + + val Right(_) = eval.apply(reformatCommand) + + val afterChange = getProjectFiles(ScalafmtTestModule.core, eval) + + assert( + afterChange("Main.scala").modifyTime > cached("Main.scala").modifyTime, + afterChange("Person.scala").modifyTime == cached("Person.scala").modifyTime, + afterChange("application.conf").modifyTime == cached( + "application.conf").modifyTime + ) + } + + 'reformat - checkReformat(ScalafmtTestModule.core.reformat()) + 'reformatAll - checkReformat( + ScalafmtModule.reformatAll(Tasks(Seq(ScalafmtTestModule.core.sources)))) } } From a58982ef85eba6c554ab912689870f6d3b97959f Mon Sep 17 00:00:00 2001 From: rockjam <5min4eq.unity@gmail.com> Date: Sun, 6 May 2018 00:07:58 +0300 Subject: [PATCH 9/9] add docs about scalafmt support --- docs/pages/2 - Configuring Mill.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/pages/2 - Configuring Mill.md b/docs/pages/2 - Configuring Mill.md index a229fa72afd..43191950445 100644 --- a/docs/pages/2 - Configuring Mill.md +++ b/docs/pages/2 - Configuring Mill.md @@ -213,6 +213,28 @@ You can use Scala compiler plugins by setting `scalacPluginIvyDeps`. The above example also adds the plugin to `compileIvyDeps`, since that plugin's artifact is needed on the compilation classpath (though not at runtime). +## Reformatting your code + +Mill supports code formatting via [scalafmt](https://scalameta.org/scalafmt/) out of the box. + +To have a formatting per-module you need to make your module extend `mill.scalalib.scalafmt.ScalafmtModule`: + +```scala +// build.sc +import mill._ +import mill.scalalib._ +import mill.scalalib.scalafmt._ + +object foo extends ScalaModule with ScalafmtModule { + def scalaVersion = "2.12.4" +} +``` + +Now you can reformat code with `mill foo.reformat` command. + +You can also reformat your project's code globally with `mill mill.scalalib.scalafmt.ScalafmtModule/reformatAll __.sources` command. +It will reformat all sources that matches `__.sources` query. + ## Common Configuration ```scala