Skip to content

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 24 Oct 15:38
· 331 commits to develop since this release
5c1ca30

BREAKING

  • lsp без --mode теперь работает в режиме auto: при наличии корня проекта
    подключается к общему backend, раньше — прямой stdio. Для редактора это значит,
    что несколько окон одного проекта делят один backend.
  • mcp --mode для workspace-профиля по умолчанию broker, раньше stdio. Для
    MCP-клиентов это значит общий демон вместо отдельного процесса на клиента.
  • [diagnostics] ordinaryAppSupport без значения берётся из <DefaultRunMode>
    основной конфигурации, раньше — значение по умолчанию.

Added

  • config: [source].exclude_globs — глоб-шаблоны файлов и каталогов, исключаемых из
    проекта (служебные каталоги инструментов на любой глубине, сгенерированные файлы
    рядом с исходниками). Шаблоны относительно каталога конфига, действуют там же, где
    [source].exclude: LSP, CLI и MCP. Без ключа поведение прежнее.
  • metadata: модуль обычной формы читает необязательное описание диалога
    Ext/Form/Form.json — элементы, реквизиты формы и привязанные процедуры, которые
    иначе заперты в двоичном Ext/Form.bin. С ним процедуры, привязанные к событиям
    формы, элементов и кнопок, не считаются неиспользуемыми, а реквизиты формы —
    локальными переменными. Читается любая версия формата от 1 (новые версии только
    добавляют поля); файл с недопустимой версией, неразбираемый или старше Form.bin
    не читается. Формат: docs/configuration/ordinary-form-sidecar.md.
  • config: ключ extends в bsl-analyzer.toml — наследование общего файла
    настроек. Родитель (путь абсолютный или от каталога файла) читается первым,
    дочерний файл накладывается поверх: таблицы сливаются рекурсивно, скаляры и
    массивы заменяются. Цепочки разрешены, цикл и отсутствующий или битый родитель
    — ошибка загрузки с путём файла; относительные пути из родителя разрешаются от
    каталога проекта. LSP и MCP следят за файлами цепочки и перечитывают
    конфигурацию при их правке. В .bsl-analyzer.json ключ отвергается.
  • diagnostics: MissingFormEventHandler — обработчик, назначенный в Form.xml
    управляемой формы (событие формы, событие элемента, действие команды), которого
    нет в модуле формы. Модуль при этом компилируется, и раньше это видела только
    проверка конфигурации с флажком «Существование назначенных обработчиков»
    («Отсутствует обработчик»). Имя сравнивается без учёта регистра; обычные формы и
    формы, заимствованные расширением, не проверяются. Critical, тип Error, включено
    по умолчанию.
  • diagnostics: новое правило UnresolvedMetadataPath (ошибка, включено по умолчанию) —
    строковый литерал первым аргументом Тип, ПредопределенноеЗначение, ОткрытьФорму,
    ПолучитьФорму, ОткрытьФормуМодально (и английских имён) называет объект
    метаданных, которого нет в конфигурации, или предопределённое значение, которого нет
    у перечисления, справочника или плана. Проверка — та же, что у обращения кодом
    (Справочники.X, Перечисления.X.Y); имя формы, общие формы, внешние обработки,
    вычисляемые строки, модули без видимой конфигурации, значения объектов без
    прочитанных предопределённых элементов и заимствованных объектов без видимой
    основной конфигурации не проверяются.
  • hir-ty: чтение через менеджер перечисления, справочника, плана видов
    характеристик, плана счетов или плана видов расчёта проверяется по метаданным:
    Перечисления.X.<Значение>, которого нет среди значений перечисления, и
    Справочники.X.<Имя>, которого нет среди предопределённых элементов (вложенные в
    группы — тоже), дают UnresolvedField — так же, как расширенная проверка
    конфигуратора даёт «Возможно ошибочное свойство». Объект без прочитанных
    предопределённых элементов (нет Ext/Predefined.xml) и заимствованный расширением
    объект без видимой основной конфигурации не проверяются; методы менеджера и
    обращение по индексу не затронуты.
  • diagnostics: в модуле обычной формы с описанием диалога (Ext/Form/Form.json)
    ЭлементыФормы.Имя разрешается в элемент формы, а обращение к элементу, которого
    в диалоге нет, даёт UnresolvedField — если модуль не добавляет элементы сам, не
    передаёт ЭтаФорма/ЭлементыФормы наружу и не исполняет код из строки
    (Выполнить, Вычислить). Без сайдкара ничего не меняется.

