Scalafix

← 返回目录 > ← 返回总览

相关工具推荐

工具 说明
Scalafmt Scala 代码格式化工具,与 Scalafix 互补
Spotless 多语言格式化调度插件,可集成 Scalafmt 做 Scala 格式化
Pre-commit 多语言 Git 钩子管理框架,可通过 local hook 调用 Scalafix
Checkstyle Java 代码风格检查工具,Scalafix 是 Scala 对应的代码质量工具

1. 简介

Scalafix 是由 Scala Center 开发维护的 Scala 代码质量和重构工具,是 Scala 生态中的主流 Linter。它支持语法规则(无需编译)和语义规则(需 SemanticDB 编译器输出)两类规则,内置 9 条规则,并支持自定义规则。

  • 主要检查语言:Scala(Scala 2.12、2.13、Scala 3)
  • 主要检查能力:检测代码异味、废弃 API、不合规语法;涵盖代码质量检查
  • 核心检查原理:基于 Scalameta 解析器,语法规则直接分析 AST,语义规则通过 SemanticDB 获取类型信息
  • 检查规则/选项:9 个内置规则(4 个语义规则如 ExplicitResultTypes、NoAutoTupling、OrganizeImports、RemoveUnused;5 个语法规则如 DisableSyntax、ProcedureSyntax 等),全量规则列表
  • GitHub 仓库https://github.com/scalacenter/scalafix(874 stars)
  • 开源协议:BSD-3-Clause
  • 最新稳定版本:0.14.7
  • 运行环境要求:需 JDK 11+;通过 sbt-scalafix 插件集成
  • 误报率:低

2. 官方文档

资源 链接
官方文档首页 https://scalacenter.github.io/scalafix/
安装文档 https://scalacenter.github.io/scalafix/docs/users/installation.html
内置规则文档 https://scalacenter.github.io/scalafix/docs/rules/overview.html
配置文档 https://scalacenter.github.io/scalafix/docs/users/configuration.html
GitHub 仓库 https://github.com/scalacenter/scalafix
Releases 页面 https://github.com/scalacenter/scalafix/releases

3. 社区优秀实践

3.1 ZIO

ZIO 是 Scala 函数式编程框架,使用 Scalafmt 统一格式,并通过 Scalafix 管理代码质量规则。

ZIO 的实践特点:

  • 通过 .scalafmt.confproject.excludeFilters 排除 Scalafix 测试规则目录
  • 使用 Scalafmt 的 rewrite.rules 完成部分代码重写,与 Scalafix 规则互补

3.2 Cats

Cats 是 Typelevel 生态核心库,同时使用 Scalafmt 和 Scalafix 管理代码质量。

Cats 的实践特点:

  • .scalafmt.conf 中通过 project.excludeFilters = ["scalafix/*"] 排除 Scalafix 规则测试目录
  • 将 Scalafix 自定义规则测试放在独立目录中管理
  • 使用 Scalafmt 的 rewrite.scala3.convertToNewSyntax = true 统一 Scala 3 新语法

3.3 Play Framework

Play Framework 是 Scala/Web 领域主流 Web 框架,使用 Scalafmt 统一格式,配合 Scalafix 做代码质量检查。

Play Framework 的实践特点:

  • 通过 Scalafmt 的 rewrite.rules 自动整理 import 和修饰符顺序,减少 Scalafix 的 OrganizeImports 规则负担
  • 使用 fileOverride 为 Scala 3 目录切换 dialect,确保 Scalafix 规则在不同 Scala 版本下兼容

4. 工具配置说明

4.1 配置文件说明

Scalafix 涉及以下配置文件:

配置文件 用途 使用场景
.scalafix.conf Scalafix 主配置文件(HOCON 格式),声明启用的规则及规则参数 所有项目,控制规则集与规则行为

配置文件默认位置:仓库根目录 .scalafix.conf(HOCON 格式)。

4.2 .scalafix.conf 配置详解

.scalafix.conf 是 Scalafix 的主配置文件,通过 rules 字段声明启用的规则列表,并可为每个规则配置参数。

配置项说明

