From cbf96e5c40207b2071d9352c14368c1a8dc1aae7 Mon Sep 17 00:00:00 2001 From: xiangtianyu Date: Thu, 29 Aug 2024 20:31:05 +0800 Subject: [PATCH] Chat reference code (#83) * reference chat * reference chat * answer language will always upload * update webview * pure chat code ref --- .../SelectedCodeGenerateBaseAction.java | 3 +- .../editor/popupmenu/BasicEditorAction.java | 9 +- .../editor/popupmenu/NewChatAction.java | 33 +- .../PopupMenuEditorActionGroupUtil.java | 32 +- .../editor/popupmenu/ReferenceCodeAction.java | 56 + .../devpilot/enums/EditorActionEnum.java | 4 - .../chat/DevPilotChatToolWindow.java | 44 +- .../chat/DevPilotChatToolWindowService.java | 68 +- .../toolwindows/components/EditorInfo.java | 67 +- .../EditorActionConfigurationState.java | 4 - .../zhongan/devpilot/util/EditorUtils.java | 15 +- .../webview/model/CodeReferenceModel.java | 65 +- .../resources/messages/devpilot_en.properties | 3 +- .../resources/messages/devpilot_zh.properties | 3 +- src/main/resources/webview/index.html | 1565 ++++------------- 15 files changed, 651 insertions(+), 1320 deletions(-) create mode 100644 src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/ReferenceCodeAction.java diff --git a/src/main/java/com/zhongan/devpilot/actions/editor/SelectedCodeGenerateBaseAction.java b/src/main/java/com/zhongan/devpilot/actions/editor/SelectedCodeGenerateBaseAction.java index 279d5dc9..69823a5f 100644 --- a/src/main/java/com/zhongan/devpilot/actions/editor/SelectedCodeGenerateBaseAction.java +++ b/src/main/java/com/zhongan/devpilot/actions/editor/SelectedCodeGenerateBaseAction.java @@ -56,8 +56,7 @@ public void actionPerformed(@NotNull AnActionEvent e) { service.clearRequestSession(); var showText = getShowText(); - var codeReference = new CodeReferenceModel(editorInfo.getFilePresentableUrl(), - editorInfo.getFileName(), editorInfo.getSelectedStartLine(), editorInfo.getSelectedEndLine(), getEditorActionEnum()); + var codeReference = CodeReferenceModel.getCodeRefFromEditor(editorInfo, getEditorActionEnum()); var codeMessage = MessageModel.buildCodeMessage( UUID.randomUUID().toString(), System.currentTimeMillis(), showText, username, codeReference); diff --git a/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/BasicEditorAction.java b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/BasicEditorAction.java index 1e74a58e..3e5510e4 100644 --- a/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/BasicEditorAction.java +++ b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/BasicEditorAction.java @@ -7,6 +7,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsActions; import com.intellij.psi.PsiElement; +import com.zhongan.devpilot.webview.model.CodeReferenceModel; import javax.swing.Icon; @@ -23,18 +24,18 @@ public abstract class BasicEditorAction extends AnAction { PopupMenuEditorActionGroupUtil.registerOrReplaceAction(this); } - protected abstract void actionPerformed(Project project, Editor editor, String selectedText, PsiElement psiElement); + protected abstract void actionPerformed(Project project, Editor editor, String selectedText, PsiElement psiElement, CodeReferenceModel codeReferenceModel); public void actionPerformed(@NotNull AnActionEvent event) { var project = event.getProject(); var editor = event.getData(PlatformDataKeys.EDITOR); if (editor != null && project != null) { - actionPerformed(project, editor, editor.getSelectionModel().getSelectedText(), null); + actionPerformed(project, editor, editor.getSelectionModel().getSelectedText(), null, null); } } - public void fastAction(Project project, Editor editor, String selectedText, PsiElement psiElement) { - actionPerformed(project, editor, selectedText, psiElement); + public void fastAction(Project project, Editor editor, String selectedText, PsiElement psiElement, CodeReferenceModel codeReferenceModel) { + actionPerformed(project, editor, selectedText, psiElement, codeReferenceModel); } public void update(AnActionEvent event) { diff --git a/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/NewChatAction.java b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/NewChatAction.java index e90c2ba1..f507c51f 100644 --- a/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/NewChatAction.java +++ b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/NewChatAction.java @@ -3,9 +3,13 @@ import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; +import com.zhongan.devpilot.gui.toolwindows.chat.DevPilotChatToolWindowService; +import com.zhongan.devpilot.gui.toolwindows.components.EditorInfo; import com.zhongan.devpilot.util.DevPilotMessageBundle; +import com.zhongan.devpilot.webview.model.CodeReferenceModel; import org.jetbrains.annotations.NotNull; @@ -24,13 +28,30 @@ public void update(@NotNull AnActionEvent event) { @Override public void actionPerformed(@NotNull AnActionEvent event) { var project = event.getProject(); - if (project != null) { - ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("DevPilot"); - if (toolWindow == null) { - return; - } - toolWindow.show(); + if (project == null) { + return; } + + ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("DevPilot"); + if (toolWindow == null) { + return; + } + toolWindow.show(); + + var editor = event.getData(PlatformDataKeys.EDITOR); + if (editor == null) { + return; + } + + var editorInfo = new EditorInfo(editor); + if (editorInfo.getSourceCode() == null) { + return; + } + + var codeReference = CodeReferenceModel.getCodeRefFromEditor(editorInfo, null); + var service = project.getService(DevPilotChatToolWindowService.class); + service.clearRequestSession(); + service.referenceCode(codeReference); } } diff --git a/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/PopupMenuEditorActionGroupUtil.java b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/PopupMenuEditorActionGroupUtil.java index b32a34f1..3a07ab08 100644 --- a/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/PopupMenuEditorActionGroupUtil.java +++ b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/PopupMenuEditorActionGroupUtil.java @@ -27,7 +27,6 @@ import com.zhongan.devpilot.util.DevPilotMessageBundle; import com.zhongan.devpilot.util.DocumentUtil; import com.zhongan.devpilot.util.LanguageUtil; -import com.zhongan.devpilot.util.PerformanceCheckUtils; import com.zhongan.devpilot.util.PsiElementUtils; import com.zhongan.devpilot.util.PsiFileUtil; import com.zhongan.devpilot.webview.model.CodeReferenceModel; @@ -54,11 +53,9 @@ public class PopupMenuEditorActionGroupUtil { private static final Map ICONS = new LinkedHashMap<>(Map.of( - EditorActionEnum.CHECK_PERFORMANCE.getLabel(), AllIcons.Plugins.Updated, EditorActionEnum.GENERATE_COMMENTS.getLabel(), AllIcons.Actions.InlayRenameInCommentsActive, EditorActionEnum.GENERATE_TESTS.getLabel(), AllIcons.Modules.GeneratedTestRoot, EditorActionEnum.FIX_CODE.getLabel(), AllIcons.Actions.QuickfixBulb, - EditorActionEnum.REVIEW_CODE.getLabel(), AllIcons.Actions.PreviewDetailsVertically, EditorActionEnum.EXPLAIN_CODE.getLabel(), AllIcons.Actions.Preview)); public static void refreshActions(Project project) { @@ -67,13 +64,14 @@ public static void refreshActions(Project project) { DefaultActionGroup group = (DefaultActionGroup) actionGroup; group.removeAll(); group.add(new NewChatAction()); + group.add(new ReferenceCodeAction()); group.addSeparator(); var defaultActions = EditorActionConfigurationState.getInstance().getDefaultActions(); defaultActions.forEach((label) -> { var action = new BasicEditorAction(DevPilotMessageBundle.get(label), DevPilotMessageBundle.get(label), ICONS.getOrDefault(label, AllIcons.FileTypes.Unknown)) { @Override - protected void actionPerformed(Project project, Editor editor, String selectedText, PsiElement psiElement) { + protected void actionPerformed(Project project, Editor editor, String selectedText, PsiElement psiElement, CodeReferenceModel codeReferenceModel) { ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("DevPilot"); toolWindow.show(); var editorActionEnum = EditorActionEnum.getEnumByLabel(label); @@ -88,16 +86,8 @@ protected void actionPerformed(Project project, Editor editor, String selectedTe return; } - switch (editorActionEnum) { - case CHECK_PERFORMANCE: - // display result, and open diff window - PerformanceCheckUtils.showDiffWindow(selectedText, project, editor); - break; - case GENERATE_COMMENTS: - DocumentUtil.diffCommentAndFormatWindow(project, editor, result); - break; - default: - break; + if (editorActionEnum == EditorActionEnum.GENERATE_COMMENTS) { + DocumentUtil.diffCommentAndFormatWindow(project, editor, result); } }; Map data = new HashMap<>(); @@ -142,10 +132,10 @@ protected void actionPerformed(Project project, Editor editor, String selectedTe } } - if (LanguageSettingsState.getInstance().getLanguageIndex() == 1 - && editorActionEnum != EditorActionEnum.GENERATE_COMMENTS) { - // todo 拿到用户真正希望回答的语言 + if (LanguageSettingsState.getInstance().getLanguageIndex() == 1) { data.put(ANSWER_LANGUAGE, "zh_CN"); + } else { + data.put(ANSWER_LANGUAGE, "en_US"); } var service = project.getService(DevPilotChatToolWindowService.class); @@ -153,11 +143,13 @@ protected void actionPerformed(Project project, Editor editor, String selectedTe service.clearRequestSession(); var showText = DevPilotMessageBundle.get(label); - var codeReference = new CodeReferenceModel(editorInfo.getFilePresentableUrl(), - editorInfo.getFileName(), editorInfo.getSelectedStartLine(), editorInfo.getSelectedEndLine(), editorActionEnum); + + if (codeReferenceModel == null) { + codeReferenceModel = CodeReferenceModel.getCodeRefFromEditor(editorInfo, editorActionEnum); + } var codeMessage = MessageModel.buildCodeMessage( - UUID.randomUUID().toString(), System.currentTimeMillis(), showText, username, codeReference); + UUID.randomUUID().toString(), System.currentTimeMillis(), showText, username, codeReferenceModel); service.sendMessage(SessionTypeEnum.MULTI_TURN.getCode(), editorActionEnum.name(), data, null, callback, codeMessage); } diff --git a/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/ReferenceCodeAction.java b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/ReferenceCodeAction.java new file mode 100644 index 00000000..82fc2d3c --- /dev/null +++ b/src/main/java/com/zhongan/devpilot/actions/editor/popupmenu/ReferenceCodeAction.java @@ -0,0 +1,56 @@ +package com.zhongan.devpilot.actions.editor.popupmenu; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowManager; +import com.zhongan.devpilot.gui.toolwindows.chat.DevPilotChatToolWindowService; +import com.zhongan.devpilot.gui.toolwindows.components.EditorInfo; +import com.zhongan.devpilot.util.DevPilotMessageBundle; +import com.zhongan.devpilot.webview.model.CodeReferenceModel; + +import org.jetbrains.annotations.NotNull; + +public class ReferenceCodeAction extends AnAction { + + public ReferenceCodeAction() { + super(DevPilotMessageBundle.get("devpilot.action.reference.chat"), DevPilotMessageBundle.get("devpilot.action.reference.chat"), AllIcons.Actions.Find); + PopupMenuEditorActionGroupUtil.registerOrReplaceAction(this); + } + + @Override + public void update(@NotNull AnActionEvent event) { + event.getPresentation().setEnabled(event.getProject() != null); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent event) { + var project = event.getProject(); + if (project == null) { + return; + } + + ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("DevPilot"); + if (toolWindow == null) { + return; + } + toolWindow.show(); + + var editor = event.getData(PlatformDataKeys.EDITOR); + if (editor == null) { + return; + } + + var editorInfo = new EditorInfo(editor); + if (editorInfo.getSourceCode() == null) { + return; + } + + var codeReference = CodeReferenceModel.getCodeRefFromEditor(editorInfo, null); + var service = project.getService(DevPilotChatToolWindowService.class); + service.referenceCode(codeReference); + } + +} diff --git a/src/main/java/com/zhongan/devpilot/enums/EditorActionEnum.java b/src/main/java/com/zhongan/devpilot/enums/EditorActionEnum.java index 5ea540f1..2da21f5c 100644 --- a/src/main/java/com/zhongan/devpilot/enums/EditorActionEnum.java +++ b/src/main/java/com/zhongan/devpilot/enums/EditorActionEnum.java @@ -4,8 +4,6 @@ public enum EditorActionEnum { - CHECK_PERFORMANCE("devpilot.action.performance.check", "Performance check in the following code"), - GENERATE_COMMENTS("devpilot.action.generate.comments", "Generate comments in the following code"), COMMENT_METHOD("devpilot.action.generate.method.comments", ""), @@ -14,8 +12,6 @@ public enum EditorActionEnum { FIX_CODE("devpilot.action.fix", "Fix This in the following code"), - REVIEW_CODE("devpilot.action.review", "Review code in the following code"), - EXPLAIN_CODE("devpilot.action.explain", "Explain this in the following code"), COMPLETE_CODE("devpilot.action.completions", "code completions"); diff --git a/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindow.java b/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindow.java index d0cca251..6a95038c 100644 --- a/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindow.java +++ b/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindow.java @@ -31,7 +31,9 @@ import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import javax.swing.JComponent; @@ -47,6 +49,15 @@ public class DevPilotChatToolWindow { private final Project project; + private static final Map codeActionMap = new ConcurrentHashMap<>(); + + static { + codeActionMap.put("FixCode", EditorActionEnum.FIX_CODE); + codeActionMap.put("CommentCode", EditorActionEnum.GENERATE_COMMENTS); + codeActionMap.put("ExplainCode", EditorActionEnum.EXPLAIN_CODE); + codeActionMap.put("TestCode", EditorActionEnum.GENERATE_TESTS); + } + public DevPilotChatToolWindow(Project project) { super(); this.project = project; @@ -105,10 +116,13 @@ private void registerJsCallJavaHandler(JBCefBrowser browser) { var time = System.currentTimeMillis(); var username = DevPilotLlmSettingsState.getInstance().getFullName(); var uuid = UUID.randomUUID().toString(); - var message = messageModel.getContent(); - var userMessageModel = MessageModel.buildUserMessage(uuid, time, message, username); - service.sendMessage(SessionTypeEnum.MULTI_TURN.getCode(), "PURE_CHAT", null, message, null, userMessageModel); + ApplicationManager.getApplication().invokeLater(() -> { + var message = service.getUserContentCode(messageModel); + var userMessageModel = MessageModel.buildCodeMessage(uuid, time, message.getContent(), username, message.getCodeRef()); + service.sendMessage(SessionTypeEnum.MULTI_TURN.getCode(), "PURE_CHAT", null, message.getContent(), null, userMessageModel); + }); + return new JBCefJSQuery.Response("success"); } case "InterruptChatStream": { @@ -179,7 +193,8 @@ private void registerJsCallJavaHandler(JBCefBrowser browser) { ApplicationManager.getApplication().invokeLater( () -> EditorUtils.openFileAndSelectLines(project, codeReferenceModel.getFileUrl(), - codeReferenceModel.getSelectedStartLine(), codeReferenceModel.getSelectedEndLine())); + codeReferenceModel.getSelectedStartLine(), codeReferenceModel.getSelectedStartColumn(), + codeReferenceModel.getSelectedEndLine(), codeReferenceModel.getSelectedEndColumn())); return new JBCefJSQuery.Response("success"); } @@ -196,16 +211,17 @@ private void registerJsCallJavaHandler(JBCefBrowser browser) { service.regenerateMessage(); return new JBCefJSQuery.Response("success"); } - case "FixCode": { - service.handleActions(EditorActionEnum.FIX_CODE, null); - return new JBCefJSQuery.Response("success"); - } - case "CommentCode": { - service.handleActions(EditorActionEnum.GENERATE_COMMENTS, null); - return new JBCefJSQuery.Response("success"); - } - case "ExplainCode": { - service.handleActions(EditorActionEnum.EXPLAIN_CODE, null); + case "FixCode": + case "CommentCode": + case "ExplainCode": + case "TestCode": { + var payload = jsCallModel.getPayload(); + var messageModel = JsonUtils.fromJson(JsonUtils.toJson(payload), MessageModel.class); + if (messageModel == null) { + return new JBCefJSQuery.Response("error"); + } + + service.handleActions(messageModel.getCodeRef(), codeActionMap.get(command), null); return new JBCefJSQuery.Response("success"); } case "CopyCode": { diff --git a/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindowService.java b/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindowService.java index 3f26b64d..67dcc8c1 100644 --- a/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindowService.java +++ b/src/main/java/com/zhongan/devpilot/gui/toolwindows/chat/DevPilotChatToolWindowService.java @@ -12,6 +12,7 @@ import com.zhongan.devpilot.constant.DefaultConst; import com.zhongan.devpilot.enums.EditorActionEnum; import com.zhongan.devpilot.enums.SessionTypeEnum; +import com.zhongan.devpilot.gui.toolwindows.components.EditorInfo; import com.zhongan.devpilot.integrations.llms.LlmProvider; import com.zhongan.devpilot.integrations.llms.LlmProviderFactory; import com.zhongan.devpilot.integrations.llms.entity.DevPilotChatCompletionRequest; @@ -21,6 +22,7 @@ import com.zhongan.devpilot.util.JsonUtils; import com.zhongan.devpilot.util.MessageUtil; import com.zhongan.devpilot.util.TokenUtils; +import com.zhongan.devpilot.webview.model.CodeReferenceModel; import com.zhongan.devpilot.webview.model.EmbeddedModel; import com.zhongan.devpilot.webview.model.JavaCallModel; import com.zhongan.devpilot.webview.model.LocaleModel; @@ -34,6 +36,8 @@ import java.util.Map; import java.util.function.Consumer; +import org.apache.commons.lang3.StringUtils; + import static com.zhongan.devpilot.enums.SessionTypeEnum.MULTI_TURN; @Service @@ -212,10 +216,64 @@ public void handleActions(EditorActionEnum actionEnum, PsiElement psiElement) { BalloonAlertUtils.showWarningAlert(DevPilotMessageBundle.get("devpilot.alter.code.not.selected"), 0, -10, Balloon.Position.above); return; } - myAction.fastAction(project, editor, editor.getSelectionModel().getSelectedText(), psiElement); + myAction.fastAction(project, editor, editor.getSelectionModel().getSelectedText(), psiElement, null); + }); + } + + public void handleActions(CodeReferenceModel codeReferenceModel, EditorActionEnum actionEnum, PsiElement psiElement) { + if (codeReferenceModel == null || StringUtils.isEmpty(codeReferenceModel.getSourceCode())) { + handleActions(actionEnum, psiElement); + return; + } + + ActionManager actionManager = ActionManager.getInstance(); + BasicEditorAction myAction = (BasicEditorAction) actionManager + .getAction(DevPilotMessageBundle.get(actionEnum.getLabel())); + ApplicationManager.getApplication().invokeLater(() -> { + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (editor == null) { + BalloonAlertUtils.showWarningAlert(DevPilotMessageBundle.get("devpilot.alter.code.not.selected"), 0, -10, Balloon.Position.above); + return; + } + myAction.fastAction(project, editor, codeReferenceModel.getSourceCode(), psiElement, codeReferenceModel); }); } + public MessageModel getUserContentCode(MessageModel messageModel) { + var message = messageModel.getContent(); + + if (messageModel.getCodeRef() != null) { + var codeRef = messageModel.getCodeRef(); + var sourceCode = codeRef.getSourceCode(); + var language = codeRef.getLanguageId(); + if (language == null) { + language = ""; + } + var codeFormat = String.format("```%s\n%s\n```\n", language, sourceCode); + codeRef.setVisible(false); + messageModel.setContent(message + "\n" + codeFormat); + return messageModel; + } + + Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (editor == null || !editor.getSelectionModel().hasSelection()) { + return messageModel; + } + + var editorInfo = new EditorInfo(editor); + if (editorInfo.getSourceCode() == null) { + return messageModel; + } + + var codeReference = CodeReferenceModel.getCodeRefFromEditor(editorInfo, null); + var codeFormat = String.format("```%s\n%s\n```\n", codeReference.getLanguageId(), codeReference.getSourceCode()); + + messageModel.setContent(message + "\n" + codeFormat); + messageModel.setCodeRef(codeReference); + + return messageModel; + } + // get user message by assistant message id public MessageModel getUserMessage(String id) { var index = getMessageIndex(id); @@ -357,4 +415,12 @@ public void presentRepoCodeEmbeddedState(boolean isEmbedded, String repoName) { callWebView(javaCallModel); } + + public void referenceCode(CodeReferenceModel referenceModel) { + var javaCallModel = new JavaCallModel(); + javaCallModel.setCommand("ReferenceCode"); + javaCallModel.setPayload(referenceModel); + + callWebView(javaCallModel); + } } diff --git a/src/main/java/com/zhongan/devpilot/gui/toolwindows/components/EditorInfo.java b/src/main/java/com/zhongan/devpilot/gui/toolwindows/components/EditorInfo.java index a0812f75..9ba40e09 100644 --- a/src/main/java/com/zhongan/devpilot/gui/toolwindows/components/EditorInfo.java +++ b/src/main/java/com/zhongan/devpilot/gui/toolwindows/components/EditorInfo.java @@ -10,6 +10,9 @@ import com.intellij.openapi.vcs.LocalFilePath; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.IconUtil; +import com.zhongan.devpilot.util.LanguageUtil; + +import java.util.Locale; import javax.swing.Icon; @@ -22,16 +25,24 @@ public class EditorInfo { private Icon fileIcon; + private String languageId; + private String fileName; private String fileUrl; private String filePresentableUrl; + private String sourceCode; + private Integer selectedStartLine; + private Integer selectedStartColumn; + private Integer selectedEndLine; + private Integer selectedEndColumn; + public EditorInfo(Editor chosenEditor) { this.chosenEditor = chosenEditor; @@ -42,11 +53,31 @@ public EditorInfo(Editor chosenEditor) { this.fileName = file.getName(); LocalFilePath localFilePath = new LocalFilePath(file.getPath(), false); this.fileIcon = getIcon(chosenEditor.getProject(), localFilePath); + var language = LanguageUtil.getLanguageByExtension(file.getExtension()); + if (language != null) { + this.languageId = language.getLanguageName().toLowerCase(Locale.ROOT); + } } SelectionModel selectionModel = chosenEditor.getSelectionModel(); - this.selectedStartLine = chosenEditor.getDocument().getLineNumber(selectionModel.getSelectionStart()) + 1; - this.selectedEndLine = chosenEditor.getDocument().getLineNumber(selectionModel.getSelectionEnd()) + 1; + this.sourceCode = selectionModel.getSelectedText(); + + var startPosition = selectionModel.getSelectionStartPosition(); + var endPosition = selectionModel.getSelectionEndPosition(); + + if (startPosition != null) { + var startLogicalPosition = chosenEditor.visualToLogicalPosition(startPosition); + + this.selectedStartLine = startLogicalPosition.line; + this.selectedStartColumn = startLogicalPosition.column; + } + + if (endPosition != null) { + var endLogicalPosition = chosenEditor.visualToLogicalPosition(endPosition); + + this.selectedEndLine = endLogicalPosition.line; + this.selectedEndColumn = endLogicalPosition.column; + } } private Icon getIcon(@Nullable Project project, @NotNull FilePath filePath) { @@ -73,6 +104,14 @@ public void setFileIcon(Icon fileIcon) { this.fileIcon = fileIcon; } + public String getLanguageId() { + return languageId; + } + + public void setLanguageId(String languageId) { + this.languageId = languageId; + } + public String getFileName() { return fileName; } @@ -97,6 +136,14 @@ public void setFilePresentableUrl(String filePresentableUrl) { this.filePresentableUrl = filePresentableUrl; } + public String getSourceCode() { + return sourceCode; + } + + public void setSourceCode(String sourceCode) { + this.sourceCode = sourceCode; + } + public Integer getSelectedStartLine() { return selectedStartLine; } @@ -105,6 +152,14 @@ public void setSelectedStartLine(Integer selectedStartLine) { this.selectedStartLine = selectedStartLine; } + public Integer getSelectedStartColumn() { + return selectedStartColumn; + } + + public void setSelectedStartColumn(Integer selectedStartColumn) { + this.selectedStartColumn = selectedStartColumn; + } + public Integer getSelectedEndLine() { return selectedEndLine; } @@ -112,4 +167,12 @@ public Integer getSelectedEndLine() { public void setSelectedEndLine(Integer selectedEndLine) { this.selectedEndLine = selectedEndLine; } + + public Integer getSelectedEndColumn() { + return selectedEndColumn; + } + + public void setSelectedEndColumn(Integer selectedEndColumn) { + this.selectedEndColumn = selectedEndColumn; + } } diff --git a/src/main/java/com/zhongan/devpilot/settings/actionconfiguration/EditorActionConfigurationState.java b/src/main/java/com/zhongan/devpilot/settings/actionconfiguration/EditorActionConfigurationState.java index 15447381..7c3c2f6c 100644 --- a/src/main/java/com/zhongan/devpilot/settings/actionconfiguration/EditorActionConfigurationState.java +++ b/src/main/java/com/zhongan/devpilot/settings/actionconfiguration/EditorActionConfigurationState.java @@ -9,12 +9,10 @@ import java.util.ArrayList; import java.util.List; -import static com.zhongan.devpilot.enums.EditorActionEnum.CHECK_PERFORMANCE; import static com.zhongan.devpilot.enums.EditorActionEnum.EXPLAIN_CODE; import static com.zhongan.devpilot.enums.EditorActionEnum.FIX_CODE; import static com.zhongan.devpilot.enums.EditorActionEnum.GENERATE_COMMENTS; import static com.zhongan.devpilot.enums.EditorActionEnum.GENERATE_TESTS; -import static com.zhongan.devpilot.enums.EditorActionEnum.REVIEW_CODE; @State( name = "com.zhongan.devpilot.settings.actionconfiguration.EditorActionConfigurationState", @@ -28,10 +26,8 @@ public class EditorActionConfigurationState implements PersistentStateComponent< defaultActions = new ArrayList<>(); defaultActions.add(EXPLAIN_CODE.getLabel()); defaultActions.add(FIX_CODE.getLabel()); - defaultActions.add(CHECK_PERFORMANCE.getLabel()); defaultActions.add(GENERATE_COMMENTS.getLabel()); defaultActions.add(GENERATE_TESTS.getLabel()); - defaultActions.add(REVIEW_CODE.getLabel()); } public static EditorActionConfigurationState getInstance() { diff --git a/src/main/java/com/zhongan/devpilot/util/EditorUtils.java b/src/main/java/com/zhongan/devpilot/util/EditorUtils.java index e2681751..545fbfe8 100644 --- a/src/main/java/com/zhongan/devpilot/util/EditorUtils.java +++ b/src/main/java/com/zhongan/devpilot/util/EditorUtils.java @@ -22,7 +22,8 @@ public class EditorUtils { // repo和根目录的映射关系,用于打开文件时快速定位到根目录 private static final Map repoMapping = new HashMap<>(); - public static void openFileAndSelectLines(@NotNull Project project, String fileUrl, int startLine, int endLine) { + public static void openFileAndSelectLines(@NotNull Project project, String fileUrl, + int startLine, Integer startColumn, int endLine, Integer endColumn) { VirtualFile codeFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(fileUrl); if (codeFile == null || !codeFile.exists()) { @@ -32,9 +33,17 @@ public static void openFileAndSelectLines(@NotNull Project project, String fileU Editor editor = FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, codeFile), true); if (editor != null) { + if (startColumn == null) { + startColumn = 0; + } + + if (endColumn == null) { + endColumn = 0; + } + SelectionModel selectionModel = editor.getSelectionModel(); - int startOffset = editor.getDocument().getLineStartOffset(startLine - 1); - int endOffset = editor.getDocument().getLineEndOffset(endLine - 1); + int startOffset = editor.getDocument().getLineStartOffset(startLine) + startColumn; + int endOffset = editor.getDocument().getLineStartOffset(endLine) + endColumn; selectionModel.setSelection(startOffset, endOffset); ScrollingModel scrollingModel = editor.getScrollingModel(); diff --git a/src/main/java/com/zhongan/devpilot/webview/model/CodeReferenceModel.java b/src/main/java/com/zhongan/devpilot/webview/model/CodeReferenceModel.java index b29d3be0..64c457fe 100644 --- a/src/main/java/com/zhongan/devpilot/webview/model/CodeReferenceModel.java +++ b/src/main/java/com/zhongan/devpilot/webview/model/CodeReferenceModel.java @@ -3,17 +3,28 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.zhongan.devpilot.enums.EditorActionEnum; +import com.zhongan.devpilot.gui.toolwindows.components.EditorInfo; @JsonIgnoreProperties(ignoreUnknown = true) public class CodeReferenceModel { + private String languageId; + private String fileUrl; private String fileName; + private String sourceCode; + private Integer selectedStartLine; + private Integer selectedStartColumn; + private Integer selectedEndLine; + private Integer selectedEndColumn; + + private boolean visible = true; + @JsonIgnore private EditorActionEnum type; @@ -21,14 +32,34 @@ public CodeReferenceModel() { } - public CodeReferenceModel(String fileUrl, String fileName, Integer selectedStartLine, Integer selectedEndLine, EditorActionEnum type) { + public static CodeReferenceModel getCodeRefFromEditor(EditorInfo editorInfo, EditorActionEnum actionEnum) { + return new CodeReferenceModel(editorInfo.getLanguageId(), editorInfo.getFilePresentableUrl(), + editorInfo.getFileName(), editorInfo.getSourceCode(), editorInfo.getSelectedStartLine(), + editorInfo.getSelectedStartColumn(), editorInfo.getSelectedEndLine(), editorInfo.getSelectedEndColumn(), actionEnum); + } + + public CodeReferenceModel(String languageId, String fileUrl, String fileName, String sourceCode, + Integer selectedStartLine, Integer selectedStartColumn, + Integer selectedEndLine, Integer selectedEndColumn, EditorActionEnum type) { + this.languageId = languageId; this.fileUrl = fileUrl; this.fileName = fileName; + this.sourceCode = sourceCode; this.selectedStartLine = selectedStartLine; + this.selectedStartColumn = selectedStartColumn; this.selectedEndLine = selectedEndLine; + this.selectedEndColumn = selectedEndColumn; this.type = type; } + public String getLanguageId() { + return languageId; + } + + public void setLanguageId(String languageId) { + this.languageId = languageId; + } + public String getFileUrl() { return fileUrl; } @@ -45,6 +76,14 @@ public void setFileName(String fileName) { this.fileName = fileName; } + public String getSourceCode() { + return sourceCode; + } + + public void setSourceCode(String sourceCode) { + this.sourceCode = sourceCode; + } + public Integer getSelectedStartLine() { return selectedStartLine; } @@ -53,6 +92,14 @@ public void setSelectedStartLine(Integer selectedStartLine) { this.selectedStartLine = selectedStartLine; } + public Integer getSelectedStartColumn() { + return selectedStartColumn; + } + + public void setSelectedStartColumn(Integer selectedStartColumn) { + this.selectedStartColumn = selectedStartColumn; + } + public Integer getSelectedEndLine() { return selectedEndLine; } @@ -61,6 +108,22 @@ public void setSelectedEndLine(Integer selectedEndLine) { this.selectedEndLine = selectedEndLine; } + public Integer getSelectedEndColumn() { + return selectedEndColumn; + } + + public void setSelectedEndColumn(Integer selectedEndColumn) { + this.selectedEndColumn = selectedEndColumn; + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + public EditorActionEnum getType() { return type; } diff --git a/src/main/resources/messages/devpilot_en.properties b/src/main/resources/messages/devpilot_en.properties index f4df0aa2..3a14f7d5 100644 --- a/src/main/resources/messages/devpilot_en.properties +++ b/src/main/resources/messages/devpilot_en.properties @@ -13,8 +13,9 @@ com.zhongan.devpilot.actions.editor.popupmenu.BasicEditorAction=DevPilot devpilot.prompt.text.placeholder=Ask me anything devpilot.reference.content=Reference: -devpilot.action.new.chat=New DevPilot Chat +devpilot.action.new.chat=Open DevPilot Chat devpilot.action.new.chat.desc=New chat with DevPilot +devpilot.action.reference.chat=Reference Code in Chat devpilot.action.generate.comments=Generate Comments devpilot.action.generate.tests=Generate Tests devpilot.action.fix=Fix This diff --git a/src/main/resources/messages/devpilot_zh.properties b/src/main/resources/messages/devpilot_zh.properties index 74a52aad..b092a82e 100644 --- a/src/main/resources/messages/devpilot_zh.properties +++ b/src/main/resources/messages/devpilot_zh.properties @@ -13,8 +13,9 @@ com.zhongan.devpilot.actions.editor.popupmenu.BasicEditorAction=DevPilot devpilot.prompt.text.placeholder=\u8BF7\u8F93\u5165\u60A8\u7684\u95EE\u9898 devpilot.reference.content=\u5F15\u7528\uFF1A -devpilot.action.new.chat=\u65B0\u5EFADevPilot\u4F1A\u8BDD +devpilot.action.new.chat=\u6253\u5f00DevPilot\u4f1A\u8BDD devpilot.action.new.chat.desc=\u6253\u5F00\u65B0\u7684DevPilot\u4F1A\u8BDD +devpilot.action.reference.chat=\u5f15\u7528\u4ee3\u7801\u5757 devpilot.action.generate.comments=\u884C\u5185\u6CE8\u91CA devpilot.action.generate.tests=\u751F\u6210\u5355\u6D4B devpilot.action.fix=\u4FEE\u590D\u4EE3\u7801 diff --git a/src/main/resources/webview/index.html b/src/main/resources/webview/index.html index e5c18031..78dcdf3a 100644 --- a/src/main/resources/webview/index.html +++ b/src/main/resources/webview/index.html @@ -7,7 +7,7 @@ DevPilot