ESKA · справочник форматирования

Настройки форматирования

01

Статус контракта

T120 реализует политику в общем Rust core: профиль, схема, resolver, migration preview/apply и протокол текста. T121 добавляет библиотеку eska-fmt с алгоритмом BSL, T122 — SDBL и точечную запись встроенных запросов. В T123 готовы eska-fmt / eska fmt , RPC 1.33 и интерфейс Explorer. T144 завершена для локальной поставки и Linux/VSCodium; отчёт приёмки . Анализатор не требуется для разрешения настроек или форматирования.

Первичный конфиг — eska.toml , секция [format] . JSON Schema версии 1 описывает эту секцию, а не целый манифест. Численные ограничения и область применения проверяет также строгий загрузчик проекта/workspace. Смена версии профиля требует явного выбора; новая версия приложения сама не меняет defaults профиля 1c версии 1.

02

Конфигурация

[format]
profile = "team"
profile_version = 1
exclude = ["**/generated/**"]

[format.profiles.team]
based_on = "1c"

[format.profiles.team.common]
column_limit = 100

[format.bsl]
indent_style = "space"
indent_width = 4

[[format.overrides]]
include = ["src/CommonModules/Legacy/**"]

[format.overrides.bsl]
column_limit = 0

Без секции используется 1c версии 1. Существующие явные параметры tools.bsl-analyzer.formatting учитываются для BSL. При несовместимости со значением новой секции операция отклоняется до записи. use_tabs=true и indent_size=1 означают один таб шириной 4 колонки; другой размер в режиме табуляции неоднозначен и требует явной миграции. В режиме пробелов сохраняется число пробелов. indent_size не становится шириной табуляции автоматически.

Порядок: разрешённый профиль → workspace common/язык → member common/язык → overrides workspace, затем member → параметры операции. В одном списке overrides последнее совпадение побеждает. include обязательно, exclude внутри правила отменяет только это правило. Пути относительно объявившего правила eska.toml ; поддерживаются * , ? , ** и / . **/ совпадает также с нулём каталогов. Абсолютные пути, .. , обратные слеши и классы [] в glob не принимаются.

Таблицы наследуют отдельные ключи; скаляры и списки заменяются целиком. exclude=[] очищает наследованные исключения, column_limit=0 отключает ограничение, false сохраняет свой смысл. Исключения не снимают защиту исходников. Пользовательские профили объявляются в format.profiles.<name> и наследуют based_on ; встроенные 1c и eska переопределить нельзя. Неизвестные профили и циклы отклоняются. Параметры отступов редактора не переопределяют стиль проекта.

03

Пресет eska

Встроенный eska версии 1 повторяет устойчивые правила оформления двух пользовательских образцов BSL. Он выбирается в проекте или workspace:

[format]
profile = "eska"
profile_version = 1

Пресет наследует 1c : табуляция шириной 4 колонки, канонический регистр ключевых слов, пробелы вокруг операторов и после запятой. Для BSL он включает:

  • лимит 150 колонок с переносами превышений и сохранением существующих переносов аргументов, правых частей присваиваний и бинарных выражений;
  • выравнивание = соседних присваиваний и запятых соседних однострочных вызовов одного метода с одинаковым числом аргументов;
  • отдельную группу для инициализации объекта перед заполнением его полей: у инициализации обычный пробел перед = , поля выравниваются между собой;
  • закрывающую скобку многострочного вызова на отдельной строке;
  • перенос многострочной строки после = и выравнивание её | по открывающей кавычке, включая обычный текст и строки в аргументах вложенных вызовов;
  • минимум одну пустую строку после объявления метода и перед его окончанием;
  • пустую строку между блоком Если , цикла или Попытка и соседними операциями;
  • пустые строки у границ тела с несколькими операциями; тело с одной операцией оформляется без внутренних пустых строк;
  • пустую строку перед Возврат , кроме единственной операции в ветке;
  • пустые строки вокруг многострочных инструкций между соседними операциями;
  • пустые строки вокруг групп присваиваний полям и самостоятельных вызовов методов одного объекта, включая его инициализацию перед заполнением.

Число операций определяется отдельно для каждой ветки Если / ИначеЕсли / Иначе и Попытка / Исключение . Вложенный блок считается одной операцией, многострочный вызов — тоже; комментарии и пустые операторы не учитываются.

