Scalafix

Scalafix

  • User guide
  • Developer guide
  • Browse sources
  • GitHub

›Usage

Usage

  • Installation
  • Configuration
  • Suppressing rules

Rules

  • All rules
  • RemoveUnused
  • DisableSyntax
  • NoAutoTupling
  • LeakingImplicitClassVal
  • NoValInForComprehension
  • ProcedureSyntax

Misc

  • Related projects
Edit

Installation

Requirements

macOS, Linux and Windows: Scalafix runs on macOS, Linux and Windows. Every pull request is tested on both Linux and Windows.

Java 8. Scalafix supports only Java 8 at the moment. Running Scalafix on Java 9+ results in error: unable to load symbol table errors. See #880 for updates on adding support for Java 11.

Scala 2.11 and 2.12: Scalafix works only with the latest version of Scala 2.11 and Scala 2.12. See scalameta/scalameta#1695 for updates on adding support for Scala 2.13 once it's out.

ScalafixScala CompilerScalameta
0.9.0-RC12.11.12 / 2.12.64.0.0
0.5.102.11.12 / 2.12.42.1.7

sbt

Start by installing the sbt plugin in project/plugins.sbt

// project/plugins.sbt
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.0-RC1")

Maven Central

From the sbt shell, let's run the rule ProcedureSyntax

> myproject/scalafix ProcedureSyntax

It's normal that the first invocation of scalafix takes a while to download Scalafix artifacts from Maven Central.

If all went well and your project uses the deprecated "procedure syntax", you should have a diff in your sources like this