Changed

  • diagnostics: UnresolvedMetadataPath проверяет и строки-имена типов конструктора
    Новый ОписаниеТипов(...) (первый, второй и третий аргумент, каждое имя списка через
    запятую) теми же правилами, что и Тип(...). Кроме того, в Тип и ОписаниеТипов
    сообщается имя набора типов без имени объекта (ДокументСсылка, СправочникСсылка,
    CatalogRef, ЛюбаяСсылка): платформа его не принимает («Тип не определен» /
    «Недопустимое значение параметра»). ОтчетОбъект без имени — самостоятельный тип на
    сервере и не сообщается.
  • config: [diagnostics] ordinaryAppSupport, если он не задан, берётся из
    <DefaultRunMode> основной конфигурации: OrdinaryApplication — true, иначе
    (и без основной конфигурации) — false. Явное значение по-прежнему главнее.
    Это же значение теперь получает модель сред исполнения
    (EnvOptions::ordinary_app_support), которую раньше включал только
    ТолстыйКлиентОбычноеПриложение в [features].checked_environments, — правила
    диагностик и модель сред больше не расходятся. Действует в LSP, analyze,
    check-config (показывает источник значения) и в настройках диагностик
    MCP-сервера; правка Configuration.xml подхватывается без перезапуска (в MCP —
    настройками диагностик).
  • diagnostics: модули объекта, менеджера, набора записей и менеджера значения в
    конфигурации с <DefaultRunMode> ManagedApplication или Auto проверяются и
    относительно толстого клиента управляемого приложения — платформа компилирует их
    там. Клиент судится как в клиент-серверном варианте: ModuleAccessibility
    сообщает об обращении к общему модулю только с флагом «Сервер» (без «Вызов
    сервера» и «Клиент (управляемое приложение)») и о вызове &НаСервере-метода
    своего модуля из кода без директивы. В конфигурации обычного приложения и без
    основной конфигурации толстый клиент управляемого приложения не добавляется.
    Вызов &НаСервере-метода своего модуля из кода без директивы сообщается и для
    толстого клиента обычного приложения, когда он проверяется.
  • diagnostics: внешнее соединение, если оно включено в
    [features].checked_environments, судится как в клиент-серверном варианте.
    ModuleAccessibility больше не сообщает о вызове общего модуля с флагом «Вызов
    сервера» из внешнего соединения (платформа его там видит) и сообщает о вызове
    &НаСервере- или &НаСервереБезКонтекста-метода модуля объекта, менеджера,
    набора записей и менеджера значения из кода без директивы (платформа: «Процедура
    или функция с указанным именем не определена»). Тело такого метода проверяется
    только относительно сервера. По умолчанию внешнее соединение не проверяется, и
    проверка прежняя.
  • diagnostics: быстрое исправление UnusedParameters «Удалить неиспользуемый
    параметр»: параметр уходит из объявления, а аргумент на его позиции — из каждого
    вызова метода в модуле (имя сравнивается без учёта регистра, вызовы через
    ЭтотОбъект./ЭтаФорма. тоже правятся, пропущенный аргумент и запятые
    учитываются). Не предлагается для Экспорт-метода, в модуле с Выполнить /
    Вычислить или с ОписаниеОповещения / УстановитьДействие, имя обработчика
    которого не один строковый литерал, когда имя метода встречается в строке модуля или в теле расширения,
    когда имя читается не вызовом, когда имя параметра ещё встречается в методе (в любой
    ветке препроцессора, в строке) и когда вызов передаёт на этой позиции не литерал и
    не простое имя — выбросить вызов функции или чтение поля значит потерять его эффект.
    Исправление ручное, в source.fixAll не входит.

