Список активных правил#
AsciiIdentifiersWart#
Запрещает символы вне 7-битной ASCII-кодировки (код > 0x7F) в именах идентификаторов. Правило исключает кириллицу, математические символы и другие не-латинские буквы.
Режим работы по умолчанию:
Правило настроено как ошибка — компиляция останавливается при обнаружении нарушения.
Почему это важно:
Визуально неразличимые символы: латинская
aи кириллическаяавыглядят одинаково, но имеют разные коды. Это приводит к ошибкам поиска и рефакторинга.Совместимость: ASCII-идентификаторы гарантированно работают во всех инструментах, редакторах и системах контроля версий.
Читаемость командой: единый стандарт именования упрощает чтение кода разработчиками с разными языковыми настройками.
Проверяемые элементы кода:
объекты (
object);классы, трейты, перечисления (
class,trait,case class,enum);псевдонимы типов (
type);методы и их параметры (
def);поля и локальные переменные (
val,var);переменные в паттерн-матчинге (
case x =>).
Примеры кода, вызывающего ошибку компиляции:
val сумма = 10 // кириллица в имени
def рассчитать(): Int = 0 // кириллица в имени метода
case class Документ(id: Int) // кириллица в имени класса
val userNаme = "x" // кириллическая "а" внутри латинского имени
val π = 3.14 // символ вне ASCII
Корректные примеры:
val sum = 10
def calculate(): Int = 0
case class Document(id: Int)
val userName = "x"
MixedLanguagesWart#
Обнаруживает смешение кириллицы и латиницы внутри одного слова в строковых литералах. Правило не запрещает многоязычные строки — слова на разных языках допустимы при разделении пробелом, цифрой или знаком препинания.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Опечатки в сообщениях: случайное нажатие клавиши переключения раскладки приводит к бессмысленным словам вроде
Система недоступнa(латинскаяaв конце).Поиск и замена: смешанные слова не находятся при поиске по шаблону, что затрудняет локализацию и исправление.
Качество локализации: правило помогает поддерживать чистоту текстов в пользовательских интерфейсах и логах.
Проверяемые элементы кода:
строковые литералы (
"...");части строковых интерполяций (
s"...",raw"...",f"...").
Исключения из проверки: регулярные выражения (литералы вида "[a-zа-я]").
Примеры кода, вызывающего предупреждение:
val msg = "приветWorld" // смешение в одном слове
def test(s: String = "helloМир") = {} // смешение в параметре по умолчанию
val err = "Система недоступнa" // латинская "a" в кириллическом слове
Корректные примеры:
val msg = "привет World" // разделение пробелом
val msg = "hello Мир" // разделение пробелом
val msg = "привет123" // цифра как разделитель
val regex = "[a-zA-Zа-яА-Я]" // исключение для регулярных выражений
NetWart#
Запрещает прямое использование HttpURLConnection и HttpClient для выполнения HTTP-запросов. Правило требует применения централизованного инструмента Btk_HttpPkg.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Отсутствие логирования:
HttpURLConnectionне предоставляет возможности централизованного логирования запросов и ответов, что затрудняет диагностику проблем в продакшене.Безопасность: Централизованный клиент
Btk_HttpPkgреализует политики таймаутов, повторных попыток и валидации сертификатов, исключая риски при прямом использовании низкоуровневых классов.Поддерживаемость: Единая точка вызова упрощает обновление версий библиотек и применение изменений в политике работы с внешними сервисами.
Проверяемые элементы кода:
вызовы методов на объектах типа
java.net.HttpURLConnection;вызовы методов на объектах типа
org.apache.http.client.HttpClient.
Примеры кода, вызывающего предупреждение:
val conn = new HttpURLConnection(url)
conn.connect()
val client = HttpClients.createDefault()
val response = client.execute(request)
Корректные примеры:
Btk_HttpPkg().get(url)
Btk_HttpPkg().post(url)
CommitWart#
Предупреждает об использовании ручного управления коммитами транзакций через конструкцию if (i % batchSize == 0). Правило рекомендует применять метод session.commitWorkAuto() для автоматического сохранения изменений при обработке больших объёмов данных.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Утечки памяти: Ручное управление коммитами легко приводит к ошибкам — пропущенный коммит удерживает записи в кэше сессии, вызывая рост потребления памяти.
Некорректная работа с транзакциями: При ошибке в середине батча часть данных может быть закоммичена, а часть — нет, нарушая целостность данных.
Сложность поддержки: Автоматический метод
commitWorkAuto()инкапсулирует логику батчинга, упрощая чтение и модификацию кода.
Проверяемые элементы кода:
конструкции
ifс оператором остатка от деления (%) и последующим вызовомsession.flush(true);конструкции
ifс оператором остатка от деления (%) и последующим вызовомsession.commitWork().
Примеры кода, вызывающего предупреждение:
for ((item, i) <- items.zipWithIndex) {
process(item)
if (i % 100 == 0) {
session.flush(true)
}
}
for ((item, i) <- items.zipWithIndex) {
process(item)
if (i % batchSize == 0) {
session.commitWork()
}
}
Корректные примеры:
for ((item, i) <- items.zipWithIndex) {
process(item)
session.commitWorkAuto()
}
ManagedWart#
Запрещает использование конструкции resource.managed из библиотеки scala-arm для управления ресурсами с автоматическим освобождением. Правило рекомендует применять стандартный механизм scala.util.Using, встроенный в язык начиная с Scala 2.13.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Зависимость от сторонней библиотеки:
resource.managedтребует подключения библиотеки scala-arm, которая не поддерживается активно и создаёт дополнительные зависимости проекта.Стандартизация:
scala.util.Usingявляется частью стандартной библиотеки Scala, обеспечивая единообразие кодовой базы и упрощая миграцию между версиями языка.Безопасность ресурсов: Стандартный механизм гарантирует корректное освобождение ресурсов даже при возникновении исключений, с чёткой семантикой и документацией.
Проверяемые элементы кода:
вызовы метода
managedв контексте управления ресурсами (например, в генераторахfor).
Примеры кода, вызывающего предупреждение:
import resource._
for (conn <- managed(getConnection())) {
// работа с соединением
}
val result = managed(resource).acquireFor { r =>
r.process()
}
Корректные примеры:
import scala.util.Using
Using.resource(getConnection()) { conn =>
// работа с соединением
}
Using(getConnection()) { conn =>
conn.process()
}.get
NDateInterpolation#
Запрещает прямое использование объектов типа NDate в строковых интерполяциях и конкатенациях. Правило требует явного вызова метода .toNString() для преобразования даты в строковое представление.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Некорректное форматирование: Прямая вставка
NDateв строку приводит к неопределённому формату даты, зависящему от реализацииtoString().Локализация: Метод
.toNString()гарантирует единообразное отображение даты в соответствии с настройками локали пользователя.Читаемость кода: Явное преобразование делает намерение разработчика очевидным и упрощает поддержку кода.
Проверяемые элементы кода:
строковые интерполяции с использованием
NDate(s"...", f"...", raw"...");конкатенация строк с объектами типа
NDate.
Примеры кода, вызывающего предупреждение:
val ndate: NDate = getCurrentDate()
val msg = s"Date: $ndate"
val msg2 = "Date: " + ndate
Корректные примеры:
val ndate: NDate = getCurrentDate()
val msg = s"Date: ${ndate.toNString()}"
val msg2 = "Date: " + ndate.toNString()
SelectStatementWart#
Запрещает использование метода getVar внутри строковых интерполяций при формировании SQL-запросов в методах selectStatement, prepareSelectStatement и onRefresh. Правило требует применения bind-параметров для безопасной работы с базой данных.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Риск SQL-инъекций: Подстановка значений через
getVarв строку запроса создаёт уязвимость к инъекциям при недостаточной валидации входных данных.Производительность: Bind-параметры позволяют СУБД кэшировать план выполнения запроса, что повышает производительность при повторных вызовах.
Читаемость запросов: Использование
:параметрделает структуру SQL-запроса прозрачной и упрощает отладку.
Проверяемые элементы кода:
переопределённые методы
selectStatement,prepareSelectStatement,onRefreshс возвращаемым типомString;строковые интерполяции внутри этих методов, содержащие вызовы
getVar.
Примеры кода, вызывающего предупреждение:
override def selectStatement: String =
s"SELECT * FROM table WHERE id = ${getVar("flt_sShema")}"
override def prepareSelectStatement: String =
s"SELECT name FROM users WHERE role = ${getVar("role")}"
Корректные примеры:
override def selectStatement: String =
"SELECT * FROM table WHERE id = :flt_sShema"
override def prepareSelectStatement: String =
"SELECT name FROM users WHERE role = :role"
StaticSizeChunkWart#
Запрещает явное указание параметра chunkSize при вызове метода Btk_BulkProcessPkg.chunkedQuery. Правило требует использования значения по умолчанию для автоматического определения оптимального размера пакета обработки.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Адаптивная производительность: Автоматический размер чанка учитывает текущую нагрузку на систему и характеристики данных, обеспечивая оптимальную скорость обработки.
Избежание ошибок настройки: Фиксированный размер чанка может привести к переполнению памяти при больших объёмах данных или к неэффективной обработке при малых объёмах.
Упрощение кода: Отказ от ручной настройки размера уменьшает количество параметров, которые необходимо поддерживать и документировать.
Проверяемые элементы кода:
вызовы метода
chunkedQueryиз пакетаBtk_BulkProcessPkg;явная передача параметра
chunkSizeсо значением, отличным от значения по умолчанию.
Примеры кода, вызывающего предупреждение:
Btk_BulkProcessPkg().chunkedQuery(
api = this,
chunkSize = 5000,
sqlText = """SELECT id, gid FROM large_table"""
) { item =>
process(item)
}
Корректные примеры:
Btk_BulkProcessPkg().chunkedQuery(
api = this,
sqlText = """SELECT id, gid FROM large_table"""
) { item =>
process(item)
}
SqlInterpolationWart#
Запрещает использование обычных строковых интерполяторов (s, f, raw) внутри вызовов SQL-методов (SQL, ASQL, ATSQL). Правило требует применения параметризованных запросов с методом .on() для предотвращения SQL-инъекций.
Режим работы по умолчанию:
Правило работает как предупреждение — компиляция продолжается, но выводится сообщение.
Почему это важно:
Безопасность: Параметризованные запросы полностью исключают возможность SQL-инъекций, даже при обработке недоверенных входных данных.
Семантическая корректность: Метод
.on()гарантирует правильное экранирование и преобразование типов значений перед передачей в СУБД.Поддерживаемость: Чёткое разделение шаблона запроса и значений параметров упрощает чтение и модификацию кода.
Проверяемые элементы кода:
вызовы методов
SQL,ASQL,ATSQLс аргументами, содержащими строковые интерполяцииs"...",f"...",raw"...";конкатенация строк внутри аргументов этих методов с использованием переменных.
Примеры кода, вызывающего предупреждение:
val svName = "John"
val query = SQL(s"SELECT * FROM users WHERE name = $svName")
Корректные примеры:
val svName = "John"
val query = SQL"SELECT * FROM users WHERE name = {name}".on("name" -> svName)
val query2 = SQL("SELECT * FROM users WHERE name = {name}").on("name" -> svName)
val query2 = SQL"SELECT * FROM users WHERE name = $svName"