Scalafmt


1.5.1

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

NOTE To install Coursier see here

Create a standalone executable in /usr/local/bin/scalafmt with (sudo if necessary):

coursier bootstrap com.geirsson:scalafmt-cli_2.12:1.5.1 \
  -r bintray:scalameta/maven \
  -o /usr/local/bin/scalafmt --standalone --main org.scalafmt.cli.Cli
scalafmt --version # should be 1.5.1

Alternatively you can create a slim 15 KiB bootstrap script with:

coursier bootstrap com.geirsson:scalafmt-cli_2.12:1.5.1 \
  -r bintray:scalameta/maven \
  -o scalafmt --main org.scalafmt.cli.Cli
./scalafmt --version # should be 1.5.1
It is recommended to put this bootstrap script in your code repository to make sure everyone on your team, as well as CI, uses the same scalafmt version. To configure which files to format, see project.

To customize the JVM options, use the Coursier option --java-opt, more info with

coursier bootstrap --help | grep -A 1 "\-\-java-opt"

Pre-release

Our CI publishes a pre-release version of scalafmt to Bintray on every merge into master. To use a pre-release, replace 1.5.1 with the version here:

If you use coursier to install a pre-release, be sure to include the flag -r bintray:scalameta/maven so that the artifact can be resolved.

If you use sbt to install a pre-release, be sure to add the following setting

resolvers += Resolver.bintray("scalameta", "maven")

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 formula
brew install --HEAD olafurpg/scalafmt/scalafmt
scalafmt --version // should be 1.5.1

// 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: d8caf40df4dc8ed8de1a92bc1405064028e1ef00
build time: Thu May 17 15:32:32 UTC 2018
scalafmt 1.5.1-111-d8caf40d
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>
                           when using --stdin, use --assume-filename to hint to scalafmt that the input is an .sbt file.
  --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 < foo.sbt # required when using --stdin 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

Please upvote this Jetbrains ticket about adding built-in support for Scalafmt in the IntelliJ Scala plugin.
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

// In project/plugins.sbt. Note, does not support sbt 0.13, only sbt 1.0.
addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.1")
The plugin provides several tasks and settings.
object autoImport {
  val scalafmt = taskKey[Unit]("Format Scala sources with scalafmt.")
  val scalafmtCheck =
    taskKey[Boolean](
      "Fails if a Scala source is mis-formatted. Does not write to files.")
  val scalafmtOnCompile =
    settingKey[Boolean](
      "Format Scala source files on compile, off by default.")
  val scalafmtConfig = taskKey[Option[File]](
    "Optional location of .scalafmt.conf file. " +
      "If None the default config is used.")
  val scalafmtSbt = taskKey[Unit](
    "Format *.sbt and project/*.scala files for this sbt build.")
  val scalafmtSbtCheck =
    taskKey[Boolean](
      "Fails if a *.sbt or project/*.scala source is mis-formatted. " +
        "Does not write to files.")
  val scalafmtOnly = inputKey[Unit]("Format a single given file.")
}
The sbt plugin is enabled by default for the Test and Compile configurations. To enable the plugin for integration tests
inConfig(IntegrationTest)(scalafmtConfigSettings)
and then use it:scalafmt to format.

Pro tip. To share configuration across projects, you can define a setting in build.sbt to generate .scalafmt.conf programmatically on sbt load.

// define setting key to write configuration to .scalafmt.conf
SettingKey[Unit]("scalafmtGenerateConfig") :=
  IO.write( // writes to file once when build is loaded
    file(".scalafmt.conf"),
    """style = IntelliJ
      |# Your configuration here
      """.stripMargin.getBytes("UTF-8")
  )

neo-sbt-scalafmt

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

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:

Mill

Mill have scalafmt support built-in:

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.5.1"
// Scala.js
libraryDependencies += "com.geirsson" %%% "scalafmt-core" % "1.5.1"

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

Obtain a configuration object with parseHoconConfig

scala> val config = org.scalafmt.Scalafmt.parseHoconConfig("align=most").get
scala> org.scalafmt.Scalafmt.format("""
       object Align {
         val x = 1
         val xx = 2
      }""", config).get
res0: java.lang.String = 
"object Align {
  val x  = 1
  val xx = 2
}
"

To format code with top-level statements like *.sbt files

scala> val base = org.scalafmt.Scalafmt.parseHoconConfig("align=most").get
scala> val config = org.scalafmt.Scalafmt.configForSbt(base)
scala> org.scalafmt.Scalafmt.format("""
         val x = 1
         val xx = 2
      """, config).get
