- 开发工具
- 代码质量
- Lint
- 格式化
【免费下载链接】ktlint
An anti-bikeshedding Kotlin linter with built-in formatter
ktlint 是一款遵循 "anti-bikeshedding"(反无休止风格争论)理念的 Kotlin 静态代码检查工具,内置格式化器,其设计灵感源自 JavaScript 生态的standard与 Go 生态的gofmt。本指南以当前仓库的 README.md 为主线,带你完成从安装、默认扫描到自动修复的完整实践闭环,并深入仓库源码说明其"零配置"背后的实现原理,帮助你快速掌握在 Kotlin 项目中使用 ktlint 的日常操作与扩展方式。
ktlint 的核心特性
ktlint 的目标是让团队无需在代码风格上反复争论,用一套开箱即用的约定即可完成风格统一。根据仓库 README.md 的归纳,其关键特性包括:
- 无需配置即可使用(No configuration required):开箱即用,默认扫描规则覆盖绝大多数 Kotlin 风格约定;
- 内置规则集(Built-in Rule sets):标准规则集由 100+ 条规则组成,详见下文"内置标准规则集"一节;
- 内置格式化器(Built-in formatter):大部分风格违规可以被自动修复;
- 支持
.editorconfig:规则可通过.editorconfig进行细粒度调整与开关; - 多种内置报告器(reporters):
plain、json、html、checkstyle等; - 可执行 JAR 与原生二进制:既可在 JVM 上运行,也可通过 GraalVM 原生镜像直接执行;
- 可扩展自定义规则集与报告器:通过 JAR 加载第三方规则与输出格式。
快速开始
第一步:安装
在 macOS 或 Linux 上,最简单的方式是通过 Homebrew 安装:
brew install ktlint除 Homebrew 外,ktlint 还支持多种安装渠道:
- 原生二进制与可执行 JAR:每个 release 均提供 Linux x86-64、macOS Apple Silicon、Windows x86-64 三种原生可执行文件(GraalVM 原生镜像),以及需要 JVM 的
ktlint可执行 JAR 和供 Windows 使用的ktlint.bat,详见 安装与下载校验; - 其他包管理器:如 MacPorts(
port install ktlint)等; - 构建工具集成:通过 Maven / Gradle 插件接入构建生命周期,详见 集成方式。
注意:原生可执行文件由 GraalVM
native-image预编译,运行时无法通过命令行加载第三方规则集/报告器 JAR,只能使用内置规则与报告器;需要自定义扩展时请使用可执行 JAR(ktlint)。
第二步:检查并格式化代码
ktlint 会递归扫描当前目录及其子目录下所有.kt与.kts文件,并对能够自动修复的违规进行修正:
# 自动修复代码风格违规(两种写法等价) ktlint --format # 或 ktlint -F在仓库的 KtlintCommandLine.kt 中可以确认--format与-F为同一选项的两个名称。更完整的命令行用法(globs、报告器、baseline、git hooks 等)参见 CLI 使用文档。
零配置背后的实现:默认扫描模式与内置标准规则集
为什么直接运行ktlint就能检查整个项目?源码给出了答案。
默认匹配模式
在 FileUtils.kt 中定义了默认的文件扩展名与默认 glob 模式:
private val DEFAULT_KOTLIN_FILE_EXTENSIONS = setOf("kt", "kts") internal val DEFAULT_PATTERNS = DEFAULT_KOTLIN_FILE_EXTENSIONS.map { "**/*.$it" }即默认情况下匹配所有递归路径下的**/*.kt与**/*.kts。当命令行未提供任何文件参数时,KtlintCommandLine.kt 会启用DEFAULT_PATTERNS,随后通过Files.walkFileTree遍历目录树;隐藏目录(如.git)会被跳过,见 FileUtils.kt。
内置标准规则集
标准规则集在 StandardRuleSetProvider.kt 中注册了 100+ 条规则,覆盖命名、间距、换行、KDoc、导入排序、缩进等方方面面。几个有代表性的规则:
规则 ID(standard:前缀) | 职责 | 源码位置 |
|---|---|---|
filename | 文件名必须与顶层类一致 | FilenameRule.kt |
final-newline | 文件末尾必须有换行 | FinalNewlineRule.kt |
indent | 缩进风格(配合indent_size/indent_style) | IndentationRule.kt |
import-ordering | 导入语句排序 | ImportOrderingRule.kt |
max-line-length | 最大行长度 | MaxLineLengthRule.kt |
no-unused-imports/no-wildcard-imports | 未使用与通配符导入 | NoUnusedImportsRule.kt / NoWildcardImportsRule.kt |
no-semi/no-trailing-spaces | 禁止分号与行尾空格 | NoSemicolonsRule.kt / NoTrailingSpacesRule.kt |
spacing-*(如op-spacing、comma-spacing、paren-spacing) | 各类符号周围空格 | 对应 SpacingAroundOperatorsRule.kt 等 |
trailing-comma-on-declaration-site/-call-site | 尾随逗号策略 | TrailingCommaOnDeclarationSiteRule.kt 等 |
部分规则之间存在执行顺序依赖(例如max-line-length需要依赖某些换行规则先执行),规则的依赖关系图见 规则依赖说明(示意图rule-dependencies.png位于 documentation/release-latest/docs/assets/images/rule-dependencies.png)。
另外,标准规则集中标记为experimental(实验性)的规则默认不执行,必须在.editorconfig中设置ktlint_experimental = enabled才会启用。
通过 .editorconfig 配置规则
ktlint 使用有限的.editorconfig属性进行额外配置。每个属性在未显式定义时都有合理的默认值;属性需要在[*.{kt,kts}]分段下设置才能生效。详细参考 配置文档。
注意:IntelliJ IDEA 存在一个与
.editorconfig相关的自动格式化问题,会在 glob 语句中额外加入空格,把[*{kt,kts}]变成[*{kt, kts}],导致 ktlint 忽略该分段。应始终写作[*.{kt,kts}]且中间无空格。
代码风格
默认采用ktlint_official风格,也可切换为intellij_idea或android_studio:
[*.{kt,kts}] ktlint_code_style = ktlint_official启用 / 禁用规则
规则集与单条规则分别通过ktlint_前缀的属性进行开关:
[*.{kt,kts}] ktlint_standard = disabled # 禁用 standard 规则集全部规则 ktlint_experimental = enabled # 启用所有规则集中的实验性规则 ktlint_custom-rule-set = enabled # 启用自定义规则集(非 ktlint 提供) ktlint_standard_final-newline = disabled # 禁用单条规则 final-newline ktlint_standard_some-experimental-rule = enabled # 启用标准规则集中的某条实验性规则规则属性的优先级高于规则集属性:例如即使整个规则集被禁用,只要某条规则被单独启用,该规则仍会执行。
规则专属配置项
一些规则支持专属配置属性,仅在该规则启用时生效:
| 配置项 | 对应规则 |
|---|---|
ij_kotlin_allow_trailing_comma/ij_kotlin_allow_trailing_comma_on_call_site | 尾随逗号相关规则 |
ij_kotlin_imports_layout/ij_kotlin_packages_to_use_import_on_demand | import-ordering/no-wildcard-imports |
indent_size/indent_style | indent |
insert_final_newline | final-newline |
ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than | chain-method-continuation |
ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than | class-signature |
ktlint_ignore_back_ticked_identifier | max-line-length |
ktlint_function_naming_ignore_when_annotated_with | function-naming |
ktlint_function_signature_body_expression_wrapping/ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than | function-signature |
max_line_length | max-line-length及若干其他规则 |
按目录覆盖配置
.editorconfig天然支持按目录分段覆盖属性,例如:
[*.{kt,kts}] ktlint_standard_import-ordering = disabled [api/*.{kt,kts}] ktlint_standard_indent = disabled上述配置中import-ordering在所有包(含api子包)被禁用,而indent仅在api包及其子包被禁用。
常用命令行操作
下面命令均可在 CLI 使用文档 找到完整说明,其参数解析与执行逻辑位于 KtlintCommandLine.kt。
使用 glob 精确指定扫描范围
glob 采用.gitignore风格语法,从左到右处理,!前缀表示取反(排除);隐藏文件夹会被跳过:
# 检查 src/ 下所有 .kt 文件,但排除以 Test.kt 结尾的文件 ktlint 'src/**/*.kt' '!src/**/*Test.kt' # 检查 src/ 下所有 .kt 文件,但排除 generated 目录及其子目录 ktlint 'src/**/*.kt' '!src/**/generated/**'若只给出排除模式而没有包含模式,ktlint 会自动使用默认包含模式(**/*.kt、**/*.kts)作为兜底,见 FileUtils.kt。
加载自定义规则集
ktlint --ruleset=/path/to/custom-ruleset.jar # 或 ktlint -R /path/to/custom-ruleset.jar--ruleset选项在源码中定义为可逗号分隔、可多次指定的参数(KtlintCommandLine.kt),即一次可以加载多个自定义规则集 JAR。若规则集中含实验性规则,同样需要ktlint_experimental = enabled才会运行。
违规报告与多报告器
未指定报告器时默认使用plain报告器。可按文件分组、按规则统计,或输出多种格式:
# 按文件分组显示违规 ktlint --reporter=plain?group_by_file # 按规则统计违规数量(适合存量项目分析规则分布) ktlint --reporter=plain-summary # 同时输出到控制台与文件(多个 reporter 可叠加) ktlint --reporter=plain --reporter=checkstyle,output=ktlint-report-in-checkstyle-format.xml内置报告器包括plain、plain-summary、json、sarif、checkstyle、html,其实现分布在 ktlint-cli-reporter-json、ktlint-cli-reporter-checkstyle、ktlint-cli-reporter-html 等独立模块中。第三方报告器可通过--reporter=<id>,artifact=/path/to/reporter.jar,output=...方式加载。
使用 baseline 渐进式清理存量问题
存量项目违规较多时,可先建立 baseline,后续运行会静默忽略 baseline 中已登记的违规:
ktlint --baseline=ktlint-baseline.xml # 文件不存在时会自动创建读取 stdin 与输出到 stdout
# 从 stdin 读取代码并检查,违规输出到 stderr ktlint --stdin # 从 stdin 读取并格式化,格式化结果写到 stdout,违规输出到 stderr ktlint --stdin -F配合--stdin-path /path/to/file/Foo.kt可为 stdin 内容提供一个虚拟文件路径,供依赖文件名的规则(如filename)使用;此时--format不会改写该真实文件。从源码看,当从 stdin 读取时 ktlint 会自动禁用filename规则(KtlintCommandLine.kt),因为该规则无法与 stdin 配合使用。
生成 .editorconfig 脚手架
# 按指定代码风格生成 .editorconfig ktlint generateEditorConfig --code-style ktlint_official # 生成时同时考虑自定义规则集的规则 ktlint --ruleset=/path/to/custom-ruleset.jar generateEditorConfig --code-style android_studio生成的配置文件只包含当前已加载规则实际使用到的配置项。该功能由 GenerateEditorConfigSubCommand.kt 实现。
安装 Git 钩子
在提交或推送前自动执行检查:
ktlint installGitPreCommitHook ktlint installGitPrePushHook退出码约定
与 CI 或工具链集成时需关注退出码(定义于 KtlintCommandLine.kt):
| 退出码 | 含义 |
|---|---|
| 0 | 执行成功;若含格式化选项,则无违规或全部违规已被自动修复 |
| 1 | 已成功格式化但仍有至少一条违规需手动修复(通常不可自动修复) |
| 2 | 发生 IO 异常,检查日志 |
| 3 | stdin 输入不是合法的 Kotlin(脚本)代码 |
| 4 | stdin 输入执行期间发生异常,开启日志查看堆栈 |
| 5 | 命令行选项指向无效路径 |
| 6 | 提供的规则集 JAR 不受支持 |
| 7 | 报告器配置无效 |
| 123 | 使用--force-lint-after-format时格式化结果无法通过再解析(仅用于回归测试) |
其他常用选项
--color/--color-name=<colorName>:彩色输出并自定义颜色;-h/--help:打印帮助信息;--limit=<n>:限制最多显示的错误数(默认显示全部);--relative:以相对于工作目录的路径输出(dir/file.kt而非绝对路径);--patterns-from-stdin[=<分隔符>]:从 stdin 读取额外的匹配模式(默认以换行分隔,空字符串表示使用 NUL 字节);与--stdin互斥;-V/--version:打印版本信息;--log-level/-l:设置最小日志级别(trace、debug、info、warn、error、none),默认info;--ignore-autocorrect-failures:忽略所有无法自动修复的违规(源码过滤逻辑见 KtlintCommandLine.kt)。
扩展 ktlint:自定义规则集
ktlint 依赖 JavaServiceLoader机制发现 classpath 上的规则集。仓库中的 ktlint-ruleset-template 是一个可直接克隆的最小示例工程(Gradle 构建),完整的开发说明见 自定义规则集文档。
编写一条规则
规则继承RuleV2,并在 AST 遍历钩子中实现检查逻辑。以模板中的 NoVarRule.kt 为例:
public class NoVarRule : RuleV2( ruleId = RuleId("$CUSTOM_RULE_SET_ID:no-var"), about = RuleV2.About( maintainer = "Your name", repositoryUrl = "https://github.com/your/project/", issueTrackerUrl = "https://github.com/your/project/issues", ), ) { override fun beforeVisitChildNodes( node: ASTNode, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> AutocorrectDecision, ) { if (node.elementType == VAR_KEYWORD) { emit(node.startOffset, "Unexpected var, use val instead", false) } } }一条规则需要实现以下钩子中的一个或多个:
Rule.beforeFirstNode;RuleAutocorrectApproveHandler.beforeVisitChildNodes;RuleAutocorrectApproveHandler.afterVisitChildNodes;Rule.afterLastNode。
在 AST 遍历过程中,这些钩子按名称所示顺序被调用;可以用 IntelliJ IDEA 的 PsiViewer 插件查看任意代码的 AST 结构辅助开发(截图 psi-viewer.png)。
注册规则集
规则集通过 CustomRuleSetProvider.kt 暴露规则实例,并需要在resources/META-INF/services/io.github.ktlint.core.cli.ruleset.core.api.RuleSetV2Provider文件中注册提供者全限定名,ktlint 才能通过ServiceLoader发现它。
构建并运行
cd ktlint-ruleset-template/ ../gradlew build然后使用-R加载构建出的 JAR 并检查示例代码:
echo 'var v = 0' > test.kt ktlint -R build/libs/ktlint-ruleset-template.jar --log-level=debug --relative test.kt从--log-level=debug输出可以看到,自定义规则custom:no-var会被合并进规则执行顺序中(与标准规则集规则一起按依赖关系排序),并输出违规信息。如果你只想集成到既有项目而不必逐条手写规则,也可以直接使用社区 Gradle/Maven 插件(如 jlleitschuh/ktlint-gradle、jeremymailen/kotlinter-gradle、diffplug/spotless 等,参见 集成文档)。
结语
从零配置扫描、-F一键格式化,到.editorconfig细粒度调优,再到自定义规则集扩展,ktlint 为 Kotlin 项目的代码风格治理提供了一条完整路径。日常使用中记住三个核心动作即可:直接运行ktlint做检查、用ktlint -F自动修复、用ktlint --baseline=...处理存量项目。更细致的用法可随时查阅仓库内的 CLI 文档 与 规则配置文档。
- 开发工具
- 代码质量
- Lint
- 格式化
【免费下载链接】ktlint
An anti-bikeshedding Kotlin linter with built-in formatter
相关推荐
Ktlint 完整指南:无需配置的 Kotlin 代码风格检查与自动格式化工具
Ktlint 完整指南:无需配置的 Kotlin 代码风格检查与自动格式化工具 Ktlint 是一个面向 Kotlin 的「反自行车棚效应」(anti bike
开发工具代码质量Lint格式化ktlint 快速上手指南:从零开始安装、Lint 与自动格式化 Kotlin 代码
ktlint 快速上手指南:从零开始安装、Lint 与自动格式化 Kotlin 代码 本篇指南以 ktlint 官方快速入门文档( documentation/
开发工具代码质量Lint格式化Kotlin代码规范利器ktlint:零配置自动格式化完整指南
Kotlin代码规范利器ktlint:零配置自动格式化完整指南 Kotlin代码规范利器ktlint是一款强大的 Kotlin代码格式化工具 ,能够帮助开发者自
开发工具代码质量Lint格式化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考