Cursor IDE для 1С. Кодревью и рефакторинг с помощью AI

21.04.25

Разработка - Рефакторинг и качество кода

Цель статьи: кратко показать инструмент и возможности Cursor IDE.

Основные возможности Cursor IDE

  • Главное - это AI чат-помощник с поддержкой русского языка (с помощью него можно задавать вопросы и вносить правки в код)
  • Автодополнение и подсказки 1С
  • Автоматический рефакторинг (может внести изменения в код и обосновать, почему так сделал, переименование переменных и т.п.)
  • Проверка качества кода 1С (поиск узких мест, ошибки и т.п.).

 

Подготовка 1С

  1. Выгружаем код конфигурации 1С в файлы в папку (Конфигурация - Выгрузить конфигурацию в файлы)

 

Подготовка Cursor IDE

  1. Скачиваем и устанавливаем Cursor IDE с сайта (без VPN и регистрации 🙃)
  2. Для удобства навигации по метаданным 1С ставим плагин
  3. Для подсветки синтаксиса 1С как вариант ставим плагин
  4. Опционально можно поставить плагин для выбора темы оформления

 

Работа в Cursor IDE

Запускаем и выбираем папку с файлами конфигурации

 

 

Работа с AI чат - помощником

  1. Открываем нужный файл с кодом
  2. Пишем текстом в AI чате, что хотим сделать с кодом/проверить 

 

Пример 1. Рефакторинг к стандартам 1С

Псевдо-код расчета вознаграждения менеджерам

 

Промт-запросы в AI чате:

  1. Добавь комментарии к коду
  2. Сделай рефакторинг, учти стандарты от 1С и алгоритмическую сложность

 

Код до рефакторинга

Перем ТаблицаПродаж;  // Глобальная переменная (риск утечки памяти)

// Рассчитывает вознаграждение менеджеров (плохой пример)
Функция РассчитатьВознаграждения_Плохо(Месяц, Год)
    // Каждый раз загружает все продажи (медленно)
    ТаблицаПродаж = ПолучитьПродажиЗаПериод(Месяц, Год);  // Нет кеширования
    
    // Создаём таблицу для результатов (лишний расход памяти)
    ТаблицаРезультатов = Новый ТаблицаЗначений;
    ТаблицаРезультатов.Колонки.Добавить("Менеджер");
    ТаблицаРезультатов.Колонки.Добавить("Вознаграждение");
    
    // Проходим по всем менеджерам (O(n))
    Для каждого Менеджер Из Справочники.Менеджеры.Выбрать() Цикл
        СуммаПродаж = 0;
        
        // Вложенный цикл по продажам (O(n²)) – медленно!
        Для каждого СтрокаПродажи Из ТаблицаПродаж Цикл
            Если СтрокаПродажи.Менеджер = Менеджер.Ссылка Тогда
                СуммаПродаж = СуммаПродаж + СтрокаПродажи.Сумма;
            КонецЕсли;
        КонецЦикла;
        
        // Жёстко закодированные проценты (негибко)
        Если СуммаПродаж > 1000000 Тогда
            Процент = 0.1;
        ИначеЕсли СуммаПродаж > 500000 Тогда
            Процент = 0.07;
        Иначе
            Процент = 0.05;
        КонецЕсли;
        
        Вознаграждение = СуммаПродаж * Процент;
        
        // Добавляем результат
        НоваяСтрока = ТаблицаРезультатов.Добавить();
        НоваяСтрока.Менеджер = Менеджер.Наименование;
        НоваяСтрока.Вознаграждение = Вознаграждение;
    КонецЦикла;
    
    Возврат ТаблицаРезультатов;   
КонецФункции

 

Код после рефакторинга

// Быстрый расчёт с группировкой и кешированием
Функция РассчитатьВознаграждения_Оптимально(Месяц, Год)
    // Кешируем запрос, если данные уже загружались
    СтатическиеДанные = Неопределено;
    Если СтатическиеДанные = Неопределено Тогда
        СтатическиеДанные = ПолучитьПродажиЗаПериод(Месяц, Год);
    КонецЕсли;
    
    // Группируем продажи по менеджерам (O(n))
    ПродажиПоМенеджерам = Новый Соответствие;
    Для каждого СтрокаПродажи Из СтатическиеДанные Цикл
        Ключ = СтрокаПродажи.Менеджер;
        Если Не ПродажиПоМенеджерам.Получить(Ключ) Тогда
            ПродажиПоМенеджерам.Вставить(Ключ, 0);
        КонецЕсли;
        ПродажиПоМенеджерам[Ключ] = ПродажиПоМенеджерам[Ключ] + СтрокаПродажи.Сумма;
    КонецЦикла;
    
    // Получаем настройки процентов (гибко)
    Настройки = ПолучитьНастройкиВознаграждения();  // Например, из справочника
    
    // Формируем результаты
    ТаблицаРезультатов = Новый ТаблицаЗначений;
    ТаблицаРезультатов.Колонки.Добавить("Менеджер");
    ТаблицаРезультатов.Колонки.Добавить("Вознаграждение");
    
    Для каждого Ключ, Сумма Из ПродажиПоМенеджерам Цикл
        Менеджер = Справочники.Менеджеры.НайтиПоСсылке(Ключ);
        Процент = РассчитатьПроцент(Сумма, Настройки);  // Логика вынесена отдельно
        Вознаграждение = Сумма * Процент;
        
        НоваяСтрока = ТаблицаРезультатов.Добавить();
        НоваяСтрока.Менеджер = Менеджер.Наименование;
        НоваяСтрока.Вознаграждение = Вознаграждение;
    КонецЦикла;
    
    Возврат ТаблицаРезультатов;
КонецФункции

// Определяет процент по настройкам
Функция РассчитатьПроцент(Сумма, Настройки)
    Для каждого СтрокаНастройки Из Настройки Цикл
        Если Сумма >= СтрокаНастройки.Минимум Тогда
            Возврат СтрокаНастройки.Процент;
        КонецЕсли;
    КонецЦикла;
    Возврат 0.05;  // Значение по умолчанию
КонецФункции

 

Пример 2. Более сложный пример рефакторинга логики

Псевдо-код записи нового пользователя ИБ

 

Промт-запросы в AI чате:

  1. Добавь комментарии к коду
  2. Сделай рефакторинг

 

Код до рефакторинга 

Процедура ПередЗаписью(Отказ)
    // Включаем привилегированный режим для операций с пользователями ИБ
    УстановитьПривилегированныйРежим(Истина);  
    
    // Проверяем, является ли текущий пользователь или редактируемый объект администратором
    ТекущийПользовательАдминистратор = ПараметрыСеанса.ТекущийПользователь = Справочники.Пользователи.Администратор; 
    ТекущийОбъектАдминистратор = Ссылка = Справочники.Пользователи.Администратор;
        
    // Проверяем, что для пользователя выбрана хотя бы одна роль
    РезультатПоиска = Роли.НайтиСтроки(Новый Структура("Выбрано", Истина));    
    Если РезультатПоиска.Количество() = 0 Тогда 
        Отказ = Истина;
        Возврат;
    КонецЕсли; 

    // Для нового пользователя
    Если ЭтоНовый() Тогда
        // Проверяем, не существует ли уже пользователь с таким именем
        ТекущийПользователь = ПользователиИнформационнойБазы.НайтиПоИмени(СокрЛП(Наименование));  
        Если ТекущийПользователь <> Неопределено Тогда
            Отказ = Истина;     
            УстановитьПривилегированныйРежим(Ложь);
            Возврат;  
        КонецЕсли;
        
        // Создаем нового пользователя ИБ
        ТекущийИдентификатор = ЗаписатьПользователяИБ(); 
        Если ТекущийИдентификатор = Неопределено Тогда
            Отказ = Истина;      
            УстановитьПривилегированныйРежим(Ложь);
            Возврат;  
        КонецЕсли; 
        
        // Сохраняем идентификатор созданного пользователя
        ИдентификаторПользователяИБ = ТекущийИдентификатор;                                       
    // Для существующего пользователя    
    Иначе    
        // Проверяем, существует ли пользователь ИБ
        ТекущийПользователь = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(ИдентификаторПользователяИБ);  
        Если ТекущийПользователь <> Неопределено Тогда
            Отказ = Истина;     
            УстановитьПривилегированныйРежим(Ложь);
            Возврат;  
        КонецЕсли;
        
        // Обновляем данные пользователя ИБ
        ТекущийИдентификатор = ЗаписатьПользователяИБ(); 
        Если ТекущийИдентификатор = Неопределено Тогда
            Отказ = Истина;      
            УстановитьПривилегированныйРежим(Ложь);
            Возврат;  
        КонецЕсли; 
        
        // Обновляем идентификатор пользователя
        ИдентификаторПользователяИБ = ТекущийИдентификатор; 
                
    КонецЕсли;   
    
    // Очищаем табличную часть с ролями
    Роли.Очистить();
    
    // Отключаем привилегированный режим
    УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры

