Kotlin 诊断系统负责在程序编译期间检测、创建和报告错误及警告。它为开发者提供关于代码问题的具体、可操作性的反馈。本文档涵盖了 Kotlin 编译器中诊断系统的架构和实现、诊断的定义、渲染和测试方式,以及它们如何与语言版本设置进行交互。
有关语言版本设置的详细信息,请参阅 语言版本设置。
诊断系统与 Kotlin 编译器前端紧密集成,特别是与 FIR(前端 IR)系统。诊断在编译的各个阶段生成,并提供反馈,帮助开发者理解和修复其代码中的问题。
来源:compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt
Kotlin 编译器中的诊断被组织成几个类别。每个诊断都有一个特定的类型、严重级别(错误、警告或信息),并且可能包含提供上下文特定信息的参数。
来源:compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt
诊断的创建和表示过程涉及多个协同工作的组件。
来源:analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KaFirDiagnostics.kt analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KaFirDiagnosticsImpl.kt
诊断在编译器中使用类似 DSL 的方法进行定义。每个诊断都定义了其严重级别(错误、警告或信息)、适用的 PSI 元素类型以及所需的任何参数。
例如,在 FirDiagnosticsList.kt 中,诊断的定义如下:
每个诊断在 FirErrorsDefaultMessages.kt 中都有相应的消息模板。
消息模板中的占位符在渲染诊断时会被实际的参数值替换。
来源:compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt
诊断系统与语言版本设置紧密集成,后者决定了特定 Kotlin 版本中可用的语言功能。不同的语言版本可能在什么构成错误或警告方面有不同的规则。
来源:compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
某些诊断可以使用 @Suppress 注解进行抑制,允许开发者在特定情况下静默警告或错误。但是,某些关键错误无法被抑制,如 FirNonSuppressibleErrorNames.kt 中所定义的。这确保了基本错误始终会被报告。
| 类别 | 不可抑制错误的示例 |
|---|---|
| 元错误 | UNSUPPORTED、UNSUPPORTED_FEATURE、NEW_INFERENCE_ERROR |
| 语法 | ILLEGAL_CONST_EXPRESSION、EXPRESSION_EXPECTED |
| 类型系统 | CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS、NO_CONSTRUCTOR |
| 名称解析 | INVISIBLE_REFERENCE、UNRESOLVED_REFERENCE |
Kotlin 编译器包含一套详尽的诊断测试,以确保它们得到正确报告。这些测试组织在 DiagnosticTestGenerated.java 和 FirLightTreeOldFrontendDiagnosticsWithLatestLanguageVersionTestGenerated.java 等文件中。
诊断测试通常包括:
来源:compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsWithLatestLanguageVersionTestGenerated.java compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/PhasedJvmDiagnosticPsiTestGenerated.java
Kotlin 编译器为 JVM、JavaScript 和 Native 目标提供了特定于平台的诊断系统。这些诊断解决了每个平台特有的问题。
例如,特定于 JVM 的诊断包括:
JVM_STATIC_NOT_IN_OBJECT_OR_CLASS_COMPANIONJVM_STATIC_ON_NON_PUBLIC_MEMBERJVM_FIELD_IN_INTERFACE来源:compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrorsDefaultMessages.kt compiler/fir/checkers/checkers.jvm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/jvm/FirJvmErrors.kt
让我们看一个简单的诊断报告示例。考虑以下 Kotlin 代码:
诊断过程如下:
Int(文字 42)和 String(声明的类型)之间的类型不匹配。TYPE_MISMATCH 诊断,并带有期望类型和实际类型的参数。此诊断无法被抑制,因为类型不匹配被认为是必须修复的基本错误。
Kotlin 诊断系统是编译器的一个复杂组件,用于检测和报告代码中的问题。它与语言版本设置紧密集成,确保诊断适用于指定的 Kotlin 版本。该系统为开发者提供清晰、可操作的反馈,帮助他们编写正确且符合习惯的 Kotlin 代码。
来源:compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt