Scalafmt Documentation

repository·main·Indexed 23 days ago

https://github.com/scalameta/scalafmt

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

Tokens
28.8K
Snippets
75
Records
158
Agent score
80%

What's inside Scalafmt

  1. Convert to Scala 3 new syntax

    main

    If rewrite.scala3.convertToNewSyntax is 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 (...) to if ... then, while (...) to while ... do, and for (...) to for ... do (if the dialect sets allowSignificantIndentation and ...newSyntax.control is set).
    • Vararg splices: : _* or @ _* to * (if dialect sets allowPostfixStarVarargSplices and ...newSyntax.deprecated is set).
    • Imports: wildcard _ to * and rename => to as (if dialect sets allowStarWildcardImport/allowAsForImportRename and ...newSyntax.deprecated is set).
    • Wildcards: type wildcard _ to ? (if dialect sets allowQuestionMarkAsTypeWildcard and ...newSyntax.deprecated is set).
    • Anonymous type params: * to _ (if dialect sets allowUnderscoreAsTypePlaceholder).
  2. Understand Scalafmt interval checks

    main

    In v3.11.2, many parameters were converted to intervals using min and max bounds.

    An interval check is considered enabled if at least one of min or max is non-negative. A value satisfies the check if:

    1. min is negative OR the value is $\ge$ min.
    2. max is negative OR the value is $\le$ max.
  3. Understand Scalafmt performance characteristics

    main
    Scalafmt 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.
  4. Configure Vertical Multiline formatting

    main

    Vertical 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 exceeds maxColumn or if the number of arguments exceeds verticalMultiline.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) Use danglingParentheses.exclude instead.
    verticalMultiline.atDefnSite = true
    verticalMultiline.arityThreshold = 2
    verticalMultiline.newlineAfterOpenParen = true
  5. Use project.layout to automate dialect selection

    main

    The project.layout setting allows you to specify a project structure naming convention. This helps scalafmt automatically select the appropriate dialect for cross-building when using fileOverride.

    Supported options:

    • StandardConvention (since v3.2.0): Assumes Scala source code is under src/main/scala or src/test/scala, with alternate cross-build dialects in src/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.

  6. How the scalafmt formatting process works

    main

    The scalafmt formatting process follows these stages:

    1. Code Parsing: Uses the scalameta parser to generate an AST. Parsing errors originate from scalameta.
    2. Format-agnostic Rewrites: Applies rules that do not depend on specific whitespace decisions.
    3. Preparing Whitespace Splits: Identifies possible whitespace options (newline, single space, or no space) between adjacent non-whitespace tokens, assigning penalties and policies to each.
    4. 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).
    5. 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.
  7. Optimize Scalafmt performance with parallelism in sbt

    main

    Scalafmt performance can be tuned at two levels:

    1. Across tasks (subprojects/configurations): sbt runs tasks in parallel by default. You can limit the number of concurrent Scalafmt tasks using ConcurrentRestrictionTags in build.sbt:
    import org.scalafmt.sbt.ConcurrentRestrictionTags
    Global / concurrentRestrictions += Tags.limit(org.scalafmt.sbt.ConcurrentRestrictionTags.Scalafmt, 4)
    1. Within a task (across files): Use scalafmtParallelism to format files within a single task concurrently. This is highly effective for large single-module projects or CI runs:
    Global / scalafmtParallelism := 4

    Warning: 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)
  8. Understand Scalafmt API stability and compatibility

    main

    When integrating Scalafmt, choose your API based on your stability requirements:

    • org.scalafmt.interfaces: Pure Java APIs with no external dependencies. This is the recommended way to interact with Scalafmt via the scalafmt-dynamic module.
    • org.scalafmt.Scalafmt: An older public API. While stable, it has limitations: it does not support the version setting in .scalafmt.conf, does not respect project.excludeFilters, does not automatically handle *.sbt or *.sc files, 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 of scalafmt-interfaces.
    • org.scalafmt.config: Case classes for .scalafmt.conf intended for internal use only.
    • org.scalafmt.cli: The private implementation of the command-line interface.
  9. Install scalafmt pre-release versions

    main

    To 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:snapshots flag to resolve the artifact.
    • Using sbt: You must add the Sonatype snapshots resolver to your settings.
  10. Compile the Scalafmt project

    main

    The project uses sbt for building. To run fast unit tests for the JVM, use sbt tests/test. Avoid using sbt test unless 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 source and choosing the build.sbt file.

    sbt tests/test