При wrap_binary = "fit" переносы выбираются по приоритету операций: сначала Или , затем И , сравнения, сложение и умножение. Короткое сравнение остаётся целиком, включая вызов слева и правый операнд. Существующий перенос перед или после = / <= внутри такого сравнения убирается даже при preserve_existing_line_breaks = true ; ручные переносы логических и арифметических частей сохраняются. Внутри скобок выбор повторяется независимо. Явные wrap_binary = "preserve" и "one_per_line" сохраняют свой смысл.

Соседние обычные операции остаются подряд, без обязательного разделения каждой пары. Комментарий непосредственно перед отделяемой инструкцией остаётся с ней: пустая строка добавляется перед комментарием. Если тело пересекается с директивами препроцессора, для его внутренних границ сохраняется обычная политика пустых строк: физически альтернативные ветки не суммируются как последовательные операции.

Правила доступны независимо в [format.bsl] и включены в пресете со значением 1 :

[format.bsl]
blank_lines_around_blocks = 1
blank_lines_inside_multistatement_blocks = 1
blank_lines_before_return = 1
blank_lines_around_multiline_statements = 1
blank_lines_between_object_groups = 1

У каждого параметра диапазон 0..16 ; 0 отключает соответствующее правило. При включённом правиле внутренних границ пустые строки у единственной операции убираются, включая ветку с одним Возврат или многострочной инструкцией. Компактность такой ветки имеет приоритет на её внутренних границах; у методов сохраняются blank_lines_inside_methods . В остальных промежутках структурный минимум имеет приоритет над max_empty_lines ; совпадающие требования объединяются, а не складываются.

Многострочность определяется по итоговому выводу инструкции до выравнивания, поэтому новый перенос сразу добавляет разделители, а свёрнутая инструкция сразу участвует в однострочной таблице. Многострочные присваивания всегда завершают таблицу = ; одиночное присваивание получает обычный пробел. Таблица не добавляется, если её отступы создадут превышение column_limit .

Группа объекта состоит минимум из двух соседних операций: присваиваний его полям/элементам и самостоятельных вызовов его методов. Инициализация перед первой такой операцией входит в группу: Запрос = Новый Запрос , затем Запрос.Текст = ... и Запрос.УстановитьПараметр(...) . Серия Контекст.Вставить(...) образует группу без обязательной инициализации рядом. blank_lines_between_object_groups добавляет разделители перед группой и после неё, сохраняя выравнивание и существующие либо обязательные внутренние интервалы.

Получатель определяется по левой части присваивания или по самостоятельному вызову. Упоминания в аргументах и правых частях не учитываются: присваивания Отбор = Запрос.Выполнить() и ВыборкаОтбора = Отбор.Выбрать() остаются отдельной парой между подготовкой запроса и заполнением контекста. Одиночное обращение к объекту не создаёт группу. При повторной инициализации начинается следующая группа, даже если имя переменной совпадает.

Учитываются вложенные пути, индексы, регистр имён и прилегающие комментарии; строковые индексы сравниваются точно. Без инициализации пути получателей должны совпадать целиком; после инициализации в группу входит заполнение его вложенных полей и элементов. Переход уровня, директива, eska-fmt off/on , другой получатель или обычная операция прерывают группу. Порядок операций сохраняется; определение типов и смысл методов не требуются.

Границы таблиц присваиваний и вызовов учитывают итоговую политику пустых строк: при max_empty_lines = 0 удалённый промежуток объединяет соседние строки уже за один проход. Вызовы разделяются сохранённой пустой строкой, комментарием, другим получателем, числом аргументов или уровнем вложенности. В таблицу входит вызов, который после форматирования занимает одну строку, в том числе после сворачивания переносов при preserve_existing_line_breaks = false и wrap_arguments = "fit" . Сохранённые многострочные литералы и выражения остаются границами таблицы. Внутренние запятые вложенных вызовов не выравниваются по внешним. Выравнивание вызовов отключается для группы, которая из-за него выйдет за column_limit .

separate_object_initialization = true отделяет присваивание объекту от таблиц выравнивания, если последующие присваивания той же группы заполняют его поля или элементы коллекции. Учитываются вложенные пути ( Контекст.Документ.Дата ), индексы и регистр идентификаторов. Значения строковых индексов сравниваются точно. Определение типов и анализ правой части не требуются; пустая строка после инициализации этим правилом не добавляется. Например:

ДокументОбъект = МенеджерОбъекта.СоздатьДокумент();
ДокументОбъект.Дата        = ТекущаяДатаСеанса();
ДокументОбъект.Комментарий = "Ляляля";

Опция действует вместе с align_assignments ; явное false возвращает единую таблицу присваиваний, включая инициализацию.

Лимит выбран по образцам: 464 непустые строки кода без отдельных комментариев и многострочных литералов, максимум 150 колонок при табуляции 4. При лимите 120 превышение дали бы 16 строк. Комментарии достигали 173 колонок, строки внутри литералов — 194; их содержимое не переносится. Как и у 1c , лимит мягкий: неразрывный идентификатор или литерал может быть длиннее него. Смешанные отступы образцов приводятся к табуляции; вручную расставленные пробелы перед или после запятых — к общей колонке запятых. Для SDBL eska сохраняет правила 1c .

Профиль по умолчанию остаётся 1c . Явные настройки format.common , format.bsl , overrides и параметры операции имеют приоритет над пресетом. Например, существующее format.bsl.column_limit = 120 продолжит задавать лимит 120. Свой профиль может наследовать based_on = "eska" . Все правила и разрешение пресета принадлежат ESKA; адаптер IDE не реализует их повторно.

При генерации bsl-analyzer.toml профиль передаёт поддерживаемые параметры проверок: для eska это, в частности, LineLength.maxLineLength = 150 . Отступы и допустимое число пустых строк также согласуются со стилем ESKA. Приоритеты, сохранение отключённых правил и границы workspace описаны в конфигурации анализатора .

04

Каталог опций версии 1

Общие параметры допустимы в common , bsl , sdbl и соответствующих таблицах профилей/overrides. keyword_case профиля SDBL по умолчанию upper , BSL — canonical . Типы, диапазоны, enum и остальные defaults входят в JSON Schema.

