aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorChristopher Vogt <oss.nsp@cvogt.org>2017-03-09 00:54:45 -0500
committerChristopher Vogt <oss.nsp@cvogt.org>2017-03-09 00:54:45 -0500
commit919d7987fad82f59f998a29d79a82116049af1b9 (patch)
treea6a67d4653a5010c401124b7de2978b1f540f23b /plugins
parentc45c8f241d6b2c268fd18341cf80d5467f9b50c6 (diff)
downloadcbt-919d7987fad82f59f998a29d79a82116049af1b9.tar.gz
cbt-919d7987fad82f59f998a29d79a82116049af1b9.tar.bz2
cbt-919d7987fad82f59f998a29d79a82116049af1b9.zip
refactor scalafmt to new plugin style
turn replaceSections into helper function instead of trait method proguard scalafmt build currently suffers from non-deterministic formatting. Try a few times to reproduce commited Proguard.scala
Diffstat (limited to 'plugins')
-rw-r--r--plugins/scalafmt/Scalafmt.scala145
-rw-r--r--plugins/scalafmt/build/build.scala2
2 files changed, 89 insertions, 58 deletions
diff --git a/plugins/scalafmt/Scalafmt.scala b/plugins/scalafmt/Scalafmt.scala
index 5f4e054..9d42cbd 100644
--- a/plugins/scalafmt/Scalafmt.scala
+++ b/plugins/scalafmt/Scalafmt.scala
@@ -8,75 +8,106 @@ import java.io.File
import java.nio.file.Files._
import java.nio.file._
-/**
- * This plugin provides scalafmt support for cbt.
- *
- */
+/** This plugin provides scalafmt support for cbt. */
trait Scalafmt extends BaseBuild {
- /**
- * Reformat scala source code according to `scalafmtConfig` rules
- *
- * @return always returns `ExitCode.Success`
- */
- final def scalafmt: ExitCode = Scalafmt.format(sourceFiles, scalafmtConfig)
-
- /**
- * Scalafmt formatting config.
- *
- * Tries to get style in following order:
- * • project local .scalafmt.conf
- * • global ~/.scalafmt.conf
- * • default scalafmt config
- *
- * Override this task if you want to provide
- * scalafmt config programmatically on your own.
- */
- def scalafmtConfig: ScalafmtConfig =
- Scalafmt.getStyle(
- project = projectDirectory.toPath,
- home = Option(System.getProperty("user.home")) map (p => Paths.get(p))
+ /** Reformat scala source code according to `scalafmtConfig` rules */
+ def scalafmt = {
+ val scalafmtLib = new ScalafmtLib(lib)
+ scalafmtLib.format( sourceFiles ).config(
+ scalafmtLib.loadConfig(
+ projectDirectory.toPath
+ ) getOrElse ScalafmtConfig.default
)
+ }
}
-object Scalafmt {
+class ScalafmtLib(lib: Lib){ scalafmtLib =>
+ def userHome = Option( System.getProperty("user.home") ).map(Paths.get(_))
- def getStyle(project: Path, home: Option[Path]): ScalafmtConfig = {
- val local = getConfigPath(project)
- val global = home flatMap getConfigPath
- val customStyle = for {
- configPath <- local.orElse(global)
- style <- StyleCache.getStyleForFile(configPath.toString)
- } yield style
+ /** Tries to load config from .scalafmt.conf in given directory or fallback directory */
+ def loadConfig( directory: Path, fallback: Option[Path] = userHome ): Option[ScalafmtConfig] = {
+ def findIn( base: Path ): Option[Path] = {
+ Some( base.resolve(".scalafmt.conf").toAbsolutePath ).filter(isRegularFile(_))
+ }
- customStyle.getOrElse(ScalafmtConfig.default)
+ findIn( directory ).orElse( fallback flatMap findIn )
+ .flatMap ( file => StyleCache.getStyleForFile(file.toString) )
}
- def format(files: Seq[File], style: ScalafmtConfig): ExitCode = {
- val results = files.filter(_.string endsWith ".scala").map(_.toPath).map{ path =>
- val original = new String(readAllBytes(path))
- org.scalafmt.Scalafmt.format(original, style) match {
- case Formatted.Success(formatted) =>
- if (original != formatted) {
- val tmpPath = Paths.get(path.toString ++ ".scalafmt-tmp")
- write(tmpPath, formatted.getBytes)
- move(tmpPath, path, StandardCopyOption.REPLACE_EXISTING)
- Some(1)
- } else {
- Some(0)
+ case class format(files: Seq[File]){
+ /**
+ * @param whiteSpaceInParenthesis more of a hack to make up for missing support in Scalafmt. Does not respect alignment and maxColumn.
+ */
+ case class config(
+ config: ScalafmtConfig,
+ whiteSpaceInParenthesis: Boolean = false
+ ) extends (() => Seq[File]){
+ def lib = scalafmtLib
+ def apply = {
+ val (successes, errors) = scalafmtLib.lib.transformFilesOrError(
+ files,
+ org.scalafmt.Scalafmt.format(_, config) match {
+ case Formatted.Success(formatted) => Right(
+ if( whiteSpaceInParenthesis ){
+ scalafmtLib.whiteSpaceInParenthesis(formatted)
+ } else formatted
+ )
+ case Formatted.Failure( e ) => Left( e )
}
- case Formatted.Failure(e) =>
- System.err.println(s"Scalafmt failed for $path\nCause: $e\n")
- None
+ )
+ if(errors.nonEmpty)
+ throw new RuntimeException(
+ "Scalafmt failed to format some files:\n" ++ errors.map{
+ case (file, error) => file.string ++ ": " ++ error.getMessage
+ }.mkString("\n"),
+ errors.head._2
+ )
+ successes
}
}
- if(results.forall(_.nonEmpty)){
- System.err.println(s"Formatted ${results.flatten.sum} Scala sources")
- ExitCode.Success
- } else ExitCode.Failure
}
- private def getConfigPath(base: Path): Option[Path] = {
- Some( base.resolve(".scalafmt.conf").toFile )
- .collect{ case f if f.exists && f.isFile => f.toPath.toAbsolutePath }
+ private def whiteSpaceInParenthesis: String => String =
+ Seq(
+ "(\\(+)([^\\s\\)])".r.replaceAllIn(_:String, m => m.group(1).mkString(" ") ++ " " ++ m.group(2) ),
+ "([^\\s\\(])(\\)+)".r.replaceAllIn(_:String, m => m.group(1) ++ " " ++ m.group(2).mkString(" ") )
+ ).reduce(_ andThen _)
+
+ def cbtRecommendedConfig = {
+ import org.scalafmt.config._
+ val c = ScalafmtConfig.defaultWithAlign
+ c.copy(
+ maxColumn = 110,
+ continuationIndent = c.continuationIndent.copy(
+ defnSite = 2
+ ),
+ align = c.align.copy(
+ tokens = AlignToken.default ++ Set(
+ // formatting for these alignment tokens seems to be deterministic right now
+ // Maybe because of scala meta. Killing the class loader between runs seems not to help.
+ // Starting a new jvm each time does.
+ AlignToken( "=>", ".*" ),
+ AlignToken( ":", ".*" ),
+ AlignToken( "=", ".*" )
+ ) + AlignToken.caseArrow,
+ arrowEnumeratorGenerator = true,
+ mixedOwners = true
+ ),
+ binPack = c.binPack.copy(
+ parentConstructors = true
+ ),
+ spaces = c.spaces.copy(
+ inImportCurlyBraces = true
+ ),
+ lineEndings = LineEndings.unix,
+ newlines = c.newlines.copy(
+ penalizeSingleSelectMultiArgList = false
+ ),
+ runner = c.runner.copy(
+ optimizer = c.runner.optimizer.copy(
+ forceConfigStyleOnOffset = -1
+ )
+ )
+ )
}
}
diff --git a/plugins/scalafmt/build/build.scala b/plugins/scalafmt/build/build.scala
index b37d769..e592873 100644
--- a/plugins/scalafmt/build/build.scala
+++ b/plugins/scalafmt/build/build.scala
@@ -1,7 +1,7 @@
import cbt._
class Build(val context: Context) extends Plugin {
- private val ScalafmtVersion = "0.5.7"
+ private val ScalafmtVersion = "0.6.2"
override def dependencies =
super.dependencies ++