Нейросеть выдумала метод общего модуля, а проверка через Выполнить его пропустила: как поймать такое до запуска
ОбщегоНазначения.ПолучитьЗначениеРеквизитаОбъекта выглядит как функция БСП, но в типовой УТ 11.5 её нет. Есть, например, ЗначениеРеквизитаОбъекта и ЗначениеРеквизитаОбъектов. Нейросеть пишет такие имена уверенно, а проверка синтаксиса через Выполнить их пропускает, как и выдуманный справочник с выдуманным реквизитом. Узнаёте вы об ошибке, когда выполнение дошло до этой строки, и хорошо, если на копии.
Ниже два приёма, которыми такие имена ловятся до запуска. Первый проверяет, есть ли метод в общем модуле, и сам метод при этом не выполняется. Второй собирает ошибки имён в запросе за один раз, хотя платформа отдаёт их по одной. Оба собраны в обработку, ссылка в конце.
Что пропускает проверка через Выполнить
Конфигуратор и EDT проверяют код, который уже лежит в модуле конфигурации. Кусок из чата до этого живёт в консоли кода, и проверить его без запуска можно так: обернуть в Если Ложь Тогда ... КонецЕсли и отдать Выполнить. Платформа компилирует фрагмент целиком, ветка не выполняется, ошибка приходит со строкой и колонкой. Вот что этот приём видит, а что нет:
Код = "Если Ложь Тогда | Спр = Справочники.ВыдуманныйСправочник; | Имя = ОбщегоНазначения.НесуществующийМетод(1); |КонецЕсли;"; Выполнить(Код); // ошибки нет
Прогон на типовой УТ 11.5:
| Что внутри Если Ложь | Ответ платформы |
|---|---|
1 + ; |
Ошибка в выражении |
цикл без КонецЦикла |
Ожидается ключевое слово 'КонецЦикла' |
НесуществующаяГлобальнаяФункция(1) |
Процедура или функция с указанным именем не определена |
НесуществующийОбщийМодуль.Метод(1) |
Переменная не определена |
| справочник, которого нет, и реквизит, которого нет | ошибки нет |
ОбщегоНазначения.НесуществующийМетод(1) |
ошибки нет |
По таблице граница проходит по точке. Имя до первой точки компилятор проверяет: глобальную функцию, общий модуль, менеджер вроде Справочники. Имя после точки он принимает на веру, с ним разбираются уже при выполнении. Модуль ОбщегоНазначения есть в любой конфигурации на БСП, поэтому первую половину выдуманного имени проверка видит, а вторую нет.
Справочники, документы, регистры и их реквизиты проверить несложно: всё это отдаёт Метаданные. С методами общего модуля хуже. Сам модуль в Метаданные.ОбщиеМодули есть, а списка его экспортных методов там нет, и текст модуля из пользовательского сеанса не прочитать.
Метод общего модуля: вызов со ста аргументами
Вызвать метод по-настоящему, чтобы проверить, нельзя: он что-нибудь сделает. Обёртка Если Ложь, как видно выше, молчит. Остаётся вызвать его так, чтобы платформа отказала раньше, чем войдёт в тело.
Ста параметров у обычного метода нет. Платформа сверяет число аргументов с объявлением до входа в метод. Если метод в модуле есть, ответ будет "Слишком много фактических параметров", и тело не выполнится. Если метода нет, ответ другой: "Метод объекта не обнаружен". По тексту ошибки и видно, выдуман метод или нет.

