Scalafmt - code formatter for Scala


1.0.0-RC4

Join the chat at https://gitter.im/olafurpg/scalafmt

Any style guide written in English is either so brief that it’s ambiguous, or so long that no one reads it.
-- Bob Nystrom, "Hardest Program I've Ever Written", Dart, Google.

Scalafmt turns the mess on the left into the (hopefully) readable, idiomatic and consistently formatted Scala code on the right.

object FormatMe { List(number) match
{ case head :: Nil
if head % 2 == 0 => "number is even"
  case head :: Nil =>
  "number is not even"
  case Nil =>
  "List is empty" }
  function(arg1,
  arg2(arg3(arg4,
  arg5, "arg6")
  , arg7 + arg8),
  arg9.select(1, 2,
  3, 4, 5, 6)) }
object FormatMe {
  List(number) match {
    case head :: Nil if head % 2 == 0 =>
      "number is even"
    case head :: Nil =>
      "number is not even"
    case Nil =>
      "List is empty"
  }
  function(
    arg1,
    arg2(arg3(arg4, arg5, "arg6"),
         arg7 + arg8),
    arg9.select(1, 2, 3, 4, 5, 6))
}

The goal of scalafmt is to produce good enough formatted code so that you can focus on programming instead of manipulating syntax trivia. Scalafmt can be used in several environments such as the command line, text editors and build tools.

It is not a goal to format every single Scala source file under the sun. In particular, scalafmt cannot format deeply nested computer generated code.

Scalafmt is maintained by @olafurpg in his free time. Bug reports, feature requests, questions and PRs are welcome. Complaints and unfriendly attitude is not welcome.

Curious to learn more about scalafmt? Check out this talk:

Installation


CLI

The recommended way to install the scalafmt command line tool is with Coursier.

Coursier

Nailgun

Nailgun is recommended if you want to integrate scalafmt with a text editor like vim/Emacs/Atom/Sublime/VS Code.

Nailgun keeps scalafmt running on a local server to avoid the JVM startup penalty and also so scalafmt can benefit from JIT. This makes scalafmt up to 10x faster when formatting a single file from the CLI. The downside to Nailgun is that the setup is complicated and the long-running server needs to be restarted once in awhile.

Homebrew

You can install scalafmt via homebrew using a custom cask
brew install --HEAD olafurpg/scalafmt/scalafmt
scalafmt --version // should be 1.0.0-RC4

// to upgrade between releases
brew upgrade scalafmt

--help

NOTE. This help page is generated from the master branch and may include flags that have not been published yet.
build commit: d204ae1437
build time: Sun Jun 18 18:29:21 UTC 2017
scalafmt 1.0.0-RC4+10-d204ae14
Usage: scalafmt [options] [<file>...]

  -h, --help               prints this usage text
  -v, --version            print version 
  <file>...                file or directory, in which case all *.scala files are formatted.
  --stdout                 write formatted files to stdout
  --git <value>            if true, ignore files in .gitignore (default false)
  --exclude <value>        file or directory, in which case all *.scala files are formatted.
  -c, --config <value>     a file path to .scalafmt.conf.
  --config-str <value>     configuration defined as a string
  --stdin                  read from stdin and print to stdout
  --no-stderr              don't use strerr for messages, output to stdout
  --assume-filename <value>
                           required to format .sbt files with --stdin flag.
  --test                   test for mis-formatted code, exits with status 1 on failure.
  --migrate2hocon <value>  migrate .scalafmt CLI style configuration to hocon style configuration in .scalafmt.conf
  --diff                   If set, only format edited files in git diff against master.
  --diff-branch <value>    If set, only format edited files in git diff against provided branch.
  --build-info             prints build information
  --quiet                  don't print out stuff to console.
  --debug                  print out diagnostics to console.
  --non-interactive        disable fancy progress bar, useful in ci or sbt plugin.
Examples:
scalafmt # Format all files in the current project, configuration is determined in this order:
         # 1. .scalafmt.conf file in current directory
         # 2. .scalafmt.conf inside root directory of current git repo
         # 3. no configuration, default style
