Перейти к содержимому
XBSL (1C:Element)
Русский
Esc
navigateopen⌘Jpreview
На этой странице

Правила линтера 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 отключает плагины и возвращает встроенные значения из этой таблицы.

Последнее обновление 6 сентября 2026 г.

Эта страница была полезной?