Scalafix - a Scala rewrite tool


0.5.0-M7

Join the chat at https://gitter.im/scalacenter/scalafix

Scalafix is a Scala code rewriting tool and library. This effort follows the Scala Center Advisory Board proposal: Clarification of Scala to Dotty migration path. The goal of the project is to help automate migration between different Scala compiler and library versions.

Installation


Integrations are currently limited to the command-line and sbt. It may be possible to add IDE integrations such as IntelliJ/ENSIME in the future, but it is not a priority.

sbt-scalafix

The sbt-plugin is the recommended integration for semantic rewrites.
// ===> project/plugins.sbt
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.0-M7")

// ===> build.sbt
scalaVersion := "2.12.3" // 2.11.11 is also supported.
// if scalacOptions is defined with append `++=`, do nothing.
// if scalacOptions is defined like this: scalacOptions := List(...),
// then do one of the following
scalacOptions ++= List(...) // change := to ++=
// or
scalacOptions := List(...)                    // keep unchanged
scalacOptions ++= scalafixScalacOptions.value // add this line

// ===> sbt shell (example usage)
> scalafix                               // Run .scalafix.conf rewrites
> scalafix RemoveUnusedImports           // Run specific rewrite
> myProject/scalafix RemoveUnusedImports // Run rewrite in one project only
> test:scalafix RemoveUnusedImports      // Run rewrite in single configuration
> scalafix ExplicitR<TAB>                // use tab completion
> scalafix replace:com.foobar/com.buzbaz // refactor (experimental)
> scalafix file:rewrites/MyRewrite.scala // run local custom rewrite
> scalafix github:org/repo/v1            // run library migration rewrite

Verify sbt installation

