Scalafix

Scalafix

  • User guide
  • Developer guide
  • Browse sources
  • GitHub

›Implementing rules

Implementing rules

  • Setup
  • Before you write code
  • Tutorial
  • Local rules

API Reference

  • Overview
  • Patch
  • SymbolMatcher
  • SymbolInformation
  • SemanticType
  • SemanticTree

Contributing

  • Guide
Edit

Setup

Scalafix supports writing custom linter and rewrite rules. Custom rules have access to a rich Scalafix public API and users can run custom rules with the same UX as built-in rules, including tab completions in the sbt-scalafix plugin.

sbt

The quickest way to get started in sbt is to use the scalafix.g8 project template:

cd repo-name # The project you want to implement rules for.

sbt new scalacenter/scalafix.g8 --repo="Repository Name"
cd scalafix
sbt tests / test

The --repo=<repository name> option should match the name of your GitHub repository with dashes replaced by spaces. For github.com/organization/scalafix-enterprise-rules, type Scalafix Enterprise Rules.

The template generates a scalafix/ directory with four different directories with sources.

scalafix
├── rules/src/main
│   ├── resources/META-INF/services
│   │   └── scalafix.v1.Rule // ServiceLoader configuration to load rule
│   └── scala/fix
│       └── Rewrite.scala // Implementation of a rewrite rule
├── input/src/main/scala/test
│   └── RewriteTest.scala // Unit test for rewrite rule,
│                         // must have corresponding file in output.
│                         // no corresponding output file needed.
├── output/src/main/scala/test
│   └── RewriteTest.scala // Expected output from running rewrite
│                         // on RewriteTest.scala from input project
└── tests/src/test/scala/fix
    └── RuleSuite.scala
  • rules: contains rule implementations.
  • input: input Scala source files to be analyzed by the rule. Every Scala source file in this directory becomes a unit test.
  • output: this directory is only used for rewrites, it can be ignored for linters. The structure of the output project should mirror the input project file by file. The text contents of the files should be the expected output after running the rule on the input sources. A mismatch from an output file and the result of running the rewrite rule on an input file becomes a test failure.
  • tests: a directory containing a single test suite to configure scalafix-testkit.

sbt-projectmatrix is used to generate several sub-projects for each directory.

  • rules is set up to cross-publish against all Scala binary versions for which scalafix-core is available.
  • input and output are cross-built against all Scala versions on which the rule can be applied.
  • tests verifies each input sub-project against a rules sub-project.

Failure to cross-build will reduce the reach of your rule, as users running Scalafix in a Scala version you are not building for will get either resolution errors (for published rules) or potential compilation errors (for unpublished rules, compiled on-the-fly). Note that scalafix-core brings scala-collection-compat, which allows to use the Scala 2.13 collection framework on Scala 2.12, and therefore removes the need for maintaining different source files depending on the Scala version.

The scalafix/ directory is a self-contained sbt build and can live in the same directory as your existing library.

To run unit tests, execute tests / test.

$ sbt
> ~tests / test

Import into IntelliJ

The project generated should import into IntelliJ like a normal project. Input and output test files are written in plain *.scala files and should have full IDE support.

Customizing input and output projects

The input and output projects are regular sbt projects and can have custom library dependencies. To add library dependencies to the input project, add the following sbt settings

 lazy val input = project.settings(
+  libraryDependencies += "org" %% "name" % "version"
 )

The only requirement is that the input project uses a Scala compiler version that is either supported by SemanticDB compiler plugin or built-in in the compiler.

The output project can use any Scala compiler version.

Running a single test

To run a single test case instead of the full test suite run the following command: tests / testOnly *MySuite -- -z MyRegex. This will run only test cases with the names matching the regular expression "MyRegex" inside test suites matching the regular expression *MySuite. See the ScalaTest documentation section: Selecting suites and tests for more details about the -z option.

Library API

To test custom Scalafix rules outside of sbt use the library API of scalafix-testkit directly. Start by adding a dependency on the scalafix-testkit artifact

cs fetch ch.epfl.scala:scalafix-testkit_2.12.20:0.14.3

Next, create a test suite that extends AbstractSemanticRuleSuite

package myproject
class MyTests
    extends scalafix.testkit.AbstractSemanticRuleSuite
    with org.scalatest.funsuite.AnyFunSuiteLike {

  runAllTests()
}

This setup assumes there will be a resource file scalafix-testkit.properties with instructions about the full classpath of the input sources and source directories for the input and output sources. To learn more about what values should go into scalafix-testkit.properties, consult the Scaladocs.

Latest Scaladoc: TestkitProperties

Before you write code →
  • sbt
    • Import into IntelliJ
    • Customizing input and output projects
    • Running a single test
  • Library API
Scalafix
Docs
Get startedRulesExtend Scalafix
Community
Chat on DiscordDiscuss on Scala Users
More
GitHub
Copyright © 2025 Scala Center