scalafmt --test # throw exception on mis-formatted files, won't write to files.
scalafmt --diff # Format all files that were edited in git diff against master branch.
scalafmt --diff-branch 2.x # same as --diff, except against branch 2.x
scalafmt --stdin # read from stdin and print to stdout
scalafmt --stdin --assume-filename foo.sbt # required to format .sbt files
scalafmt Code1.scala A.scala       # write formatted contents to file.
scalafmt --stdout Code.scala       # print formatted contents to stdout.
scalafmt --exclude target          # format all files in directory excluding target
scalafmt --config .scalafmt.conf   # read custom style from file
scalafmt --config-str "style=IntelliJ" # define custom style as a flag, must be quoted.
Please file bugs to https://github.com/scalameta/scalafmt/issues
      

IntelliJ

Here is the plugin. You can install it directly from within IntelliJ,

The default shortcut is Ctrl + Shift + L. Undo works, but not redo.

The plugin determines which style to use in this order:

  1. .scalafmt.conf in the project's root directory, if it exists
  2. $HOME/.scalafmt.conf, if it exists
  3. Otherwise, uses default style.
For details on how .scalafmt.conf should look like, see Configuration. The scalafmt IntelliJ plugin has a "Format on save" setting.

NOTE. You may need to enable balloons to get error message: Settings > Appearance & Behavior > Notifications > Scalafmt > Popup "Balloon". You need to first check "Display Balloon Notifications".

sbt

You can choose between

sbt-scalafmt

The com.geirsson/sbt-scalafmt plugin is a tiny wrapper around the command line interface, and provides no custom sbt functionality beyond what the command line interface offers.

addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.0.0-RC4")

neo-sbt-scalafmt

lucidsoftware/neo-sbt-scalafmt is an sbt plugin that

Please report back if you find neo-sbt-scalafmt useful. We might want to promote it to become the official sbt plugin for scalafmt.

sbt 0.13

NOTE. You might want to try out neo-sbt-scalafmt.

I recommend you try to upgrade to sbt 1.0 as soon as possible. However, if you are stuck on sbt 0.13, you can still use the latest versions of scalafmt with this workaround.

// project/plugins.sbt
libraryDependencies += "com.geirsson" %% "scalafmt-bootstrap" % "0.6.6"
// build.sbt
def latestScalafmt = "1.0.0-RC4"
commands += Command.args("scalafmt", "Run scalafmt cli.") {
  case (state, args) =>
    val Right(scalafmt) =
      org.scalafmt.bootstrap.ScalafmtBootstrap.fromVersion(latestScalafmt)
    scalafmt.main("--non-interactive" +: args.toArray)
    state
}
// run: sbt scalafmt
Here is an example repo that uses this workaround: https://github.com/olafurpg/sbt-scalafmt-0.13/blob/master/build.sbt

Gradle

It is possible to use scalafmt in gradle with the following externally maintained plugins:

Maven

It is possible to use scalafmt in Maven with the following externally maintained plugin:

Vim

NOTE. You pay the JVM startup penalty on every format unless you're using Nailgun.

Standalone library

Add to your dependencies
libraryDependencies += "com.geirsson" %% "scalafmt-core" % "1.0.0-RC4"
libraryDependencies += "com.geirsson" %% "scalafmt-cli" % "1.0.0-RC4"
// Scala.js
libraryDependencies += "com.geirsson" %%% "scalafmt-core" % "1.0.0-RC4"

Use the API like this

scala> org.scalafmt.Scalafmt.format("""
      object FormatMe { List(Split(Space, 0).withPolicy(SingleLineBlock(close)), Split(Newline, 1).withPolicy{ case Decision(t@FormatToken(_, `close`, _), s) => Decision(t, List(Split(Newline, 0)))}.withIndent(2, close, Right)) }
       """).get
res0: java.lang.String = 
"object FormatMe {
  List(
    Split(Space, 0).withPolicy(SingleLineBlock(close)),
    Split(Newline, 1)
      .withPolicy {
        case Decision(t @ FormatToken(_, `close`, _), s) =>
          Decision(t, List(Split(Newline, 0)))
      }
      .withIndent(2, close, Right)
  )
}
"

Help wanted!

Configuration