res0: java.lang.String = 
"val x  = 1
val xx = 2
"
The Scalafmt public API consists only of methods in org.scalafmt.Scalafmt. In particular, case classes in org.scalafmt.config are subject to binary and source breaking changes on any release.

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.

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

Most Popular

maxColumn

Default: 80

docstrings

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

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

assumeStandardLibraryStripMargin

Default: false
May cause non-idempotent formatting in rare cases, see #192.

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
}

Indentation

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

Alignment

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
Pro tip: Enable this setting to minimize git diffs/conflicts from renamings and other refactorings.

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:3.7.4`, 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)

align.openParenDefnSite

Default: true
// align.openParenDefnSite = true
// Column limit                          |
class IntString(int: Int, string: String)

class IntStringLong(int: Int,
                    string: String,
                    long: Long)

// align.openParenDefnSite = false
// Column limit                          |
class IntString(int: Int, string: String)
class IntStringLong(
  int: Int,
  string: String,
  long: Long
)

Newlines

The newlines.* options are used to configure when and where scalafmt should insert newlines.
You might be interested in the Vertical Multiline section.

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

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.

newlines.alwaysBeforeElseAfterCurlyIf

Default: false
// newlines.alwaysBeforeElseAfterCurlyIf = true
if(someCond) {
  foo()
}
else {
  bar()
}

// newlines.alwaysBeforeElseAfterCurlyIf = false
if(someCond) {
  foo()
} else {
  bar()
}

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)
Show/hide configuration used for this example
rewrite.rules = [
  avoidinfix
]
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 => _, _}
Show/hide configuration used for this example
rewrite.rules = [
  expandimportselectors
]

RedundantBraces

Warning. This rewrite can cause Non-idempotent formatting, see #1055.
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"
}
Show/hide configuration used for this example
rewrite.rules = [
  redundantbraces
]
rewrite.redundantBraces.stringInterpolation = true
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
}
Show/hide configuration used for this example
rewrite.rules = [
  redundantparens
]

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}
Show/hide configuration used for this example
rewrite.rules = [
  sortimports
]

AsciiSortImports

The imports are sorted by their Ascii codes

import foo.{~>, `symbol`, bar, Random}
import foo.{Random, `symbol`, bar, ~>}
Show/hide configuration used for this example
rewrite.rules = [
  asciisortimports
]

SortModifiers

Modifiers are sorted based on the given order. Affects modifiers of the following definitions: trait, class, object, type, and val+var, both as fields and class parameters.

//before
final lazy private implicit val x = 42
lazy final implicit private val y = 42

//after
private final implicit lazy val x = 42
private final implicit lazy val y = 42
//before
class Test(
  implicit
  final private val i1: Int,
  private final val i2: String
)

//after
class Test(
    implicit
    private final val i1: Int,
    private final val i2: String
)
//before
object X {
  sealed protected[X] trait ADT
  final private case object A1 extends ADT
  private final case class A2(x: Int) extends ADT
}

//after
object X {
  protected[X] sealed trait ADT
  private final case object A1 extends ADT
  private final case class A2(x: Int) extends ADT
}
If you choose the non-default sort order then you have to specify all eight modifiers in the order you wish to see them. Hint: since some modifiers are mutually exclusive, you might want to order them next to each other.

Example config:

rewrite {
  rules = [SortModifiers]
  #optional, see default values below
  sortModifiers {
    order = ["implicit", "final", "sealed", "abstract",
             "override", "private", "protected", "lazy"]
  }
}

Default values:

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)
}
Show/hide configuration used for this example
rewrite.rules = [
  prefercurlyfors
]

Vertical Multiline

If enabled this formats methods such that parameters are on their own line indented by continuationIndent.defnSite. Separation between parameter groups are indented by two spaces less than continuationIndent.defnSite. The return type is on its own line at then end.

This formatting is only triggered if the method definition exceeds the maxColumn value in width or if the number of arguments to the method exceeds the verticalMultiline.arityThreshold.
object a {
  def format(code: String, age: Int)(implicit ev: Parser, c: Context): String
}
object a {
  def format(
      code: String,
      age: Int
    )(implicit ev: Parser,
      c: Context
    ): String
}
Show/hide configuration used for this example
maxColumn = 60
verticalMultiline.atDefnSite = true
This setting ignores binPack.unsafeDefnSite, and align.openParenDefnSite.

The default configuration options are

verticalMultiline.atDefnSite = false
verticalMultiline.arityThreshold = 100
verticalMultiline.newlineBeforeImplicitKW = false
verticalMultiline.newlineAfterImplicitKW = false
verticalMultiline.newlineAfterOpenParen = false
verticalMultiline.excludeDanglingParens = [
  class
  trait
]

verticalMultiline.atDefnSite

Default: false

If true, enable vertical multiline formatting as described above.

verticalMultiline.arityThreshold

Default: 100

If set, this will trigger a vertical multi-line formatting even though the definition falls below the maxColumn width.

case class Foo(x: String)
case class Bar(x: String, y: String)
object A {
  def foo(x: String, y: String)
  def hello(how: String)(are: String)(you: String) = how + are + you
}
case class Foo(x: String)
case class Bar(
    x: String,
    y: String)
object A {
  def foo(
      x: String,
      y: String
    )
  def hello(how: String)(are: String)(you: String) = how + are + you
}
Show/hide configuration used for this example
verticalMultiline.atDefnSite = true
verticalMultiline.arityThreshold = 2

verticalMultiline.newlineAfterOpenParen

Default: false

If true, add a newline after the opening paren of a parameter list. This can be used to control the formatting of methods that have multiple parameter lists.

object a {
  def other(a: String, b: String)(c: String) = a + b + c
}
object a {
  def other(
    a: String,
    b: String
  )(
    c: String
  ) = a + b + c
}
Show/hide configuration used for this example
continuationIndent.defnSite = 2
verticalMultiline.atDefnSite = true
verticalMultiline.arityThreshold = 2
verticalMultiline.newlineAfterOpenParen = true

verticalMultiline.newlineBeforeImplicitKW

Default: false

If true, add a newline before an implicit keyword in function and class definitions.
object a {
  def format(code: String, age: Int)(implicit ev: Parser, c: Context): String
}
object a {
  def format(
      code: String,
      age: Int
    )(
      implicit ev: Parser,
      c: Context
    ): String
}
Show/hide configuration used for this example
maxColumn = 60
verticalMultiline.atDefnSite = true
verticalMultiline.newlineBeforeImplicitKW = true

verticalMultiline.newlineAfterImplicitKW

Default: false

If true, add a newline after an implicit keyword in function and class definitions.
object a {
  def format(code: String, age: Int)(implicit ev: Parser, c: Context): String
}
object a {
  def format(
      code: String,
      age: Int
    )(implicit
      ev: Parser,
      c: Context
    ): String
}
Show/hide configuration used for this example
maxColumn = 60
verticalMultiline.atDefnSite = true
verticalMultiline.newlineAfterImplicitKW = true

verticalMultiline.excludeDanglingParens

Default: class,trait

This setting defines which cases should be allowed to have dangling parens.

case class Bar(x: String, y: String)
case class Bar(
  x: String,
  y: String
)
Show/hide configuration used for this example
continuationIndent.defnSite = 2
verticalMultiline.atDefnSite = true
verticalMultiline.arityThreshold = 2
verticalMultiline.excludeDanglingParens = []

newlines.alwaysBeforeMultilineDef

Default: true

If true, add a newline before the body of a multiline def without curly braces.

object a {
  def foo(bar: Bar): Foo = bar
    .flatMap(f)
    .map(g)
}
object a {
  def foo(bar: Bar): Foo =
    bar
      .flatMap(f)
      .map(g)
}
Show/hide configuration used for this example
maxColumn = 60
verticalMultiline.atDefnSite = true

Disabling Formatting

// 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.

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
]

Miscellaneous

lineEndings

Default: unix

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
)

binPack.parentConstructors

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

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

spaces.afterKeywordBeforeParen

Default: true
// spaces.afterKeywordBeforeParen = true
if (a) foo()
while (a) foo()
for (a <- as) foo()

// spaces.afterKeywordBeforeParen = false
if(a) foo()
while(a) foo()
for(a <- as) foo()

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.

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.

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

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

Other

To find all available configuration options, it's best to browse the source code of Scalafmt. A good place to start is ScalafmtConfig. Observe that this listing below is the top-level, there are more configuration options if you visited nested fields like spaces and newlines.

version = "1.5.1"
maxColumn = 80
docstrings = scaladoc
optIn.configStyleArguments = true
optIn.breaksInsideChains = false
optIn.breakChainOnFirstMethodDot = true
optIn.selfAnnotationNewline = true
optIn.annotationNewlines = true
optIn.blankLineBeforeDocstring = false
binPack.unsafeCallSite = false
binPack.unsafeDefnSite = false
binPack.parentConstructors = false
binPack.literalArgumentLists = true
binPack.literalsMinArgCount = 5
binPack.literalsInclude = [
  ".*"
]
binPack.literalsExclude = [
  String
  "Term.Name"
]
continuationIndent.callSite = 2
continuationIndent.defnSite = 4
continuationIndent.extendSite = 4
align.openParenCallSite = true
align.openParenDefnSite = true
align.tokens = [
  {
    code = "=>"
    owner = Case
  }
]
align.arrowEnumeratorGenerator = false
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
spaces.beforeContextBoundColon = never
spaces.afterTripleEquals = false
spaces.inImportCurlyBraces = false
spaces.inParentheses = false
spaces.neverAroundInfixTypes = []
spaces.afterKeywordBeforeParen = true
spaces.inByNameTypes = true
literals.long = upper
literals.float = lower
literals.double = lower
lineEndings = unix
rewrite.rules = []
rewrite.redundantBraces.methodBodies = true
rewrite.redundantBraces.includeUnitMethods = true
rewrite.redundantBraces.maxLines = 100
rewrite.redundantBraces.stringInterpolation = false
rewrite.redundantBraces.generalExpressions = false
rewrite.sortModifiers.order = [
  implicit
  final
  sealed
  abstract
  override
  private
  protected
  lazy
]
rewrite.neverInfix.includeFilters = [
  "[\w\d_]+"
]
rewrite.neverInfix.excludeFilters = [
  until
  to
  by
  eq
  ne
  "should.*"
  "contain.*"
  "must.*"
  in
  be
  taggedAs
  thrownBy
  synchronized
  have
  when
  size
]
indentOperator.include = ".*"
indentOperator.exclude = "^(&&|\|\|)$"
newlines.neverInResultType = false
newlines.neverBeforeJsNative = false
newlines.sometimesBeforeColonInMethodReturnType = true
newlines.penalizeSingleSelectMultiArgList = true
newlines.alwaysBeforeCurlyBraceLambdaParams = false
newlines.alwaysBeforeTopLevelStatements = false
newlines.afterCurlyLambda = never
newlines.afterImplicitKWInVerticalMultiline = false
newlines.beforeImplicitKWInVerticalMultiline = false
newlines.alwaysBeforeElseAfterCurlyIf = false
newlines.alwaysBeforeMultilineDef = true
runner.debug = false
runner.eventCallback = "<FormatEvent => Unit>"
runner.parser = "<Parse[Tree]>"
runner.optimizer.dequeueOnNewStatements = true
runner.optimizer.escapeInPathologicalCases = true
runner.optimizer.maxVisitsPerToken = 513
runner.optimizer.maxEscapes = 16
runner.optimizer.maxDepth = 100
runner.optimizer.acceptOptimalAtHints = true
runner.optimizer.disableOptimizationsInsideSensitiveAreas = true
runner.optimizer.pruneSlowStates = true
runner.optimizer.recurseOnBlocks = true
runner.optimizer.forceConfigStyleOnOffset = 150
runner.optimizer.forceConfigStyleMinArgCount = 2
runner.maxStateVisits = 1000000
runner.dialect = "<Dialect>"
runner.ignoreWarnings = false
runner.fatalWarnings = false
indentYieldKeyword = true
importSelectors = nobinpack
unindentTopLevelOperators = false
includeCurlyBraceInSelectChains = true
assumeStandardLibraryStripMargin = false
danglingParentheses = false
poorMansTrailingCommasInConfigStyle = false
trailingCommas = preserve
verticalMultilineAtDefinitionSite = false
verticalMultilineAtDefinitionSiteArityThreshold = 100
verticalMultiline.atDefnSite = false
verticalMultiline.arityThreshold = 100
verticalMultiline.newlineBeforeImplicitKW = false
verticalMultiline.newlineAfterImplicitKW = false
verticalMultiline.newlineAfterOpenParen = false
verticalMultiline.excludeDanglingParens = [
  class
  trait
]
onTestFailure = ""
encoding = "UTF-8"
project.git = false
project.files = []
project.includeFilters = [
  ".*\.scala$"
  ".*\.sbt$"
  ".*\.sc$"
]
project.excludeFilters = []

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.

Which configuration options minimize diffs/conflicts in version control?

  1. align=none If alignment is enabled a renaming of one entity can impact the indentation of other entities.
  2. danglingParenthesis=true Having the closing parenthesis on the same line as the last argument makes the diff line include the parenthesis and everything following it in case that argument is renamed. So, technically this does not reduce the number of diff lines, but the length of them.

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


v1

1.5.1

1.5.0

Big thanks to all contributors!

1.4.0

See merged PRs.

1.3.0

1.2.0

See merged PRs.

1.1.0

1.0.0

This release was identical to 1.0.0-RC4.

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 May 17, 2018.

Fork me on GitHub