配置项 类型 说明
rules list[string] 启用的规则列表,按顺序执行
<RuleName>.<param> 任意 规则专属参数,键名为规则名加参数名(如 DisableSyntax.noVars

推荐配置示例

新项目推荐规则集:全部为语法规则,无需 SemanticDB。

# .scalafix.conf
rules = [
  DisableSyntax
  OrganizeImports
  RedundantSyntax
  NoAutoTupling
  ProcedureSyntax
  NoValInForComprehension
]
规则 类型 作用
DisableSyntax 语法 禁用 varreturnnullwhile 等不推荐语法
OrganizeImports 语法 整理和排序 import 语句
RedundantSyntax 语法 移除冗余语法(如多余的 Unit 返回类型)
NoAutoTupling 语法 禁用自动元组化,避免隐含参数被包装为元组
ProcedureSyntax 语法 将过程语法 def foo { } 改写为 def foo: Unit = { }
NoValInForComprehension 语法 移除 for 推导中多余的 val

进阶规则集(需 SemanticDB):团队熟悉语法规则后,可逐步引入语义规则。

# .scalafix.conf
rules = [
  DisableSyntax
  OrganizeImports
  RedundantSyntax
  NoAutoTupling
  ProcedureSyntax
  ExplicitResultTypes
  RemoveUnused
]
规则 类型 作用 前置条件
ExplicitResultTypes 语义 为公共成员补全显式返回类型 需 SemanticDB
RemoveUnused 语义 移除未使用的 import 和局部变量 需 SemanticDB + -Wunused:imports 编译选项

引入语义规则时需在 build.sbt 中配置 SemanticDB 启用选项,详见第 5 章集成方式说明。


5. 主流集成方式

5.1 sbt 集成(生态主流方式)

sbt 是 Scala 生态事实标准构建工具,Scalafix 通过官方 sbt-scalafix 插件集成(需 sbt 1.4+)。

project/plugins.sbt 中添加插件:

addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.14.7")

常用 sbt 任务:

任务 作用
sbt scalafix 运行所有启用的规则(自动修复)
sbt scalafixAll 运行所有配置(含 Test)的规则
sbt 'scalafix --check' 检查模式(不修改,CI 用,有 diff 即失败)
sbt 'scalafixAll --check' 检查所有配置(不修改)
sbt scalafix <规则名> 运行指定规则

语义规则前置条件:在 build.sbt 中启用 SemanticDB:

ThisBuild / semanticdbEnabled := true
ThisBuild / semanticdbVersion := scalafixSemanticdb.revision

增量检查:sbt-scalafix 插件可通过传递文件路径限定作用范围:

sbt "scalafix src/main/scala/com/example/Foo.scala"

注意:语义规则需要完整编译上下文(SemanticDB),仅检查变更文件可能导致语义规则结果不完整。语法规则不受此限制。

通过 pre-commit local hook 集成 Scalafix 时(hook 通过 sbt scalafix 调用 sbt 任务),pre-commit 框架默认只对暂存区中变更的 .scala 文件触发 hook。由于 Scalafix 的 local hook 使用 pass_filenames: false(让 sbt 自行管理检查范围),实际增量由 sbt 的构建范围决定。

# .pre-commit-config.yaml
- repo: local
  hooks:
    - id: scalafix
      name: Scalafix
      entry: sbt scalafix
      language: system
      files: \.scala$
      pass_filenames: false # 由 sbt 控制检查范围

注意:语义规则(如 ExplicitResultTypesRemoveUnused)需要完整编译上下文(SemanticDB),仅检查变更文件可能导致语义规则结果不完整。语法规则不受此限制。pre-commit 负责"何时触发",sbt 负责"检查什么"。CI 中可通过 pre-commit run --all-files 做全量检查。

5.2 IDE 集成

IDE 集成方式
IntelliJ IDEA 安装 Scala 插件,Scalafix 通过 sbt 任务运行,IDE 不直接集成
VS Code 安装 Metals 扩展,Metals 支持 Scalafix 规则运行和快速修复
Neovim 通过 nvim-metals LSP 集成 Scalafix

5.3 CLI 集成

通过 Coursier 安装 CLI:

cs install scalafix

常用 CLI 命令:

# 运行 .scalafix.conf 中配置的规则
scalafix

# 检查模式(不修改,CI 用)
scalafix --check

# 运行指定规则
scalafix OrganizeImports

# 指定 SemanticDB 路径(语义规则需要)
scalafix --sourceroot .

增量检查:结合 git diff 只检查暂存区中变更的 .scala 文件:

# 只检查 git 暂存区中变更的 .scala 文件
CHANGED=$(git diff --name-only --diff-filter=ACMR --cached -- '*.scala')
if [ -n "$CHANGED" ]; then
  sbt "scalafix --check $CHANGED"
fi

CI 脚本调用:在 CI 环境中通过脚本调用 Scalafix(或 sbt 任务)进行格式化检查。

GitHub Actions 示例:

name: Scalafix Check
on: [pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "21"
      - uses: sbt/setup-sbt@v1
      - run: sbt 'scalafixAll --check'

增量检查:GitHub Actions 中按 PR 变更文件触发增量检查:

- name: Check changed files only
  run: |
    CHANGED=$(git diff --name-only --diff-filter=ACMR ${{ github.event.pull_request.base.sha }} -- '*.scala' | tr '\n' ' ')
    if [ -n "$CHANGED" ]; then
      sbt "scalafix --check $CHANGED"
    fi

6. 告警抑制(屏蔽)方法

6.1 通过工具配置文件屏蔽

.scalafix.conf 中移除或注释不需要的规则:

# .scalafix.conf:移除 DisableSyntax 规则
rules = [
  OrganizeImports
  RedundantSyntax
  NoAutoTupling
  ProcedureSyntax
]

对特定规则配置参数以放宽限制:

# .scalafix.conf:DisableSyntax 规则中允许 var
rules = [
  DisableSyntax {
    noVar = false
    noReturn = true
    noNull = true
  }
  OrganizeImports
]

官方文档:规则配置

6.2 通过代码屏蔽

Scalafix 支持行级和块级注释屏蔽:

// 行级屏蔽:抑制当前行
val x = 1 // scalafix:ok

// 块级屏蔽:抑制一段代码
// scalafix:off DisableSyntax
var mutableState = 0
// scalafix:on DisableSyntax

官方文档:抑制语法

6.3 通过构建配置屏蔽

sbt 项目中可通过 scalafixConfig 指定不同配置文件,或通过 scalafixRules 动态调整规则:

// build.sbt:为 Test 配置使用不同规则集
Test / scalafixConfig := Some(file(".scalafix.test.conf"))

6.4 通过 sbt 任务范围屏蔽

通过 sbt 的 Configuration 作用域,只为特定配置运行 Scalafix:

# 只对 Compile 配置运行 Scalafix
sbt Compile/scalafix