// Создает или обновляет пользователя информационной базы
//
// Возвращает:
//   УникальныйИдентификатор - идентификатор созданного пользователя
//   Неопределено - в случае ошибки
//
Функция ЗаписатьПользователяИБ()  
    Попытка
        // Создаем нового пользователя ИБ
        ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
        
        // Заполняем основные свойства
        ПользовательИБ.Имя = СокрЛП(Наименование);
        ПользовательИБ.ПолноеИмя = СокрЛП(Наименование);
        ПользовательИБ.АутентификацияОС = Ложь;
        ПользовательИБ.АутентификацияOpenID = Ложь;
        ПользовательИБ.АутентификацияСтандартная = Истина;
        ПользовательИБ.ЗапрещеноИзменятьПароль = Ложь;
        ПользовательИБ.ПоказыватьВСпискеВыбора = Истина;
        ПользовательИБ.Пароль = "";

        // Добавляем выбранные роли
        Для Каждого Роль Из Роли Цикл 
            // Пропускаем невыбранные роли
            Если Роль.Выбрано = Ложь Тогда
                Продолжить;
            КонецЕсли;   
            
            // Ищем метаданные роли
            РезультатПоиска = Метаданные.Роли.Найти(Роль.Имя);  
            Если РезультатПоиска = Неопределено Тогда
                Продолжить;
            КонецЕсли; 
            
            // Добавляем роль пользователю
            ПользовательИБ.Роли.Добавить(РезультатПоиска);
        КонецЦикла;     
        
        // Сохраняем пользователя
        ПользовательИБ.Записать(); 
        
        // Возвращаем идентификатор созданного пользователя
        Возврат ПользовательИБ.УникальныйИдентификатор;    
    Исключение   
        // В случае ошибки возвращаем Неопределено
        Возврат Неопределено;    
    КонецПопытки;        
КонецФункции;

 

Код после рефакторинга

Процедура ПередЗаписью(Отказ)
    // Включаем привилегированный режим для выполнения административных операций
    УстановитьПривилегированныйРежим(Истина);  
    
    // 1. Проверка наличия выбранных ролей
    Если НЕ ПроверитьРоли(Отказ) Тогда
        Возврат;
    КонецЕсли;

    // 2. Проверка и создание/обновление пользователя ИБ
    Если НЕ ПроверитьИСоздатьПользователя(Отказ) Тогда
        Возврат;
    КонецЕсли;   
    
    // Очищаем табличную часть с ролями
    Роли.Очистить();
    
    // Отключаем привилегированный режим
    УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры

// Проверяет, что для пользователя выбрана хотя бы одна роль
//
// Параметры:
//   Отказ - Флаг отказа в записи (выходной параметр)
//
// Возвращает:
//   Булево - Истина, если проверка пройдена успешно
//
Функция ПроверитьРоли(Отказ) Экспорт
    РезультатПоиска = Роли.НайтиСтроки(Новый Структура("Выбрано", Истина));    
    Если РезультатПоиска.Количество() = 0 Тогда 
        Отказ = Истина;
        Возврат Ложь;
    КонецЕсли;
    
    Возврат Истина;
КонецФункции

// Проверяет и создает/обновляет пользователя информационной базы
//
// Параметры:
//   Отказ - Флаг отказа в записи (выходной параметр)
//
// Возвращает:
//   Булево - Истина, если операция выполнена успешно
//
Функция ПроверитьИСоздатьПользователя(Отказ) Экспорт
    // Получаем текущего пользователя (если существует)
    ТекущийПользователь = ПолучитьТекущегоПользователя();
    Если ТекущийПользователь <> Неопределено Тогда
        Отказ = Истина;     
        УстановитьПривилегированныйРежим(Ложь);
        Возврат Ложь;  
    КонецЕсли;
    
    // Создаем/обновляем пользователя ИБ
    ТекущийИдентификатор = ЗаписатьПользователяИБ(); 
    Если ТекущийИдентификатор = Неопределено Тогда
        Отказ = Истина;      
        УстановитьПривилегированныйРежим(Ложь);
        Возврат Ложь;  
    КонецЕсли; 
    
    // Сохраняем идентификатор пользователя ИБ
    ИдентификаторПользователяИБ = ТекущийИдентификатор;
    Возврат Истина;
