Создание плагина для IntelliJ IDE с подключением GigaChat для проверки качества кода

от автора

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

Так как мой текущий не связан с ИИ или ML, то в данной статье я описываю личный опыт создания плагина и интеграции AI в него.

Синергия нейросети и качественного кода

Разработка плагина началась с идеи объединить возможности искусственного интеллекта с инструментами для разработки, чтобы получать полезные рекомендации по коду непосредственно в среде разработки. Поскольку GigaChat способен не только понимать контекст, но и предоставлять рекомендации по улучшению кода, я решил, что интеграция его в IDE для автоматического анализа и проверки качества кода станет полезным инструментом для начинающих разработчиков точно.

Итак, для реализации идеи потребуется создать плагин для IDE, после запуска которого при выделении блока коде и нажатии комбинации клавиш «CTRL+ALT+A» GigaChat проанализировал бы код.

Конфигурация действий:

Конфигурация действий позволяет интегрировать новое действие в контекстное меню редактора в IntelliJ IDEA и добавить к нему сочетание клавиш. В нашем случае действие добавляется в EditorPopupMenu, что позволяет вызывать его на выделенном коде в редакторе.

Для этого создаем новый плагин:

При создании плагина в проекте появится файл plugin.xml в него добавляем:

<actions>     <action             id="AnalyzeSelectedCodeAction"             class="ru.kor.igor.AnalyzeSelectedCodeAction"             text="Analyze Selected Code"             description="Analyze selected code using GigaChat">         <add-to-group group-id="EditorPopupMenu" anchor="last"/>         <keyboard-shortcut keymap="$default" first-keystroke="ctrl alt A"/>     </action> </actions>

Это собственно каркас нашей конфигурации. Когда пользователь выделяет текст в редакторе и нажимает Ctrl + Alt + A или правую кнопку мыши, в этом случае в контекстном меню появится пункт «Analyze Selected Code». Любое из этих действий запускает AnalyzeSelectedCodeAction, который вызывает GigaChat для анализа выделенного кода и отображает результат в IDE.

Ранее я специально отдельно описывал подключение к АПИ GigaChat теперь воспользуюсь этим клиентом, а именно методом createClient(), добавлю в класс GigaChatDialog метод отправки запроса и парсинг ответа:

Отправка запроса

Метод sendMessage принимает строку с сообщением, которое будет отправлено на анализ в GigaChat. Запрос формируется в формате JSON и отправляется методом POST, а затем обрабатывается ответ, который возвращается в формате JSON.

bearerToken — временный токен который мы получаем для работы с сессией GigaChat

    public String sendMessage(String message) throws Exception {         Model model = new Model(message);         String json = model.toJson().toString();         RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));          Request request = new Request.Builder()                 .url(url)                 .post(body)                 .addHeader("Content-Type", "application/json")                 .addHeader("Authorization", "Bearer " + bearerToken)                 .build();          try (Response response = client.newCall(request).execute()) {             if (response.isSuccessful() && response.body() != null) {                 return response.body().string();             } else {                 throw new IOException("Unexpected code " + response + ", Response body: " + (response.body() != null ? response.body().string() : "No response body"));             }         }     }

Парсинг ответа

Метод parseResponseContent анализирует JSON-ответ и извлекает из него текстовый результат анализа, так как возвращаемый ответ содержит еще дополнительную информацию.

    public String parseResponseContent(String jsonResponse) {         JSONObject jsonObject = new JSONObject(jsonResponse);         JSONArray choicesArray = jsonObject.getJSONArray("choices");         if (choicesArray.length() > 0) {             JSONObject firstChoice = choicesArray.getJSONObject(0);             JSONObject messageObject = firstChoice.getJSONObject("message");             return messageObject.getString("content");         }         return null;     }

Пришлось добавить класс (описан ниже), описывающий структуру сообщения, так как выделенный блок кода не всегда распознавался корректно:

Класс Model

Класс Model — это модель, описывающая структуру сообщения, отправляемого на сервер. В нем задаются основные параметры, такие как модель, сообщение, настройки потока и коэффициент штрафа за повторение, что позволяет тонко настроить работу с API GigaChat.

public class Model {     private String model;     private Message message;     private boolean stream;     private double repetitionPenalty;      public Model(String userMessage) {         this.model = "GigaChat";         this.message = new Message(userMessage);         this.stream = false;         this.repetitionPenalty = 1.0;     }      public JSONObject toJson() {         JSONObject jsonObject = new JSONObject();         jsonObject.put("model", model);         jsonObject.put("messages", new JSONObject[] { message.toJson() });         jsonObject.put("stream", stream);         jsonObject.put("repetition_penalty", repetitionPenalty);         return jsonObject;     }      private static class Message {         private String role;         private String content;          public Message(String content) {             this.role = "user";             this.content = content;         }          public JSONObject toJson() {             JSONObject jsonObject = new JSONObject();             jsonObject.put("role", role);             jsonObject.put("content", content);             return jsonObject;         }     } }

Вот мы и подошли к самому главному — реализации самого действия:

Реализация действия в AnalyzeSelectedCodeAction

Класс AnalyzeSelectedCodeAction добавляет обработку события в IntelliJ IDEA, вызывая API GigaChat для анализа выделенного фрагмента кода. При выделении текста и запуске действия (Ctrl + Alt + A или через контекстное меню) отправляется запрос на анализ. Всплывающее окно отображает результат, возвращенный GigaChat.

public class AnalyzeSelectedCodeAction extends AnAction {     private GigaChatClient openAIClient = new GigaChatClient();      public AnalyzeSelectedCodeAction() throws Exception {     }      @Override     public void actionPerformed(AnActionEvent event) {         Project project = event.getProject();         Editor editor = event.getData(CommonDataKeys.EDITOR);          if (editor != null && project != null) {             SelectionModel selectionModel = editor.getSelectionModel();             String selectedText = selectionModel.getSelectedText();              if (selectedText != null && !selectedText.isEmpty()) {                 try {                     analyzeSelectedText(selectedText);                 } catch (Exception e) {                     throw new RuntimeException(e);                 }             } else {                 Messages.showMessageDialog(project, "Please select some code to analyze.", "No Code Selected", Messages.getWarningIcon());             }         }     }      private void analyzeSelectedText(String selectedText) throws Exception {         String response = openAIClient.sendMessage(selectedText);         String content = openAIClient.parseResponseContent(response);         Messages.showMessageDialog("Analysis result: " + content, "Analysis Completed", Messages.getInformationIcon());     } }

Как итог работы:

Мы можем запустить наш плагин из IDE в момент разработки:

Откроется новая IDE в другом окне, вы можете открыть любой проект, далее при выделении любого блока кода в сплывающем окне Вы получите краткий анализ кода.

В качестве дополнительных вариантов обработки кода можно попробовать изменить передаваемый запрос в GigaChat вместе с блоком кода, так как текущая реализация плагина — это общий формат обработки.

Проблемы с которыми я столкнулся при разработке:

  • Время жизни токена всего 30 минут, при отладке приложения приходилось периодически обновлять его

  • Обработка запроса — потребовалось создание отдельной модели, так как выделенный код с кавычками и с переходом на новые строки некорректно воспринимался AI

  • Сам запрос — для исключения лишнего парсинга ответа, необходим стандартизованный запрос, который всегда будет говорить GigaChat вернуть один и тот же ответ.

Вместо заключения:

Данный каркас плагина может быть адаптирован под любую работу с кодом — в том числе рефакторинг, обучение чтению кода начинающим программистам или другие разные полезности))


ссылка на оригинал статьи https://habr.com/ru/articles/857796/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *