При доработке типовых конфигураций через расширения разработчики нередко сталкиваются с ситуацией, когда код с аннотацией &ИзменениеИКонтроль успешно отрабатывает в режиме «1С:Предприятие», однако при синтаксической проверке или сохранении конфигурации в конфигураторе возникает критическая ошибка препроцессора: Модуль(5,3)}: Ожидается оператор препроцессора #<<?>>Вставка.
Разберем по шагам природу этой ошибки, выясним причину ее возникновения в глобальных клиентских модулях и рассмотрим проверенные способы устранения проблемы и альтернативные пути реализации.
Проанализируем требования платформы «1С:Предприятие» к синтаксису расширений. Механизм контроля версий исходного кода с помощью аннотации &ИзменениеИКонтроль, а также специальные директивы препроцессора #Вставка, #КонецВставки, #Удаление и #КонецУдаления появились начиная с версии платформы 8.3.15.
Если у расширения или основной конфигурации свойство Режим совместимости установлено в значение ниже 8.3.15 (например, «Версия 8.3.14» или «Версия 8.3.12»), встроенный синтаксический анализатор конфигуратора не распознает эти конструкции. В результате препроцессор считает символ # началом стандартной директивы препроцессора (такой как #Если или #Область) и, не найдя ожидаемого ключевого слова, выдает ошибку.
Рассмотрим, как синхронизировать режим совместимости:
Обратим внимание на позиционирование ошибки в диагностическом сообщении: Модуль(5,3). Тройка означает, что символ # расположен на третьей позиции строки, то есть перед ним стоят пробелы или символ табуляции.
В некоторых версиях платформы инструкции препроцессора расширений требуют строгого расположения: символ # должен быть первым символом в строке без каких-либо отступов. Кроме того, при копировании фрагментов кода из внешних источников или веб-страниц перед символом # может оказаться неразрывный пробел (символ с кодом 160), который воспринимается компилятором как синтаксическая ошибка.
Посмотрим на пример правильного оформления директивы без отступов:
#Вставка
Возврат;
#КонецВставки
Рекомендуется удалить все предшествующие пробелы и табуляции перед #Вставка и #КонецВставки, а при необходимости полностью вручную перепечатать эти строки с клавиатуры.
Выясним причину, почему в типовых конфигурациях (таких как ЗУП 3.1) возникают сложности именно с глобальными модулями. В платформе 1С действуют строгие системные ограничения на заимствование модулей:
Из-за специфики инициализации глобального контекста фоновая синтаксическая проверка конфигуратора при сохранении конфигурации может выполнять валидацию модуля до того, как контекст расширения сопоставится с базовой конфигурацией. Это порождает ложные ошибки компилятора, хотя в режиме пользовательского сеанса перехват отрабатывает штатно.
Если режим совместимости поднять невозможно или синтаксический анализатор продолжает выдавать ошибку на директивах контроля изменений, рассмотрим альтернативные варианты решения задачи без использования #Вставка.
В приведенном фрагменте кода основной задачей является безусловное прекращение выполнения процедуры оператором Возврат;. Для полной подмены логики метода идеально подходит директива &Вместо. Она не требует директив препроцессора и поддерживается более ранними версиями платформы.
Посмотрим на реализацию через метод-заменитель:
&Вместо("ИмяПроцедуры")
Процедура Расш1_ИмяПроцедуры()
// Полностью блокируем выполнение исходного алгоритма
Возврат;
КонецПроцедуры
Если в дальнейшем потребуется вернуть выполнение оригинальной процедуры по какому-либо условию, достаточно вызвать стандартный метод ПродолжитьВызов():
&Вместо("ИмяПроцедуры")
Процедура Расш1_ИмяПроцедуры()
Если НекотороеУсловие Тогда
Возврат;
КонецЕсли;
ПродолжитьВызов();
КонецПроцедуры
Если в сигнатуре заимствованного метода присутствует параметр СтандартнаяОбработка, наиболее корректным архитектурным решением будет использование директивы &Перед с отключением стандартного сценария:
&Перед("ИмяПроцедуры")
Процедура Расш1_ИмяПроцедуры(СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
КонецПроцедуры
Использование директив &Вместо или &Перед гарантирует стабильность сохранения конфигурации, устраняет конфликт препроцессора и упрощает дальнейшую поддержку кода в расширении.