КонецФункции

// Получает пользователя информационной базы по данным справочника
//
// Возвращает:
//   СправочникСсылка - Найденный пользователь или Неопределено
//
Функция ПолучитьТекущегоПользователя() Экспорт
    Если ЭтоНовый() Тогда
        // Для нового пользователя - поиск по имени
        Возврат ПользователиИнформационнойБазы.НайтиПоИмени(СокрЛП(Наименование));
    Иначе
        // Для существующего - поиск по уникальному идентификатору
        Возврат ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(ИдентификаторПользователяИБ);
    КонецЕсли;
КонецФункции

// Создает или обновляет пользователя информационной базы
//
// Возвращает:
//   УникальныйИдентификатор - Идентификатор созданного пользователя
//   Неопределено - В случае ошибки
//
Функция ЗаписатьПользователяИБ() Экспорт
    Попытка
        // 1. Создание базового объекта пользователя
        ПользовательИБ = СоздатьПользователяИБ();
        
        // 2. Назначение ролей пользователю
        НазначитьРолиПользователю(ПользовательИБ);
        
        // 3. Сохранение пользователя
        ПользовательИБ.Записать(); 
        
        Возврат ПользовательИБ.УникальныйИдентификатор;    
    Исключение   
        // В случае ошибки возвращаем Неопределено
        Возврат Неопределено;    
    КонецПопытки;        
КонецФункции

// Создает объект пользователя информационной базы с базовыми настройками
//
// Возвращает:
//   ПользовательИнформационнойБазы - Созданный объект пользователя
//
Функция СоздатьПользователяИБ() Экспорт
    ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
    
    // Настройка основных параметров пользователя
    ПользовательИБ.Имя = СокрЛП(Наименование);
    ПользовательИБ.ПолноеИмя = СокрЛП(Наименование);
    ПользовательИБ.АутентификацияОС = Ложь;
    ПользовательИБ.АутентификацияOpenID = Ложь;
    ПользовательИБ.АутентификацияСтандартная = Истина;
    ПользовательИБ.ЗапрещеноИзменятьПароль = Ложь;
    ПользовательИБ.ПоказыватьВСпискеВыбора = Истина;
    ПользовательИБ.Пароль = "";
    
    Возврат ПользовательИБ;
КонецФункции

// Назначает роли пользователю информационной базы
//
// Параметры:
//   ПользовательИБ - Объект пользователя информационной базы
//
Процедура НазначитьРолиПользователю(ПользовательИБ) Экспорт
    Для Каждого Роль Из Роли Цикл 
        // Пропускаем невыбранные роли
        Если Роль.Выбрано = Ложь Тогда
            Продолжить;
        КонецЕсли;   
        
        // Ищем метаданные роли
        РезультатПоиска = Метаданные.Роли.Найти(Роль.Имя);  
        Если РезультатПоиска = Неопределено Тогда
            Продолжить;
        КонецЕсли; 
        
        // Добавляем роль пользователю
        ПользовательИБ.Роли.Добавить(РезультатПоиска);
    КонецЦикла;
КонецПроцедуры

 

Итого по результатам

  • бегло узнали возможности Cursor IDE
  • взглянули на свой код со стороны

 

Идеи для автоматизации 

  • Использовать Cursor IDE для написания скриптов автоматизации тестирования, CI/CD
  • Использование для анализа технологического журнала и других логов
  • Поиск циклических зависимостей и т.п.

 

Выводы

  • Cursor IDE не заменит 1С:Конфигуратор
  • Поможет с ревью кода и автоматизацией рутинных операций

 

Спасибо за внимание!

Лайк, подписка, комментарий 😎

AI автоматизация кодревью оптимизация разработка скрипты

См. также

Рефакторинг и качество кода Программист Стажер Бесплатно (free)

Разбираем принципы SOLID в контексте 1С: как укротить хаос в коде, сделать его гибким, расширяемым и предсказуемым. Практические примеры, механизмы платформы помогающие в этом и шаги к чистой разработке для новичков и профи.

вчера в 11:30    636    RPGrigorev    16    

13

Рефакторинг и качество кода Обновление 1С Программист Платформа 1С v8.3 Бесплатно (free)

Методика, описанная в статье, выработана при переезде с 1С:ДО 2.1 на 1С:ДО 3.0. Может также применяться при переходе с 1С:УПП на 1C:ERP, 1C:ERP на 1C:ERP УХ и т. п. Учтены все необходимые доработки при переезде на новую конфигурацию и предупреждены возможные ошибки.