Configuration for scalafmt is defined in a plain text file .scalafmt.conf using HOCON syntax. To reuse your configuration with IntelliJ, .scalafmt.conf must be placed in the root directory of your project.

Here is an example .scalafmt.conf.

align = true    # For pretty alignment.
maxColumn = 100 # For my wide 30" display.

A note of warning. I personally use the default style, which means that the default style is by far the most tested and supported style. Most of the configuration flags are quite innocent, while some of them work very differently (esp. Scala.js). It is very difficult to guarantee that all configurations options play nicely together so I recommend you try not to go too crazy on this part.

The following sections describe the most common configuration options.

NOTE. If you are using scalafmt as a Standalone library, you can pass in a ScalafmtConfig instance, which is set to ScalafmtStyle.default by default.

style

Option 1: default
// Column 40                           |
// non bin packed parent constructors
object DefaultStyle
    extends Parent
    with SecondParent
    with ThirdParent {
  // non bin packed arguments
  function(
    argument1,
    argument2(argument3, argument4))
  // Vertical alignment only for case arrows
  x match {
    case 1  => 1
    case 11 => 1
  }
}
Option 2: IntelliJ
// Column 40                           |
// non bin packed parent constructors
object IntelliJStyle
    extends Parent
    with SecondParent
    with ThirdParent {

  function(argument1, argument2)

  // continuationIndent = 2  # for call + defn site
  // align.openParenCallSite = false
  // danglingParentheses = true
  function(
    argument1,
    argument2,
    argument3,
    argument4
  )

  // openParenCallSite = true
  def foobar(argument1: Type1,
             argument2: Type2): Int =
    argument1 + argument2

}
NOTE. There is a Scala.js style that is super experimental and does not work for complicated code.

maxColumn

Default: 80

continuationIndent.callSite

Default: 2

Example:

function(
  argument1 // indented by 2
)

continuationIndent.defnSite

Default: 4

Same as continuationIndent.callSite except for definition site. Example:

def function(
    argument1: Type1): ReturnType // Indented by 4

align

Default: some Align has several nested fields, which you can customize. However, it comes with four possible defaults: none, some, more most.

align=some

x match { // true for case arrows
  case 2  => 22
  case 22 => 222
}

def foo(a: Int, // true for defn site open paren
        b: String): Int
foo(a: Int, // true for call site open paren
    b: String): Int

val x = 2 // false for assignment
val xx = 22

case object B extends A // false for `extends`
case object BB extends A

align=none

x match { // false for case arrows
  case 2 => 22 // also comments!
  case 22 => 222 // don't align me!
}

def foo(
    a: Int, // false for defn site
    b: String): Int
foo(
  a: Int, // false for call site
  b: String): Int

align=more

val x  = 2 // true for assignment
val xx = 22

case object B  extends A // false for `extends`
case object BB extends A

q  -> 22 // true for various infix operators
qq -> 3  // and also comments!

for {
  x  <- List(1) // true for alignment enumerator
  yy <- List(2)
} yield x ** xx

x match { // true for multiple tokens across multiple lines
  case 1  => 1  -> 2  // first
  case 11 => 11 -> 22 // second

  // A blank line separates alignment blocks.
  case `ignoreMe` => 111 -> 222
}

// Align assignments of similar type.
def name   = column[String]("name")
def status = column[Int]("status")
val x      = 1
val xx     = 22

// Align sbt module IDs.
libraryDependencies ++= Seq(
  "org.scala-lang" % "scala-compiler" % scalaVersion.value,
  "com.lihaoyi"    %% "sourcecode"    % "0.1.1"
)

align=most

for {
  // align <- with =
  x  <- List()
  yy = 2
  // aligns body by arrow
  zzz <- new Integer {
          def value = 3
        }
} yield x
// Note. Only for the truest vertical aligners. This is a new option,
// feel free to open PR enabling more crazy vertical alignment here.
// Expect changes.

align.tokens

Default: [caseArrow]

An align token is a pair of code, which is the string literal of an operator of token, and owner, which is the kind of the closest tree node that owns that token. If no owner is provided, then all tree kinds will be matched.

