Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scalafmt support #308

Merged
merged 9 commits into from
May 6, 2018
36 changes: 36 additions & 0 deletions scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package mill.scalalib.scalafmt

import ammonite.ops._
import mill._
import mill.define.{Command, Sources, Worker}
import mill.scalalib._

trait ScalafmtModule extends JavaModule {

def reformat(): Command[Unit] = T.command {
worker().reformat(
filesToFormat(sources()),
scalafmtConfig().head,
scalafmtDeps().map(_.path)
)
}

def scalafmtVersion: T[String] = "1.5.1"

def scalafmtConfig: Sources = T.sources(pwd / ".scalafmt.conf")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have an alternative for Sources for a single file?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so; we could add one if it comes up repeatedly, but for now just picking the first item in the Agg[PathRef] may be fine


def scalafmtDeps = resolveDeps(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use certain scala version to resolve deps to stay stable no matter what version of scala mill uses?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any opinion, though I suppose scalafmt is meant to do the same thing regardless of scalaVersion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, version of scala doesn't affect the result of formatting with scalafmt. What I meant is the situation like this:
At some point, scala 2.13 is released. We decide to migrate mill to 2.13, but we won't be able to do that until scalafmt for 2.13 is released.

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 PathRef(file)
}


}
46 changes: 46 additions & 0 deletions scalalib/src/mill/scalalib/scalafmt/ScalafmtWorker.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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")
reformatAction(toFormat.map(_.path),
scalafmtConfig.path,
scalafmtClasspath)
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")
}
}

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)
)

}