В виде функции:
// Есть ли экспортный метод в общем модуле. Тело метода не выполняется: // при ста аргументах платформа отказывает до входа в него. // Истина - метод есть, Ложь - выдуман, Неопределено - проверить не удалось. Функция ЕстьМетодОбщегоМодуля(ИмяМодуля, ИмяМетода) Экспорт Если Метаданные.ОбщиеМодули.Найти(ИмяМодуля) = Неопределено Тогда Возврат Ложь; // модуля нет вовсе КонецЕсли; Аргументы = Новый Массив; Для Н = 1 По 100 Цикл Аргументы.Добавить(Формат(Н, "ЧГ=0")); КонецЦикла; Попытка Выполнить(ИмяМодуля + "." + ИмяМетода + "(" + СтрСоединить(Аргументы, ",") + ");"); Исключение Текст = НРег(ОписаниеОшибки()); Если СтрНайти(Текст, "слишком много фактических параметров") > 0 Или СтрНайти(Текст, "too many actual parameters") > 0 Тогда Возврат Истина; ИначеЕсли СтрНайти(Текст, "метод объекта не обнаружен") > 0 Или СтрНайти(Текст, "object method not found") > 0 Тогда Возврат Ложь; КонецЕсли; Возврат Неопределено; // другая ошибка: модуль недоступен в этом контексте и т.п. КонецПопытки; // Сюда дойдёт только метод, у которого сто параметров и больше: // он выполнился по-настоящему. Возврат Истина; КонецФункции
Вызов ЕстьМетодОбщегоМодуля("ОбщегоНазначения", "ПолучитьЗначениеРеквизитаОбъекта") вернёт Ложь, для "ЗначениеРеквизитаОбъекта" вернёт Истина. Что тело метода при этом не выполняется, проверено прогоном на платформе 8.3.27.
Оговорки. Число и порядок параметров так не проверить, только существование. Метод со ста параметрами и больше выполнился бы по-настоящему. Вызывать функцию надо там, где модуль доступен: клиентский общий модуль на сервере даёт "Переменная не определена", и функция вернёт Неопределено. И ИмяМетода должно быть именем, а не произвольной строкой: Выполнить исполнит всё, что в неё подставлено. В обработке имена приходят из разбора текста.
Тем же приёмом проверяются методы менеджеров и объектов. На Справочники.Контрагенты.НайтиПоИНН в типовой УТ 11.5 обработка отвечает: нет метода ни в платформе, ни в модуле менеджера. Для методов объекта нужен экземпляр, его обработка создаёт в памяти через СоздатьЭлемент() и не записывает. Если метода нет, она пробует то же имя в других общих модулях и его варианты: без "Получить", "Объектов" вместо "Объекта". Так рядом с ПолучитьЗначениеРеквизитаОбъекта появляются два настоящих имени из этой базы.
Запрос: платформа говорит про одну ошибку
С запросами иначе. Неверное поле платформа видит, и проверить запрос, ничего не выполняя, можно: Новый Запрос(Текст).НайтиПараметры() компилирует текст и бросает исключение с позицией ошибки. Неудобно другое: ошибка приходит одна.
Вот запрос одной из моделей с нашего стенда, задание "остатки по складам", типовая УТ 11.5, промпт без описания метаданных:
ВЫБРАТЬ ОстаткиТоваровНаСкладах.Склад КАК Склад, КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ОстаткиТоваровНаСкладах.Номенклатура) КАК КоличествоПозиций, СУММА(ОстаткиТоваровНаСкладах.КоличествоОстаток) КАК ВНаличии ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода, ) КАК ОстаткиТоваровНаСкладах ГДЕ ОстаткиТоваровНаСкладах.КоличествоОстаток <> 0 СГРУППИРОВАТЬ ПО ОстаткиТоваровНаСкладах.Склад
В этом регистре ресурс называется ВНаличии, поле виртуальной таблицы остатков ВНаличииОстаток. В соседнем регистре ТоварыОрганизаций ресурс называется Количество, и там КоличествоОстаток настоящее поле. Та же модель поставила КоличествоОстаток к остаткам на складах в пяти заданиях из тридцати. В этом запросе ошибок две, на строках 4 и 8. Платформа сообщила одну, причём про строку 8, хотя строка 4 выше:
{(8, 26)}: Поле не найдено "ОстаткиТоваровНаСкладах.КоличествоОстаток"
Этот же запрос я приводил в статье про стенд и назвал такие ошибки безобидными. Они и правда видны сразу. Неудобно, что по одной: исправите строку 8, узнаете про строку 4. В длинном запросе это несколько кругов "вставил в чат, получил ответ, проверил". И ни разу платформа не скажет, как поле называется в этой базе.
Обработка делает эти круги сама. Нашла ошибку, подменила место и скомпилировала снова. Поле меняется на NULL, выдуманная таблица на ближайшую настоящую, ЗНАЧЕНИЕ(...) на NULL. Упрощённо:
Для Проход = 1 По 40 Цикл Попытка Запрос = Новый Запрос(СтрСоединить(Строки, Символы.ПС)); Запрос.НайтиПараметры(); // компиляция без выполнения Прервать; // ошибок больше нет Исключение Ош = РазобратьОшибку(ОписаниеОшибки()); // строка, колонка, имя КонецПопытки; Ошибки.Добавить(Ош); Если Ош.Вид = "Синтаксис" Тогда Прервать; // дальше платформа текст не читает КонецЕсли; // ошибочное поле подменяем на NULL и компилируем снова Строки[Ош.Строка - 1] = ЗаменитьВСтроке(Строки[Ош.Строка - 1], Ош.Колонка, Ош.Имя, "NULL"); КонецЦикла;
Настоящие имена берутся из СхемаЗапроса: доступные поля каждого источника по его псевдониму, включая поля виртуальных таблиц с суффиксами. К КоличествоОстаток обработка подсказывает ВНаличииОстаток, КОтгрузкеОстаток.
Синтаксическая ошибка цикл останавливает. Для одной из них обработка добавляет к ответу платформы объяснение, потому что сам ответ ничего не объясняет:
ВЫБРАТЬ ПЕРВЫЕ 10 В.Код, В.Наименование, В.НаименованиеПолное ИЗ Справочник.Валюты КАК В
Платформа отвечает "Ожидается имя" и ставит маркер перед В в строке 6. В в языке запросов ключевое слово, то самое, из В (...) и В ИЕРАРХИИ, и псевдонимом быть не может. Короткий псевдоним по первой букве таблицы ставят машинально: в той же статье про стенд так назвала таблицу старшая модель, и я сам в четырёх эталонах. Этот запрос набрали уже при приёмке обработки, на полигоне. Обработка дописала к ошибке: псевдоним совпал с ключевым словом, переименуйте.
Чего так не поймать
Переменная, тип которой из текста не понять, не проверяется. Выборка.Поле, параметр процедуры, результат своей функции: вывода типов нет. Тип определяется, когда он виден из кода: СоздатьЭлемент(), НайтиПоКоду(), ТЧ.Добавить(), Для Каждого Стр Из Объект.Товары.
Запрос, который выполнился без ошибки и вернул не те строки, тоже другой случай. Имена там все настоящие, ошибка в смысле, и ловит её сверка результата с эталоном. Это и есть главная тема статьи про стенд.
И код, вырезанный из модуля, даёт предупреждения: переменные модуля и процедуры, которых во вставке нет. Ошибками они не считаются и в счёт ложных срабатываний ниже не входят.
Как проверяли
Типовая УТ 11.5.22.67, платформа 8.3.27. Набор из 28 кейсов: 19 с одной ошибкой каждый (7 запросов и 12 кусков кода) и 9 правильных. Обработка прошла все 28.
Отдельно ложные срабатывания. Настоящий код типовой конфигурации компилируется и работает, поэтому любая ошибка на нём ложная. Брали три случайные выборки по 60 процедур из кода УТ 11.5. На первых двух нашлись недоделки: 10 ложных ошибок на первой, 3 на второй. После починки все три выборки чистые, 60 процедур из 60 без ошибок. Третья выборка контрольная: её сняли после всех починок, в настройке она не участвовала.
Обработка
Оба приёма и сверка с метаданными собраны в обработку "Проверка кода и запросов нейросети". Вставляете текст из чата, нажимаете "Проверить", получаете таблицу: строка, что не так, настоящие имена из вашей базы. Кнопка "Скопировать для нейросети" кладёт список ошибок с подсказками в виде, который вставляется обратно в чат. Для запроса есть пробный прогон на 10 строк. Чтобы посмотреть, как это выглядит, не подбирая свой пример, есть кнопка "Пример с ошибками": она собирает запрос и код из метаданных вашей базы, с опечаткой в реквизите и выдуманной таблицей. В базу обработка не пишет и нейросеть не вызывает.
Другие наши инструменты
- Стенд проверки запросов нейросети - 30 заданий к типовой УТ 11.5 с эталонами: запрос модели выполняется и сверяется с эталоном построчно.
- Выгрузка структуры метаданных 1С для нейросети - дать модели настоящие имена до того, как она начнёт писать код.
- Права спросившего - запрос нейросети к базе выполняется с правами того, кто спросил.
- Анализ кода внешних обработок - проверить чужую обработку до того, как класть её в базу.
Вопрос
Что нейросеть выдумывает у вас чаще: методы БСП или поля виртуальных таблиц? И как вы это ловите: даёте модели метаданные заранее или проверяете то, что она уже написала?
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.