Fixed

  • mcp: клиент, перешедший с server/discover на initialize, снова получает инструменты.
    Так поступает Claude Code, если на discover нет ответа ~3 с. Это бывает на холодном
    кэше справки, когда сервер собирает индекс около 12 с. rmcp 3.1.4 оставляла соединение
    в inline-lifecycle, и tools/list без _meta получал -32602. Теперь rmcp 3.6.0,
    минимум 3.5.1, где это исправлено (modelcontextprotocol/rust-sdk#1248). Вместо
    устаревшего в этих версиях model::ServerInfo используется ServerConfig.

  • diagnostics: UnusedParameters больше не сообщает о параметрах обработчика операции
    веб-сервиса и обработчика получения сообщения сервиса интеграции: их сигнатуру задаёт
    описание сервиса, как у обработчика HTTP-сервиса.

  • parser: #КонецЕсли вложенной директивы больше не закрывает охватывающую область
    модуля. Это случалось в двух местах: директива внутри выражения (Если Ложь /
    #Если … Тогда / Или … / #КонецЕсли / Тогда) — восстановление после ошибки
    съедало её #Если в одиночку; и блок, накрывающий ветку ИначеЕсли оператора
    Если, — блок кончался на ИначеЕсли, а его #Иначе/#КонецЕсли доставались
    внешней области. Методы после такого места выпадали из
    #Если Не ТонкийКлиент И Не ВебКлиент … Тогда, и UnavailableInEnvironment и
    ModuleAccessibility проверяли их во всех окружениях модуля. Теперь восстановление
    оставляет #Если правилам операторов, а пересечённый блок помнится открытым до своего
    #КонецЕсли. Сообщения об ошибке разбора на этих конструкциях остаются (кроме
    ложного «неожиданного #КонецЕсли» и каскада за ним).

  • parser: условная группа #Если … #КонецЕсли, разрывающая конструкцию, больше не
    даёт ложную ошибку разбора и каскад за ней (функция, принятая за процедуру,
    «возврат значения из процедуры»). Платформа выбирает строки ветки до разбора, поэтому
    группа может стоять внутри выражения, между Если и Тогда или дать каждой ветке
    свой заголовок при общем теле и общем КонецЕсли. Такая группа читается одним
    вариантом: ветка, условие которой истинно при всех определённых символах, — код,
    заголовок, директивы и прочие ветки — непрозрачные узлы PRE_TORN_IF_PART.
    Группа, каждая ветка которой держит целые операторы, разбирается как прежде.
    Дерево условий (ConditionalTree) получает узел на такую группу, и проверки
    окружения видят условие прочитанной ветки. Переразбор метода внутри условной группы
    отказывает, если старый или новый текст метода не держит целых конструкций.

  • diagnostics: флаг общего модуля «Клиент (обычное приложение)»
    (ClientOrdinaryApplication) теперь всегда входит в среды модуля, а не только при
    включённой поддержке обычного приложения. Раньше модуль, отмеченный только этим
    флагом, получал пустое множество сред («неизвестно»), и ModuleAccessibility
    молчал, когда к нему обращались из модуля обычной формы, открываемой в толстом
    клиенте управляемого приложения, или из клиентского и серверного кода управляемой
    формы. Платформа в этих средах такой модуль не компилирует («Переменная не
    определена»). Проверяется ли сам толстый клиент обычного приложения, по-прежнему
    решает checked_environments.

  • diagnostics: модуль обычной формы больше не проверяется относительно толстого
    клиента управляемого приложения, если в основной конфигурации выключено свойство
    «Использовать обычные формы в управляемом приложении»
    (UseOrdinaryFormInManagedApplication): платформа его там не компилирует, а
    ModuleAccessibility и UnavailableInEnvironment сообщали о недоступности в
    этой среде. При включённом свойстве проверка прежняя; без основной конфигурации
    по-прежнему учитываются оба толстых клиента. Свойство перечитывается при правке
    Configuration.xml.

  • diagnostics: MismatchedArgCount больше не судит вызовы, которые платформа
    принимает. Ветвь #Если, которую не компилирует ни одно окружение модуля
    (#Если Сервер И Не Сервер Тогда — подсказка типов для редактора, клиентская
    ветвь серверного модуля), и метод, объявленный в такой ветви уровня модуля,
    аргументов не проверяют — там уже молчат UnresolvedBareCall и проверка
    минимальной версии; ветвь с нераспознанным условием и ветви модуля с
    неизвестным окружением проверяются по-прежнему. Условие, истинность которого
    не зависит от Сервер (Сервер И Не Сервер), теперь решено и в толстом клиенте
    и внешнем соединении, где Сервер зависит от режима базы, — это же уточняет
    проверки окружения (UnavailableInEnvironment, ModuleAccessibility). Новый Файл,
    Новый ДокументDOM и Новый ДокументHTML без аргументов получили
    конструктор без параметров; ЭлементDOM.ПолучитьЭлементыПоИмени(<Имя>) и
    ФоновоеЗадание.ОжидатьЗавершения(<Таймаут>) — потерянные справкой параметры.
    Все формы проверены компиляцией (/CheckConfig) и выполнением на 8.3.17 и 8.3.27;
    конструкторы, которых у платформы нет (Новый HTTPСоединение без аргументов),
    по-прежнему сообщаются.

  • diagnostics: синхронные методы HTTPСоединение (Получить,
    ОтправитьДляОбработки, Записать, Изменить, Удалить,
    ПолучитьЗаголовки, ВызватьHTTPМетод) больше не отмечаются
    UnavailableInEnvironment в тонком и толстом клиенте. Справка с 8.3.21 оставляет
    у них только серверные контексты, но вызов на клиенте лишь признан устаревшим:
    платформа 8.3.17 и 8.3.27 выполняет его в тонком и толстом клиенте. Устаревание по-прежнему
    сообщает DeprecatedPlatformApi; веб-клиент, где нет самого типа, не затронут.

  • diagnostics: ФорматированныйДокумент.УстановитьHTML, ДокументPDF.ПреобразоватьВОттенкиСерого,
    ДокументPDF.ДобавитьПодпись и ЗаписьPDF.ПреобразоватьВОттенкиСерого больше не отмечаются
    UnavailableInEnvironment в тонком клиенте, а УстановитьHTML - ещё и в толстом. Справка
    не называет у них эти клиенты, но платформа (8.3.17 и 8.3.27) выполняет вызовы и там. Синхронные
    методы МенеджерСистемыВзаимодействия не тронуты: в тонком клиенте их действительно нет.

  • diagnostics: CommonModuleAssign молчит, когда имя общего модуля совпадает с
    реквизитом контекста модуля — реквизитом управляемой формы или объекта:
    присваивание пишет в реквизит (платформа 8.3.17/8.3.27), а не в модуль. В методе
    без контекста (&НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста)
    реквизит формы не виден, и диагностика сохраняется.

  • diagnostics: ScheduledJobHandler не требует от обработчика предопределённого
    регламентного задания отсутствия параметров, если все они необязательные:
    платформа 8.3.17/8.3.27 вызывает его с пустым массивом параметров задания, и
    параметр со значением по умолчанию его принимает; ошибкой остаётся только
    обязательный параметр («Недостаточно фактических параметров»).

  • parser: метка, совпадающая с ключевым словом (~КонецЦикла:, Перейти ~Возврат;),
    разбирается как имя метки, если слово стоит вплотную за тильдой, — и платформа
    8.3.17/8.3.27 такой модуль собирает. Прежде Перейти ~КонецЦикла; закрывал цикл
    раньше времени, и модуль получал каскад ложных ParseError.

  • parser: Экспорт принимается после любого имени в Перем (Перем А Экспорт, Б Экспорт;,
    Перем А Экспорт, Б;) без ParseError, и экспортируется только имя, за которым
    он стоит: так ведёт себя платформа 8.3.17/8.3.27 — в Перем А, Б Экспорт;
    экспортирована одна Б. Подсветка объявлений следует тому же правилу.

  • hir-ty: вызов без получателя в модуле объекта, менеджера или набора записей, имя
    которого — и метод самого объекта, и глобальная функция платформы, разрешается в
    метод объекта, как это делает платформа: ПолучитьФорму() в модуле объекта отчёта
    и ПолучитьДанныеВыбора(Параметры) в модуле менеджера больше не дают
    MismatchedArgCount и TypeMismatch по сигнатуре глобальной функции, а лишний
    аргумент сверх сигнатуры метода по-прежнему отмечается. Исключение по справке:
    ПолучитьДанныеВыбора с двумя аргументами в модуле менеджера — глобальная функция.

  • diagnostics: MissedRequiredParameter больше не судит вызовы в ветви #Если,
    которую не компилирует ни одно окружение модуля (#Если Сервер И Не Сервер Тогда —
    подсказка типов для редактора, клиентская ветвь серверного модуля): платформа
    отбрасывает такую ветвь до компиляции, и вызов в ней ничего не передаёт. Касается
    и вызовов своего модуля, и вызовов общих модулей и модулей менеджеров, в том числе
    методов, объявленных в такой ветви на уровне модуля; тот же вызов в компилируемом
    коде по-прежнему сообщается. Ветвь, условие которой не решается (#Если Линукс,
    Сервер во внешнем соединении), и ветви модуля неизвестной среды судятся, как прежде.
    Проверено компиляцией (/CheckConfig) и выполнением на 8.3.17 и 8.3.27.

  • diagnostics: UnavailableInEnvironment больше не отмечает в тонком и веб-клиенте
    члены коллекций данных формы. Табличная часть объекта в модуле формы - это
    ДанныеФормыКоллекция, поэтому её методы (Добавить, НайтиСтроки, Количество,
    Индекс, Удалить, Очистить и др.) получают доступность и коллекции формы, а
    НомерСтроки её строки (в том числе Элементы.<Таблица>.ТекущиеДанные) -
    доступность ДанныеФормыЭлементКоллекции. Реквизит формы типа ТаблицаЗначений
    без объявленных колонок и реквизит объекта типа ТаблицаЗначений /
    ДеревоЗначений (Объект.<Реквизит>) - тоже ДанныеФормыКоллекция /
    ДанныеФормыДерево, на клиенте и на сервере; РеквизитФормыВЗначение по-прежнему
    даёт ТаблицаЗначений. Метод, которого у коллекции формы нет (ВыгрузитьКолонку,
    Свернуть), у такого реквизита отмечается как UnresolvedMethodCall, а
    ДанныеФормыВЗначение(<реквизит>, ...) больше не даёт TypeMismatch.

  • diagnostics: методы COMSafeArray и члены РасписаниеРегламентногоЗадания больше не
    отмечаются UnavailableInEnvironment в тонком клиенте, а свойства РасписаниеРегламентногоЗадания -
    ещё и в веб-клиенте. Страницы самих типов в справке называют эти клиенты, страницы членов - нет;
    платформа (8.3.17 и 8.3.27) выполняет вызовы там. ТребуетсяВыполнение в веб-клиенте, глобальные
    функции модальных диалогов в веб-клиенте и НачатьУдалениеФайлов / ПолучитьОбщуюФорму на
    сервере не тронуты: платформа отказывает в них при выполнении.

  • platform-help: корпус справки 8.5 (8.5.1.1423, 8.5.4.1683) больше не отвергается
    целиком. Архивы 8.5 сами описывают ФормаКлиентскогоПриложения.РежимОткрытияОкна,
    поэтому курируемое добавление свойства пропускается, когда у типа ровно одно
    свойство с обоими именами, и остаётся запись архива с описанием. Совпадение
    только одним именем или несколько свойств с обоими именами по-прежнему
    отвергаются (github#462).

  • diagnostics: успешная пересборка резидента гасит перенесённый долг сверки. Пара
    «окно убытка + рубеж фактов» захватывается под тем же локом, что и перенос, и
    гашение отказывает, если окно переоткрыли или рубеж обрезан переполнением, — тогда
    долг выживает, чтения идут полным сканом, а доставленные после подписки правки
    не теряются (github#188).

  • diagnostics: устаревший снимок конфигурации больше не запускает лишнюю полную
    пересборку. Отказ по поколению базлайна возвращает обязанность сканировать и
    сбрасывает кэш снимка, а настоящая правка конфигурации на диске по-прежнему
    вызывает пересборку (github#189).

  • search: приписывание файла корню сведено к одной ролевой процедуре
    (WorkspaceRoots::file_key): движок и публикатор базлайна — тонкие проекции,
    третьей процедуры нет; расхождение на ссылке, ведущей вне корней, закрыто
    паритет-тестами (github#278).

  • search: канонизация корня — снимок поколения: ретаргет ссылки-корня
    переканонизирует таблицу без смены root_id — строки и внешние адреса переживают
    переезд, коллизии id и резервный id конфигурации разведены, а адресованные
    запросы с нерезолвимой регистрацией отклоняются, не отвечая из покинутого
    каталога. Таблицу корней проекта — её читают query, outline, резидент
    диагностики и граф — строят под id, которые обслуживает поиск, так что id из
    выдачи search после ретаргета принимают все инструменты (github#277).

  • search: терминальный отказ инициализации индекса больше не подаётся как строка постройки:
    пустой слот читается единым дискриминатором (идёт инициализация / объявленный отказ /
    слот просто пуст) — в search status терминальные формулировки вместо «building» во
    всех разделах, структурированное поле state согласовано с прозой, терминальный отказ
    reference-цикла назван, а остановленный с демоном рантайм — тоже терминален
    (github#212).

  • search: графовый контекст записей оверлея обновляется после публикации графа:
    обязательство контекстной марки решается один раз на ключ и передаётся записи (её
    собственной грязной марке — точечный рефреш пересобирает запись от текущего
    провайдера) независимо от того, обслуживает ли стор ключ и включена ли токен-политика;
    ключ без записи и без строк стора по-прежнему ждёт исполнителя (github#234).

  • diagnostics: резидент диагностик выходит из Failed повторной попыткой (backoff 5–60 с,
    BSL_MCP_DIAG_RETRY_*), причина прошлого падения видна и во время повтора; у сборки
    появился таймаут (BSL_MCP_DIAG_BUILD_TIMEOUT_SECS, по умолчанию 600 с), а исход
    отставленной дедлайном попытки больше не публикуется; устойчивый отказ резидентных
    инструментов приходит единым структурным error.data (state/reason/retry_after_ms/
    attempts/failed_age_ms), status конверта согласован с состоянием — контракт 3.5
    (github#226).

  • mcp-server: состав проекта, заданный флагами, закреплён boot-тестом: SharedState::workspace
    на вложенных конфигурациях глубже досягаемости автопоиска строит проект через
    project::at — возврат на project_model::Project::new роняет тест (github#227).

  • debug: отказ сервера отладки (HTTP не 2xx) доходит до вызывающего с текстом descr,
    а не читается как успех; setBreakpoints, отвергнутый 8.3.17 из-за
    breakOnCondition, повторяется без него. Ошибка eval возвращает текст платформы
    из exceptionStr. Предмет, остановленный до attach, находится через
    getDbgAllTargetStates и продолжается (continue/step, параметр target);
    disconnect продолжает остановленные предметы перед отключением (github#421).
    locals и expand без ответа за 5 с — ошибка, а не пустой успех; имя файла
    аренды отладчика не длиннее 255 байт.

  • hir-ty, bsl-metadata: колонки, которые управляемая форма добавляет к таблице своего
    реквизита (<AdditionalColumns table="Объект.Товары"> в Form.xml), читаются и
    находятся на строках этой табличной части в модуле этой формы: ложный
    UnresolvedField на Объект.Товары.Добавить().<Колонка> и
    Элементы.Товары.ТекущиеДанные.<Колонка> больше не выдаётся. В другие формы, в модуль
    объекта и на строки других табличных частей колонки не попадают.

Full Changelog: v0.3.2...v0.4.0