Scala Static Analysis Tool Review

In this article:
Subscribe to our blog:

In the past we reviewed what is static code analysis and made a deep dive into static code analysis tools and now is the time to review Scala static analysis tools.

There are several good style guides to start from, such as the official Scala Style Guide, the Databricks Scala style guide and the Scala Best Practices collection.
Leif Wickland said “If your coding standard isn’t automatically and uniformly applied, you don’t have a coding standard” and I couldn’t agree more. At Codacy we believe that the enforcement of those guidelines should be outsourced to tools, and today we are going to review the main static analysis tools and linters that exist.

This review was first written in 2015 and was updated in October 2026. A lot has changed since then: Scala 3 was released, Scalastyle and Abide are no longer maintained, and this review now focuses on Scalafix, Scalafmt, WartRemover, Scapegoat and the compiler’s own warning options. All snippets below use sbt; replace x.y.z with the current version listed in each tool’s documentation.

Scalafix

Scalafix (GitHub) is a refactoring and linting tool for Scala from the Scala Center. Its rules can either report problems or rewrite your code, which also makes it useful for large-scale refactorings. Rules are syntactic (they run directly on source code) or semantic (they need type information that the compiler exports through SemanticDB).

Scalafix ships a small set of built-in rules, including:

  • DisableSyntax: reports syntax you have chosen to forbid, such as var, null, return, throw, while or XML literals
  • RemoveUnused: removes unused imports and terms reported by the compiler
  • OrganizeImports: sorts and groups import statements
  • ExplicitResultTypes: adds type annotations to inferred public members
  • ProcedureSyntax and RedundantSyntax: clean up deprecated or redundant syntax

Beyond these, there are community rules and you can write your own. Scalafix is tested with Scala 2.12, 2.13 and the current Scala 3 LTS release; some rules have documented limitations on Scala 3.

Setup with sbt

// project/plugins.sbt
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "x.y.z")
// build.sbt
inThisBuild(
  List(
    semanticdbEnabled := true,                       // required by semantic rules
    semanticdbVersion := scalafixSemanticdb.revision // only required for Scala 2.x
  )
)

scalacOptions += "-Wunused:imports" // needed by RemoveUnused on Scala 2.13 and 3.x

Rules and their settings go in a .scalafix.conf file at the root of the project:

// .scalafix.conf
rules = [
  DisableSyntax,
  OrganizeImports,
  RemoveUnused
]
DisableSyntax.noNulls = true
DisableSyntax.noReturns = true
DisableSyntax.noVars = true

Usage

sbt scalafixAll            # run the configured rules on main and test sources
sbt "scalafixAll --check"  # on CI: fail the build if any rule would change the code

Scalafix can also be installed as a command line tool with Coursier (cs install scalafix), and there are community plugins for Mill, Gradle and Maven.

Scalafmt

Scalafmt (GitHub) is a code formatter for Scala. It isn’t a linter, but it takes care of the indentation, whitespace and line-length rules that style checkers used to enforce, so code reviews can focus on the code itself.

Setup with sbt

// project/plugins.sbt
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "x.y.z")

A .scalafmt.conf file is required, and it must specify both the Scalafmt version and the Scala dialect of your sources:

// .scalafmt.conf
version = "x.y.z"        // mandatory: the Scalafmt release to use
runner.dialect = scala3  // mandatory: for example scala212, scala213 or scala3
maxColumn = 100

Usage

sbt scalafmtAll       # format main and test sources
sbt scalafmtCheckAll  # on CI: fail if any file isn't formatted
sbt scalafmtSbt       # format build files

The Scala plugin for IntelliJ supports Scalafmt, and the Metals language server can format with it in VS Code, Vim/Neovim, Emacs, Sublime Text and other editors. Mill supports Scalafmt out of the box, and there are external plugins for Maven and Gradle.

WartRemover

WartRemover (GitHub) is a flexible Scala code linting tool. It covers a great list of warts and is well documented. Note that there are several names when referring to the checks in static code analysis. The most common are checks, patterns, and more often than not, a reference to the tool name itself. In WartRemover, the checks are called warts.

WartRemover runs as a compiler plugin, so warts are reported during compilation, as warnings or as errors. It’s published for Scala 2.12, 2.13 and Scala 3, and customization is treated as a first-class feature as you can easily add your own warts.

Here are a few examples of the WartRemover warts:

  • Any and Nothing: these types are often inferred by mistake
  • AsInstanceOf and IsInstanceOf: type casts and type tests
  • Null: use of null
  • OptionPartial: Option#get, which throws on None
  • IterableOps: methods such as head or max that throw on empty collections
  • Return, Var, While and Throw
  • etc.

Setup with sbt

// project/plugins.sbt
addSbtPlugin("org.wartremover" % "sbt-wartremover" % "x.y.z")

Configuration

In WartRemover the configuration is done in build.sbt (check the setup documentation for more details). No warts are enabled by default. Warts.unsafe enables the set of warts considered stable, while Warts.all enables everything, including warts that can produce false positives. In this example we show how you can have all warts enabled except for a couple you would want to disable:

// build.sbt
Compile / compile / wartremoverErrors ++= Warts.allBut(Wart.Any, Wart.Nothing)

Scoping the setting to Compile / compile keeps the checks out of your tests and the sbt console. Use wartremoverWarnings instead of wartremoverErrors if you’d rather get warnings than a failing build.

Usage

sbt compile

This tool is integrated in the compilation process: just compile your code, and it will show you all the errors and warnings. WartRemover can also be used from Maven, Gradle (through a community plugin) or the command line.