// =======================================================
// scalafmt: {align.tokens = [{code = "=>", owner = "Case"}]}
// =======================================================
x match {
  case 1  => 1 -> 2
  case 11 => 11 -> 22
}
// =======================================================
// scalafmt: {align.tokens = ["%", "%%"]}
// =======================================================
val x = List(
  "org.scala-lang" % "scala-compiler" % scalaVersion.value,
  "com.lihaoyi"    %% "sourcecode"    % "0.1.1"
)
To find the owner part for a custom tree, depend on Scalameta and use scala.meta.Tree.productPrefix from the the (for example, Ammonite) repl
@ import $ivy.`org.scalameta:scalameta_2.12:1.7.0`, scala.meta._
@ val termMatch = q"x match { case 2 => foo(bar) }"
termMatch: Term.Match = x match {
  case 2 =>
    foo(bar)
}
@ termMatch.structure
res0: String = """
Term.Match(Term.Name("x"), Seq(Case(Lit.Int(2), None, Term.Apply(Term.Name("foo"), Seq(Term.Name("bar"))))))
"""
@ termMatch.productPrefix
res1: String = "Term.Match"
To learn more about Scalameta, see this tutorial.

align.arrowEnumeratorGenerator

Default: false
// align.arrowEnumeratorGenerator = false
for {
  x <- new Integer {
    def value = 2
  }
} yield x
// align.arrowEnumeratorGenerator = true
for {
  x <- new Integer {
        def value = 2
      }
} yield x

align.openParenCallSite

Default: true
// Column limit |
// align.openParenCallSite = true
foo(arg1, arg2)

function(arg1, // align by (
         arg2,
         arg3)
function(
  argument1,
  argument2)

// align.openParenCallSite = false
foo(arg1, arg2)
function(
  arg1, // no align by (
  arg2,
  arg3)
function(
  argument1,
  argument2)


// format: off

Disable formatting for specific regions of code by wrapping them in // format: OFF blocks:
object PrettyMatrix {
  // format: off
  val identity = Array(1, 0, 0,
                       0, 1, 0,
                       0, 0, 1)
  // format: on
}
To disable formatting for a whole file, put the comment at the top of the file.

assumeStandardLibraryStripMargin

Default: false

If true, the margin character | is aligned with the opening triple quote """ in interpolated and raw string literals.

// 40 columns                          |
object StripMargin {
  val example1 =
    s"""Examples:
       |  * one
       |  * two
       |  * $three
       |""".stripMargin

  // pipe character after opening """
  val example2 =
    s"""|Examples:
        |  * one
        |  * two
        |  * $three
        |""".stripMargin
}
NOTE. May cause non-idempotent formatting in rare cases, see #192.

docstrings

Default: ScalaDoc
// docstrings = ScalaDoc
/** Align by second asterisk.
  *
  */

// docstrings = JavaDoc
/** Align by first asterisk.
 *
 */

newlines.alwaysBeforeTopLevelStatements

Default: false
// newlines.alwaysBeforeTopLevelStatements = false
import org.scalafmt
package P {
  object O {
    val x1 = 1
    val x2 = 2
    def A = "A"
    def B = "B"
  }
}

// newlines.alwaysBeforeTopLevelStatements = true
import org.scalafmt

package P {

  object O {
    val x1 = 1
    val x2 = 2

    def A = "A"

    def B = "B"
  }
}

newlines.sometimesBeforeColonInMethodReturnType

Default: true
// Column limit                                                     |
// newlines.sometimesBeforeColonInMethodReturnType = true
implicit def validatedInstances[E](implicit E: Semigroup[E])
  : Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] = 2

// newlines.sometimesBeforeColonInMethodReturnType = false
implicit def validatedInstances[E](implicit E: Semigroup[E]): Traverse[
    Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] = 2

binPack.parentConstructors

Default: false
// column limit                        |
// binPack.parentConstructors = false
object DefaultStyle
    extends Parent
    with SecondParent
    with ThirdParent {
  // body ...
}

// column limit                        |
// bin.packParentConstructors = true
object DefaultStyle
    extends Parent with SecondParent
    with ThirdParent {
  // body ...
}

lineEndings