-  def myProcedure {
+  def myProcedure: Unit = {

Next, if we run another rule like RemoveUnused then we get an error

> myproject/scalafix RemoveUnused
[error] (Compile / scalafix) scalafix.sbt.InvalidArgument: 2 errors
[E1] The semanticdb-scalac compiler plugin is required to run semantic
rules like RemoveUnused ...
[E2] The Scala compiler option "-Ywarn-unused" is required to use
RemoveUnused ...

The first error message means the SemanticDB compiler plugin is not enabled for this project. The second error says RemoveUnused requires the Scala compiler option -Ywarn-unused. To fix both problems, add the following settings to build.sbt

 // build.sbt
 lazy val myproject = project.settings(
   scalaVersion := "2.12.6", // or 2.11.12
+  addCompilerPlugin(scalafixSemanticdb), // enable SemanticDB
   scalacOptions ++= List(
+    "-Yrangepos",          // required by SemanticDB compiler plugin
+    "-Ywarn-unused-import" // required by `RemoveUnused` rule
   )
 )

For project/*.scala files, add import scalafix.sbt.ScalafixPlugin.autoImport._ to the top of the file to resolve scalafixSemanticdb.

We run RemoveUnused again and the error is now gone

> myproject/scalafix RemoveUnused
[info] Compiling 15 Scala sources to ...
[info] Running scalafix on 15 Scala sources

If your project has unused imports, you should see a diff like this

- import scala.util.{ Success, Failure }
+ import scala.util.Success

See example project for a repository that demonstrates ProcedureSyntax and RemoveUnused.

Great! You are all set to use Scalafix with sbt :)

Beware that the SemanticDB compiler plugin in combination with -Yrangepos adds overhead to compilation time. The exact compilation overhead depends on the codebase being compiled and compiler options used. It's recommended to provide generous JVM memory and stack settings in the file .jvmopts:

-Xss8m
-Xms1G
-Xmx8G

Settings and tasks

NameTypeDescription
scalafix <args>InputTaskKey[Unit]Invoke scalafix command line interface directly. Use tab completion to explore supported arguments or consult --help
scalafixConfigSettingKey[Option[File]].scalafix.conf file to specify which scalafix rules should run. Defaults to .scalafix.conf in the root directory, if it exists.

Main and test sources

The task myproject/scalafix runs for main sources in the project myproject. To run Scalafix on test sources, execute myproject/test:scalafix instead. To run on both main and test sources, execute ; myproject/scalafix ; myproject/test:scalafix

Integration tests

By default, the scalafix command is enabled for the Compile and Test configurations. To enable Scalafix for other configuration like IntegrationTest, add the following to your project settings

 lazy val myproject = project
   .configs(IntegrationTest)
   .settings(
     Defaults.itSettings,
+    inConfig(IntegrationTest)(scalafixConfigSettings(IntegrationTest))
     // ...
   )

Multi-module builds

The scalafix task aggregates like the compile and test tasks. To run Scalafix on all projects for both main and test sources you can execute all scalafix test:scalafix.

Optionally, add a command alias to your build to run Scalafix on your entire project with the shorthand fix

// top of build.sbt
addCommandAlias("fix", "all compile:scalafix test:scalafix")

Enforce in CI

To automatically enforce that Scalafix has been run on all sources, use scalafix --check instead of scalafix. This task fails the build if running scalafix would produce a diff or a linter error message is reported.

Optionally, add a command alias to enforce Scalafix on your entire project with the shorthand fixCheck

// top of build.sbt
addCommandAlias(
  "fixCheck",
  "; compile:scalafix --check ; test:scalafix --check"
)

Cache in CI

To avoid binary compatibility conflicts with the sbt classpath (example issue), the Scalafix plugin uses Coursier to fetch Scalafix artifacts from Maven Central. These artifacts are by default cached in the directory $HOME/.coursier/cache. To avoid redundant downloads on every pull request, it's recommended to configure your CI enviroment to cache this directory. The location can be customized with the environment variable COURSIER_CACHE

export COURSIER_CACHE=$HOME/.custom-cache

Run custom rules

It's possible to run custom Scalafix rules that have been published to Maven Central. To install a custom rule, add it to scalafixDependencies (scalafix.sbt.ScalafixPlugin.autoImport.scalafixDependencies):

// at the top of build.sbt
scalafixDependencies in ThisBuild +=
  "com.geirsson" %% "example-scalafix-rule" % "1.3.0"

Start sbt and type scalafix <TAB>, once the example-scalafix-rule dependency has been downloaded the rules SemanticRule and SyntacticRule should appear as tab completion suggestions.

$ sbt
> scalafix Syn<TAB>
> scalafix SyntacticRule

If all went well, you should see a diff adding the comment // v1 SyntacticRule! to all Scala source files.

+// v1 SyntacticRule!

Exclude files from SemanticDB

By default, the SemanticDB compiler plugin will process all files in a project.

Use -P:semanticdb:exclude:<regex> to exclude files from the SemanticDB compiler plugin.

scalacOptions += "-P:semanticdb:exclude:Macros.scala"

Separate multiple patterns with pipe | to exclude multiple files.

scalacOptions += "-P:semanticdb:exclude:Macros.scala|Schema.scala"

To learn more about SemanticDB compiler options visit https://scalameta.org/docs/semanticdb/guide.html#scalac-compiler-plugin

Avoid using slashes like / in -P:semanticdb:exclude since that will not work on Windows. The argument is compiled to a regular expression and gets matched against the java.io.File.getAbsolutePath representation of each file.

Exclude files from Scalafix

By default, the scalafix task processes all files in a project. If you use SemanticDB, the scalafix task also respects -P:semanticdb:exclude.

Use unmanagedSources.in(Compile, scalafix) to optionally exclude files from the scalafix task.

unmanagedSources.in(Compile, scalafix) :=
  unmanagedSources.in(Compile).value
    .filterNot(file => file.getName == "Macros.scala")

Replace Compile with Test to customize which test sources should be processed.

Customize SemanticDB output directory

By default, the SemanticDB compiler plugin emits *.semanticdb files in the classDirectory.

Use -P:semanticdb:targetroot:path to configure SemanticDB to emit *.semanticdb files in a custom location. For example:

scalacOptions += {
  val targetroot = target.value / "semanticdb"
  s"-P:semanticdb:targetroot:$targetroot"
}

To learn more about SemanticDB compiler options visit https://scalameta.org/docs/semanticdb/guide.html#scalac-compiler-plugin

Disable Scalafix for specific project

Use .disablePlugins(ScalafixPlugin) to disable Scalafix for a particular project.

  lazy val myproject = project
    .settings(...)
+   .disablePlugins(ScalafixPlugin)

When using Scala.js or Scala Native, use .jsConfigure or .nativeConfigure to disable Scalafix for only the Scala.js or Scala Native project. For example:

  lazy val myproject = crossProject(JVMPlatform, JSPlatform)
    .settings(...)
+   .jsConfigure(_.disablePlugins(ScalafixPlugin))

Enable SemanticDB for current shell session

Instead of permanently enabling SemanticDB in build.sbt, use the scalafixEnable command to enable SemanticDB the current active sbt shell session.

> scalafixEnable
...
> scalafix ExplicitResultTypes

The scalafixEnable command automatically runs addCompilerPlugin(scalafixSemanticdb) and scalacOptions += "-Yrangepos" for all eligible projects in the builds. The change in Scala compiler options means the project needs to be re-built on the next compile.

The scalafixEnable command must be re-executed after every reload and when sbt shell is exited.

Optionally enable SemanticDB

It's possible to optionally enable the SemanticDB compiler plugin by updating build.sbt like this:

  // build.sbt
- addCompilerPlugin(scalafixSemanticdb)
- scalacOptions += "-Yrangepos"
+ def shouldEnableSemanticdb: Boolean = ??? // fill this part
+ libraryDependencies ++= {
+   if (shouldEnableSemanticdb) List(compilerPlugin(scalafixSemanticdb))
+   else List()
+ }
+ scalacOptions ++= {
+   if (shouldEnableSemanticdb) List("-Yrangepos")
+   else List()
+ }

Verify installation

To verify that the SemanticDB compiler plugin is enabled, check that the settings scalacOptions and libraryDependencies contain the values below.

> show scalacOptions
[info] * -Yrangepos
> show libraryDependencies
[info] * org.scalameta:semanticdb-scalac:2.12.6:plugin->default(compile)

Example project

For a minimal example project using sbt-scalafix, see the scalacenter/scalafix-sbt-example repository.

git clone https://github.com/scalacenter/sbt-scalafix-example
cd scalafix-sbt-example
sbt "scalafix RemoveUnused"
git diff // should produce a diff

Command line

First, install the Coursier command-line interface.

Next, bootstrap a scalafix binary with Coursier

coursier bootstrap ch.epfl.scala:scalafix-cli_2.12.6:0.9.0-RC1 -f --main scalafix.cli.Cli -o scalafix
./scalafix --version # Should say 0.9.0-RC1

Help

Scalafix 0.9.0-RC1+15-c9b6cb3b-SNAPSHOT
Usage: scalafix [options] [<path> ...]

Scalafix is a refactoring and linting tool. Scalafix
supports both syntactic and semantic linter and rewrite
rules. Syntactic rules can run on source code without
compilation. Semantic rules can run on source code that has
been compiled with the SemanticDB compiler plugin. 

Common options:

  --rules | -r [String ...] (default: [])
    Scalafix rules to run, for example ExplicitResultTypes. The
    syntax for rules is documented in
    https://scalacenter.github.io/scalafix/docs/users/configuration#rules

  --files | -f [<path> ...] (default: [])
    Files or directories (recursively visited) to fix.

  --config <path> (default: null)
    File path to a .scalafix.conf configuration file. Defaults
    to .scalafix.conf in the current working directory, if
    any.

  --check
    Check that all files have been fixed with scalafix, exiting
    with non-zero code on violations. Won't write to files.

  --stdout
    Print fixed output to stdout instead of writing in-place.

  --diff
    If set, only apply scalafix to added and edited files in git
    diff against the master branch.

  --diff-base String (default: null)
    If set, only apply scalafix to added and edited files in git
    diff against a provided branch, commit or tag.

  --syntactic
    Run only syntactic rules, ignore semantic rules even if they
    are explicitly configured in .scalafix.conf or via
    --rules

  --verbose
    Print out additional diagnostics while running scalafix.

  --help | -h
    Print out this help message and exit

  --version | -v
    Print out version number and exit

Semantic options:

  --classpath Classpath (default: "<classpath>")
    Full classpath of the files to fix, required for semantic
    rules. The source files that should be fixed must be
    compiled with semanticdb-scalac. Dependencies are
    required by rules like ExplicitResultTypes, but the
    dependencies do not need to be compiled with
    semanticdb-scalac.

  --sourceroot <path> (default: null)
    Absolute path passed to semanticdb with
    -P:semanticdb:sourceroot:<path>. Relative filenames
    persisted in the Semantic DB are absolutized by the
    sourceroot. Defaults to current working directory if not
    provided.

  --auto-classpath
    If set, automatically infer the --classpath flag by scanning
    for directories with META-INF/semanticdb

  --auto-classpath-roots [<path> ...] (default: [])
    Additional directories to scan for --auto-classpath

  --scalac-options [String ...] (default: [])
    The scala compiler options used to compile this --classpath,
    for example -Ywarn-unused-import

  --scala-version String (default: "2.12.6")
    The Scala compiler version that was used to compile this
    project.

Tab completions:

  --bash
    Print out bash tab completions. To install:
    ```
    # macOS, requires "brew install bash-completion"
    scalafix --bash > /usr/local/etc/bash_completion.d/scalafix
    # Linux
    scalafix --bash > /etc/bash_completion.d/scalafix
    ```

  --zsh
    Print out zsh tab completions. To install:
    ```
    scalafix --zsh > /usr/local/share/zsh/site-functions/_scalafix
    unfunction _scalafix
    autoload -U _scalafix
    ```

Less common options:

  --exclude [<glob> ...] (default: [])
    Unix-style glob for files to exclude from fixing. The glob
    syntax is defined by `nio.FileSystem.getPathMatcher`.

  --tool-classpath URLClassLoader (default: "<classloader>")
    Additional classpath for compiling and classloading custom
    rules.

  --charset Charset (default: "UTF-8")
    The encoding to use for reading/writing files

  --no-sys-exit
    If set, throw exception in the end instead of System.exit

  --no-stale-semanticdb
    Don't error on stale semanticdb files.

  --settings ScalafixConfig (default: {})
    Custom settings to override .scalafix.conf

  --out-from String (default: null)
    Write fixed output to custom location instead of in-place.
    Regex is passed as first argument to
    file.replaceAll(--out-from, --out-to), requires
    --out-to.

  --out-to String (default: null)
    Companion of --out-from, string that is passed as second
    argument to fileToFix.replaceAll(--out-from, --out-to)

  --auto-suppress-linter-errors
    Insert /* scalafix:ok */ suppressions instead of reporting
    linter errors.

  --cwd <path> (default: "/Users/ollie/dev/scalafix")
    The current working directory


SNAPSHOT

Our CI publishes a snapshot release to Sonatype on every merge into master. Each snapshot release has a unique version number, jars don't get overwritten. To find the latest snapshot version number, go to https://oss.sonatype.org/content/repositories/snapshots/ch/epfl/scala/scalafix-core_2.12/ and select the largest version number (the one with the newest "Last Modified" timestamp). Once you have found the version number, adapt the version number in the instructions below

If using the sbt plugin

// project/plugins.sbt
resolvers += Resolver.sonatypeRepo("snapshots")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.0-RC1+15-c9b6cb3b-SNAPSHOT-SNAPSHOT")

If using the command-line interface

coursier launch ch.epfl.scala:scalafix-cli_2.12.6:0.9.0-RC1+15-c9b6cb3b-SNAPSHOT-SNAPSHOT -r sonatype:snapshots --main scalafix.cli.Cli -- --help
Next →
  • Requirements
  • sbt
    • Settings and tasks
    • Main and test sources
    • Integration tests
    • Multi-module builds
    • Enforce in CI
    • Cache in CI
    • Run custom rules
    • Exclude files from SemanticDB
    • Exclude files from Scalafix
    • Customize SemanticDB output directory
    • Disable Scalafix for specific project
    • Enable SemanticDB for current shell session
    • Optionally enable SemanticDB
    • Verify installation
    • Example project
  • Command line
    • Help
  • SNAPSHOT
Scalafix
Docs
Get startedRulesExtend Scalafix
Community
Chat on GitterDiscuss on Scala Users
More
GitHub
Copyright © 2018 Scala Center