Scapegoat

Scapegoat is another compiler plugin, closer in spirit to Java’s FindBugs: it looks for suspicious code that is likely to lead to bugs, such as comparisons that can never succeed, Option.get or empty if blocks. Take a look at the list of inspections to see if they suit your projects. It produces HTML and XML reports and can also write Scalastyle-compatible, Markdown and GitLab Code Quality output.

Setup with sbt

// project/plugins.sbt
addSbtPlugin("com.sksamuel.scapegoat" % "sbt-scapegoat" % "x.y.z")
// build.sbt (optional)
scapegoatDisabledInspections := Seq("UnusedMethodParameter")

Usage

sbt scapegoat

The project is actively maintained, with new releases tracking new Scala versions, but its Scala 3 support is still limited: at the time of writing, its README lists 123 inspections for Scala 2 and only 5 for Scala 3. The sbt-scapegoat README explains how to suppress warnings by file, by inspection or by line.

Compiler warnings and sbt-tpolecat

Before adding any plugin, turn on the checks the Scala compiler already has. On Scala 3, useful options include -Wunused:all (unused imports, private members, locals and parameters), -Wvalue-discard, -Wnonunit-statement and -Werror, which turns warnings into errors. Recent releases (3.5.2+, and 3.3.5+ on the LTS line) also accept -Wall to enable every warning option, -Wconf lets you fine-tune how individual warnings are reported, and scalac -W prints the full list of warning options.

// build.sbt (Scala 3)
scalacOptions ++= Seq(
  "-Wunused:all",
  "-Wvalue-discard",
  "-Wnonunit-statement",
  "-Werror"
)

On Scala 2.13, -Xlint enables a set of recommended warnings, alongside options such as -Wunused, -Wdead-code, -Wvalue-discard and -Werror. Option names differ between Scala 2 and Scala 3; the Scala 3 migration guide includes a compiler options lookup table, and the Scala 2 options are documented here. If you combine -Werror with Scalafix’s RemoveUnused, check the Scalafix documentation first, because unused warnings that fail compilation can stop the rule from running.

If you’d rather not maintain that list yourself, sbt-tpolecat configures a recommended set of compiler options based on your Scala version, with separate development, CI and release modes:

// project/plugins.sbt
addSbtPlugin("org.typelevel" % "sbt-tpolecat" % "x.y.z")

When you use it, adjust its settings (for example tpolecatExcludeOptions) instead of editing scalacOptions directly.

No longer maintained: Scalastyle, Abide and Linter

Scalastyle – Scalastyle was probably the most popular Scala style checker when this review was first written, with an extensive list of checks covering code style and best practices. It is no longer maintained: its last release, 1.0.0, dates from 2017 (before Scala 3 existed), and its repository hasn’t received a commit since 2019. A community fork, beautiful-scala/scalastyle, published releases until 2021 and is now archived as well. For new projects, Scalafmt covers the formatting and whitespace rules, Scalafix’s DisableSyntax covers checks such as “no null”, “no return”, “no var” and “no while”, and compiler warnings catch unused code.

Abide – Abide was a framework for writing lint rules, hosted under the scala GitHub organization. It never had a release, its repository is archived, and its README states that it has been superseded by Scalafix.

Linter – Linter was a compiler plugin with a nice list of checks. Its repository is archived and hasn’t had code changes since 2016. Compiler warnings, Scapegoat and WartRemover cover many of the same problems.

Which one should I use?

Ultimately, this is a personal choice depending on the needs of the project you are working on. As Scapegoat’s README points out, running several analysis tools on the same codebase is not a problem: the warnings you can get are the union of all the enabled tools, and the worst case is seeing the same warning twice.

So you probably want to combine more than one tool to cover a wide range of possible errors and to ensure that your code remains clean and consistent:

  • Every project: enable compiler warnings (by hand or with sbt-tpolecat) and format with Scalafmt.
  • Linting and automated refactoring: add Scalafix, with DisableSyntax for the constructs your team wants to forbid and RemoveUnused and OrganizeImports to keep imports tidy.
  • Strict, functional style enforced at compile time: add WartRemover, starting with Warts.unsafe.
  • Bug-pattern inspections: Scapegoat, especially on Scala 2 code bases, given its limited Scala 3 coverage.

However, one of the bigger criteria to choose is their workflow integration. If it disrupts your development process you will probably quickly stop checking the results. So make sure you integrate it where it makes more sense for you: IDE, pre-commit hook, continuous integration tool etc. The check tasks shown above (scalafixAll --check, scalafmtCheckAll) are handy for CI because they fail the build instead of rewriting files.

Shameless Plug: If you’re looking for a tool that makes it easier to enforce your coding standard, without you having to manually configure everything locally you should take a look at Codacy. Codacy runs analyzers on every commit and pull request and keeps track of issues over time, to save you time in code reviews and help you merge with confidence. The documentation that we have on every issue makes it also easier to improve your skills and onboard developers faster to the Scala Magic.

Conclusion

You can find several active and well-documented Scala static analysis tools to analyze your code and guide you through your development process. You can enforce strict standards, manage complexity and detect semantic problems, which is undeniably of a great help. If your team is developing in Scala without any of those, you should definitely give it a try. Don’t be scared by the number of issues! Start small by enabling only a few checks and increase slowly over time. Let me know how it goes in the comments and happy Scala coding!

Subscribe to our blog

Stay updated with our monthly newsletter.