Default: unix

includeCurlyBraceInSelectChains

Default: true
// includeCurlyBraceInSelectChains = true
List(1)
  .map { x =>
    x + 2
  }
  .filter(_ > 2)

// includeCurlyBraceInSelectChains = false
List(1).map { x =>
    x + 2
}.filter(_ > 2)
For more details, see this comment.

optIn.breakChainOnFirstMethodDot

Default: true

If true, forces a select chain (pipeline) to break if there is a newline at the start of the chain.

// original
foo
  .map(_ + 1)
  .filter( > 2)

// optIn.breakChainOnFirstMethodDot = true
foo
  .map(_ + 1)
  .filter( > 2)

// optIn.breakChainOnFirstMethodDot = false
foo.map(_ + 1).filter( > 2)
// note. chain starts at .foo() in a.b.foo()

See this comment for further motivation.

newlines.penalizeSingleSelectMultiArgList

Default: true
// newlines.penalizeSingleSelectMultiArgList = true
logger.elem(a,
            b,
            c)

// newlines.penalizeSingleSelectMultiArgList = false
logger
  .elem(a, b, c)

See this comment for further motivation.

binPack.literalArgumentLists

Default: true
// binPack.literalArgumentLists = true
val secret: List[Bit] = List(0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1,
  0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
  0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1)

// binPack.literalArgumentLists = false
val secret: List[Bit] = List(
  0,
  0,
  1,
  1,
  // really long list...
  1
)

runner.optimizer.forceConfigStyleOnOffset

Default: 150

Set to -1 to disable. Increase number to require bigger argument bodies to trigger flag.

// Before: Argument body is too big
Account(userName = "user",
        fullName = "user@localhost",
        mailAddress = "",
        password = "",
        isAdmin = false,
        url = None,
        registeredDate = new Date(),
        updatedDate = new Date(),
        lastLoginDate = None,
        image = image,
        isGroupAccount = false,
        isRemoved = false)
// After: "config style"
Account(
  userName = "user",
  fullName = "user@localhost",
  mailAddress = "",
  password = "",
  isAdmin = false,
  url = None,
  registeredDate = new Date(),
  updatedDate = new Date(),
  lastLoginDate = None,
  image = image,
  isGroupAccount = false,
  isRemoved = false
)

Set runner.optimizer.forceConfigStyleMinArgCount = 1 to enable this rule for function calls with only 1 argument (default = 2).

By forcing config style, scalafmt is able to greatly optimize performance eliminating a large number of "search state exploded" errors. See these flame graphs.

rewrite.rules

Default: disabled

To enable a rewrite rule, add it to the config like this rewrite.rules = [SortImports].

AvoidInfix

a success b
a error (b, c)
a map { x =>
  x + 2
}
"o" % "a" % "v" c(D)
future recover {
  case e: Err => 0
} map (_.toString)
a.success(b)
a.error(b, c)
a.map { x =>
  x + 2
}
("o" % "a" % "v").c(D)
future
  .recover {
    case e: Err => 0
  }
  .map(_.toString)
