Skip to content

Legacy Diagnostics API

Warning

This page documents the legacy diagnostics API based on KtFile.collectDiagnostics(), KtElement.diagnostics(filter), and the KaDiagnosticCheckerFilter enum. The whole surface is obsolete, and most of it is already deprecated. See Diagnostics for the replacement.

The legacy surface consisted of five endpoints. Their semantics were not aligned with each other: KtElement.diagnostics() covered a single element while KtFile.diagnostics() was recursive; collectDiagnostics() was eager and diagnostics() was lazy; suppressed diagnostics were reachable for files only, through diagnosticsIgnoringSuppression(). Each endpoint also took a KaDiagnosticCheckerFilter, a closed enum which named four of the eight combinations of the three checker kinds.

The KaDiagnostics query replaces all of them with a single entry point and composable modifiers.

Endpoints

Legacy endpoint Replacement
KtElement.diagnostics(filter): Collection<...> element.diagnostics().withCheckers(...).directOnly(true)
KtElement.directDiagnostics(filter): Collection<...> element.diagnostics().withCheckers(...).directOnly(true)
KtFile.collectDiagnostics(filter): Collection<...> file.diagnostics().withCheckers(...).toList()
KtFile.diagnostics(filter): Sequence<...> file.diagnostics().withCheckers(...)
KtFile.diagnosticsIgnoringSuppression(filter) file.diagnostics().withCheckers(...).ignoreSuppressed(false)

Checker filters

KaDiagnosticCheckerFilter becomes a set of KaDiagnosticCheckerKind values passed to withCheckers(). Unlike the enum, the set covers every combination of kinds:

KaDiagnosticCheckerFilter withCheckers() argument
ONLY_COMMON_CHECKERS KaDiagnosticCheckerKind.COMMON, which is also the default
ONLY_EXTENDED_CHECKERS KaDiagnosticCheckerKind.EXTENDED
ONLY_EXPERIMENTAL_CHECKERS KaDiagnosticCheckerKind.EXPERIMENTAL
EXTENDED_AND_COMMON_CHECKERS KaDiagnosticCheckerKind.COMMON, KaDiagnosticCheckerKind.EXTENDED

Because ONLY_COMMON_CHECKERS is what a query requests by default, a withCheckers() call can be dropped entirely when migrating from it.

Watch out for the scope

The legacy KtElement.diagnostics(filter) and KtElement.directDiagnostics(filter) both returned the diagnostics of the element alone, while KtFile.collectDiagnostics(filter) was recursive. In the new API, the scope is a modifier instead of being encoded in the endpoint name, and the default is the recursive one, which is the correct choice in most cases:

// Legacy: the element alone
element.diagnostics(KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS)

// Same behavior
element.diagnostics().directOnly(true)

// Everything reported inside the element, which the
// legacy element endpoints could not express
element.diagnostics()

Dropping directOnly(true) while migrating is often the actual fix: a diagnostic which concerns an element may be reported on one of its children, so the direct result was rarely the complete answer. See directOnly.

Migration examples

Collecting file diagnostics

// Legacy
analyze(file) {
    val diagnostics = file.collectDiagnostics(
        KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS,
    )
    val messages = diagnostics.map { it.defaultMessage }
}

// New
analyze(file) {
    val messages = file.diagnostics()
        .map { it.defaultMessage }
        .toList()
}

The query is lazy, so the toList() call is what materializes the result. Where the legacy collection was only iterated over, toList() can be dropped, and the analysis then stops as soon as the iteration does.

Extended checkers

// Legacy
file.diagnostics(
    KaDiagnosticCheckerFilter.EXTENDED_AND_COMMON_CHECKERS,
)

// New
file.diagnostics().withCheckers(
    KaDiagnosticCheckerKind.COMMON,
    KaDiagnosticCheckerKind.EXTENDED,
)

Suppressed diagnostics

// Legacy
file.diagnosticsIgnoringSuppression(
    KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS,
)

// New
file.diagnostics().ignoreSuppressed(false)

Suppression is per-diagnostic data now rather than a collection mode: the query yields suppressed diagnostics together with the regular ones, and each of them is marked with isSuppressed. The endpoint also works for any element, not only for a file.

Stability

collectDiagnostics() is the only stable endpoint here: it is neither experimental nor deprecated, even though its semantics are superseded. The other legacy endpoints are experimental and deprecated.

The replacement is annotated @KaExperimentalApi, so migrating from collectDiagnostics() does trade a stable endpoint for one whose contract may still change between versions. It is, however, the only surface which can express element scopes, suppressed diagnostics, and arbitrary combinations of checker kinds.