Ключ Default Смысл / English
indent_style tab tab или space ; indentation character
indent_width 4 Колонок на уровень; columns per block
tab_width 4 Визуальная ширина таба; tab stop width
continuation_indent_width 4 Добавочный отступ продолжения; continuation columns
column_limit 120 Ориентир длины, 0 без лимита; soft column limit
keyword_case По языку canonical , upper , lower , preserve ; token spelling
space_after_comma true Пробел после запятой; comma spacing
space_around_operators true Пробелы вокруг бинарных операторов; binary spacing
space_inside_parentheses false Внутренние пробелы скобок; inner parentheses spacing
space_before_call_parenthesis false Пробел перед скобкой вызова; call parentheses spacing
wrap_arguments fit fit , one_per_line , preserve ; call argument layout
wrap_binary fit fit , one_per_line , preserve ; binary expression layout
break_before_binary_operators true Оператор начинает продолжение; leading operator
max_empty_lines 1 Максимум пустых строк; consecutive empty lines
trim_trailing_whitespace true Удаление хвостовых пробелов вне литералов/комментариев; trailing trivia
insert_final_newline true Финальный перевод строки; final newline
comments indent_only indent_only или preserve ; comment indentation
align_assignments false Только BSL: выравнивание соседних присваиваний; assignment columns
separate_object_initialization false Только BSL: исключать инициализацию из таблиц выравнивания перед заполнением её полей/элементов; separate receiver initialization
align_call_arguments false Только BSL: колонки запятых соседних одинаковых однострочных вызовов; adjacent call argument columns
closing_parenthesis_on_new_line false Только BSL: отдельная строка закрывающей скобки перенесённого вызова; multiline call closing delimiter
preserve_existing_line_breaks false Только BSL: при fit сохранять переносы аргументов/бинарных выражений, а также строку после = ; retain existing breaks while fitting
indent_multiline_strings false Только BSL: переносить многострочный литерал после = и выравнивать отступ перед `
blank_lines_between_methods 1 Только BSL: пустые строки между методами; method separation
blank_lines_inside_methods 0 Только BSL: минимум пустых строк после объявления и перед концом метода, 0..16 ; inner method boundaries
blank_lines_around_blocks 0 Только BSL: минимум пустых строк между блоком и соседними операциями, 0..16 ; control block separation
blank_lines_inside_multistatement_blocks 0 Только BSL: минимум пустых строк у границ тела с несколькими операциями; при 1..16 тело с одной операцией компактное, 0 отключает правило; branch body boundaries
blank_lines_before_return 0 Только BSL: минимум пустых строк перед Возврат , 0..16 ; return separation
blank_lines_around_multiline_statements 0 Только BSL: разделение многострочной инструкции и соседних операций, 0..16 ; multiline statement separation
blank_lines_between_object_groups 0 Только BSL: разделители перед и после групп присваиваний полям и вызовов методов одного получателя, 0..16 ; object operation groups
select_items one_per_line Только SDBL: fit , one_per_line , preserve ; SELECT item layout
condition_items one_per_line Только SDBL: переносы условий; condition layout
group_items one_per_line Только SDBL: группировки/итоги/индекс; grouping layout
order_items one_per_line Только SDBL: порядок; sort list layout
blank_lines_between_queries 1 Только SDBL: пустые строки между запросами/UNION; query separation
clause_newlines true Только SDBL: секции с новой строки; clause separation
align_aliases false Только SDBL: выравнивание КАК/AS; alias columns

Например, ширина 2 и space дают два пробела вместо таба; space_after_comma переключает Метод(А,Б) ↔ Метод(А, Б) ; space_around_operators — А=Б+В ↔ А = Б + В ; keyword_case — если ↔ Если / ЕСЛИ ; wrap_arguments — Метод(А, Б) ↔ вызов с каждым аргументом на своей строке; select_items — ВЫБРАТЬ А, Б ↔ список полей по строкам; align_aliases / align_assignments добавляют пробелы до общей колонки. Golden-примеры проверяют оба алгоритма через публичный протокол.

05

Миграция и машинный контракт

Миграция выполняется явно: preview содержит точный исходный текст и результат. Apply повторно проверяет план, текущие байты, тип файла и права. До замены создаёт исключительно новый .eska-fmt-backup-<sha256>.toml рядом с манифестом; совпавший backup допускается только при точном совпадении байтов. Чужой backup не заменяется. Повтор apply к уже применённому плану возвращает тот же backup. BOM/CRLF, прочие настройки и комментарии вне переносимой секции сохраняются. Подменённый план, изменившийся манифест или защищённый файл не применяются. Обычное форматирование миграцию манифеста не выполняет.

Протокол форматтера имеет schema_version=1 : language ( bsl / sdbl ), полный options , снимок text , nullable range . Координаты — полуоткрытые UTF-8 byte offsets, границы проверяются до разбора. Лимит снимка — 4 MiB. Ответ содержит source_sha256 , список edits и фактический formatted_range . Адаптер IDE преобразует координаты в нативные и проверяет версию своего документа; форматтер не получает команды сохранить владельца. Полная эффективная политика содержит происхождение каждой настройки, версию профиля, язык и признак исключения.

06

Защита поддержки и методов изменения с контролем

Правила обязательны для eska-fmt , eska fmt , IDE/RPC и форматирования запросов; настройки стиля и --style их не отключают. Они строже обычного разрешения редактирования:

Состояние исходника Допуск fmt
Запрет изменения на поддержке Форматирование запрещено
Редактирование с сохранением поддержки Только явно выбранный непустой участок
Собственный объект / снятая поддержка Обычные операции документа и диапазона
Неизвестные или повреждённые правила Форматирование запрещено

Для редактирования с поддержкой format/document требует непустой range , не совпадающий со всем файлом. Возвращаемые правки должны оставаться строго внутри выбранных байтов. Если расширение до синтаксической конструкции меняет текст снаружи, весь план отклоняется с selection_expansion : нужно выделить конструкции целиком, включая отступы. Отсутствующее/пустое выделение и выбор всего файла дают selection_required . Форматирование всего файла при сохранении тоже запрещено. CLI пока не предоставляет произвольный byte-range: для такого участка используется выделение IDE/RPC.

При массовом запуске по проекту, workspace или каталогу CLI пропускает недоступные для полного fmt файлы до чтения и разбора их текста и продолжает обработку разрешённых. JSON содержит status:"skipped" и skip_reason : source_read_only , support_unknown либо selection_required . Human-вывод перечисляет пропуски. Это относится к apply, --check и --diff ; сами пропуски не повышают exit code. Явный запуск на одном запрещённом файле завершается с кодом 2. Исключённые через exclude файлы по-прежнему имеют status:"excluded" .

Методы &ИзменениеИКонтроль / &ChangeAndValidate сохраняются целиком: аннотации, заголовок, тело, комментарии, #Удаление и #Вставка . Обычный код того же модуля можно форматировать; его правки не пересекают защищённые методы. Выделение внутри такого метода не меняет его. Неоднозначные условные границы метода отклоняются без правок. Сервер независимо проверяет ответ компонента, включая старую версию форматтера, которая ещё не знает этого запрета.

Явно выбранный встроенный запрос ( --query-at , --query-index либо отдельный query-черновик) считается выбранным участком владельца. Для него сохраняются проверки поддержки и точечной записи. Внутри ИзменениеИКонтроль запрещено даже форматирование запроса: change_control_protected . Обычное ручное редактирование запроса этим правилом fmt не меняется.

При выдаче IDE-плана и перед публикацией CLI заново проверяются актуальные правила поддержки; неизвестное состояние разрешением не считается.

07

BSL: алгоритм и проверенные границы

Форматтер разбирает заголовки/параметры методов, выражения, вызовы, обращения через точку и индекс, переменные, условия, циклы, исключения, переходы и асинхронный синтаксис. Обе языковые формы сохраняются. Препроцессорные ветви проверяются раздельно и объединяются только при согласованной структуре блоков. Аннотации и препроцессор остаются у левого края. Вне защищённого метода текст #Удаление / #Delete сохраняется побайтно; активная вставка участвует в разборе. Неизвестный синтаксис возвращает ошибку без правок.

Форматирование BSL сохраняет значения строк и не форматирует находящийся в них запрос. При indent_multiline_strings = true (включено в eska ) меняется только отступ перед | ; содержимое после | , экранированные кавычки, физические переводы строк и комментарии между продолжениями сохраняются точно. Для остальных литералов и при false исходные байты токена не меняются. Отдельные комментарии сохраняют собственную строку; комментарии после запятой и перед закрывающей скобкой не теряются при переносе аргументов. comments=preserve оставляет целиком содержащую комментарий конструкцию. trim_trailing_whitespace=false сохраняет пробелы на оставленных физических строках; max_empty_lines ограничивает их количество. Отдельно заданный blank_lines_between_methods имеет приоритет для интервала между методами.

Выделение расширяется до полных синтаксических конструкций, что отражается в formatted_range ; остальные байты сохраняются. При выделении только хвостовых пробелов в конце файла диапазон ответа включает их фактическую правку. Ошибки могут содержать nullable offset — UTF-8 byte offset начала проблемного токена/конструкции. Общие отказы политики не обязаны иметь позицию исходника. После печати выполняются повторный разбор и сравнение всех значимых токенов, включая точные литералы и комментарии.

Ограничения: снимок 4 MiB, 262144 токена, 128 уровней выражений/скобок/блоков, 64 уровня препроцессора; весь результат ограничен 16 MiB, включая суммарные отступы всех конструкций. Превышение возвращает output_too_large до записи любого файла запланированной операции. Несогласуемые ветви и неподдержанные конструкции отклоняются. Это не проверка типов, доступности API или полноты бизнес-логики.

Проверки T121 : 13 сценариев выполнены платформой 8.3.27.2325 в отдельной ИБ, исходный и форматированный код дали ожидаемые значения. Выборка 40 модулей buhmfo и пяти расширений прошла сравнение токенов и повторный проход; исходники пользователя не записывались. Это не сборка всей buhmfo. Дополнительные диагностики 27 fixtures завершены CLI анализатора; замечания о стиле/контекстах не объявляются отсутствующими.

08

SDBL и встроенные запросы

Один алгоритм обрабатывает отдельный запрос и SDBL-черновик. Форматтер использует read-only проекцию секций из core: SELECT, JOIN/ON, WHERE, GROUP BY/HAVING, ORDER BY, вложенные SELECT, UNION, INTO/INDEX BY/DROP, пакеты и итоги. CASE и известные позиции СКД сохраняются исходными токенами; это не расширяет разрешения визуального конструктора. Неизвестная структура отклоняет весь запрос без частичной правки. Проверка грамматических границ не заменяет проверку типов и выполнение платформой.

select_items , condition_items , group_items , order_items принимают fit , one_per_line , preserve . Например, WHERE A=1 AND B=2 превращается в строки WHERE , A = 1 , AND B = 2 ; режим fit оставляет помещающийся список вместе. clause_newlines=false допускает SELECT A, B FROM T . При align_aliases=true пробелы ставятся перед общей колонкой AS/КАК; AS внутри CAST выравниванию не подлежит. Ключевые слова/вызовы меняют регистр только в своих ролях: путь T.Where , псевдоним и &where остаются исходными.

Выделение расширяется до полного запроса пакета со всеми ветвями UNION; вложенный запрос форматируется вместе с содержащим его запросом. // eska-fmt off/on сохраняет целиком затронутый запрос пакета. comments=preserve сохраняет запрос целиком при наличии комментариев. Непереносимые литералы/комментарии могут превышать column_limit . Ограничения core: 65536 токенов и 256 секций/запросов, не более 32 уровней вложенных SELECT. Отдельный снимок по-прежнему ограничен 4 MiB.

format_query использует извлечение и query::format_plan core для выбранного статического BSL-литерала или запроса XML. Общий BSL fmt не трогает строковые значения. Динамические выражения не собираются в предполагаемый запрос. Обратная запись проверяет снимок, кодирует кавычки/entities и меняет только выбранное значение. Комментарии владельца переносятся по неизменным токенам; неоднозначный якорь отклоняет операцию. Для BSL может сохраниться начальный перевод строки запроса, необходимый для физической строки исходного комментария. CDATA может стать экранированным текстом внутри того же query-элемента; соседние XML-узлы/другие запросы остаются побайтно прежними.

Приёмка T122 : 7 запросов и повторные 13 BSL-сценариев выполнены платформой 8.3.27.2325. Ещё 16 сценариев T114 выполнены в обеих версиях на отдельной ИБ с тестовыми метаданными: 32/32, включая регистр, параметры виртуальных таблиц и СКД. Это не выполнение запросов в рабочей buhmfo.

09

CLI: файл, объект, member и проект

В Explorer общий шаблон files.readonlyInclude не передаётся как запрет поверх разового native-разрешения записи в сеансе. Редактор применяет свои актуальные ограничения при штатном форматировании; провайдер возвращает план для его буфера. Права файловой системы, поддержка поставщика и блокировки владельца повторно проверяются ESKA. Разовое разрешение редактора их не отменяет.

eska-fmt [scope] и eska fmt [scope] имеют одинаковые аргументы. Scope — путь к файлу или каталогу относительно --project-dir (по умолчанию текущий каталог). В проекте без scope выбираются BSL/SDBL из Designer source; каталог объекта задаётся обычным путём, например src/Catalogs/Items . --member NAME и --workspace используют общий resolver выбора ESKA. Отдельный BSL/SDBL-файл работает без манифеста с профилем 1С. Существующий ошибочный манифест не игнорируется.

--check , --diff , --dump-config взаимоисключающие и ничего не записывают. Без них применяется проверенный план. --style JSON задаёт sparse override операции; все ключи и происхождение видны в --dump-config . Встроенный запрос выбирается явно: --query-at BYTE для BSL или --query-index INDEX для XML, индексы и координаты с нуля. Это режим одного файла. --migrate-config показывает миграцию корневого манифеста workspace/проекта, --apply-migration применяет её с backup.

--format json : {schema_version:1,formatter_version,mode,files,migration,error} . Каждая запись files содержит path, language, source_sha256, changed, status, edits, effective, diff. source_sha256 — null у исключённого файла и при --dump-config : текст не читается. Status: unchanged , excluded , skipped , planned , applied , failed , not_applied . Для skipped присутствует дополнительное поле skip_reason с машинной причиной защиты. Error — nullable структурированная ошибка {code,field,offset?} ; схема и значения не зависят от locale. В режиме diff правки также содержатся в edits; human вывод показывает исходную и новую версии. Код 0 — успех/предпросмотр, 1 — только --check с необходимыми изменениями, 2 — ошибка; отмена — 130. До записи всего плана проверяются снимки, права, поддержка и межпроцессные блокировки источников.

Чистый вход компонента eska-fmt __format-text принимает один JSON Request версии 1 на stdin, возвращает Response на stdout. Ошибка: {schema_version:1,error} с кодом 2. Вход не читает конфигурацию, файлы или индекс; полная политика передана вызывающим. Это тот же алгоритм, который используется CLI.

Примеры (scope относительно --project-dir ):

eska-fmt Module.bsl --check --format json
eska fmt src/Catalogs/Items --diff
eska fmt --member MyExtension
eska fmt --workspace --check
eska-fmt Query.sdbl --dump-config
eska-fmt Module.bsl --query-at 123 --diff
eska-fmt Schema.xml --query-index 0
eska-fmt --migrate-config
eska-fmt --apply-migration

Межпроцессная защита использует пустые lock-файлы в .eska/source-locks проекта; для отдельного файла — в его родительском каталоге. Это служебное состояние. Lock inode не удаляется при закрытии: владение снимает ОС при закрытии последнего handle, в том числе при завершении процесса. Снимок и политика поддержки всё равно проверяются до записи. Молчаливое снятие чужой блокировки не предусмотрено. План ограничен 128 MiB исходного/нового текста; обход — 100000 узлов и 128 уровней. Предпросмотр не создаёт lock-файлы. Применение сначала проверяет все файлы, получает leases и готовит все временные замены; только потом публикует исходники. Операция не обещает видеть dirty-буфер посторонней IDE. Внешние изменения диска проверяются по точным байтам; отказ preflight сохраняет весь план неприменённым.

Metadata API 1.33 предоставляет format/document , format/query и bounded uploads. Сервер передаёт полную политику отдельному процессу eska-fmt , проверяет его контракт и полученные byte edits; алгоритм в project-компонент не встраивается. RPC-контракт . До выдачи плана повторно проверяются источник, поддержка, манифест и ревизия query-сессии. CRLF нативного черновика сверяется с LF checkpoint в core; план по-прежнему адресует точный текст и его исходные UTF-8 координаты. Реальная CLI/RPC-приёмка запускается tests/formatting_acceptance.py с явными путями к трём бинарникам; стенд автоматически создаётся в playground.

10

Приёмка поставки и задержки

Выборочные пакеты и receipts используют designer-xml-4 ; установка . Проверены formatter-only, shell + formatter, Explorer + project + formatter без анализатора и полный набор с отдельным анализатором. VSIX прошёл проверку 1331 файлов, установку и повтор после перезапуска в ru/en. Undo/Redo, сохранение, устаревший ответ, несовместимый компонент, BOM/CRLF и защита родителя проверены нативными командами VSCodium. Публичный релиз и пользовательская глобальная установка не изменялись.

Release CLI, первый процесс / медиана 7 повторов: малый BSL 4,3 / 3,8 мс, реальный модуль 200 КБ 16,2 / 18,7 мс, пакет 60 операторов 14,7 / 11,9 мс, полная копия расширения из 25 BSL-файлов (251 КБ) 52,7 / 47,4 мс. Применение копии и повторный check прошли, XML и исходное расширение не изменены. CLI/facade/RPC дают одинаковые планы. В установленном VSCodium: первый вызов 282–305 мс, повторный 130–158 мс, с работающим анализатором и без него.

Начальные бюджеты этого стенда: CLI ≤25 мс для малого BSL, ≤75 мс для модуля 200 КБ, ≤50 мс для пакета и ≤200 мс для проекта из 25 файлов; VSCodium ≤750 мс при первом вызове и ≤400 мс при повторном. Это исходные ориентиры данного оборудования, а не переносимые CI-лимиты и не бюджет конструктора T143. Кэш ОС не очищался. Полный массовый fmt buhmfo не заявлен: нужны scope/exclude с учётом ограничений размера. Windows/macOS/VS Code/Remote не проверены.

Воспроизведение замеров: tests/formatting_performance.py --installation ROOT --corpus CORPUS_JSON --real-project EXTENSION_ROOT , с ESKA_TEST_ROOT , указывающим на соседний eska-playground . Скрипт создаёт собственную копию, работает через установленные CLI, применяет только копию и сверяет исходные SHA-256.