For more examples, see this diff. Configuration contains include/exclude operator filters (those values are build in, and can't be configured outside)

ExpandImportSelectors

import a.{
    b,
    c
  }, h.{
    k, l
  }
  import d.e.{f, g}
  import a.{
      foo => bar,
      zzzz => _,
      _
    }

import a.b
import a.c
import h.k
import h.l
import d.e.f
import d.e.g
import a.{foo => bar, zzzz => _, _}

RedundantBraces

object RedundantBraces {
  def foo = {
    List(1, 2, 3).sum
  }

  // stringInterpolation = true
  q"Hello ${name}"
}
object RedundantBraces {
  def foo =
    List(1, 2, 3).sum

  // stringInterpolation = true
  q"Hello $name"
}
Configuration options and default values:

RedundantParens

Removes redundant parentheses in guard clauses.

object RedundantParenthesis {
  def c(b: List[Int]): List[Int] =
    for {
      a <- b
      if (a.nonEmpty)
    } yield a
}
object RedundantParenthesis {
  def c(b: List[Int]): List[Int] =
    for {
      a <- b
      if a.nonEmpty
    } yield a
}

SortImports

The imports are sorted by the groups: symbols, lower-case, upper-case.

import foo.{Zilch, bar, Random, sand}
import foo.{bar, sand, Random, Zilch}

AsciiSortImports

The imports are sorted by their Ascii codes

import foo.{~>, `symbol`, bar, Random}
import foo.{Random, `symbol`, bar, ~>}

PreferCurlyFors

Replaces parentheses into curly braces in for comprehensions that contain multiple enumerator generators.

object a {
  for(a <- as; b <- bs if b > 2)
    yield (a, b)
}
object a {
  for {
    a <- as
    b <- bs if b > 2
  } yield (a, b)
}

project

Configure which source files should be formatted in this project.

# Only format files tracked by git.
project.git = true
# manually exclude files to format.
project.excludeFilters = [
   regex1
   regex2
]
# manually include files to format.
project.includeFilters = [
  regex1
  regex2
]

Other

Scalafmt has a ton of internal configuration options which may be removed without notice. However, just in case you want to try them out, here they are.
maxColumn = 80
onTestFailure = 
project.git = false
project.files = []
project.includeFilters = [".*\.scala$"
  ".*\.sbt$"]
project.excludeFilters = []
align.openParenCallSite = true
align.openParenDefnSite = true
align.ifWhileOpenParen = true
align.treeCategory.Defn.Trait = class/object/trait
align.treeCategory.Enumerator.Val = for
align.treeCategory.Defn.Class = class/object/trait
align.treeCategory.Defn.Object = class/object/trait
align.treeCategory.Defn.Val = val/var/def
align.treeCategory.Defn.Def = val/var/def
align.treeCategory.Defn.Var = val/var/def
align.treeCategory.Enumerator.Generator = for
align.arrowEnumeratorGenerator = false
align.tokens = [code = "=>"
  owner = Case]
continuationIndent.callSite = 2
continuationIndent.defnSite = 4
continuationIndent.extendSite = 4
optIn.configStyleArguments = true
optIn.breakChainOnFirstMethodDot = true
optIn.selfAnnotationNewline = true
optIn.annotationNewlines = true
assumeStandardLibraryStripMargin = false
runner.optimizer.maxEscapes = 16
runner.optimizer.dequeueOnNewStatements = true
runner.optimizer.maxVisitsPerToken = 513
runner.optimizer.acceptOptimalAtHints = true
runner.optimizer.maxDepth = 100
runner.optimizer.forceConfigStyleMinArgCount = 2
runner.optimizer.disableOptimizationsInsideSensitiveAreas = true
runner.optimizer.forceConfigStyleOnOffset = 150
runner.optimizer.recurseOnBlocks = true
runner.optimizer.escapeInPathologicalCases = true
runner.optimizer.pruneSlowStates = true
runner.eventCallback = org.scalafmt.config.ScalafmtRunner$$$Lambda$3947/66207294@65ebf4fe
runner.parser = scala.meta.internal.parsers.ScalametaParser$$anon$202@3b5bd94a
runner.debug = false
runner.fatalWarnings = false
runner.maxStateVisits = 1000000
runner.ignoreWarnings = false
runner.dialect = Dialect(true, true, true, true, true, true, true, true, false, true, false, false, true, true, true, true, true, )
encoding = UTF-8
newlines.afterImplicitKWInVerticalMultiline = false
newlines.neverInResultType = false
newlines.sometimesBeforeColonInMethodReturnType = true
newlines.alwaysBeforeTopLevelStatements = false
newlines.afterCurlyLambda = never
newlines.penalizeSingleSelectMultiArgList = true
newlines.neverBeforeJsNative = false
newlines.alwaysBeforeCurlyBraceLambdaParams = false
newlines.beforeImplicitKWInVerticalMultiline = false
version = 1.0.0-RC4
unindentTopLevelOperators = false
poorMansTrailingCommasInConfigStyle = false
indentOperator.include = ".*"
indentOperator.exclude = "^(&&|\|\|)$"
docstrings = ScalaDoc
lineEndings = unix
rewrite.rules = []
rewrite.redundantBraces.includeUnitMethods = true
rewrite.redundantBraces.maxLines = 100
rewrite.redundantBraces.stringInterpolation = false
rewrite.neverInfix.includeFilters = ["[\w\d_]+"]
rewrite.neverInfix.excludeFilters = [until
  to
  by
  eq
  ne
  should.*
  contain.*
  must.*
  in
  be
  taggedAs
  thrownBy
  synchronized
  have
  when]
danglingParentheses = false
includeCurlyBraceInSelectChains = true
binPack.literalsInclude = [".*"]
binPack.literalsExclude = [String
  Term.Name]
binPack.literalsMinArgCount = 5
binPack.unsafeCallSite = false
binPack.unsafeDefnSite = false
binPack.literalArgumentLists = true
binPack.parentConstructors = false
indentYieldKeyword = true
importSelectors = noBinPack
verticalMultilineAtDefinitionSite = false
spaces.neverAroundInfixTypes = []
spaces.beforeContextBoundColon = Never
spaces.afterTripleEquals = false
spaces.inImportCurlyBraces = false
spaces.inParentheses = false

Gotchas


Scalafmt tries to automatically reformat as much as possible. However, sometimes you need to help scalafmt decide how to format your code.

Infix applications

Infix applications are methods calls that use the syntax like a + b instead of a.+(b). Scalafmt preserves your line breaks in infix applications, even if this means the maxColumn setting is not respected.
// column limit |
// if you have long infix appplications
a.b(c) && d.e(f, g, h)
// then scalafmt may format like this
a.b(c) && d.e(
  f, g, h)
// which is ugly. You can fix it by inserting
// a newline after && and it will look like this
a.b(c) &&
  d.e(f, g, h)

Config style

You can use "config style" to tell scalafmt to break a function application.
// Put newline after opening (
// and newline before closing )
// to force one argument on each line.

// OK: Config style
function(
  longerArg1 = defaultValue1,
  longerArg2 = defaultValue2,
  longerArg3 = defaultValue3
)
// NOT Config style
function(longerArg1 = defaultValue1,
         longerArg2 = defaultValue2,
         longerArg3 = defaultValue3)

Community


Related projects

Have a scalafmt related project? Please consider opening a pull request to list it here:

Adopters

Are you using scalafmt? Please consider opening a pull request to list your organization here: Here are the download numbers from Maven Central. Here are the download numbers for the IntelliJ plugin.

FAQ / Troubleshooting


Why not Scalariform?

Scalariform does an excellent job of tidying up common formatting errors. However, Finally, scalafmt is my Master's thesis project. I thought it would be a fun challenge to write a code formatter :)

Why is scalafmt so slow?

My benchmarks show that scalafmt is for most common cases around 4-6x slower than scalariform (btw, scalariform is already impressively fast). This means that formatting your average 1.000 LOC file on modern hardware will take around 200ms, which should still feel close enough to instant.

The main feature that makes scalafmt slower than scalariform is the column-width limit. To figure the "best" way to break a long line, Scalafmt may try thousands of different formatting solutions.

I am sure that scalafmt could benefit greatly from micro optimizations. Any help here is appreciated.

Code formatters create unnecessary diffs!

That's not a question, but I agree that code formatters like scalafmt do sometimes increase the size of diffs in code reviews. I still believe it's worth it, considering

  1. Proper formatting helps you catch bugs!
  2. you can enable non-whitespace diffs during code review. For Github, add ?w=1 to the URL to ignore whitespace changes.
  3. git blame has a -w flag to ignore whitespace changes so you can still blame your colleagues for their crappy code.
  4. code is read waaay more often outside of code reviews, for example when you are actually coding.

Is the formatting output stable between releases?

No, the formatting rules will evolve even between PATCH releases. I recommend you inspect the diff for every scalafmt update.

Known issues


Developing code formatters is notoriously hard and scalafmt has been no exception. The following are the biggest known issues with scalafmt:

Deeply nested code

AKA. "Search state exploded"

0.5.0 made big improvements on this issue. In my test corpus, only 13 out of 27.000 source files trigger this error now.

Scalafmt cannot yet format all files with deeply nested functions calls. Deeply nested code is troublesome because the number of possible formatting options grows exponentially with each new layer of nesting. Instead of taking seconds or minutes to complete formatting, scalafmt chooses to bail early and leave the source file unformatted.

There are two workaround if you are affected by this issue:

Other cool code formatters like ClangFormat, dartfmt and rfmt use better techniques to solve this issue, which scalafmt can maybe learn from.

Non-idempotent

Scalafmt is non-idempotent for certain files. See #339. This means you should be careful about enforcing scalafmt in your CI build.

In my test corpus, as of v0.5.0, only 12 files out of 27.000 source files are affected by this issue. If sources are already formatted by scalafmt, no source file in the test corpus triggers non-idempotent formatting.

Pro tip. As awkward as I feel recommending this, you may want to run scalafmt twice on your codebase for the first time you reformat it.

Performance

Scalafmt is 6x slower than Scalariform. For 98% of source files this won't be a problem if you have a decently modern laptop. However, if you only work in files with 4.000 LOC it might be a problem. I'm quite sure that micro-optimizations can squeeze out at least ~2x performance improvements, maybe even more. Moreover, I think incremental formatting has the possibility to increase the performance by several orders of magnitude in interactive IDE environments where scalafmt is invoked on file save.

Changelog


1.0.x

1.0.0-RC4

1.0.0-RC3

If no major issues are reported within one week of this release, then it will be promoted to v1.0. PS. If you are using sbt-scalafmt, please give neo-sbt-scalafmt a try!

1.0.0-RC2

See 1.0.0-RC3

1.0.0-RC1

See 1.0.0-RC3

0.7.x

0.7.0-RC1

NOTE. BROKEN RELEASE, use 1.0.0-RC1 instead. See #943 and https://issues.sonatype.org/browse/OSSRH-31815.

0.6.x

0.6.8

0.6.7

All of the fixes in this release are contributed by @pjrt, awesome work!

0.6.6

Fix concurrency bug in sbt-scalafmt.

0.6.5

Try to fix concurrency bug in sbt-scalafmt.

0.6.4

Try to fix concurrency bug in sbt-scalafmt.

0.6.3

0.6.2

0.6.1

0.6.0

Merged PRs: https://github.com/scalameta/scalafmt/milestone/14?closed=1.

3 million lines reformatted with 0.6.1 compared to 0.5.8: scala-repos#20

0.5.x

0.5.8

Merged PRs: https://github.com/scalameta/scalafmt/milestone/10?closed=1. Big thanks to @dwijnand and @tgodzik for contributing 5 and 2 pull requests each, respectively!

0.5.6

Merged PRs: https://github.com/scalameta/scalafmt/milestone/11?closed=1.

0.5.5

0.5.4

0.5.3

0.5.2

This release was made possible with contributions from 7 new contributors. Big thanks to @avdv, @pjrt, @MasseGuillaume, @mpociecha, @rbellamy, @ysusuk and @dguo-coursera! Also thanks to everyone who reported issues.

0.5.1

0.5.0

0.4.x

0.4.10

0.4.9

0.4.8

0.4.7

0.4.6

0.4.5

0.4.4

0.4.3

Big thanks to @cb372, @phalodi and @caoilte for contributing to this release!

0.4.2

0.4.1

0.4.0

Big thanks to everyone who contributed to this release: @mmatloka, @melrief, @stefanobaghino, @johnynek, @RatanRSur, @Gmadorell, @Synesso, @Lambdista and @easel

0.3.x

0.3.1

0.3.0

I'm really excited to announce this release with lots of new features and improvements.

0.2.x

0.2.12

0.2.11

0.2.10

0.2.9

0.2.8

0.2.7

Skipping, messed up Sonatype release.

0.2.6

0.2.5

0.2.4

0.2.3

0.2.2

NOTE. This release contains a bug, see #192. Please hold off from upgrading.

This release changes the formatting rules for many small cases. I recommend you reformat your whole project in one commit.

0.2.1

0.2.0

0.1.x

0.1.6

0.1.5

0.1.4

0.1.3

0.1.2

0.1.1

This page was last updated on Jun 18, 2017.

Fork me on GitHub