Опирается на правила:
JS-CS-1…JS-CS-5иJS-CS-X1…JS-CS-X3из Java Style Guide → раздел 9. Enforcement через Checkstyle.
Важно знать
- Checkstyle обязателен через стандартный gradle plugin.
- Конфиг в репо (
config/checkstyle/checkstyle.xml), не submodule, не external.- Только механические правила: именование, импорты, отступы, whitespace.
- Семантика (Lombok, комментарии, Java 21+) — НЕ в Checkstyle, через
ucp-java-style-review.maxWarnings = 0+ignoreFailures = falseобязательно.- Suppression с
justifyидо: YYYY-MM-DD.- Привязка к
check, неcheckSecurity— lint-уровень.@SuppressWarningsбез justify ≥ 30 символов — запрещено.
Style Guide делится на две части: механические правила (нейминг, импорты, отступы) — проверяемы регулярками, выносим в Checkstyle. Семантические правила (Lombok defaults, комментарии, Java 21+ фичи) — требуют контекста, остаются для AI-скилла ucp-java-style-review. Checkstyle и скилл — дополняющие, не альтернативные.
Подключение Checkstyle
JS-CS-1: gradle plugin + config в репо.
plugins {
id 'checkstyle'
}
checkstyle {
toolVersion = '10.20.2'
configFile = file('config/checkstyle/checkstyle.xml')
configProperties = [ 'baseDir': rootDir ]
maxWarnings = 0
ignoreFailures = false
}
tasks.withType(Checkstyle).configureEach {
reports {
xml.required = true
html.required = true
sarif.required = true
}
}
sarif.required = true — output в SARIF формат публикуется в GitHub Code Scanning (как SpotBugs).
Конфиг в репо сервиса:
- Не как submodule (тогда update требует submodule pull).
- Не как зависимость в Maven (тогда invisible инструменты управляют правилами).
- В
config/checkstyle/checkstyle.xml— явно, читабельно, в diff.
Базовый шаблон конфига поставляется через ucp-bootstrap-design при создании нового сервиса.
Что покрывает Checkstyle
JS-CS-2: только механика.
Именование (JS-2.1–JS-2.8)
<module name="TypeName">
<property name="format" value="^[A-Z][a-zA-Z0-9]*$"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-zA-Z0-9_]*$"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
</module>
<module name="ConstantName">
<property name="format" value="^[A-Z][A-Z0-9_]*$"/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
MethodName разрешает _ в test methods (createOrder_whenValid_returns201 — JS-2.6.1).
Импорты (JS-3.1, JS-3.2)
<module name="AvoidStarImport">
<property name="excludes" value="java.util"/>
</module>
<module name="UnusedImports"/>
<module name="CustomImportOrder">
<property name="customImportOrderRules"
value="STANDARD_JAVA_PACKAGE###THIRD_PARTY_PACKAGE###SPECIAL_IMPORTS"/>
<property name="separateLineBetweenGroups" value="true"/>
</module>
AvoidStarImport с исключением java.util (см. Импорты).
Отступы (JS-5.1–JS-5.3)
<module name="LineLength">
<property name="max" value="120"/>
</module>
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="4"/>
</module>
Whitespace
<module name="WhitespaceAround"/>
<module name="EmptyLineSeparator">
<property name="allowMultipleEmptyLines" value="false"/>
</module>
<module name="NoWhitespaceBefore"/>
Что НЕ покрывает Checkstyle
JS-CS-2 (запрет): семантика остаётся скиллу.
| Правило | Почему не Checkstyle |
|---|---|
JS-6.1 @RequiredArgsConstructor обязателен | Требует контекста (есть ли DI-зависимости в final fields) |
JS-6.5 @Data запрещён | Regex может ловить, но в legacy местах есть много false positive |
JS-7.5 Javadoc не используем | /** ... */ блок может быть obvious-комментарием |
JS-8.4 Exhaustive switch без default | Требует знания sealed-иерархии |
JS-2.5 Аббревиатуры 2 vs 3 буквы | Regex слишком complex для надёжности |
Эти проверяет ucp-java-style-review (AI-скилл) при PR review.
Не пытайтесь натянуть semantic-правила через regex в Checkstyle — false positives заспамят dashboard, команда начнёт игнорировать.
maxWarnings + ignoreFailures
JS-CS-3: жёсткий enforcement.
checkstyle {
maxWarnings = 0
ignoreFailures = false
}
maxWarnings = 0— любой warning ломает сборку.ignoreFailures = false—./gradlew checkупадёт при finding.
Без этого — Checkstyle выводит warnings, никто не смотрит. Через год — тысячи warnings, любая попытка добавить новое правило заваливается на старом долге.
Suppression
JS-CS-3 (suppression): срок и justify обязательны.
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<!-- justify: legacy package с auto-generated классами; рефакторинг до 2026-09-01 -->
<suppress files=".*[/\\]generated[/\\].*" checks="."/>
<!-- justify: jOOQ generated POJOs требуют CamelCase с большой буквы (ConnectorsPojo); до: never (generated code) -->
<suppress files=".*Pojo\.java" checks="TypeName"/>
</suppressions>
По аналогии с security suppressions:
justifyобязателен.до: YYYY-MM-DD— срок пересмотра. Для generated кода —never.
Раз в квартал — script ищет expired suppressions.
Привязка к check
JS-CS-4: lint-уровень.
tasks.named('check') {
dependsOn 'checkstyleMain', 'checkstyleTest'
}
Checkstyle прогоняется на каждом ./gradlew check (включая тесты). Не security-уровень (как SpotBugs+FindSecBugs в checkSecurity), а lint — проверяется быстро, на каждом локальном build.
В CI:
- PR build —
./gradlew check(включает Checkstyle). - Merge build — то же.
- Release build — то же.
@SuppressWarnings в коде
JS-CS-X1: только с justification.
// ✓ — явная причина
@SuppressWarnings("checkstyle:MethodLength")
// justify: complex state machine, decomposition планируется до 2026-09-30
public void processOrderStateMachine(Order order, OrderEvent event) {
// 200+ lines of state logic
}
// ✗ — без justification
@SuppressWarnings("checkstyle:MethodLength")
public void processOrderStateMachine(Order order, OrderEvent event) { ... }
ucp-java-style-review проверяет: при наличии @SuppressWarnings("checkstyle:...") — должен быть комментарий-justify ≥ 30 символов в соседних строках.
Что запрещено
| Антипаттерн | Правило | Что взамен |
|---|---|---|
@SuppressWarnings("checkstyle:...") без justify | JS-CS-X1 | комментарий ≥ 30 символов |
Удалить правило из checkstyle.xml локально | JS-CS-X2 | обсудить с командой, обновить для всех |
| Checkstyle для семантики (regex для cyclomatic) | JS-CS-X3 | ucp-java-style-review |
maxWarnings > 0 | JS-CS-3 | 0 |
ignoreFailures = true | JS-CS-3 | false |
| Конфиг как submodule | JS-CS-1 | в репо сервиса |
Suppression без до: | JS-CS-3 | срок обязателен |
| Без SARIF output | JS-CS-1 | sarif.required = true |
Куда дальше
- Java → раздел 9. Enforcement через Checkstyle — нормативные формулировки.
- Именование —
TypeName,MethodName, etc. - Импорты —
AvoidStarImport,UnusedImports. - Отступы и форматирование —
LineLength,Indentation. - Lombok — НЕ в Checkstyle, в AI-скилле.
- Комментарии — Javadoc НЕ в Checkstyle.
- Security → SAST — параллельный enforcement через SpotBugs.
- Security → findings response — общий suppression-паттерн.