Правила линтера XBSL
Полный перечень проверок линтера с уровнями важности и областью применения.
Полный перечень проверок линтера. Файл дополняется при добавлении правил; актуальный
список в рантайме – xbsl --list-rules (или MCP list_rules). Сейчас правил: 191.
Таблица описывает инструментарий в поставке. Установленный плагин может добавить свои правила
и переопределить severity и включённость по умолчанию (см. Расширение),
поэтому список в рантайме способен отличаться от этого: xbsl --list-rules показывает, что
действительно работает в вашем окружении, а XBSL_NO_PLUGINS=1 – набор ниже.
Граница: линтер дополняет компилятор, но не заменяет его
Линтер работает по тексту, AST и модели проекта. Правила знают типы “на первом шаге”:
объявленный номинальный тип переменной и его члены, объекты проекта и порождаемые ими типы,
значения перечислений, глобальные типы подключённых библиотек (из архива .xlib).
Вывод типа ВЫРАЖЕНИЯ у движка есть – модуль xbsl.typeinfer отвечает про получателя, член,
конструктор, приведение и настойчивую операцию, а вывод типов цепочек и локальных переменных
питает ховер и автодополнение в редакторе. Проверки на него не опираются: правила судят по
объявленным типам – см. ниже про то, чего линтер не делает.
Часть находок поймал бы и компилятор: неизвестный тип, число аргументов, не-исключение в
поймать, возврат не по сигнатуре. Здесь ценность линтера не в том, что он видит больше, а
в том, что он видит это раньше – за секунды на рабочей машине, до сборки и деплоя, и
показывает точное место. Остального же компилятор не проверяет вовсе: соглашения по
написанию кода, типографику, структуру проекта (дубли Ид, парность файлов),
неиспользуемые переменные, секреты в исходниках.
Чего линтер не делает – всё, что требует полного вывода типов выражений: избыточное
приведение, утечку ресурса в общем случае, соответствие ТИПА возвращаемого значения сигнатуре.
Два последних стоит различать. Структурное несоответствие возврата (значение в методе-ничто,
пустой возврат в типизированном) правило code/return-mismatch ловит, а возврат строки из
метода с : Число пропустит – для этого нужно вывести тип выражения. Ресурс же судится
единственной формой, где всё сказано самим объявлением: правило code/unclosed-resource
прослеживает закрываемое от объявления до перебора в том же методе, а ресурс, ушедший в вызовы
или коллекции, остаётся вне досягаемости.
Проверка корректности кода – серверная компиляция при деплое; линтер идёт перед ней и снимает частые ошибки заранее.
Как читать таблицу
- Правило – идентификатор
группа/имя. Группа (часть до/) позволяет включать и выключать правила пачкой. - Уровень –
error(сборка и CI должны падать),warning(нарушено соглашение),info(подсказка, обычно выключена). - Умолч. – ✓ правило входит в набор по умолчанию, – включается явно.
- Область –
файл(правило видит один файл) илипроект(нужен индекс всего проекта: дубли Ид, неизвестные типы, кросс-модульные вызовы). - Ссылка в конце описания – раздел документации платформы, стоящий за правилом. В VS Code код такого правила в панели “Проблемы” открывает этот раздел прямо в редакторе.
Тиры
Правила разбиты на тиры A–D по тому, на что они опираются. Тир – это и есть быстрый фильтр
для --select/--ignore (наряду с группой и идентификатором): --select A,B гоняет только
структуру и текст, --ignore D убирает семантику над stdlib.
Как читать колонки: error · warning · info; ✓ – входит в набор по умолчанию, – включается явно; область – один файл или весь проект.
Тир A – структура и YAML
Файл существует, парсится, у объекта есть уникальный UUID, имя совпадает с файлом.
| Правило | Область | Что проверяет | ||
|---|---|---|---|---|
yaml/valid |
✓ | файл | YAML не парсится | |
yaml/duplicate-key |
✓ | файл | Скалярный ключ задан в одном узле YAML дважды: загрузчик молча оставляет последнее значение, все проверки схемы читают уже слитый документ, а компилятор отклоняет файл при деплое. Помечаются второе и последующие вхождения с указанием строки первого; ключ слияния << и нескалярные ключи не судятся, ключи сравниваются как их различает загрузчик (тег и текст) |
|
yaml/id-uuid |
✓ | файл | Ид не является UUID | |
yaml/id-required |
✓ | файл | У объекта нет Ид | |
yaml/name-matches-file |
✓ | файл | Имя не совпадает с именем файла | |
yaml/id-unique |
✓ | проект | Дубли Ид в проекте | |
yaml/standard-field-length |
✓ | файл | Длина стандартного реквизита сверх лимита платформы (Наименование > 400, Код > 50) – применение отвергает реквизит, и он выпадает из объекта доки |
|
yaml/ref-needs-nullable |
✓ | файл | Ссылочный тип в позиции Тип без ? (Товары.Ссылка, ПолеВвода<Товары.Ссылка>) – у ссылки нет значения по умолчанию, компиляция падает Default value initialization is not supported доки |
|
yaml/no-expression-in-literal |
✓ | файл | Выражение =... внутри узла литерального типа (Шрифт: {Тип: АбсолютныйШрифт, Размер: =...}) – платформа принимает здесь только литерал, вычислять нужно весь объект доки |
|
yaml/localization-key-unique |
✓ | файл | Ключ, объявленный в словаре ЛокализованныеСтроки дважды – у секций Строки и Шаблоны одно пространство имён, файл перевода судится тоже; применение отвечает “Имя не уникально” и откатывает проект доки |
|
yaml/unused-component |
✓ | проект | Компонент интерфейса, который нигде не размещён и не создан: ни значением Тип в разметке, ни новый в коде (code/unused-method его не видит – методы компонента зовёт его же yaml). Употребление – значение в yaml (имя-ключ словаря переводов не считается) либо любое слово модуля. Не судятся точка входа и ОбластьВидимости: Глобально – публичная поверхность библиотеки. Без файла-дескриптора проекта среди проверяемых правило молчит: на подмножестве компонент, размещённый снаружи, выглядел бы мёртвым |
|
yaml/duplicate-subtree |
– | проект | Поддерево разметки, повторяющее устройство поддерева ДРУГОГО файла (имена, идентификаторы и тексты в слепок не входят): новую форму заводят копированием соседней. Порог 40 узлов выведен замером – ниже он ловит раскладку, а не копии. Не судятся повтор внутри одного файла, источник данных списка и словарь локализованных строк; называются только максимальные группы. Выключено по умолчанию: мера одинаковости – решение проекта | |
project/identifier |
✓ | файл | Имя или поставщик проекта не идентификатор доки | |
project/presentation |
✓ | файл | Представление проекта не заполнено доки | |
project/version |
✓ | файл | Версия проекта не A.B.C доки | |
structure/xbsl-pair |
✓ | файл | Модуль .xbsl без парного .yaml | |
project/path-matches-descriptor |
✓ | файл | Путь {{поставщик}}/{{имя}} разошёлся с дескриптором – сборка отвергнет проект до компиляции доки |
|
yaml/unknown-component-property |
✓ | файл | Ключ разметки, которого у компонента нет, а у ДРУГОГО компонента ui-схемы есть (Флажок + ЗамещающийТекст – свойство ПолеВвода): применение отвечает Неизвестное свойство; имя, которого нет ни у одного компонента, не трогается – документация перечисляет ключи yaml не полностью доки |
|
yaml/inline-command-name |
✓ | файл | Имя у команды, объявленной прямо в разметке (инлайновый фрагмент командного интерфейса или команда-свойство): применение отвергает узел (“Имя команды разрешено задавать только в элементах проекта типа фрагмент командного интерфейса”) и стенд откатывается; к команде обращаются через параметр обработчика, а имя даёт только фрагмент отдельным элементом проекта доки |
Тир B – текст и соглашения
Кодировка, переводы строк, пробелы, типографика (тире, кавычки, многоточие), длина строки, секреты в исходниках.
| Правило | Область | Что проверяет | ||
|---|---|---|---|---|
security/hardcoded-secret |
✓ | файл | Ключ или пароль литералом в коде | |
typography/em-dash |
– | файл | Длинное тире в комментарии | |
typography/ellipsis |
✓ | файл | Символ многоточия в комментарии | |
typography/curly-quotes |
✓ | файл | Кудрявые кавычки | |
typography/guillemets-comment |
– | файл | Ёлочки в комментарии | |
typography/yo-in-text |
– | файл | Буква “ё” в тексте интерфейса | |
whitespace/trailing |
✓ | файл | Хвостовые пробелы | |
whitespace/mixed-newline |
✓ | файл | Смешанные переводы строк | |
encoding/utf8 |
✓ | файл | Файл не в UTF-8 | |
style/tab-indent |
✓ | файл | Табуляция в отступе доки | |
style/line-length |
✓ | файл | Строка длиннее 120 символов доки |
Тир C – структура кода, базовый синтаксис и соглашения по написанию
Баланс блоков и скобок, заголовки циклов и методов, локальные переменные и группа style/ –
соглашения из раздела документации “Рекомендации по написанию кода”. Часть правил style/
выключена по умолчанию (накопленный долг, info): включаются --select style для замера.
| Правило | Область | Что проверяет | ||
|---|---|---|---|---|
code/parse-error |
✓ | файл | Синтаксическая ошибка (полный разбор по грамматике платформы) доки | |
code/statement-no-effect |
✓ | файл | Оператор-выражение без эффекта: значение отбрасывается (часто опечатка в ключевом слове вида возрат 5) |
|
code/return-mismatch |
✓ | файл | Возврат не по сигнатуре метода (значение в методе-ничто, пустой возврат в типизированном) – компилятор такой код отвергает доки |
|
code/call-arity |
✓ | файл | Число аргументов локального вызова вне диапазона [обязательные, все] сигнатуры доки | |
code/brackets |
✓ | файл | Дисбаланс скобок () [] {} | |
code/blocks |
✓ | файл | Дисбаланс блоков и ‘;’ доки | |
code/ternary-and-or |
✓ | файл | Составное условие тернарного оператора без скобок доки | |
code/query-in-loop |
✓ | файл | Запрос внутри цикла | |
code/param-type-required |
✓ | файл | Параметр без типа и без значения по умолчанию доки | |
code/duplicate-annotation |
✓ | файл | Повторная аннотация у объявления (точный повтор имени без аргументов; аннотации копятся до ближайшего объявления, и комментарий между ними их не разделяет) – компилятор такой модуль отвергает доки | |
code/module-var-not-const |
✓ | файл | Объявление пер / знч / исп на уровне МОДУЛЯ – там живёт только константа, выражение вне тела метода компилятор отвергает, и применение откатывает проект доки |
|
code/param-redeclared |
✓ | файл | Объявление знч / пер / исп в теле метода с именем его же параметра, вложенные блоки (цикл, ветка, попытка) включительно – метод одна область видимости вместе с параметрами, компилятор отвечает “Переменная с именем X уже определена” при применении, и проект откатывается; переменные цикла и поймать, параметры лямбд и тела полных лямбд не судятся доки |
|
code/loop-header |
✓ | файл | Неверный заголовок цикла ‘для’ доки | |
code/invalid-string-escape |
✓ | файл | Недопустимая управляющая последовательность в строковом литерале (\', регексные \d) – компилятор отвергает такой литерал; валидны \н \в \т \\ \" \% \$ \ю<код> и латинские написания доки |
|
code/unused-local |
✓ | файл | Неиспользуемая локальная переменная | |
code/unused-loop-var |
✓ | файл | Неиспользуемая переменная цикла | |
code/ref-field-needs-req |
✓ | файл | Поле-ссылка структуры без ‘обз’ доки | |
style/boolean-compare |
✓ | файл | Сравнение булева значения с Истина/Ложь доки | |
style/undefined-is |
✓ | файл | Проверка Неопределено оператором ‘это’ доки | |
style/negated-is |
✓ | файл | Отрицание оператора ‘это’ снаружи доки | |
style/semicolon-line |
✓ | файл | ‘;’ не на отдельной строке доки | |
style/wrap-operator |
✓ | файл | Операция в конце перенесённой строки доки | |
style/wrap-comma |
✓ | файл | Запятая в начале перенесённой строки доки | |
style/camel-case |
✓ | файл | Имя не в UpperCamelCase доки | |
style/const-case |
✓ | файл | Константа не БОЛЬШИМИ_БУКВАМИ доки | |
style/exception-prefix |
✓ | файл | Имя исключения без пометки: у русского имени это префикс “Исключение”, у латинского – суффикс Exception доки | |
style/abbreviation-case |
✓ | файл | Аббревиатура заглавными буквами в имени доки | |
style/enum-name-vid |
✓ | файл | Имя перечисления начинается с “Тип” доки | |
style/collection-literal |
✓ | файл | Ручное наполнение коллекции вместо литерала доки | |
style/redundant-tostring |
✓ | файл | ‘.ВСтроку()’ в конкатенации доки | |
style/interpolation |
✓ | файл | Конкатенация вместо интерполяции доки | |
style/type-colon-space |
✓ | файл | Пробелы вокруг двоеточия типа доки | |
style/union-spaces |
✓ | файл | Пробелы вокруг ‘|’ в составном типе доки | |
style/nullable-shorthand |
✓ | файл | Неопределено в типе без сокращения ‘?’ доки | |
style/redundant-type |
✓ | файл | Избыточная аннотация типа при инициализации доки | |
style/optional-params-last |
✓ | файл | Необязательный параметр перед обязательным доки | |
code/resource-bare-name |
✓ | файл | Ресурс{Ресурсы/Имя.svg} – ключ ресурса задается ОТНОСИТЕЛЬНО каталога Ресурсы; сам каталог в ключе ломает поиск доки |
|
query/named-parameter |
✓ | файл | Именованный параметр &Имя внутри литерала запроса – значения в литерал передаются интерполяцией (%Имя) доки |
|
code/this-in-static-method |
✓ | файл | Ключевое слово этот в теле статического метода – статический метод общий для всего типа и контекста объекта не имеет, проект компилятор отвергает доки |
|
code/instance-call-from-static |
✓ | файл | Вызов обычного метода того же владельца по голому имени из статического метода – документация запрещает это прямо; вызывайте метод у значения либо сделайте его статическим доки | |
code/close-in-before-close |
✓ | файл | Закрыть() внутри ПередЗакрытием – платформа игнорирует вызов, и форму не закрывает уже ничто |
|
query/no-isnull |
✓ | файл | ЕСТЬNULL( внутри литерала запроса – такой функции в языке запросов нет |
|
style/abstract-name |
✓ | файл | Абстрактное имя переменной (Данные, Элемент, Объект, Строка, Значение, Документ – точное или с числовым хвостом Данные1) не отражает суть; основа внутри длинного имени (ДанныеКлиента) и поля структур (контракт сериализации) не трогаются доки |
|
style/single-letter-name |
✓ | файл | Однобуквенное имя переменной, параметра или переменной цикла – по стандарту имён односимвольными бывают только параметры коротких лямбда-выражений ((А, Б) -> А + Б) доки |
|
style/negated-boolean-name |
✓ | файл | Булева переменная названа от отрицания (НеПодключен, НетОшибок) – имя образуют от истинного значения признака (Подключен, ЕстьОшибки); судится только доказанное Булево: аннотация типа или булев литерал в инициализации доки |
|
style/type-in-name |
✓ | файл | Имя переменной начинается с типа-контейнера (МассивСтруктурИмен, СтруктураОтвета) – тип виден по объявлению и подсказке редактора, в имя его не включают доки |
|
style/numeral-in-const-name |
✓ | файл | Числительное в имени константы (ТАЙМАУТ_ОДНА_МИНУТА) описывает её значение – константу называют абстрактно (ТАЙМАУТ), чтобы смена значения не ломала имя доки |
Тир D – семантика над stdlib, формы и метамодель
Требует индекс проекта и данные платформы: неизвестные типы и объекты, значения перечислений, модель выполнения (клиент/сервер), обработчики форм, свойства и запросы.
| Правило | Область | Что проверяет | ||
|---|---|---|---|---|
yaml/choice-needs-static-list |
✓ | файл | ВыборЗначения без статичного СпискаВыбора доки | |
yaml/slot-needs-list |
✓ | файл | Слот, описанный в ui-схеме типом Массив<...>, получил один компонент вместо списка: применение сборки отвергает такую разметку, а линт до сих пор молчал доки |
|
yaml/value-choice-title |
✓ | файл | У ВыборЗначения с явным ВидОтображенияПереключателя: Переключатель задан Заголовок – платформа его не рисует, и поле остаётся без подписи; кладите подпись отдельной Надпись рядом с переключателем (узлы без явного вида и с тип-аргументом Массив<...> – группа флажков – не судятся) |
|
code/unknown-type |
✓ | проект | Неизвестный тип | |
code/catch-non-exception |
✓ | файл | Тип в поймать не исключение (stdlib-тип без сигнатуры исключения или локальная структура) – компилятор такой код отвергает доки |
|
code/unknown-member |
✓ | файл | Обращение к отсутствующему члену переменной известного stdlib-типа – простого или дженерика, у которого аргументы типизируют члены, но не называют их (первый шаг цепочки, у опечаток подсказка) | |
code/member-kind-mismatch |
✓ | проект | Метод стандартной библиотеки прочитан как свойство (или наоборот) доки | |
code/unknown-static-member |
✓ | проект | Обращение к отсутствующему члену по имени типа (ДатаВремя.Минимальная()); тип результата такого вызова переносится на следующий шаг цепочки. Голое имя читается как тип, только если проект не придаёт ему другого смысла; парный yaml модуля учитывается и при проверке одиночного файла |
|
yaml/foreign-not-public |
✓ | проект | Ссылка из yaml (позиция типа, цель навигации ТипФормы, корень цепочки биндинга =Модуль.Метод() или квалифицированное имя Подсистема::Элемент) на элемент чужой подсистемы, у которого ОбластьВидимости не ВПроекте/Глобально – снаружи своей подсистемы он недоступен, и импорт не поможет; квалифицированная запись судится по названной подсистеме доки |
|
code/foreign-not-public |
✓ | проект | Модуль называет элемент чужой подсистемы, у которого ОбластьВидимости не ВПроекте/Глобально – в записанной позиции типа или корнем цепочки Модуль.Метод(), включая квалифицированную запись Подсистема::Элемент: компилятор отвергает обращение на этой строке, импорт не поможет, аннотация @ВПроекте на методе тоже. Модуль проекта не принадлежит ни одной подсистеме, и всякий непубличный элемент для него чужой доки |
|
code/call-arity-cross |
✓ | проект | Число аргументов вызова Модуль.Метод(...) вне диапазона сигнатуры модуля-адресата доки |
|
code/undefined-name |
✓ | проект | Неизвестное имя в выражении (опечатки вида Адресар вместо Адреса) и в короткой интерполяции строки ("?$format=json" – подстановка имени format, нужен \$) – компилятор такой код отвергает |
|
code/unknown-object-type |
✓ | проект | Неизвестный тип объекта проекта | |
yaml/unknown-type |
✓ | проект | Неизвестный тип в yaml | |
yaml/dynlist-missing-field |
✓ | проект | Нет поля динамического списка доки | |
yaml/dynlist-row-editing |
✓ | проект | Обработчик ПриРедактированииСтроки у списка с ПЛОСКИМ динамическим источником: событие объявлено для узловых строк иерархии, у плоского списка платформа его не вызывает вовсе – по нажатию открывается автоформа объекта; дайте объекту свою форму объекта доки |
|
yaml/dynlist-joined-table-param |
✓ | файл | Параметр (&Имя) или биндинг (=...) в аргументах либо фильтре ПРИСОЕДИНЕННОЙ таблицы динамического списка: у основной таблицы это законно, у присоединённой не вычисляется – компилятор молчит, а список отказывает в рантайме; оставьте в yaml литерал, живое значение присваивайте из кода (Источник.ПрисоединенныеТаблицы[i].Аргументы) доки |
|
yaml/dynlist-filter-disabled |
✓ | проект | Элемент отбора динамического списка объявлен с Использовать: Ложь, а парный модуль включает его присваиванием: гонка первого показа – платформа рисует список, не дожидаясь кода, и первый кадр показывает всю таблицу; объявляйте отбор включённым с пустым значением доки |
|
yaml/list-form-needs-dynlist |
✓ | файл | Форма наследует ФормаСписка, а в содержимом таблица по ИсточникДанныхМассив и ни одного типа с ДинамическийСписок: каркас списка заточен под таблицу динамического списка, и пункт навигации молча исчезает – дайте таблице динамический список либо наследуйте обычную форму (Тип: Форма) доки |
|
yaml/ref-input-auto-commands |
– | файл | Ссылочное ПолеВвода без своих Команды: платформа рисует рядом собственную кнопку открытия значения в отдельном окне (у ссылочного поля Авто разворачивается во фрагмент командного интерфейса). Чаще всего кнопка и нужна, поэтому правило информационное и выключено; глушится пустым фрагментом доки |
|
yaml/toggle-command-pair |
✓ | файл | Две соседние ОбычныеКоманды с зеркальной Видимость (=X и =не X) изображают одну команду с двумя состояниями – у платформы она есть готовой: ПереключаемаяКоманда несёт представления и изображения обоих состояний, начальное Активна задаётся литералом, состоянием владеет платформа. Общий обработчик пары усиливает картину, но не требуется доки |
|
yaml/dynlist-column-sort-lost |
– | файл | Колонка таблицы над динамическим списком, чьё значение – ВЫЗОВ: заголовок сортировать не будет, платформа сортирует по ПОЛЮ источника, а не по отображаемому тексту. Привязывайте колонку к полю либо добавьте поле-представление в сам список. Колонка с ОтключитьСортировку: Истина не судится – сортировки у неё нет по объявлению. Выключено по умолчанию: нужна ли этой колонке сортировка, из файла не видно доки |
|
yaml/badge-column-image |
✓ | файл | У СтандартнаяКолонкаТаблицы с Вид: Значок задано Изображение – платформа картинку не показывает: значение рисуется тегами-пилюлями, а картинка задокументирована только для Вид: Картинка; уберите Вид (картинка встанет рядом с текстом значения) либо задайте Вид: Картинка доки |
|
code/unknown-enum-value |
✓ | проект | Неизвестное значение перечисления доки | |
yaml/enum-needs-nullable |
✓ | проект | Перечисление без nullable; судится в обоих написаниях – поле ввода узнаётся как Edit<...>, это английское написание платформы (InputField не написание, его ловит yaml/unknown-type) доки |
|
yaml/enum-default-value |
✓ | проект | ЗначениеПоУмолчанию поля-перечисления пишется голым именем объявленного значения: запись с именем типа (ВидимостьМетки.Невидимая) или несуществующее имя сборка отвергает доки |
|
yaml/unknown-enum-value |
✓ | файл | Значение свойства компонента вне списка перечисления ui-схемы (ВыравниваниеСодержимогоПоВертикали: Конец – по вертикали значения Конец нет) |
|
yaml/bare-object-value |
✓ | файл | Голое слово в свойстве, принимающем Объект (Значение: Титул) – платформа ждёт литерал в кавычках, выражение с = либо $-ссылку локализованной строки доки |
|
code/unknown-resource |
✓ | проект | Имени из Ресурс{...} нет ни в каталогах Ресурсы проекта, ни в библиотеке картинок платформы доки |
|
form/unknown-handler |
✓ | проект | Обработчик формы не найден в модуле доки | |
form/handler-signature |
✓ | проект | Сигнатура обработчика не совпадает с событием доки | |
code/unknown-form-component |
✓ | файл | Обращение к компоненту, которого нет в разметке формы доки | |
code/server-call-from-handler |
✓ | проект | Серверный метод недоступен клиентскому обработчику доки | |
code/image-binding-server-call |
✓ | проект | Свойство Изображение компонента платформы связано выражением, чей вызов – напрямую или транзитивно через клиентские методы – разрешается в серверный метод (модуль элемента серверного вида, общий модуль с Окружение: Сервер, метод @НаСервере): картинка приезжает отдельным серверным вызовом после отрисовки и перезапрашивается при каждой перерисовке; отдавайте её вместе с данными (полем запроса или присоединённой таблицы) либо стройте из клиентских данных доки |
|
code/client-annotation-in-server-module |
✓ | проект | Клиентская аннотация в серверном общем модуле доки | |
code/client-module-in-http-service |
✓ | проект | Клиентский общий модуль в серверном окружении доки | |
code/server-annotation-in-client-module |
✓ | проект | Серверная аннотация в клиентском общем модуле доки | |
code/query-needs-server |
✓ | проект | Блок Запрос{...} в методе клиентского модуля (форма либо общий модуль с клиентским Окружение) без @НаСервере – на клиенте такого типа нет, сборку компилятор отвергает доки |
|
code/local-method-cross-component |
✓ | проект | Кросс-компонентный вызов локального метода доки | |
code/local-method-cross-module |
✓ | проект | Межмодульный вызов локального метода доки | |
naming/yo |
✓ | файл | Буква “ё” в имени доки | |
naming/underscore |
✓ | файл | Подчёркивание в имени доки | |
naming/abbreviation |
✓ | файл | Аббревиатура заглавными буквами в имени доки | |
naming/latin-term |
✓ | файл | Англоязычный термин записан русскими буквами доки | |
naming/enum-vid |
✓ | файл | Имя перечисления со словом “Тип” доки | |
naming/kind-in-name |
✓ | файл | Вид элемента в его имени доки | |
naming/filler-word |
✓ | файл | Слово-пустышка в имени доки | |
naming/module-suffix |
✓ | файл | Постфикс окружения в имени общего модуля доки | |
naming/number |
✓ | файл | Число имени не по виду элемента доки | |
naming/boolean-name |
✓ | файл | Имя булева реквизита доки | |
naming/presentation |
✓ | файл | Представление элемента доки | |
naming/prefix-by-kind |
✓ | файл | Имя вида без обязательного префикса доки | |
code/unknown-ns-object |
✓ | проект | Неизвестный объект в пространстве имён вида | |
query/unknown-table |
✓ | проект | Неизвестная таблица в запросе доки | |
query/in-subquery-composite |
✓ | проект | ‘В’ с подзапросом по составному типу доки | |
yaml/unknown-property |
✓ | файл | Неизвестное свойство объекта | |
code/reserved-name |
✓ | файл | Зарезервированное имя: Тип, type или Type полем структуры или параметром – применение на сервере отвергает все три (написание с заглавной подтверждено живым apply) |
|
yaml/builtin-property-name |
✓ | файл | Совпадение со встроенным свойством | |
yaml/size-needs-no-stretch |
– | файл | Размер без отключения растягивания доки | |
yaml/col-width-needs-no-stretch |
– | файл | Числовая Ширина колонки таблицы (все три вида колонок) без РастягиватьПоГоризонтали: при растягивании число работает как доля свободного места, а не пиксели – колонка выходит шире заданного, содержимое уезжает от соседней. Пиксельной ширине – РастягиватьПоГоризонтали: Ложь, доле с гарантированным минимумом – МинимальнаяШирина. Выключено по умолчанию: ширина-как-доля – законная техника, статически от ловушки не отличается доки |
|
yaml/matrix-group-max-width |
– | файл | Числовая МаксимальнаяШирина у группы с матричной компоновкой: максимум – это и РАСПОЛАГАЕМАЯ ширина, автоматические колонки раскладываются по нему, а не по окну, и телефон рисует страницу десктопной шириной (контент уходит за правый край). Отдавайте Авто. Выключено по умолчанию: страница только для десктопа живёт с максимумом нормально доки |
|
yaml/card-literal-stretch-weight |
– | файл | Литеральный ВесПриРастягивании у карточки или у группы внутри неё: вес – это flex с НУЛЕВОЙ базой, а в вертикальной колонке (мобильная раскладка) база относится к высоте – Safari схлопывает карточку и обрезает её скруглением, Chrome не показывает ничего. Снимайте вес на телефоне биндингом. Выключено по умолчанию: карточка, живущая только в широком ряду, носит вес законно доки |
|
code/unused-method |
– | проект | Метод нигде не используется | |
code/duplicate-method-body |
– | проект | Тело метода дословно повторяется в ДРУГОМ файле: сравнивается нормализованное тело (без комментариев, пустых строк и отступов) от пяти строк. Платформенный хук отделяется по аннотации @Обработчик, а не по списку имён – одинаковое тело хука в каждом объекте нормально; копии внутри одного файла не судятся. Выключено по умолчанию: сводить ли две копии в один метод – решение проектировщика |
|
yaml/missing-import |
✓ | проект | Ссылка из yaml (позиция типа, цель навигации ТипФормы или корень цепочки биндинга =ЧужойМодуль.Метод()) на публичный элемент чужой подсистемы, которой нет в секции Импорт – импорт в парном модуле разметку не покрывает; корень биндинга судится после вычета всего, что объясняет имя само по себе: объявлений этого yaml, парного модуля и неявных имён платформы доки |
|
code/unused-import |
✓ | проект | Модуль импортирует подсистему, ни один элемент которой в его КОДЕ не упомянут – редактор платформы такие импорты показывает, а копятся они сами: код, которому импорт был нужен, переписан, строка осталась. Ссылка из ПАРНОГО yaml употреблением не считается: у yaml своя секция импорта доки | |
code/missing-import |
✓ | проект | Модуль называет тип публичного элемента чужой подсистемы, а строки импорта этой подсистемы у него нет – компиляция проекта падает на этой строке. Судятся и ЗАПИСАННЫЕ позиции типа (параметр, переменная, возврат, новый, как, это, аргументы обобщённого), и корень цепочки (Модуль.Метод()); у корня сначала вычитается всё, что объясняет имя само по себе: объявления метода и модуля, неявные имена платформы и секции ПАРНОГО yaml доки |
|
yaml/missing-subsystem-usage |
✓ | проект | Элементы и модули подсистемы импортируют другую подсистему, а в описании своей (Подсистема.yaml) её нет в блоке Использование – применение проекта падает, и узнаётся это только на деплое. Импорт даёт краткие имена, но саму подсистему разрешает Использование; замечание – на описании подсистемы, там же и правка доки |
|
yaml/computed-binding-assigned |
✓ | проект | Каждый экземпляр компонента связывает свойство ВЫЧИСЛЯЕМЫМ выражением, а компонент присваивает это свойство в своём модуле – на присваивании платформа падает (IllegalStateException). Именованный аргумент – не присваивание, а экземпляр из кода, связь голым путём, литерал или экземпляр без связи делают присваивание законным – правило срабатывает, только когда вычисляемым связан каждый экземпляр | |
yaml/localization-missing-import |
✓ | проект | Неквалифицированная ссылка $Словарь.Ключ, чей словарь лежит в подсистеме, которой нет в секции Импорт ЭТОГО yaml, – применение отвергает узел как неимпортированное пространство имён; импорт в парном модуле разметку не покрывает, а квалифицированная форма $Подсистема::Словарь.Ключ работает без импорта доки |
|
yaml/presentation-field |
✓ | файл | Поле представления объекта доки | |
yaml/unexpected-type-argument |
✓ | файл | Параметр типа у свойства, которое ui-схема объявляет без параметра, – это другой тип, применение сборки его отвергнет (ДополнительныеКоманды формы принимают ФрагментКомандногоИнтерфейса, а не ФрагментКомандногоИнтерфейса<ОбычнаяКоманда>); английское дерево судится так же – ключ, компонент, свойство и голова типа канонизируются, аргумент сравнивается с умолчанием имя за именем в любом написании доки |
|
yaml/property-since-compat |
✓ | проект | Свойство компонента новее, чем РежимСовместимости проекта (версию появления несёт ui-схема) – применение отвергает его как неизвестное доки |
|
query/deletion-mark-immediate |
✓ | проект | Условие с пометкой удаления в запросе к объекту с РежимУдаления: Немедленно – поля пометки у него нет, запрос падает применением доки |
|
code/load-object-unwrap |
✓ | файл | Форс-разворот результата ЗагрузитьОбъект() у ссылки из поля записи или строки табличной части (Строка.Сервис!.ЗагрузитьОбъект()!) – запись могли удалить физически (РежимУдаления: Немедленно, форма удаления помеченных), и разворот роняет весь обход; проверять результат на Неопределено (собственная .Ссылка строки запроса не судится) доки |
|
yaml/item-id-required |
✓ | файл | Элемент коллекции метаданных (реквизит, табличная часть, элемент перечисления, параметр ключа доступа) без Ид, который объявляет его класс – применение отвечает ID required |
|
code/unknown-row-field |
✓ | проект | Поле строки динамического списка (СтрокаДинамическогоСписка<Форма.Тип>), которого нет среди Поля списка доки |
|
code/row-field-null |
✓ | проект | Поле динамического списка, взятое через ссылку (Исполнитель.Номер), имеет тип `<тип> |
|
yaml/unknown-attribute-property |
✓ | файл | Ключ, которого класс самого реквизита не объявляет (Длина у обычного реквизита – её объявляет стандартный Код, а у числового есть ДлинаЦелойЧасти) – применение сборки отвергает объект |
|
yaml/empty-group-sized |
✓ | файл | Пустая Группа с Высота/Ширина (числом – всегда; биндингом =... – только без Имя) – рендер выбрасывает узел, зазора не будет |
|
yaml/insert-row-needs-align |
✓ | файл | Горизонтальная группа со вставкой КонтейнерHtml и без ВыравниваниеСодержимогоПоВертикали: дети равняются ПО БАЗОВОЙ ЛИНИИ, а у вставки она своя – элемент со вставкой съезжает вниз относительно соседей (на живом ряду 50 px). Отвечает ближайший горизонтальный предок, поэтому ряд с уже выровненной внутренней полосой молчит доки |
|
yaml/hint-too-long |
✓ | файл | Подсказка длиннее предела отрисовки – хвост не показывается вовсе |
|
yaml/popup-in-markup |
✓ | проект | ВсплывающийКомпонент (или проектный компонент, транзитивно наследующий его) размещён в yaml-разметке: содержимое рисуется прямо в строке формы ещё до открытия окна – свойства, ограничивающего отрисовку окном, у платформы нет, а скрытие через Видимость ломает само окно; окно собирают кодом на каждое открытие – новый ВсплывающийКомпонент(...) и затем ОткрытьВоВсплывающемОкне() доки |
|
yaml/date-input-needs-plain-date |
✓ | файл | ПолеВвода<Дата?> – поле ввода даты, допускающей пустое значение, рендер молча не рисует; тип делается непустым, “не задано” – пустая дата доки |
|
yaml/binding-needs-auto |
✓ | проект | Биндинг свойства без пустого значения зовёт метод с nullable-возвратом – клиент регистрирует “Неожиданное значение” на каждом пересчёте; “не задано” – это значение Авто | |
code/client-available-needs-context |
✓ | проект | @ДоступноСКлиента у метода модуля компонента интерфейса, который не статический и без @Контекстный – тип компонента не синглтонный, применение отвергает модификатор доки |
|
code/client-available-unused |
– | проект | Метод объявлен @ДоступноСКлиента, но клиентского места, которое его называет, в проекте нет – ни модуля клиентского окружения, ни клиентского метода серверного модуля, ни yaml, ни строкового литерала. Аннотация открывает клиенту поверхность, которой никто не пользуется. Выключено по умолчанию, как code/unused-method: клиентский вызов бывает не виден статически доки |
|
code/server-module-in-client-context |
✓ | проект | Обращение Модуль.Член(...) к общему модулю с Окружение: Сервер из метода, исполняемого на клиенте (компонент интерфейса, команда, клиентский общий модуль) – на клиенте типа нет доки |
|
code/component-in-server-context |
✓ | проект | Обращение Компонент.Член(...) к компоненту интерфейса из кода, компилируемого для сервера – метод @НаСервере где угодно либо метод без аннотации в серверном или клиент-серверном модуле: тип компонента живёт на клиенте, и серверная компиляция отвечает “Переменная X не определена” доки |
|
yaml/delete-current-needs-immediate |
✓ | файл | ПриУдаленииОбъектаПоСсылке: УдалятьТекущий у реквизита владельца, чей РежимУдаления только помечает (ПометкаУдаления – это ещё и умолчание) – применение отвечает Action УдалятьТекущий cannot apply to object with a DeletionMark доки |
|
code/access-context-read-noop |
✓ | проект | Расширение контекста доступа правом Чтения для типа, у которого в yaml стоит Чтение: РазрешеноВсем: читать и так разрешено всем, выдавать нечего – вызов лишь создаёт впечатление защищённости. Если право в списке одно, снимается вся строка; если есть другие – только Чтение доки |
|
code/per-object-permissions-need-common |
✓ | проект | Объект вычисляет разрешения для каждого объекта, но в его модуле нет обработчика ВычислитьРазрешенияДоступа – общий расчёт обязателен и при per-object, пусть и возвращает пустой массив доки |
|
code/permission-field-not-declared |
✓ | проект | В ВычислитьРазрешенияДоступаДляОбъектов читается поле, которого нет среди РасчетРазрешенийПо, либо объявленное поле берётся через Сущность вместо Запись доки |
|
code/permission-handlers-need-recalc |
✓ | проект | Модуль объявляет обработчик разрешений (ВычислитьРазрешенияДоступа и родня), а ПересчитатьРазрешенияДоступа этой сущности не вызван нигде в проекте – платформа обработчик сама не вызывает, и правка прав молча не действует; пересчёт с получателем не-сущностью (документированный цикл) глушит правило, виды без метода пересчёта (право-элементы) не судятся доки |
|
code/permission-right-not-computable |
✓ | проект | Обработчик ВычислитьРазрешенияДоступа (или ...ДляОбъектов) выдаёт право, не объявленное вычислимым в yaml сущности (РазрешенияВычисляются / РазрешенияВычисляютсяДляКаждогоОбъекта, явно или через ПоУмолчанию) – сборка применяется, а пересчёт разрешений падает уже в рантайме: право не указано как вычислимое. Права собираются только из конструкторов новый РазрешениеДоступа(...) в обоих пространствах (Сущность.Право.*, HttpСервисПраво.*), транзитивно по вызовам проекта – делегирование в общий модуль прав видно, находка привязывается к сущности; КонтекстДоступа.Дополнить не считается, недовыдача законна, виды без контроля доступа не судятся доки |
|
yaml/placeholder-key-in-strings |
✓ | файл | Ключ с подстановкой $0 в секции Строки словаря ЛокализованныеСтроки: секция компилируется в метод БЕЗ параметров, и вызов с аргументом падает на применении “Неизвестный метод” доки |
|
yaml/localization-ref-to-template |
✓ | проект | Ссылка $Словарь.Ключ указывает на ключ секции Шаблоны: ссылка ищет ключ только в Строки, и применение падает с “Не удалось найти локализованную строку” (стенд откатывается). Ключ шаблонов, на который никто не ссылается, не судится – из кода его зовут законно доки |
|
code/compare-with-localized |
✓ | проект | Локализованное значение (Словарь.Ключ(), Представление()) сравнивается с литералом или со вторым локализованным – на другом языке ветка молча не срабатывает доки |
|
code/url-params-partial-encoding |
– | файл | Вызов метода Url СПараметрамиЗапроса: значение параметра кодируется частично – “&” и “=” внутри значения остаются разделителями, и значение-адрес приходит обрезанным по первому “&”; строку собирать самим объектом параметров и клеить к базовому адресу. Выключено по умолчанию: видны ли “&” в значениях, статически не решается доки |
|
code/bound-property-assign |
✓ | файл | Свойство, ВЫЧИСЛЯЕМОЕ выражением в парной разметке (Высота: =Общее.ЭтоУзкийЭкран()?820:528), присваивается из кода – платформа такое присваивание отвергает, а в попытка/поймать отказ не виден; связь с данными (голый путь) не трогается, она двунаправленная по устройству |
|
yaml/event-needs-importance |
✓ | файл | В описании СобытиеЖурналаСобытий не задана Важность: её умолчание – ИзКонструктора, и тогда платформа требует значение в КАЖДОМ конструкторе, а пропуск хотя бы в одном месте записи роняет применение на строке конструктора; явное Важность: ИзКонструктора объявляет выбор и снимает предупреждение доки |
|
yaml/event-property-type |
✓ | файл | Тип свойства СобытиеЖурналаСобытий вне закрытого списка платформы: перечисление проекта туда положить нельзя – отказ приходит только серверной компиляцией и стоит деплоя; список берётся из метамодели (EventLogEventProperty.Тип), ? и квалификация Стд:: терпятся, вариантные значения пишутся строковыми кодами с перечнем допустимых кодов в Описание свойства доки |
|
code/collection-field-needs-req |
✓ | файл | Поле структуры с обобщённым типом без конструктора без аргументов (ЧитаемыйМассив<Строка>) и без обз, ? или инициализатора – применение отвечает “не может быть проинициализировано значением по умолчанию”; Массив<Строка> и подобные конструируются пустыми и не трогаются доки |
|
code/var-needs-init |
✓ | проект | Переменная объявлена одним типом, у которого нет ни конструктора, ни значения по умолчанию (пер Ответ: ОтветHttp) – компиляция отвечает “не имеет конструктора и значения по умолчанию”; перечисление, аннотация, одиночка и имя, перекрытое типом проекта, пропускаются доки |
|
code/unknown-tabular-member |
✓ | проект | Обращение к отсутствующему члену коллекции строк табличной части (Объект.Секция.Член в модуле формы объекта, голое имя секции или этот.Секция в модулях сущности) – коллекция это Массив<Сущность.Секция>, и привычное из другой платформы Количество() здесь зовётся Размер(); секцию затеняет одноимённый модуль, реквизиты не судятся |
|
code/global-unavailable |
✓ | проект | Вызов глобального имени вне его окружения: Сообщить (только клиент) в серверном модуле – применение отвечает “Метод недоступен в текущем окружении”, Вычислить (только сервер) в клиентском методе без @НаСервере; @НаКлиенте/@НаСервере переопределяют окружение модуля, доступность имён – из строк “Доступность” пакетов глобального контекста доки |
|
style/shadow-project-name |
✓ | проект | Переменная, параметр или метод с именем элемента проекта (знч Склады при справочнике Склады) – объявление закрывает обращение к элементу из этой области; платформенные имена параметров обработчиков с именами проекта не пересекаются доки |
|
style/shadow-own-property |
✓ | проект | Локальная ПЕРЕМЕННАЯ с именем свойства своего же элемента: внутри метода имя разрешается в переменную, и присваивание до свойства не доходит. Судятся только модули, где такое свойство в области видимости, – компонента интерфейса и объекта; параметр с тем же именем это обычный способ передать значение и не судится доки | |
code/unclosed-resource |
✓ | файл | Закрываемый ресурс (знч Выборка = Запрос{...}.Выполнить()), брошенный досрочным выходом из перебора: полный проход платформа закрывает сама, а возврат или прервать в середине оставляет ресурс открытым, и платформа пишет в журнал событий незакрытый ресурс; объявление через исп закрывает его на любом пути выхода. Ресурс, пришедший параметром, закрытый вручную и возвращённый вызывающему, оставлены автору доки |
|
code/use-needs-closeable |
✓ | файл | Модификатор исп у типа, который описан каталогом и не наследует Закрываемое – модификатор существует ради автоматического Закрыть(), и компилятор отвергает объявление доки |
|
conventions/untranslated-visible-literal |
✓ | проект | Видимый текст, оставшийся кириллическим литералом там, где то же свойство проект уже вынес ссылкой на словарь локализации – намерение считается в разрезе вида элемента, и свойство-тёзка другого вида не судится; молчит на проекте, у которого в дескрипторе меньше двух языков локализации | |
conventions/untranslated-code-literal |
– | проект | Видимый текст, оставшийся кириллическим литералом В МОДУЛЕ – судится по СТОКУ, куда он попадает (аргумент платформенного вызова сообщения, свойство события журнала или то же самое через метод, пробрасывающий свой параметр); разметка, чистая интерполяция и одиночные слова пропускаются, а на проекте с менее чем двумя языками локализации правило молчит | |
conventions/missing-translation |
– | проект | Токен проекта или кириллическая строка комментария, которых ещё нет в словаре перевода проекта – одна находка на первое вхождение в файле; правило молчит, пока рядом с проектом (или выше) не лежит словарь xbsl-translation (см. xbsl translate) |
|
code/unknown-structure-field |
✓ | проект | Обращение к полю структуры, объявленной В ПРОЕКТЕ, сверяется с её объявлением: переименовали поле – потребитель в другом модуле краснеет здесь, а не на серверной компиляции. Тип берётся из объявления переменной (Модуль.Структура, голое имя структуры своего модуля), из конструктора новый и из элемента коллекции в для X из Список; имя, объявленное в методе ещё чем-нибудь, тёзка stdlib-типа, второй шаг цепочки и латинские написания члена не судятся |
Подробнее о группах
Запросы: В с подзапросом по составному типу (правило query/in-subquery-composite)
Стандарт платформы “Использование выражения В с подзапросом для выражений составного типа”:
на большинстве СУБД такой вариант реализован неэффективно, и условие пишется через СУЩЕСТВУЕТ.
Правило – предупреждение, стандарт обязателен:
ГДЕ Т.Значение В (ВЫБРАТЬ Ф.Значение ИЗ Фильтры КАК Ф) // предупреждение
ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ 1 ИЗ Фильтры КАК Ф ГДЕ Ф.Значение = Т.Значение) // так
Составным считается тип поля с двумя и более альтернативами в yaml (Строка|Число|?): ? – не
тип, а допустимость Неопределено, и Массив<Строка|Число> тоже не составной. Под сомнение
ставится только поле, тип которого известен наверняка: Алиас.Поле или Таблица.Поле, где алиас
однозначен в пределах блока, а поле нашлось в yaml таблицы; список значений (В (1, 2, &Коды))
стандарта не касается. Правило понимает и английские формы (IN, NOT, SELECT).
Свойства проекта (правила project/)
Четыре правила по стандарту “Заполнение свойств проекта”: Поставщик и Имя – идентификаторы,
образованные от представлений (каждое слово с прописной буквы: КабинетСотрудника,
НовыеЭлементарныеТехнологии); Представление и ПредставлениеПоставщика заполнены – это
официальное название проекта и название компании-разработчика; Версия – три числа A.B.C
(семантическое версионирование), а не 1.0.
Имена элементов проекта (правила naming/)
Двенадцать правил по стандарту платформы “Имена элементов проекта” – он обязателен в новом коде,
поэтому все они предупреждения. Проверяются описания (.yaml): имя самого элемента и имена его
реквизитов, измерений, ресурсов, табличных частей и значений перечисления.
Число имени сверяется с видом элемента: справочники, документы, регистры и табличные части
именуются во множественном числе, перечисления и структуры – в единственном (naming/number).
Для русского имени это разбор морфологический, а не по окончаниям: Номенклатура единственного
числа стандарту не противоречит, а Задачи и Партии без падежа читаются как родительный падеж
единственного. Нужен extra [morph] (pip install "xbsl[morph]"); без него русские имена молчат.
Английское имя (переведённое дерево) судится по последнему слову суффиксной эвристикой с перечнем
неправильных множественных, extra ему не нужен; несчисляемые слова и неоднозначные хвосты
остаются нерешёнными.
Остальное: буква ё и подчёркивания в именах, аббревиатура одним словом (Ндс, а не НДС),
англоязычный термин оригиналом (Xml, а не Хмл), Вид вместо Тип у перечислений, вид
элемента внутри его имени (ОтчетЗависшиеЗадачи), слова-пустышки (Управление, Менеджер),
постфикс окружения у общего модуля (ОбменДаннымиКлиентИСервер – окружение задаётся свойством),
булев реквизит через отрицание (НетОшибок вместо Успешно), незаполненное Представление и
обязательные префиксы отдельных видов (КлючДоступа, ПравоНа, Навигация).
Соглашения по написанию кода (правила style/)
Двадцать восемь правил по документации платформы (“Соглашения по написанию кода”, “Идиомы
языка”) и стандарту разработки “Имена переменных и констант”: оформление и переносы
выражений, именование, описание типов и сигнатуры, литералы коллекций, интерполяция строк,
проверки булевых значений и Неопределено.
Из стандарта имён переменных и констант проверяется доказуемая по токенам часть: абстрактные
имена, однобуквенные имена вне лямбд, кириллические и латинские аббревиатуры не одним словом,
булевы имена от отрицания, тип-контейнер в имени, числительные в именах констант и тень имён
элементов проекта. Остаются на авторе и ревью: избыточные слова в имени, сокращения за
пределами регистра аббревиатур, числа вместо уточнения при осмысленной основе (Этап1 против
Данные1 различаются только смыслом) и абстрактность имени константы за пределами
числительных (роль НАЧАЛЬНЫЙ_ЭТАП против значения ЭТАП_ПРИЕМА_АНКЕТА токенам не видна).
Правила, которым чистый код уже соответствует, включены по умолчанию (warning) – они защищают
от регресса. Правила, под которые обычно накоплен долг, идут как info и выключены – их включают,
чтобы замерить долг и убирать его:
xbsl путь/к/исходникам --select style # все соглашения, включая выключенные
xbsl путь/к/исходникам --ignore style # без них
Блоки Запрос{ ... } (отдельный DSL) и строковые литералы (HTML/CSS/SVG вставок) из этих проверок
исключены. Не проверяются и остаются на авторе с ревью: кратность отступа четырём, идиомы
коллекций, Строки.Соединить() при массовой конкатенации, идиомы ?. / ?? и выбор вместо
цепочки иначе если.
Семантика кода (правила code/)
Самая большая группа – шестьдесят четыре правила, тридцать четыре из них ошибки. Это то, что компилятор
отвергнет или что платформа выполнит не так, как читается: неизвестное имя или член типа, число
аргументов вызова, окружение (клиентский код в серверном методе и наоборот), обращение к
экземпляру через тип, неперехваченное не-исключение, незакрытый ресурс, обход по коллекции при
её изменении, а также обходы платформенных ловушек, у которых нет иного признака, кроме формы
кода. Часть правил проектные (--stdin их не гоняет): им нужны парный yaml и имена объектов.
Описания элементов (правила yaml/)
Пятьдесят семь правил по описаниям (.yaml): обязательные и уникальные Ид, известные ключи
и типы, ссылки на компоненты, обработчики и локализованные строки, требования платформы к типам
полей (ссылка и перечисление допускают пустое значение), настройки динамических списков и форм,
а также ловушки вёрстки, которые применяются без ошибки, но рисуются не так, как задумано.
Шесть правил – info и выключены: они говорят “так работает платформа”, а не “здесь ошибка”.
Соглашения проекта (правила conventions/)
Правила о том, о чём договорился ПРОЕКТ, а не о том, чего требует платформа. В базовом наборе
живёт семья двуязычного проекта: conventions/untranslated-visible-literal (включено по
умолчанию) сообщает про видимый текст, оставшийся кириллическим литералом там, где то же
свойство проект уже ведёт через словарь локализации, а conventions/untranslated-code-literal
и conventions/missing-translation (оба выключены) расширяют это на литералы модулей и словарь
перевода – обязана ли каждая читаемая человеком строка приходить из словаря, каждый проект
решает сам, и базовый набор этого не навязывает.
Группа заодно и точка расширения: надстройка проекта регистрирует под conventions/ свои
правила-соглашения (запрет номеров задач в комментариях, внутренних отсылок и подобное) и сама
решает их severity и включённость – см. Расширение.
Правда рантайма – xbsl --list-rules; таблица выше описывает только базовый набор.
Мелкие группы
typography/– типографские символы в прозе и комментариях: длинное тире, символ многоточия, кудрявые кавычки, ёлочки в комментариях, а также буква “ё” в тексте, который читает пользователь;whitespace/– хвостовые пробелы и смешанные переводы строк;encoding/– файл не в UTF-8;structure/– парностьИмя.yamlиИмя.xbsl;security/– секрет в исходниках (токен, пароль, ключ);form/– обработчик формы, которого нет в модуле, и обработчик, сигнатура которого противоречит событию компонента (проектные правила);query/– запросы: неизвестная таблица,ЕСТЬNULL, именованный параметр, немедленная пометка удаления и стандарт проВс подзапросом (разобран выше).
Включение и выключение
--select и --ignore принимают идентификатор правила, группу (часть до /, напр. style)
или букву тира A/B/C/D. Плагин может переопределить severity правила (группа
entry-points xbsl.severity); XBSL_NO_PLUGINS=1 отключает плагины и возвращает встроенные
значения из этой таблицы.