Scalafmt Documentation
repository·main·Indexed 23 days ago
https://github.com/scalameta/scalafmtA code formatter for the Scala programming language designed to enforce consistent coding styles. It includes a CLI tool for formatting source files, support for various Scala dialects (Scala 2, Scala 3, and sbt), and a comprehensive configuration system via .scalafmt.conf using HOCON syntax to control indentation, line length (maxColumn), and alignment presets.
What's inside Scalafmt
- Scalafmt is a code formatter for Scala. It helps maintain consistent code style across Scala projects. For detailed installation instructions and usage guides, refer to the official user documentation.
Convert to Scala 3 new syntax
mainIf
rewrite.scala3.convertToNewSyntaxis enabled, Scalafmt will apply new Scala 3 syntax rules. This is applied when the appropriate dialect is selected (e.g.,runner.dialect = scala3).Supported rewrites include:
- Control syntax:
if (...)toif ... then,while (...)towhile ... do, andfor (...)tofor ... do(if the dialect setsallowSignificantIndentationand...newSyntax.controlis set). - Vararg splices:
: _*or@ _*to*(if dialect setsallowPostfixStarVarargSplicesand...newSyntax.deprecatedis set). - Imports: wildcard
_to*and rename=>toas(if dialect setsallowStarWildcardImport/allowAsForImportRenameand...newSyntax.deprecatedis set). - Wildcards: type wildcard
_to?(if dialect setsallowQuestionMarkAsTypeWildcardand...newSyntax.deprecatedis set). - Anonymous type params:
*to_(if dialect setsallowUnderscoreAsTypePlaceholder).
- Control syntax:
Understand Scalafmt interval checks
mainIn v3.11.2, many parameters were converted to intervals using
minandmaxbounds.An interval check is considered enabled if at least one of
minormaxis non-negative. A value satisfies the check if:minis negative OR the value is $\ge$min.maxis negative OR the value is $\le$max.
Note on the deprecated Edition setting
mainTheeditionsetting was removed in version 2.7.0. While it is kept for backwards compatibility with old configuration files, new changes to Scalafmt's default formatting behavior will not respect theeditionsetting.Understand Scalafmt performance characteristics
mainScalafmt is designed for correctness, which can result in slower performance compared to other formatters like Scalariform. While performance is typically negligible for most files on modern hardware, very large files (e.g., ~4,000 LOC) may experience noticeable delays. Future improvements aim to implement incremental formatting to significantly increase performance in interactive IDE environments.Configure Vertical Multiline formatting
mainVertical multiline formatting (since v1.6.0) ensures that method parameters are placed on their own lines, indented by
indent.defnSite. This is triggered if the method definition exceedsmaxColumnor if the number of arguments exceedsverticalMultiline.arityThreshold.Key parameters:
verticalMultiline.atDefnSite: Enables vertical multiline at the definition site.verticalMultiline.arityThreshold: The number of arguments that triggers vertical multiline.verticalMultiline.newlineAfterOpenParen: If true, forces a newline after the opening parenthesis.verticalMultiline.excludeDanglingParens: (Deprecated in 3.4.0) UsedanglingParentheses.excludeinstead.
verticalMultiline.atDefnSite = true verticalMultiline.arityThreshold = 2 verticalMultiline.newlineAfterOpenParen = trueUse project.layout to automate dialect selection
mainThe
project.layoutsetting allows you to specify a project structure naming convention. This helps scalafmt automatically select the appropriate dialect for cross-building when usingfileOverride.Supported options:
StandardConvention(since v3.2.0): Assumes Scala source code is undersrc/main/scalaorsrc/test/scala, with alternate cross-build dialects insrc/main/scala-2.13.
If set, scalafmt will attempt to detect the dialect. If the detected dialect is compatible with the overall
runner.dialect, no changes are applied. It supports Scala 2.10-2.13 and Scala 3. For major Scala 2 versions, it selects the Scala 2.13 dialect.How the scalafmt formatting process works
mainThe scalafmt formatting process follows these stages:
- Code Parsing: Uses the
scalametaparser to generate an AST. Parsing errors originate from scalameta. - Format-agnostic Rewrites: Applies rules that do not depend on specific whitespace decisions.
- Preparing Whitespace Splits: Identifies possible whitespace options (newline, single space, or no space) between adjacent non-whitespace tokens, assigning penalties and policies to each.
- Route Search: An optimization step that searches for a path through tokens and splits that minimizes total penalty. It uses a priority queue of partial states, selecting the state with the lowest penalty and highest token offset (closest to completion).
- Output: Writes the code using the selected splits and performs format-dependent rewrites (e.g., inserting braces, adding/removing end markers, modifying blank lines, rewriting comments/docstrings, and handling trailing commas). Finally, it performs alignment to add horizontal space where possible.
- Code Parsing: Uses the
Optimize Scalafmt performance with parallelism in sbt
mainScalafmt performance can be tuned at two levels:
- Across tasks (subprojects/configurations): sbt runs tasks in parallel by default. You can limit the number of concurrent Scalafmt tasks using
ConcurrentRestrictionTagsinbuild.sbt:
import org.scalafmt.sbt.ConcurrentRestrictionTags Global / concurrentRestrictions += Tags.limit(org.scalafmt.sbt.ConcurrentRestrictionTags.Scalafmt, 4)- Within a task (across files): Use
scalafmtParallelismto format files within a single task concurrently. This is highly effective for large single-module projects or CI runs:
Global / scalafmtParallelism := 4Warning: High parallelism values can oversubscribe CPUs if other subprojects are also running in parallel. Also, if
scalafmtFailOnErrors = true, a task hitting an unparseable file will write none of its files.import org.scalafmt.sbt.ConcurrentRestrictionTags Global / concurrentRestrictions += Tags.limit(org.scalafmt.sbt.ConcurrentRestrictionTags.Scalafmt, 4)- Across tasks (subprojects/configurations): sbt runs tasks in parallel by default. You can limit the number of concurrent Scalafmt tasks using
Understand Scalafmt API stability and compatibility
mainWhen integrating Scalafmt, choose your API based on your stability requirements:
Stable Public APIs (Recommended)
org.scalafmt.interfaces: Pure Java APIs with no external dependencies. This is the recommended way to interact with Scalafmt via thescalafmt-dynamicmodule.org.scalafmt.Scalafmt: An older public API. While stable, it has limitations: it does not support theversionsetting in.scalafmt.conf, does not respectproject.excludeFilters, does not automatically handle*.sbtor*.scfiles, and does not cache.scalafmt.conf.
Internal APIs (Avoid)
The following are subject to binary breaking changes and should not be used by consumers:
org.scalafmt.dynamic: The private implementation ofscalafmt-interfaces.org.scalafmt.config: Case classes for.scalafmt.confintended for internal use only.org.scalafmt.cli: The private implementation of the command-line interface.
Install scalafmt pre-release versions
mainTo use a pre-release version of scalafmt (published to Sonatype Snapshots on every merge to master), replace
@STABLE_VERSION@with the specific snapshot version.- Using Coursier: You must include the
-r sonatype:snapshotsflag to resolve the artifact. - Using sbt: You must add the Sonatype snapshots resolver to your settings.
- Using Coursier: You must include the
Compile the Scalafmt project
mainThe project uses
sbtfor building. To run fast unit tests for the JVM, usesbt tests/test. Avoid usingsbt testunless you specifically need to run cross-platform Scala.js tests, benchmarks, or documentation compilation, as it is significantly slower.You can import the project into IntelliJ IDEA by selecting
File -> New -> Project from existing sourceand choosing thebuild.sbtfile.sbt tests/test