Diktat превращает код-ревью Kotlin в автоматизированную рутину
Знакома ситуация, когда на пулреквесте треть комментариев уходит на споры об оформлении? Кто-то оставил отрицательный boolean вроде isNoError, кто-то смешал порядок методов в классе, а кто-то сравнил числа с плавающей точкой через оператор ==. Формально код компилируется и тесты проходят, но читать такую кодовую базу через полгода становится физически больно.
Обычно для Kotlin берут связку ktlint и detekt. Первый следит за отступами и пробелами, второй ищет явные запахи кода. Но между ними остается серая зона архитектурного стиля и соглашений, где команды либо пишут собственные правила, либо тратят время на ручные замечания. Репозиторий diKTat от команды SaveOurTool решает именно эту задачу.
Что такое diKTat
Проект представляет собой строгий набор правил кодовой конвенции для Kotlin. Технически diKTat построен поверх ktlint и анализирует синтаксическое дерево (AST) файлов. В репозиторий зашит объемный гайдлайн, разбитый по разделам: именование, комментарии KDoc, структура классов, функции, работа с типами и переменными.
Инструмент содержит больше ста проверок, многие из которых вообще не встречаются в других статических анализаторах. Главное удобство в том, что diKTat умеет не просто ругаться в консоль, а автоматически исправлять найденные несоответствия на лету.
Неочевидные проверки, которые спасают код
Большинство линтеров фокусируются на форматировании. DiKTat копает глубже и ловит семантические странности.
Чистота именования и логики
В diKTat встроен запрет на переменные с двойным отрицанием. Если объявить флаг val isNotValid = false, линтер потребует переименовать его в позитивный аналог. Конструкции вроде !isNotValid ломают мозг при чтении, поэтому правило экономит нервы всей команде.
Также проверяются вызовы функций с отрицанием. Вместо !list.isEmpty() инструмент настойчиво предложит написать list.isNotEmpty().
Порядок членов внутри классов
Частая беда больших файлов на Kotlin заключается в каше из полей, функций и объектов. DiKTat жестко контролирует структуру:
- Константы времени компиляции
- Обычные свойства
- Late-init свойства
- Блоки
init(причем инструмент запрещает плодить несколькоinitблоков без явной необходимости) - Конструкторы
- Публичные, internal, protected и private методы
- Companion object
Если кто-то положит приватный хелпер перед публичным API, билд в CI упадет.
Безопасность типов и вычислений
Инструмент запрещает прямое сравнение типов Float и Double через ==. Из-за особенностей двоичного представления чисел с плавающей точкой такое сравнение часто приводит к трудноуловимым багам. DiKTat заставит использовать проверку дельты через abs(a - b) > EPS или перейти на BigDecimal.
Еще одна приятная проверка отслеживает избыточные касты. Если Kotlin уже выполнил Smart Cast внутри условия, вызов as Type будет помечен как лишний шум.
// Было
if (x is String) {
print((x as String).length)
}
// Стало после автофикса
if (x is String) {
print(x.length)
}
Как запускать и настраивать
DiKTat можно запустить через терминал, интегрировать в сборку Gradle или Maven, а также подключить через агрегатор Spotless.
Подключение в Gradle
Для проектов на Gradle с Kotlin DSL плагин подключается в пару строк:
plugins {
id("com.saveourtool.diktat") version "2.0.0"
}
diktat {
inputs {
include("src/**/*.kt")
exclude("src/test/kotlin/excluded/**")
}
reporters {
plain()
html {
output = file("build/reports/diktat.html")
}
}
}
Проверка запускается командой ./gradlew diktatCheck, а автоисправление всего, до чего анализатор сможет дотянуться, выполняется через ./gradlew diktatFix.
Тонкая настройка правил
Конфигурация живет в обычном YAML-файле diktat-analysis.yml. Каждое правило включается или выключается отдельно, у многих есть специфичные параметры:
name: HEADER_MISSING_OR_WRONG_COPYRIGHT
enabled: true
configuration:
isCopyrightMandatory: true
copyrightText: Copyright (c) MyTeam, 2024. All rights reserved.
name: HEADER_NOT_BEFORE_PACKAGE
enabled: true
ignoreAnnotated: [Generated, Controller]
Если нужно подавить конкретную проверку локально, стандартная аннотация @Suppress("FUNCTION_NAME_INCORRECT_CASE") или общий @Suppress("diktat") работают прямо в коде.
Постепенное внедрение через baseline
Включить строгий линтер на старом проекте с 50 тысячами строк кода без подготовки невозможно. Разработчики утонут в тысячах предупреждений.
Для этого в diKTat предусмотрен режим baseline. При первом запуске утилита генерирует XML-файл со всеми текущими косяками в проекте:
./diktat --baseline=diktat-baseline.xml "src/**/*.kt"
Файл с базовой линией коммитится в репозиторий. После этого линтер перестает ругаться на старый код и блокирует билд только в том случае, если кто-то принес новые нарушения в свежем коммите.
Интеграция с GitHub Actions

Инструмент умеет отдавать отчеты в формате SARIF. В сочетании с GitHub Actions ошибки стилей и предупреждения подсвечиваются прямо в интерфейсе пулреквеста с точным указанием строк. Никаких сторонних ботов для комментариев настраивать не придется.
name: Upload SARIF report
uses: github/codeql-action/upload-sarif@v1
if: always()
with:
sarif_file: build/reports/diktat/diktat.sarif
Стоит ли пробовать
DiKTat очень бескомпромиссный. Местный гайдлайн требует явного порядка импортов, ограничивает длину функций тридцатью строками, контролирует наличие документации KDoc для публичных методов и запрещает лишние var.
Для пет-проекта на двоих такие ограничения покажутся избыточными. Но если над сервисом работает распределенная команда или вы развиваете open-source библиотеку, diKTat снимает головную боль по синхронизации стиля и освобождает время на код-ревью для обсуждения архитектуры, а не пробелов. Начать проще всего с подключения Gradle-плагина в режиме проверки одного модуля и генерации baseline.