To verify the installation, check that the scalacOptions include -Xplugin-require:semanticdb
> show scalacOptions
[info] * -Yrangepos                  // required
[info] * -Xplugin-require:semanticdb // recommended
[info] * -P:semanticdb:sourceroot:/* // recommended

scalafix-sbt-example

For a minimal working example usage of sbt-scalafix, see the scalacenter/scalafix-sbt-example repository.
git clone https://github.com/olafurpg/scalafix-sbt-example
cd scalafix-sbt-example
sbt "scalafix RemoveUnusedImports"
git diff // should produce a diff

sbt settings and tasks

Name Type Description
scalafix <rewrite>..Unit Run scalafix on project sources. See Rewrites or use tab completion to explore supported rewrites.
scalafixBuild <rewrite>..Unit Run scalafix on the build sources, *.sbt and project/*. Note. Requires semanticdb-sbt enabled globally for semantic rewrites.
scalafixEnabledBoolean True by default. If false, then sbt-scalafix will not enable the semanticdb-scalac compiler plugin.
scalafixConfigOption[File] Location of .scalafix.conf. See Configuration for more details.
scalafixSourcerootFile The root directory of this project.
scalafixScalacOptionsSeq[String] Necessary Scala compiler settings for scalafix to work.
scalafixVersionString Which version of scalafix-cli to run.
scalafixScalaVersionString Which Scala version of scalafix-cli to run.
scalafixSemanticdbVersionString Which version of org.scalameta:semanticdb-scalac to run.
scalafixVerboseBoolean If true, print out debug information.

semanticdb-sbt

Experimental. semanticdb-sbt is a Scala 2.10 compiler plugin that extracts semantic information from the sbt compiler. To enable semanticdb-sbt,
// ~/.sbt/0.13/plugins/plugins.sbt
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.0-M7")
// ~/.sbt/0.13/build.sbt
import scalafix.sbt.ScalafixPlugin.autoImport._
scalafixBuildSettings // enable semanticdb-sbt for sbt metabuilds.
Note. This integration is new, you can expect to face problems from enabling sbt-scalafix globally. In particular, sbt-scalafix does not at the moment support older versions of 2.11 than 2.11.11 and 2.12 than 2.12.3. It's possible to disable sbt-scalafix with scalafixEnabled := false. Please report back on your experience.

scalafix-core

Scalafix can be used as a library to run custom rewrites.
// ===> build.sbt
libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % "0.5.0-M7"
// (optional) Scala.js is also supported
libraryDependencies += "ch.epfl.scala" %%% "scalafix-core" % "0.5.0-M7"
Example usage of the syntactic API.
package fix

import scala.meta.Name
import scalafix.Patch
import scalafix.Rewrite
import scalafix.rewrite.RewriteCtx

object MyRewrite {
  // Syntactic "lambda-rewrite"
  val Reverse: Rewrite = Rewrite.syntactic { ctx =>
    ctx.tree.collect {
      case tree @ Name(name) => ctx.replaceTree(tree, name.reverse)
    }.asPatch
  }
  // Syntactic "class-rewrite"
  case object Uppercase extends Rewrite {
    override def rewrite(ctx: RewriteCtx): Patch =
      ctx.tree.collect {
        case tree @ Name(name) => ctx.replaceTree(tree, name.toUpperCase)
      }.asPatch
  }
}
println(MyRewrite.Reverse("object Hello { println('world) }"))
// object olleH { nltnirp('world) }
println(MyRewrite.Uppercase("object Hello { println('world) }"))
// object HELLO { PRINTLN('world) }
The semantic API requires a more complicated setup. Please use scalacenter/scalafix.g8.

scalafix-cli

The recommended way to install the scalafix command-line interface is with coursier.
// coursier
coursier bootstrap ch.epfl.scala:scalafix-cli_2.11.11:0.5.0-M7 -f --main scalafix.cli.Cli -o scalafix
./scalafix --help

// homebrew
brew install --HEAD olafurpg/scalafmt/scalafix
scalafix --help

// wget
wget -O scalafix https://github.com/scalacenter/scalafix/blob/master/scalafix?raw=true
./scalafix --help

Once the scalafix cli is installed, consult the --help page for further usage instructions

--help

scalafix 0.5.0-M7
Usage: scalafix [options] [<file>...]
  --usage  
        Print usage and exit
  --help | -h  
        Print help message and exit
  --version | -v  
        Print version number and exit
  --verbose  
        If set, print out debugging inforation to stderr.
  --config | -c  <.scalafix.conf>
        File path to a .scalafix.conf configuration file.
  --config-str | -c  <imports.organize=false>
        String representing scalafix configuration
  --sourceroot  </foo/myproject>
        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.
  --classpath  <entry1.jar:entry2.jar:target/scala-2.12/classes>
        java.io.File.pathSeparator separated list of directories or jars containing '.semanticdb' files. The 'semanticdb' files are emitted by the semanticdb-scalac compiler plugin and are necessary for semantic rewrites like ExplicitReturnTypes to function.
  --rewrites | -r  <ProcedureSyntax OR file:LocalFile.scala OR scala:full.Name OR https://gist.com/.../Rewrite.scala>
        Rewrite rules to run.
  --stdout  
        If set, print fix to stdout instead of writing to file.
  --test  
        Exit non-zero code if files have not been fixed. Won't write to files.
  --out-from  </shared/>
        Regex that is passed as first argument to fileToFix.replaceAll(outFrom, outTo)
  --out-to  </custom/>
        Replacement string that is passed as second argument to fileToFix.replaceAll(outFrom, outTo)
  --exclude  <core Foobar.scala>
        Space separated list of regexes to exclude which files to fix. If a file match one of the exclude regexes, then it will not get fixed. Defaults to excluding no files.
  --single-thread  
        If true, run on single thread. If false (default), use all available cores
  --no-sys-exit  
        If true, does not sys.exit at the end. Useful for example in sbt-scalafix
  --quiet-parse-errors  
        Don't report parse errors for non-explictly passed filepaths.
  --bash  
        Print out bash completion file for scalafix. To install on
          scalafix --bash > /usr/local/etc/bash_completion.d/scalafix # Mac
          scalafix --bash > /etc/bash_completion.d/scalafix           # Linux
  --zsh  
        Print out zsh completion file for scalafix. To install:
          scalafix --zsh > /usr/local/share/zsh/site-functions/_scalafix
  --non-interactive  
        Don't use fancy progress bar.
  --project-id  <value>
        String ID to prefix reported messages with
Available rewrites: DottyKeywords, NoValInForComprehension, RemoveXmlLiterals, VolatileLazyVal, ProcedureSyntax, ExplicitUnit, DottyVolatileLazyVal, DottyVarArgPattern, Sbt1, ExplicitReturnTypes, RemoveUnusedImports, NoAutoTupling

NOTE. The command line tool is mostly intended to be invoked programmatically
from build-tool integrations such as sbt-scalafix. The necessary fixture to run
semantic rewrites is tricky to setup manually.

Scalafix chooses which files to fix according to the following rules:
- scalafix <directory> <rewrite> finds *.scala files in <directory>
- when <rewrite> is semantic
  - if --classpath and --sourceroot are provided, then those are used to find .semanticdb files
  - otherwise, Scalafix will automatically look for META-INF/semanticdb directories from the
    current working directory.

Examples (semantic):
  $ scalafix # automatically finds .semanticdb files and runs rewrite configured in .scalafix.conf.
  $ scalafix <directory> # same as above except only run on files in <directory>
  $ scalafix --rewrites RemoveUnusedImports # same as above but run RemoveUnusedImports.
  $ scalafix --classpath <foo.jar:target/classes> # explicitly pass classpath, --sourceroot is cwd.
  $ scalafix --classpath <foo.jar:target/classes> --sourceroot <directory>
  $ cat .scalafix.conf
  rewrites = [ProcedureSyntax]
  $ scalafix Code.scala # Same as --rewrites ProcedureSyntax

Exit status codes:
 Ok=0
 UnexpectedError=1
 ParseError=2
 ScalafixError=4
 InvalidCommandLineOption=8
 MissingSemanticApi=16
 StaleSemanticDB=32
 TestFailed=64
 LinterError=128

Configuration


Scalafix reads configuration from a file using HOCON syntax. I recommend you put a file .scalafix.conf into the root directory of your project.

rewrites

You can either run a pre-made that comes with scalafix or a custom rewrite that you write yourself.

Pre-made rewrites

Available rewrites are listed in Rewrites.
rewrites = [ProcedureSyntax] # No rewrites are run if empty.

Custom rewrites

Scalafix supports loading rewrites from a few different URI protocols.

scala:

If a rewrites is on the classpath, you can classload it with the scala: protocol.
rewrite = "scala:scalafix.internal.rewrite.ProcedureSyntax"

github:

If a rewrite is written in a single file and you want a short syntax, you can use the github: protocol for sharing your rewrite
rewrite = "github:typelevel/cats/v1.0.0"
// expands into https://raw.githubusercontent.com/typelevel/cats/master/scalafix/rewrites/src/main/scala/fix/Cats_v1_0_0.scala

replace:

Experimental

To replace usage of one class/object/trait/def with another. Note, does not move definitions like "Move" does in an IDE. This only moves use-sites.
rewrite = "replace:com.company.App/io.company.App"
// From sbt shell: > scalafix replace:from/to
To rename a method
rewrite = "replace:com.company.App.start/init"

file:

If a rewrites is written in a single file on disk, you can load it with the file: protocol.
rewrite = "file:readme/MyRewrite.scala" // from local file

http:

If a rewrite is written in a single source file on the internet, you can load it with the https: or http: protocol
rewrite = "https://gist.githubusercontent.com/olafurpg/fc6f43a695ac996bd02000f45ed02e63/raw/80218434edb85120a9c6fd6533a4418118de8ba7/ExampleRewrite.scala"

lint

Override the default severity level of a LintMessage with lint
// Assuming 'Foo' is a rewrite and 'warningID'/'errorID' are LintCategory IDs.
lint.error = [ Foo.warningID ] // promote Foo.warnigID to an error
lint.warning = [ Foo.errorID ] // demote Foo.errorID to a warning
lint.info = [ Foo.errorID ] // demote Foo.errorID to info
lint.ignore = [ Foo.errorID ] // don't report Foo.errorID
lint.explain = true // print out detailed explanation for lint messages.

patches

For simple use-cases, it's possible to write custom rewrites directly in .scalafix.conf.
patches.removeGlobalImports = [
  "scala.collection.mutable" // scala.meta.Importee
]
patches.addGlobalImports = [
  "scala.collection.immutable"
]
patches.replaceSymbols = [
  { from = "scala.collection.mutable.ListBuffer"
    to   = "com.geirsson.mutable.CoolBuffer" }
]
// Helper to see which symbols appear in your source files
debug.printSymbols = true
For more advanced use-cases, I recommend you use see Creating your own rewrite.

Rewrites


Scalafix comes with a few rewrites out-of-the-box. These rewrites have been chosen to meet the long-term goal of scalafix to clarify the Scala to Dotty migration path. To create custom rewrites, see scalafix-core.

ExplicitReturnTypes

Experimental

Dotty requires implicit vals and defs to explicitly annotate return types. The ExplicitReturnTypes rewrite inserts the inferred type from the compiler for implicit definitions that are missing an explicit return type. For example,
// before
implicit val tt = liftedType
// after
implicit val tt: TypedType[R] = liftedType

RemoveUnusedImports

This rewrite acts upon "Unused import" warnings emitted by the Scala compiler. See slick/slick/pulls#1736 for an example diff from running sbt "scalafix RemoveUnusedImports".

To use this rewrite:

// before
import scala.List
import scala.collection.{immutable, mutable}
object Foo { immutable.Seq.empty[Int] }

// after
import scala.collection.immutable
object Foo { immutable.Seq.empty[Int] }

Note. . This rewrite does a best-effort at preserving original formatting. In some cases, the rewritten code may be formatted weirdly

// before
import scala.concurrent.{
  CancellationException,
  TimeoutException
}
// after
import scala.concurrent.

  TimeoutException
It's recommended to use a code formatter after running this rewrite.

RemoveXmlLiterals

This rewrites replaces XML literals with a xml"" interpolator from scala-xml-quote project.
// tries to use single quote when possible
<div>{bar}</div>
xml"<div>${bar}</div>"

// multi-line literals get triple quote
<div>
  <span>{"Hello"}</span>
</div>
xml"""<div>
  <span>${"Hello"}</span>
</div>"""

// skips XML literals in pattern position
x match { case <a></a> => }
x match { case <a></a> => }

// replaces escaped {{ with single curly brace {
<div>{{</div>
xml"<div>{</div>"

ProcedureSyntax

"Procedure syntax" is not supported in Dotty. Methods that use procedure syntax should use regular method syntax instead. For example,
// before: procedure syntax
def main(args: Seq[String]) {
  println("Hello world!")
}
// after: regular syntax
def main(args: Seq[String]): Unit = {
  println("Hello world!")
}

DottyVolatileLazyVal

Adds a @volatile annotation to lazy vals. The @volatile annotation is needed to maintain thread-safe behaviour of lazy vals in Dotty.

// before
lazy val x = ...
// after
@volatile lazy val x = ...

With @volatile, Dotty uses a deadlock free scheme that is comparable-if-not-faster than the scheme used in scalac.

ExplicitUnit

Adds an explicit Unit return type to def declarations without a return type

// before
trait A {
  def doSomething
}
// after
trait A {
  def doSomething: Unit
}

Such members already have a return type of Unit and sometimes this is unexpected. Adding an explicit return type makes it more obvious.

DottyVarArgPattern

Replaces @ symbols in VarArg patterns with a colon (:). See http://dotty.epfl.ch/docs/reference/changed/vararg-patterns.html

// before
case List(1, 2, xs @ _*)
// after
case List(1, 2, xs : _*)

NoAutoTupling

Adds explicit tuples around argument lists where auto-tupling is occurring.

To use this rewrite:

// before
def someMethod(t: (Int, String)) = ...
someMethod(1, "something")
// after
def someMethod(t: (Int, String)) = ...
someMethod((1, "something"))

Auto-tupling is a feature that can lead to unexpected results, making code to compile when one would expect a compiler error instead. Adding explicit tuples makes it more obvious.

Note. Some auto-tupling cases are left unfixed, namely the ones involving constructor application using `new`
case class Foo(x: (String, Boolean))
new Foo("string", true) // won't be fixed
Foo("string", true)     // will be fixed
This is a known limitation.

NoValInForComprehension

Removes val from definitions in for-comprehension.

// before
for {
  n <- List(1, 2, 3)
  val inc = n + 1
} yield inc
// after
for {
  n <- List(1, 2, 3)
  inc = n + 1
} yield inc

The two syntaxes are equivalent and the presence of the val keyword has been deprecated since Scala 2.10.

Sbt1

Experimental

To use this rewrite:

// before
x <+= (y in Compile)
// after
x += (y in Compile).value
This rewrite currently handles many basic cases but may produce incorrect output in more advanced cases. Please report back your experience.

Planned rewrites...

See here.

Creating your own rewrite


It is possible to implement custom rewrites with Scalafix. Depending on what your rewrite does, it may be a lot of work or very little work. Don't hestitate to get an estimate on Join the chat at https://gitter.im/scalacenter/scalafix for how complicated it would be to implement your rewrite.

Before you begin

Before you dive right into the code of your rewrite, it might be good to answer the following questions first.

What diff do you want to make?

Scalafix is a tool to automatically produce diffs. Before implementing a rewrite, it's good to manually migrate/refactor a few examples first. Manually refactoring code is helpful to estimate how complicated the rewrite is.

Is the expected output unambiguous?

Does the rewrite require manual intervention or do you always know what output the rewrite should produce? Scalafix currently does not yet support interactive refactoring. However, Scalafix has support for configuration, which makes it possible to leave some choice to the user on how the rewrite should behave.

Who will use your rewrite?

The target audience/users of your rewrite can impact the implementation the rewrite. If you are the only end-user of the rewrite, then you can maybe take shortcuts and worry less about rare corner cases that may be easier to fix manually. If your rewrite is intended to be used by the entire Scala community, then you might want to be more careful with corner cases.

What code will your rewrite fix?

Is your rewrite specific to a particular codebase? Or is the rewrite intended to be used on codebases that you don't have access to? If your rewrite is specific to one codebase, then it's easier to validate if your rewrite is ready. You may not even need tests, since your codebase is your only test. If your rewrite is intended to be used in any random codebase, you may want to have tests and put more effort into handling corner cases. In general, the smaller the target domain of your rewrite, the easier it is to implement a rewrite.

How often will your rewrite run?

Are you writing a one-off migration script or will your rewrite run on every pull request? A rewrite that runs on every pull request should ideally have some unit tests and be documented so that other people can help maintain the rewrite.

scalacenter/scalafix.g8

Run the following commands to generate a skeleton project

cd reponame // The project you want to implement rewrites for.

// --rewrite= should ideally match the GitHub repo name, to make
// it possible for users to run `scalafix "github:org/reponame/v1.0"`
sbt new scalacenter/scalafix.g8 --rewrite="reponame" --version="v1.0"
cd scalafix
sbt tests/test

Note that the scalafix directory is a self-contained sbt build and can be put into the root directory of your repo. The tests are written using scalafix-testkit.

scalafix-testkit

Scalafix-testkit is a module to help you write/run/debug/test scalafix rewrites. The scalacenter/scalafix.g8 template boilerplate to use scalafix-testkit. The anatomy of a scalafix-testkit project is like this
scalafix
├── rewrites // rewrite implementations
├── input    // code that runs through rewrite
├── output   // expected output from running input on rewrites
└── tests    // tiny project where unit tests run
The key features of scalafix-testkit are

Example rewrites

The Scalafix repository contains several example rewrites and tests, see here. These examples may serve as inspiration for your rewrite.

Vocabulary

The following sections explain useful vocabulary when working with Scalafix.

Rewrite

A rewrite is a small program/function that can produce diffs. To implement a rewrite, you extend the Rewrite class. To run a rewrite, users execute scalafix --rewrites MyRewrite. Multiple rewrites can be composed into a single rewrite. For example, the migration for Dotty may involve ProcedureSyntax, ExplicitUnit, DottyVarArgPattern, ExplicitReturnTypes and a few other rewrites. It is possible to combine all of those rewrites into a single Dotty rewrite so users can run scalafix --rewrites Dotty.

RewriteCtx

A rewrite context contains data structures and utilities to rewrite a single source file. For example, the rewrite context contains the parsed Tree, Tokens, lookup tables for matching parentheses and more.

Patch

A "Patch" is a data structure that describes how to produce a diff. Two patches can combined into a single patch with the + operator. A patch can also be empty. Patches can either be low-level "token patches", that operate on the token level or high-level "tree patches" that operate on parsed abstract syntax tree nodes. The public API for patch operations is available in PatchOps.scala
trait PatchOps {
  def removeImportee(importee: Importee): Patch
  def replaceToken(token: Token, toReplace: String): Patch
  def removeTokens(tokens: Tokens): Patch
  def removeToken(token: Token): Patch
  def replaceTree(from: Tree, to: String): Patch
  def rename(from: Name, to: Name): Patch
  def rename(from: Name, to: String): Patch
  def addRight(tok: Token, toAdd: String): Patch
  def addLeft(tok: Token, toAdd: String): Patch
  def lint(msg: LintMessage): Patch

  def removeGlobalImport(symbol: Symbol)(implicit semanticCtx: SemanticCtx): Patch
  def addGlobalImport(symbol: Symbol)(implicit semanticCtx: SemanticCtx): Patch
  def addGlobalImport(importer: Importer)(implicit semanticCtx: SemanticCtx): Patch
  def replaceSymbol(fromSymbol: Symbol.Global, toSymbol: Symbol.Global)(
      implicit semanticCtx: SemanticCtx): Patch
  def replaceSymbols(toReplace: (String, String)*)(implicit semanticCtx: SemanticCtx): Patch
  def renameSymbol(fromSymbol: Symbol.Global, toName: String)(
      implicit semanticCtx: SemanticCtx): Patch
}
Some things are typically easier to do on the token level and other things are easier to do on the tree level. The Patch API is constantly evolving and we regularly add more utility methods to accomplish common tasks. If you experience that it's difficult to implement something that seems simple then don't hesitate to ask on Join the chat at https://gitter.im/scalacenter/scalafix.

LintMessage

Rewrites are able to emit "lint messages" with info/warn/error severity using ctx.lint(lintCategory.at(String/Position)): Patch. To report a lint message, first create a LintCategory and then report it as a Patch
val divisionByZero = LintCategory.error("Division by zero is unsafe!")
def rewrite(ctx: RewriteCtx): Patch = {
  val tree: Tree = // ...
  ctx.lint(divisionByZero.at(tree.pos))
}

LintCategory

A LintCategory is group of lint messages of the same kind. A LintCategory has a default severity level (info/warn/error) at which it will be reported. Scalafix users can override the default severity with lint.

Scalameta

Scalafix uses Scalameta to implement rewrites. Scalameta is a clean-room implementation of a metaprogramming toolkit for Scala. This means it's not necessary to have experience with Scala compiler internals to implement Scalafix rewrites. In fact, Scalafix doesn't even depend on the Scala compiler. Since Scalafix is not tied so a single compiler, this means that Scalafix rewrites in theory can work with any Scala compiler, including Dotty and IntelliJ Scala Plugin.

Semanticdb

Semanticdb is a compiler plugin for Scala 2.x in the Scalameta project that collects information to build a SemanticCtx. For more information about Scalahost, see the Scalameta documentation.

Token

A token is for example an identifier println, a delimiter [ ), or a whitespace character like space or newline. In the context of Scalafix, a Token means the data structure scala.meta.Token. See Scalameta tutorial for more details. See Wikipedia for a more general definition.

Tokens

Tokens is a list of Token. See Scalameta tutorial

Tree

A Tree is a parsed abstract syntax tree. In the context of Scalafix, a Tree means the data structure scala.meta.Tree. See Scalameta tutorial for more details. See Wikipedia for a more general definition.

Syntactic

A Rewrite is "syntactic" when it does not require information from type-checking such as resolved names (println => scala.Predef.println), types or terms, or inferred implicit arguments. A syntactic rewrite can use Tokens and Tree, but not SemanticCtx.

Semantic

A Rewrite is "semantic" if it requires information from the compiler such as types, symbols and reported compiler messages. A semantic rewrite can use a SemanticCtx.

SemanticCtx

A SemanticCtx encapsulates a compilation context, providing capabilities to perform semantic operations for Semantic rewrites. To learn more about SemanticCtx and its associated data structures (Symbol, Denotation, ...), see the Scalameta tutorial.

Sharing your rewrite

You have implemented a rewrite, you have tests, it works, and now you want to share it with the world. Congrats! There are several ways to share a rewrite if the rewrite is contained in a single file and uses no external dependencies,

If your rewrite uses a custom library, then it's a bit tricky to share it. See #201 for more updates.

FAQ


If you have any questions, don't hesitate to ask on gitter Join the chat at https://gitter.im/scalacenter/scalafix.

Troubleshooting

I get resolution errors for org.scalameta:semanticdb-scalac

Make sure you are using a supported Scala version: 2.11.11, 2.12.3. Note, the version must match exactly, including the last number.

Enclosing tree [2873] does not include tree [2872]

Scalafix requires code to compile with the scalac option -Yrangepos. A macro that emits invalid tree positions is usually the cause of compiler errors triggered by -Yrangepos. Other tools like the presentation compiler (ENSIME/Scala IDE) require -Yrangepos to work properly.

I get exceptions about coursier

If you use sbt-coursier, make sure you are on version 1.0.0-RC10.

Scalafix doesn't do anything

RemoveUnusedImports does not remove unused imports

Make sure that you followed the instructions in RemoveUnusedImports regarding scalac options.

Features

IDE support

Scalafix has no IDE support at the moment.

Changelog


0.5.x

0.5.0

Note. This changelog is still incomplete and will be updated before the final 0.5.0 release.

New features for end users

This release introduces major improvements to sbt-scalafix, scalafix-cli.

New features for rewrite authors

Bug fixes / Improvements

Breaking changes

From 0.5 onwards, our CI will check binary breaking changes in the public API on every pull request. Note that modules inside the package scalafix.internal don't promise binary compatibility between any releases, including PATCH upgrades.

0.4.x

0.4.2

0.4.1

First of all, I'd like to welcome Gabriele Petronella, @gabro, to the scalafix team! See #184. Big thanks you everybody who contributed this release via issues, pull requests, online discussions on Join the chat at https://gitter.im/scalacenter/scalafix and and offline discussions at Scaladays Copenhagen last week!

0.4.0

This release represents a significant milestone for Scalafix. Scalafix no longer runs as a compiler plugin as it did in previous releases. Instead, Scalafix runs now independently from the compiler, and uses the Scalameta Semantic API to query information from the compiler.

New features

Breaking changes

git shortlog -sn --no-merges v0.3.0..v0.4.0 tells us that 4 people contributed to this release:

0.3.x

0.3.4

0.3.3

0.3.2

See merged PRs.

0.3.1

0.3.0

0.2.1

0.2.0

0.1.0

Fork me on GitHub