вчера в 11:00    332    PROSTO-1C    2    

3

Рефакторинг и качество кода Программист Платформа 1С v8.3 Россия Бесплатно (free)

Диалог "Вопрос" использовался очень интенсивно в старых версиях кода и также его используют в УФ довольно часто. Иногда очень неудобно использовать рефакторинг через асинхронные вызовы ПоказатьВопрос и ВопросАсинх по разным причинам. Есть ещё одно решение, как избежать больших переделок кода, когда Вы не планируете его использовать где-то на других платформах и Веб-клиентах.

26.03.2025    439    ksuman    6    

3

HighLoad оптимизация Рефакторинг и качество кода Технологический журнал Программист Платформа 1С v8.3 Россия Бесплатно (free)

Технологии бегут вперёд, но боль производительности 1С остаётся вечной: инфраструктура, код или настройки? Пока ИИ не научился чинить всё «на лету», мы автоматизировали ключевое — диагностику. Читайте статью — показываем, как превратить хаос диагностики в понятные графики и цифры. Спойлер: это работает даже если ваша 1С — «чёрный ящик» на старом железе.

19.03.2025    2939    EFSOL_oblako    9    

9

Рефакторинг и качество кода Программист Стажер Платформа 1С v8.3 Бесплатно (free)

В процессе обучения студенты бывает, что по невнимательности или торопливости допускают кучу ошибок. Далеко не у всех  преподавателей есть на это время, но новички допускают поначалу прилично  много ошибок и как всегда идет "крик души" в общем чате обучения. Поэтому я решила  немного рассказать и показать в надежде, что данная статья кому-нибудь  "облегчит страдания" студента.

17.03.2025    2482    Bukaska    5    

8

Нейросети Рефакторинг и качество кода Тестирование QA Программист Платформа 1С v8.3 Бесплатно (free)

Искусственный интеллект в код-ревью – это не фантастика, а реальность, которая уже сегодня помогает разработчикам улучшать свои проекты. Расскажем о том, как ИИ может автоматически находить баги и предлагать улучшения, экономя ваше время и ресурсы.

11.03.2025    5470    mrXoxot    52    

53

Рефакторинг и качество кода Тестирование QA Программист Платформа 1С v8.3 Бесплатно (free)

В последней статье по докладу Александра Кириллова, с которым он выступил на конференции INFOSTART TECH EVENT 2024, обсудим особенности тестирования после завершения рефакторинга платформеннозависимого кода

11.03.2025    581    it-expertise    0    

3

Инструментарий разработчика Рефакторинг и качество кода Программист Платформа 1С v8.3 Бесплатно (free)

Расширяемый форматтер структуры модулей 1С. Умеет автоматически расставлять стандартные области и раскидывать по ним процедуры и функции модуля, оформлять стандартные комментарии к методам с помощью ИИ. Также умеет анализировать модуль - извлекать структуру вызовов, используемые поля и т.д. Реализован в виде расширения (.cfe). Можно использовать как платформу для обработки кода в своих задачах автоматизации разработки.

12.02.2025    7505    478    wonderboy    45    

120
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. amiralnar 9 22.04.25 08:36 Сейчас в теме
Можно свести статью к одному предложению: "Установим Cursor и чат AI будет нам что-то делать с нашим кодом."
Ни реальных сценариев, ни сравнения с разными моделями, ни капли совести у автора.
kirillkr; +1 Ответить
2. dimzfresh 48 22.04.25 08:59 Сейчас в теме
(1) По поводу глубины обзора - нет и не планировалось.
Первым же предложением в статье написано, что это краткий обзор ⚠

Cursor IDE - может анализировать исходники в директории.
Другие AI чаты про другое.

В примерах «до» и «после» изменения происходили по текстовому запросу в чате.
В рамках псевдо кода результат с комментариями явно дает понять, что изменилось.

Мне нравится ваша цитата про то, что «AI будет что-то нам делать..»!
Подход верный, доверяй, но проверяй результат👍
3. wonderboy 511 22.04.25 09:43 Сейчас в теме
Результаты могут сильно отличаться в зависимости от выбранной модельки.

Если кому-то интересно подробнее о Cursor для 1С, с кейсами, можете посмотреть мои обзоры:
https://vk.com/video-219359576_456239021

https://vk.com/video-219359576_456239022

Вот еще на aider:

https://vk.com/video-219359576_456239019
Оставьте свое сообщение