diff --git a/build.gradle.kts b/build.gradle.kts index 11d3d0b..f169586 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -55,7 +55,7 @@ dependencies { implementation("com.fasterxml.jackson.core:jackson-databind:2.18.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2") // Use latest version implementation("org.commonmark:commonmark:0.21.0") - + implementation("org.apache.httpcomponents:httpclient:4.5.13") // IntelliJ Platform Gradle Plugin Dependencies Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html intellijPlatform { diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/CheckInvalidTestCasesAction.java b/src/main/java/com/github/jaksonlin/testcraft/application/actions/CheckInvalidTestCasesAction.java similarity index 66% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/actions/CheckInvalidTestCasesAction.java rename to src/main/java/com/github/jaksonlin/testcraft/application/actions/CheckInvalidTestCasesAction.java index 95a3e87..9d00bbc 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/CheckInvalidTestCasesAction.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/actions/CheckInvalidTestCasesAction.java @@ -1,7 +1,8 @@ -package com.github.jaksonlin.testcraft.presentation.actions; +package com.github.jaksonlin.testcraft.application.actions; -import com.github.jaksonlin.testcraft.application.commands.testscan.UnittestFileBatchScanCommand; -import com.github.jaksonlin.testcraft.core.services.InvalidTestCaseConfigService; +import com.github.jaksonlin.testcraft.infrastructure.commands.testscan.UnittestFileBatchScanCommand; +import com.github.jaksonlin.testcraft.infrastructure.services.config.InvalidTestCaseConfigService; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationManager; @@ -11,6 +12,12 @@ public class CheckInvalidTestCasesAction extends AnAction { + @Override + public void update(@NotNull AnActionEvent e) { + super.update(e); + e.getPresentation().setText(I18nService.getInstance().message("action.CheckInvalidTestCasesAction.text")); + } + @Override public void actionPerformed(@NotNull AnActionEvent e) { diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/GenerateAnnotationCommandAction.java b/src/main/java/com/github/jaksonlin/testcraft/application/actions/GenerateAnnotationCommandAction.java similarity index 65% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/actions/GenerateAnnotationCommandAction.java rename to src/main/java/com/github/jaksonlin/testcraft/application/actions/GenerateAnnotationCommandAction.java index beacd48..80d849d 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/GenerateAnnotationCommandAction.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/actions/GenerateAnnotationCommandAction.java @@ -1,7 +1,8 @@ -package com.github.jaksonlin.testcraft.presentation.actions; +package com.github.jaksonlin.testcraft.application.actions; -import com.github.jaksonlin.testcraft.application.commands.unittestannotations.GenerateAnnotationCommand; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.commands.unittestannotations.GenerateAnnotationCommand; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; import com.github.jaksonlin.testcraft.util.Pair; import com.github.jaksonlin.testcraft.util.PsiUtil; import com.intellij.openapi.actionSystem.AnAction; @@ -13,6 +14,12 @@ public class GenerateAnnotationCommandAction extends AnAction { + @Override + public void update(@NotNull AnActionEvent e) { + super.update(e); + e.getPresentation().setText(I18nService.getInstance().message("action.GenerateAnnotationCommandAction.text")); + } + @Override public void actionPerformed(@NotNull AnActionEvent e) { Pair psiMethodInfo = PsiUtil.findMethodAtCaret(e); // Call the static method diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunCaseAnnoationCheckAction.java b/src/main/java/com/github/jaksonlin/testcraft/application/actions/RunCaseAnnoationCheckAction.java similarity index 64% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunCaseAnnoationCheckAction.java rename to src/main/java/com/github/jaksonlin/testcraft/application/actions/RunCaseAnnoationCheckAction.java index f5db6d4..33c678e 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunCaseAnnoationCheckAction.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/actions/RunCaseAnnoationCheckAction.java @@ -1,7 +1,8 @@ -package com.github.jaksonlin.testcraft.presentation.actions; +package com.github.jaksonlin.testcraft.application.actions; -import com.github.jaksonlin.testcraft.application.commands.unittestannotations.CheckAnnotationCommand; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.commands.unittestannotations.CheckAnnotationCommand; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; import com.github.jaksonlin.testcraft.util.Pair; import com.github.jaksonlin.testcraft.util.PsiUtil; import com.intellij.openapi.actionSystem.AnAction; @@ -28,4 +29,10 @@ public void actionPerformed(@NotNull AnActionEvent e) { } } + @Override + public void update(@NotNull AnActionEvent e) { + super.update(e); + e.getPresentation().setText(I18nService.getInstance().message("action.RunCaseAnnoationCheckAction.text")); + } + } \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/services/PitestService.java b/src/main/java/com/github/jaksonlin/testcraft/application/actions/RunPitestAction.java similarity index 56% rename from src/main/java/com/github/jaksonlin/testcraft/core/services/PitestService.java rename to src/main/java/com/github/jaksonlin/testcraft/application/actions/RunPitestAction.java index 3e42c39..995906d 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/services/PitestService.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/actions/RunPitestAction.java @@ -1,17 +1,22 @@ -package com.github.jaksonlin.testcraft.core.services; +package com.github.jaksonlin.testcraft.application.actions; -import com.github.jaksonlin.testcraft.application.commands.CommandCancellationException; -import com.github.jaksonlin.testcraft.application.commands.pitest.*; -import com.github.jaksonlin.testcraft.core.context.PitestContext; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; +import com.github.jaksonlin.testcraft.infrastructure.commands.CommandCancellationException; +import com.github.jaksonlin.testcraft.infrastructure.commands.pitest.*; +import com.github.jaksonlin.testcraft.infrastructure.services.business.PitestService; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.Service; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.components.JBScrollPane; import org.jetbrains.annotations.NotNull; -import com.github.jaksonlin.testcraft.util.MyBundle; + import javax.swing.*; import java.awt.*; import java.io.PrintWriter; @@ -19,8 +24,37 @@ import java.util.Arrays; import java.util.List; -@Service(Service.Level.APP) -public final class PitestService { +public class RunPitestAction extends AnAction { + + private final PitestService pitestService; + + public RunPitestAction() { + pitestService = ApplicationManager.getApplication().getService(PitestService.class); + } + + @Override + public void update(@NotNull AnActionEvent e) { + super.update(e); + // You can change the text here + e.getPresentation().setText(I18nService.getInstance().message("action.RunPitestAction.text")); + + + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + Project targetProject = e.getProject(); + if (targetProject == null) { + return; + } + + VirtualFile testVirtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); + if (testVirtualFile == null) { + return; + } + + runPitest(targetProject, testVirtualFile.getPath()); + } public void runPitest(Project targetProject, String testFilePath) { PitestContext context = new PitestContext(testFilePath, System.currentTimeMillis()); @@ -40,7 +74,7 @@ public void run(@NotNull ProgressIndicator indicator) { for (PitestCommand command : commands) { if (indicator.isCanceled()) { ApplicationManager.getApplication().invokeLater(() -> - Messages.showInfoMessage(MyBundle.message("pitest.run.canceled"), MyBundle.message("pitest.run.canceled.title")) + Messages.showInfoMessage(I18nService.getInstance().message("pitest.run.canceled"), I18nService.getInstance().message("pitest.run.canceled.title")) ); break; } @@ -49,7 +83,7 @@ public void run(@NotNull ProgressIndicator indicator) { } catch (Exception e) { if (e.getCause() instanceof CommandCancellationException) { ApplicationManager.getApplication().invokeLater(() -> - Messages.showInfoMessage(MyBundle.message("pitest.run.canceled"), MyBundle.message("pitest.run.canceled.title")) + Messages.showInfoMessage(I18nService.getInstance().message("pitest.run.canceled"), I18nService.getInstance().message("pitest.run.canceled.title")) ); } else { showErrorDialog(e, context); @@ -64,7 +98,7 @@ protected void showErrorDialog(Exception e, PitestContext context) { e.printStackTrace(new PrintWriter(sw)); String stackTrace = sw.toString(); String contextInformation = PitestContext.dumpPitestContext(context); - String errorMessage = MyBundle.message("error.pitest.general.title") + ": " + e.getMessage() + "; " + contextInformation + "\n" + stackTrace; + String errorMessage = I18nService.getInstance().message("error.pitest.general.title") + ": " + e.getMessage() + "; " + contextInformation + "\n" + stackTrace; JTextArea textArea = new JTextArea(errorMessage); textArea.setEditable(false); @@ -78,4 +112,4 @@ protected void showErrorDialog(Exception e, PitestContext context) { Messages.showErrorDialog(scrollPane, errorMessage) ); } -} +} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunTestFileAnnoationCheckAction.java b/src/main/java/com/github/jaksonlin/testcraft/application/actions/RunTestFileAnnoationCheckAction.java similarity index 89% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunTestFileAnnoationCheckAction.java rename to src/main/java/com/github/jaksonlin/testcraft/application/actions/RunTestFileAnnoationCheckAction.java index 49537f5..d7b3a72 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunTestFileAnnoationCheckAction.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/actions/RunTestFileAnnoationCheckAction.java @@ -1,7 +1,7 @@ -package com.github.jaksonlin.testcraft.presentation.actions; +package com.github.jaksonlin.testcraft.application.actions; -import com.github.jaksonlin.testcraft.application.commands.unittestannotations.CheckAnnotationCommand; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.commands.unittestannotations.CheckAnnotationCommand; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/CollectScanCommand.java b/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/CollectScanCommand.java deleted file mode 100644 index 140ec8f..0000000 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/CollectScanCommand.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.github.jaksonlin.testcraft.application.commands.testscan; - -public class CollectScanCommand { -} diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/completions/AnnotationCompletionContributor.java b/src/main/java/com/github/jaksonlin/testcraft/application/completions/AnnotationCompletionContributor.java similarity index 93% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/completions/AnnotationCompletionContributor.java rename to src/main/java/com/github/jaksonlin/testcraft/application/completions/AnnotationCompletionContributor.java index 2c75a25..7680a2e 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/completions/AnnotationCompletionContributor.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/completions/AnnotationCompletionContributor.java @@ -1,9 +1,9 @@ -package com.github.jaksonlin.testcraft.presentation.completions; +package com.github.jaksonlin.testcraft.application.completions; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationFieldConfig; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationSchema; -import com.github.jaksonlin.testcraft.core.annotations.DefaultValue; -import com.github.jaksonlin.testcraft.core.services.AnnotationConfigService; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationFieldConfig; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationSchema; +import com.github.jaksonlin.testcraft.domain.annotations.DefaultValue; +import com.github.jaksonlin.testcraft.infrastructure.services.config.AnnotationConfigService; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.java.JavaLanguage; diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/completions/CustomAnnotationCompletionLookupElement.java b/src/main/java/com/github/jaksonlin/testcraft/application/completions/CustomAnnotationCompletionLookupElement.java similarity index 93% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/completions/CustomAnnotationCompletionLookupElement.java rename to src/main/java/com/github/jaksonlin/testcraft/application/completions/CustomAnnotationCompletionLookupElement.java index ac7bf57..21cc180 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/completions/CustomAnnotationCompletionLookupElement.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/completions/CustomAnnotationCompletionLookupElement.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.presentation.completions; +package com.github.jaksonlin.testcraft.application.completions; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationFieldType; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationFieldType; import com.intellij.codeInsight.completion.InsertionContext; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementPresentation; diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/inspectors/UnittestInspector.java b/src/main/java/com/github/jaksonlin/testcraft/application/inspectors/UnittestInspector.java similarity index 84% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/inspectors/UnittestInspector.java rename to src/main/java/com/github/jaksonlin/testcraft/application/inspectors/UnittestInspector.java index cabce61..969e678 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/inspectors/UnittestInspector.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/inspectors/UnittestInspector.java @@ -1,8 +1,8 @@ -package com.github.jaksonlin.testcraft.presentation.inspectors; +package com.github.jaksonlin.testcraft.application.inspectors; -import com.github.jaksonlin.testcraft.util.MyBundle; -import com.github.jaksonlin.testcraft.application.commands.testscan.UnittestFileInspectorCommand; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.commands.testscan.UnittestFileInspectorCommand; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.project.Project; @@ -18,12 +18,12 @@ public class UnittestInspector extends AbstractBaseJavaLocalInspectionTool { @Override public @NotNull String getGroupDisplayName() { - return MyBundle.message("inspection.group.name"); + return I18nService.getInstance().message("inspection.group.name"); } @Override public @NotNull String getDisplayName() { - return MyBundle.message("inspection.display.name"); + return I18nService.getInstance().message("inspection.display.name"); } @Override diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/processors/LLMProcessor.java b/src/main/java/com/github/jaksonlin/testcraft/application/processors/LLMProcessor.java new file mode 100644 index 0000000..9a700f8 --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/application/processors/LLMProcessor.java @@ -0,0 +1,21 @@ +package com.github.jaksonlin.testcraft.application.processors; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class LLMProcessor { + + private String readFileContent(String filePath) { + try { + return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException("Failed to read file: " + filePath, e); + } + } + + private String getSourceCode(String sourceCodeFile) { + return readFileContent(sourceCodeFile); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/processors/UnittestMethodProcessor.java b/src/main/java/com/github/jaksonlin/testcraft/application/processors/UnittestMethodProcessor.java deleted file mode 100644 index da77d49..0000000 --- a/src/main/java/com/github/jaksonlin/testcraft/application/processors/UnittestMethodProcessor.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.github.jaksonlin.testcraft.application.processors; - -import com.github.jaksonlin.testcraft.core.context.UnittestMethodContext; -import com.intellij.psi.PsiComment; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.util.PsiTreeUtil; - -import java.util.ArrayList; -import java.util.List; - -public class UnittestMethodProcessor { - public static UnittestMethodContext fromPsiMethod(PsiMethod psiMethod) { - List comments = extractCommentsFromMethodBody(psiMethod); - return new UnittestMethodContext(psiMethod.getName(), comments); - } - - private static List extractCommentsFromMethodBody(PsiMethod psiMethod) { - List comments = new ArrayList<>(); - for (PsiComment comment : PsiTreeUtil.findChildrenOfType(psiMethod, PsiComment.class)) { - comments.add(comment.getText()); - } - return comments; - } -} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/AnnotationSettingsComponent.java b/src/main/java/com/github/jaksonlin/testcraft/application/settings/AnnotationSettingsComponent.java similarity index 71% rename from src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/AnnotationSettingsComponent.java rename to src/main/java/com/github/jaksonlin/testcraft/application/settings/AnnotationSettingsComponent.java index f4e5cf4..aed0aa6 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/AnnotationSettingsComponent.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/settings/AnnotationSettingsComponent.java @@ -1,5 +1,6 @@ -package com.github.jaksonlin.testcraft.infrastructure.settings; +package com.github.jaksonlin.testcraft.application.settings; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.intellij.json.JsonFileType; import com.intellij.openapi.editor.EditorSettings; import com.intellij.openapi.editor.ScrollType; @@ -8,7 +9,6 @@ import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBTextField; import org.jetbrains.annotations.NotNull; -import com.github.jaksonlin.testcraft.util.MyBundle; import javax.swing.*; import java.awt.*; @@ -20,7 +20,7 @@ public class AnnotationSettingsComponent { private final JCheckBox autoImportCheckBox; private final JCheckBox enableValidationCheckBox; private static final int EDITOR_HEIGHT = 300; - + private static final String EXAMPLE_JSON = "{\n" + " \"fields\": [\n" + " {\n" + @@ -96,29 +96,29 @@ public AnnotationSettingsComponent() { c.gridx = 0; c.gridy = 0; c.weighty = 0.0; - JLabel importSettingsLabel = new JBLabel("" + MyBundle.message("settings.annotation.import.title") + ""); + JLabel importSettingsLabel = new JBLabel("" + I18nService.getInstance().message("settings.annotation.import.title") + ""); contentPanel.add(importSettingsLabel, c); // Package input - addLabelAndField(contentPanel, MyBundle.message("settings.annotation.package.label"), packageTextField, 1, - MyBundle.message("settings.annotation.package.tooltip")); + addLabelAndField(contentPanel, I18nService.getInstance().message("settings.annotation.package.label"), packageTextField, 1, + I18nService.getInstance().message("settings.annotation.package.tooltip")); // Checkboxes c.gridy = 2; c.gridwidth = 2; - autoImportCheckBox = new JCheckBox(MyBundle.message("settings.annotation.autoImport")); - autoImportCheckBox.setToolTipText(MyBundle.message("settings.annotation.autoImport.tooltip")); + autoImportCheckBox = new JCheckBox(I18nService.getInstance().message("settings.annotation.autoImport")); + autoImportCheckBox.setToolTipText(I18nService.getInstance().message("settings.annotation.autoImport.tooltip")); contentPanel.add(autoImportCheckBox, c); c.gridy = 3; - enableValidationCheckBox = new JCheckBox(MyBundle.message("settings.annotation.enableValidation")); - enableValidationCheckBox.setToolTipText(MyBundle.message("settings.annotation.enableValidation.tooltip")); + enableValidationCheckBox = new JCheckBox(I18nService.getInstance().message("settings.annotation.enableValidation")); + enableValidationCheckBox.setToolTipText(I18nService.getInstance().message("settings.annotation.enableValidation.tooltip")); contentPanel.add(enableValidationCheckBox, c); // Schema Configuration section c.gridy = 4; c.insets = new Insets(15, 5, 5, 5); - JLabel schemaLabel = new JBLabel("" + MyBundle.message("settings.annotation.schema.title") + ""); + JLabel schemaLabel = new JBLabel("" + I18nService.getInstance().message("settings.annotation.schema.title") + ""); contentPanel.add(schemaLabel, c); // Schema editor @@ -129,7 +129,7 @@ public AnnotationSettingsComponent() { // Wrap editor in a panel to ensure it expands properly JPanel editorPanel = new JPanel(new BorderLayout()); - editorPanel.add(new JBLabel(MyBundle.message("settings.annotation.schema.label")), BorderLayout.NORTH); + editorPanel.add(new JBLabel(I18nService.getInstance().message("settings.annotation.schema.label")), BorderLayout.NORTH); editorPanel.add(schemaEditor, BorderLayout.CENTER); contentPanel.add(editorPanel, c); @@ -143,44 +143,44 @@ public AnnotationSettingsComponent() { helpPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JLabel helpText = new JBLabel("" + - "

" + MyBundle.message("settings.annotation.schema.help.title") + "

" + - "

" + MyBundle.message("settings.annotation.schema.help.intro") + "

" + + "

" + I18nService.getInstance().message("settings.annotation.schema.help.title") + "

" + + "

" + I18nService.getInstance().message("settings.annotation.schema.help.intro") + "

" + - "

" + MyBundle.message("settings.annotation.schema.help.structure.title") + "

" + + "

" + I18nService.getInstance().message("settings.annotation.schema.help.structure.title") + "

" + "
    " + - "
  • " + MyBundle.message("settings.annotation.schema.help.structure.1") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.structure.2") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.structure.3") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.structure.1") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.structure.2") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.structure.3") + "
  • " + "
" + - "

" + MyBundle.message("settings.annotation.schema.help.validation.title") + "

" + + "

" + I18nService.getInstance().message("settings.annotation.schema.help.validation.title") + "

" + "
    " + - "
  • " + MyBundle.message("settings.annotation.schema.help.validation.1") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.validation.2") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.validation.3") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.validation.4") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.validation.5") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.validation.1") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.validation.2") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.validation.3") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.validation.4") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.validation.5") + "
  • " + "
" + - "

" + MyBundle.message("settings.annotation.schema.help.valueProvider.title") + "

" + + "

" + I18nService.getInstance().message("settings.annotation.schema.help.valueProvider.title") + "

" + "
    " + - "
  • " + MyBundle.message("settings.annotation.schema.help.valueProvider.1") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.valueProvider.2") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.valueProvider.3") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.valueProvider.1") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.valueProvider.2") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.valueProvider.3") + "
  • " + "
" + - "

" + MyBundle.message("settings.annotation.schema.help.example.title") + "

" + + "

" + I18nService.getInstance().message("settings.annotation.schema.help.example.title") + "

" + "
" + EXAMPLE_JSON.replace("<", "<").replace(">", ">").replace("\n", "
").replace(" ", " ") + "
" + - "

" + MyBundle.message("settings.annotation.schema.help.notes.title") + "

" + + "

" + I18nService.getInstance().message("settings.annotation.schema.help.notes.title") + "

" + "
    " + - "
  • " + MyBundle.message("settings.annotation.schema.help.notes.1") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.notes.2") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.notes.3") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.notes.4") + "
  • " + - "
  • " + MyBundle.message("settings.annotation.schema.help.notes.5") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.notes.1") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.notes.2") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.notes.3") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.notes.4") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.annotation.schema.help.notes.5") + "
  • " + "
" + ""); diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/AnnotationSettingsConfigurable.java b/src/main/java/com/github/jaksonlin/testcraft/application/settings/AnnotationSettingsConfigurable.java similarity index 93% rename from src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/AnnotationSettingsConfigurable.java rename to src/main/java/com/github/jaksonlin/testcraft/application/settings/AnnotationSettingsConfigurable.java index a5da1a2..42c50a8 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/AnnotationSettingsConfigurable.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/settings/AnnotationSettingsConfigurable.java @@ -1,9 +1,9 @@ -package com.github.jaksonlin.testcraft.infrastructure.settings; +package com.github.jaksonlin.testcraft.application.settings; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationSchema; -import com.github.jaksonlin.testcraft.core.services.AnnotationConfigService; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationSchema; +import com.github.jaksonlin.testcraft.infrastructure.services.config.AnnotationConfigService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/InvalidTestCaseSettingsComponent.java b/src/main/java/com/github/jaksonlin/testcraft/application/settings/InvalidTestCaseSettingsComponent.java similarity index 75% rename from src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/InvalidTestCaseSettingsComponent.java rename to src/main/java/com/github/jaksonlin/testcraft/application/settings/InvalidTestCaseSettingsComponent.java index 213c730..2489042 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/InvalidTestCaseSettingsComponent.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/settings/InvalidTestCaseSettingsComponent.java @@ -1,12 +1,13 @@ -package com.github.jaksonlin.testcraft.infrastructure.settings; +package com.github.jaksonlin.testcraft.application.settings; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.intellij.openapi.editor.EditorSettings; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.ui.EditorTextField; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import org.jetbrains.annotations.NotNull; -import com.github.jaksonlin.testcraft.util.MyBundle; + import javax.swing.*; import java.awt.*; @@ -36,30 +37,30 @@ public InvalidTestCaseSettingsComponent() { c.gridx = 0; c.gridy = 0; c.weighty = 0.0; - JLabel validationLabel = new JBLabel("" + MyBundle.message("settings.invalidTestCase.title") + ""); + JLabel validationLabel = new JBLabel("" + I18nService.getInstance().message("settings.invalidTestCase.title") + ""); contentPanel.add(validationLabel, c); // Checkboxes c.gridy = 1; - enableCheckbox = new JBCheckBox(MyBundle.message("settings.invalidTestCase.enableCheck")); - enableCheckbox.setToolTipText(MyBundle.message("settings.invalidTestCase.enableCheck.tooltip")); + enableCheckbox = new JBCheckBox(I18nService.getInstance().message("settings.invalidTestCase.enableCheck")); + enableCheckbox.setToolTipText(I18nService.getInstance().message("settings.invalidTestCase.enableCheck.tooltip")); contentPanel.add(enableCheckbox, c); c.gridy = 2; - enableCommentCheckbox = new JBCheckBox(MyBundle.message("settings.invalidTestCase.enableCommentCheck")); - enableCommentCheckbox.setToolTipText(MyBundle.message("settings.invalidTestCase.enableCommentCheck.tooltip")); + enableCommentCheckbox = new JBCheckBox(I18nService.getInstance().message("settings.invalidTestCase.enableCommentCheck")); + enableCommentCheckbox.setToolTipText(I18nService.getInstance().message("settings.invalidTestCase.enableCommentCheck.tooltip")); contentPanel.add(enableCommentCheckbox, c); // Invalid Assertions section c.gridy = 3; c.insets = new Insets(15, 5, 5, 5); - JLabel assertionsLabel = new JBLabel("" + MyBundle.message("settings.invalidTestCase.assertions.title") + ""); + JLabel assertionsLabel = new JBLabel("" + I18nService.getInstance().message("settings.invalidTestCase.assertions.title") + ""); contentPanel.add(assertionsLabel, c); // Editor description c.gridy = 4; c.insets = new Insets(5, 5, 5, 5); - JLabel editorDesc = new JBLabel(MyBundle.message("settings.invalidTestCase.assertions.description")); + JLabel editorDesc = new JBLabel(I18nService.getInstance().message("settings.invalidTestCase.assertions.description")); contentPanel.add(editorDesc, c); // Assertion editor @@ -73,11 +74,11 @@ public InvalidTestCaseSettingsComponent() { c.weighty = 0.0; // Reset vertical weight c.insets = new Insets(10, 5, 5, 5); JLabel helpText = new JBLabel("" + - "" + MyBundle.message("settings.invalidTestCase.assertions.examples.title") + "
" + - MyBundle.message("settings.invalidTestCase.assertions.examples.1") + "
" + - MyBundle.message("settings.invalidTestCase.assertions.examples.2") + "
" + - MyBundle.message("settings.invalidTestCase.assertions.examples.3") + "
" + - MyBundle.message("settings.invalidTestCase.assertions.examples.4") + + "" + I18nService.getInstance().message("settings.invalidTestCase.assertions.examples.title") + "
" + + I18nService.getInstance().message("settings.invalidTestCase.assertions.examples.1") + "
" + + I18nService.getInstance().message("settings.invalidTestCase.assertions.examples.2") + "
" + + I18nService.getInstance().message("settings.invalidTestCase.assertions.examples.3") + "
" + + I18nService.getInstance().message("settings.invalidTestCase.assertions.examples.4") + ""); contentPanel.add(helpText, c); diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/InvalidTestCaseSettingsConfigurable.java b/src/main/java/com/github/jaksonlin/testcraft/application/settings/InvalidTestCaseSettingsConfigurable.java similarity index 93% rename from src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/InvalidTestCaseSettingsConfigurable.java rename to src/main/java/com/github/jaksonlin/testcraft/application/settings/InvalidTestCaseSettingsConfigurable.java index 52b40bb..dee1250 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/InvalidTestCaseSettingsConfigurable.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/settings/InvalidTestCaseSettingsConfigurable.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.infrastructure.settings; +package com.github.jaksonlin.testcraft.application.settings; -import com.github.jaksonlin.testcraft.core.services.InvalidTestCaseConfigService; +import com.github.jaksonlin.testcraft.infrastructure.services.config.InvalidTestCaseConfigService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.Configurable; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/OllamaSettingsComponent.java b/src/main/java/com/github/jaksonlin/testcraft/application/settings/OllamaSettingsComponent.java similarity index 68% rename from src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/OllamaSettingsComponent.java rename to src/main/java/com/github/jaksonlin/testcraft/application/settings/OllamaSettingsComponent.java index 19e3fb6..ef86cac 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/OllamaSettingsComponent.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/settings/OllamaSettingsComponent.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.infrastructure.settings; +package com.github.jaksonlin.testcraft.application.settings; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBTextField; @@ -6,10 +6,14 @@ import org.jetbrains.annotations.NotNull; import com.github.jaksonlin.testcraft.util.OllamaClient; -import com.github.jaksonlin.testcraft.util.MyBundle; + import javax.swing.*; import java.awt.*; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + public class OllamaSettingsComponent { private final JPanel mainPanel; private final JBTextField hostField = new JBTextField(); @@ -30,49 +34,49 @@ public OllamaSettingsComponent() { contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); // Connection Settings Section - JPanel connectionPanel = createSectionPanel(MyBundle.message("llm.settings.connection.title")); + JPanel connectionPanel = createSectionPanel(I18nService.getInstance().message("llm.settings.connection.title")); GridBagConstraints c = new GridBagConstraints(); c.insets = JBUI.insets(5); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.LINE_START; // Host field - addLabelAndField(connectionPanel, MyBundle.message("llm.settings.host.label"), hostField, - MyBundle.message("llm.settings.host.tooltip")); + addLabelAndField(connectionPanel, I18nService.getInstance().message("llm.settings.host.label"), hostField, + I18nService.getInstance().message("llm.settings.host.tooltip")); // Port field - addLabelAndField(connectionPanel, MyBundle.message("llm.settings.port.label"), portField, - MyBundle.message("llm.settings.port.tooltip")); + addLabelAndField(connectionPanel, I18nService.getInstance().message("llm.settings.port.label"), portField, + I18nService.getInstance().message("llm.settings.port.tooltip")); contentPanel.add(connectionPanel); contentPanel.add(Box.createVerticalStrut(10)); // Model Settings Section - JPanel modelPanel = createSectionPanel(MyBundle.message("llm.settings.model.title")); + JPanel modelPanel = createSectionPanel(I18nService.getInstance().message("llm.settings.model.title")); // Model field - addLabelAndField(modelPanel, MyBundle.message("llm.settings.model.label"), modelField, - MyBundle.message("llm.settings.model.tooltip")); + addLabelAndField(modelPanel, I18nService.getInstance().message("llm.settings.model.label"), modelField, + I18nService.getInstance().message("llm.settings.model.tooltip")); // Max Tokens field - addLabelAndField(modelPanel, MyBundle.message("llm.settings.maxTokens.label"), maxTokensField, - MyBundle.message("llm.settings.maxTokens.tooltip")); + addLabelAndField(modelPanel, I18nService.getInstance().message("llm.settings.maxTokens.label"), maxTokensField, + I18nService.getInstance().message("llm.settings.maxTokens.tooltip")); // Temperature field - addLabelAndField(modelPanel, MyBundle.message("llm.settings.temperature.label"), temperatureField, - MyBundle.message("llm.settings.temperature.tooltip")); + addLabelAndField(modelPanel, I18nService.getInstance().message("llm.settings.temperature.label"), temperatureField, + I18nService.getInstance().message("llm.settings.temperature.tooltip")); // Timeout field - addLabelAndField(modelPanel, MyBundle.message("llm.settings.timeout.label"), timeoutField, - MyBundle.message("llm.settings.timeout.tooltip")); + addLabelAndField(modelPanel, I18nService.getInstance().message("llm.settings.timeout.label"), timeoutField, + I18nService.getInstance().message("llm.settings.timeout.tooltip")); contentPanel.add(modelPanel); contentPanel.add(Box.createVerticalStrut(10)); // Output Settings Section - JPanel outputPanel = createSectionPanel(MyBundle.message("llm.settings.output.title")); - copyAsMarkdownCheckbox = new JCheckBox(MyBundle.message("llm.settings.copyMarkdown.label")); - copyAsMarkdownCheckbox.setToolTipText(MyBundle.message("llm.settings.copyMarkdown.tooltip")); + JPanel outputPanel = createSectionPanel(I18nService.getInstance().message("llm.settings.output.title")); + copyAsMarkdownCheckbox = new JCheckBox(I18nService.getInstance().message("llm.settings.copyMarkdown.label")); + copyAsMarkdownCheckbox.setToolTipText(I18nService.getInstance().message("llm.settings.copyMarkdown.tooltip")); copyAsMarkdownCheckbox.setAlignmentX(Component.LEFT_ALIGNMENT); outputPanel.add(copyAsMarkdownCheckbox); @@ -80,18 +84,18 @@ public OllamaSettingsComponent() { contentPanel.add(Box.createVerticalStrut(10)); // Test Connection Section - JPanel testPanel = createSectionPanel(MyBundle.message("llm.settings.test.title")); - JButton testConnectionButton = new JButton(MyBundle.message("llm.settings.test.button")); + JPanel testPanel = createSectionPanel(I18nService.getInstance().message("llm.settings.test.title")); + JButton testConnectionButton = new JButton(I18nService.getInstance().message("llm.settings.test.button")); testConnectionButton.setAlignmentX(Component.LEFT_ALIGNMENT); testPanel.add(testConnectionButton); // Add help text JLabel helpText = new JBLabel("" + - "

" + MyBundle.message("llm.settings.help.title") + "

" + + "

" + I18nService.getInstance().message("llm.settings.help.title") + "

" + "
    " + - "
  • " + MyBundle.message("llm.settings.help.running") + "
  • " + - "
  • " + MyBundle.message("llm.settings.help.host") + "
  • " + - "
  • " + MyBundle.message("llm.settings.help.port") + "
  • " + + "
  • " + I18nService.getInstance().message("llm.settings.help.running") + "
  • " + + "
  • " + I18nService.getInstance().message("llm.settings.help.host") + "
  • " + + "
  • " + I18nService.getInstance().message("llm.settings.help.port") + "
  • " + "
" + ""); helpText.setAlignmentX(Component.LEFT_ALIGNMENT); @@ -152,18 +156,18 @@ private void testConnection() { if (success) { JOptionPane.showMessageDialog(mainPanel, "Successfully connected to Ollama server!", - MyBundle.message("llm.settings.test.title"), + I18nService.getInstance().message("llm.settings.test.title"), JOptionPane.INFORMATION_MESSAGE); } else { JOptionPane.showMessageDialog(mainPanel, - MyBundle.message("llm.error.connection"), - MyBundle.message("llm.settings.test.title"), + I18nService.getInstance().message("llm.error.connection"), + I18nService.getInstance().message("llm.settings.test.title"), JOptionPane.ERROR_MESSAGE); } } catch (Exception e) { JOptionPane.showMessageDialog(mainPanel, - MyBundle.message("llm.error.connection") + ": " + e.getMessage(), - MyBundle.message("llm.settings.test.title"), + I18nService.getInstance().message("llm.error.connection") + ": " + e.getMessage(), + I18nService.getInstance().message("llm.settings.test.title"), JOptionPane.ERROR_MESSAGE); } } diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/OllamaSettingsConfigurable.java b/src/main/java/com/github/jaksonlin/testcraft/application/settings/OllamaSettingsConfigurable.java similarity index 81% rename from src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/OllamaSettingsConfigurable.java rename to src/main/java/com/github/jaksonlin/testcraft/application/settings/OllamaSettingsConfigurable.java index 6348712..3c71c95 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/OllamaSettingsConfigurable.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/settings/OllamaSettingsConfigurable.java @@ -1,7 +1,7 @@ -package com.github.jaksonlin.testcraft.infrastructure.settings; +package com.github.jaksonlin.testcraft.application.settings; + +import com.github.jaksonlin.testcraft.infrastructure.services.config.LLMConfigService; -import com.github.jaksonlin.testcraft.core.services.LLMService; -import com.github.jaksonlin.testcraft.util.MyBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.Configurable; import org.jetbrains.annotations.Nls; @@ -9,14 +9,16 @@ import javax.swing.*; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + public class OllamaSettingsConfigurable implements Configurable { private OllamaSettingsComponent settingsComponent = new OllamaSettingsComponent(); - private final LLMService llmService = ApplicationManager.getApplication().getService(LLMService.class); + private final LLMConfigService llmConfigService = ApplicationManager.getApplication().getService(LLMConfigService.class); @Nls(capitalization = Nls.Capitalization.Title) @Override public String getDisplayName() { - return MyBundle.message("settings.testcraft.llm"); + return I18nService.getInstance().message("settings.testcraft.llm"); } @Override @@ -36,7 +38,7 @@ public boolean isModified() { if (settingsComponent == null) { return false; } - LLMService.State state = llmService.getState(); + LLMConfigService.State state = llmConfigService.getState(); boolean modified = !settingsComponent.getHostText().equals(state.ollamaHost); modified |= !settingsComponent.getPortText().equals(String.valueOf(state.ollamaPort)); modified |= !settingsComponent.getModelText().equals(state.ollamaModel); @@ -50,7 +52,7 @@ public boolean isModified() { @Override public void apply() { try { - LLMService.State state = llmService.getState(); + LLMConfigService.State state = llmConfigService.getState(); state.ollamaHost = settingsComponent.getHostText(); state.ollamaPort = Integer.parseInt(settingsComponent.getPortText()); state.maxTokens = Integer.parseInt(settingsComponent.getMaxTokensText()); @@ -59,7 +61,7 @@ public void apply() { state.ollamaModel = settingsComponent.getModelText(); state.copyAsMarkdown = settingsComponent.getCopyAsMarkdown(); - llmService.loadState(state); + llmConfigService.loadState(state); } catch (NumberFormatException e) { // Handle invalid number format throw new IllegalStateException("Invalid number format in settings", e); @@ -69,7 +71,7 @@ public void apply() { @Override public void reset() { // Reset the settings component with the current state of the LLMService - LLMService.State state = llmService.getState(); + LLMConfigService.State state = llmConfigService.getState(); settingsComponent.setHostText(state.ollamaHost); settingsComponent.setPortText(String.valueOf(state.ollamaPort)); settingsComponent.setModelText(state.ollamaModel); diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/TestCraftSettingsConfigurable.java b/src/main/java/com/github/jaksonlin/testcraft/application/settings/TestCraftSettingsConfigurable.java similarity index 53% rename from src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/TestCraftSettingsConfigurable.java rename to src/main/java/com/github/jaksonlin/testcraft/application/settings/TestCraftSettingsConfigurable.java index 283ac7f..c9a5534 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/settings/TestCraftSettingsConfigurable.java +++ b/src/main/java/com/github/jaksonlin/testcraft/application/settings/TestCraftSettingsConfigurable.java @@ -1,22 +1,24 @@ -package com.github.jaksonlin.testcraft.infrastructure.settings; +package com.github.jaksonlin.testcraft.application.settings; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.SearchableConfigurable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.github.jaksonlin.testcraft.util.MyBundle; + import javax.swing.*; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + public class TestCraftSettingsConfigurable implements SearchableConfigurable.Parent { @Override public @NotNull String getId() { - return "com.github.jaksonlin.testcraft.infrastructure.settings"; + return "com.github.jaksonlin.testcraft.application.settings"; } @Override public String getDisplayName() { - return MyBundle.message("settings.testcraft.title"); + return I18nService.getInstance().message("settings.testcraft.title"); } @Override @@ -24,12 +26,12 @@ public String getDisplayName() { // Create a panel with a brief description of TestCraft settings JPanel panel = new JPanel(); panel.add(new JLabel("" + - "

" + MyBundle.message("settings.testcraft.title") + "

" + - "

" + MyBundle.message("settings.testcraft.description") + "

" + + "

" + I18nService.getInstance().message("settings.testcraft.title") + "

" + + "

" + I18nService.getInstance().message("settings.testcraft.description") + "

" + "
    " + - "
  • " + MyBundle.message("settings.testcraft.annotations") + " - " + MyBundle.message("settings.testcraft.annotations.description") + "
  • " + - "
  • " + MyBundle.message("settings.testcraft.asserts") + " - " + MyBundle.message("settings.testcraft.asserts.description") + "
  • " + - "
  • " + MyBundle.message("settings.testcraft.llm") + " - " + MyBundle.message("settings.testcraft.llm.description") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.testcraft.annotations") + " - " + I18nService.getInstance().message("settings.testcraft.annotations.description") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.testcraft.asserts") + " - " + I18nService.getInstance().message("settings.testcraft.asserts.description") + "
  • " + + "
  • " + I18nService.getInstance().message("settings.testcraft.llm") + " - " + I18nService.getInstance().message("settings.testcraft.llm.description") + "
  • " + "
" + "")); return panel; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationFieldConfig.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationFieldConfig.java similarity index 97% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationFieldConfig.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationFieldConfig.java index 5a89422..d264619 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationFieldConfig.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationFieldConfig.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationFieldType.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationFieldType.java similarity index 52% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationFieldType.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationFieldType.java index ad526cc..159b78c 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationFieldType.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationFieldType.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; public enum AnnotationFieldType { STRING, diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationParser.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationParser.java similarity index 96% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationParser.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationParser.java index eecd655..d019f25 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationParser.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationParser.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; -import com.github.jaksonlin.testcraft.core.context.UnittestCase; +import com.github.jaksonlin.testcraft.domain.context.UnittestCase; import org.jetbrains.annotations.Nullable; import java.util.HashMap; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationSchema.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationSchema.java similarity index 99% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationSchema.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationSchema.java index 7d54f67..5a2167b 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationSchema.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationSchema.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; import com.fasterxml.jackson.databind.ObjectMapper; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationValidator.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationValidator.java similarity index 99% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationValidator.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationValidator.java index 9fc6864..bf31da3 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/AnnotationValidator.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/AnnotationValidator.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/DefaultValue.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/DefaultValue.java similarity index 96% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/DefaultValue.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/DefaultValue.java index 351d11b..e5de1c7 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/DefaultValue.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/DefaultValue.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/FieldValidation.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/FieldValidation.java similarity index 96% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/FieldValidation.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/FieldValidation.java index 593cdb7..9b9ffee 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/FieldValidation.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/FieldValidation.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/UnittestAnnotationConfig.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/UnittestAnnotationConfig.java similarity index 97% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/UnittestAnnotationConfig.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/UnittestAnnotationConfig.java index efe1764..1fb07e5 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/UnittestAnnotationConfig.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/UnittestAnnotationConfig.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; public class UnittestAnnotationConfig { private String authorField; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValidationMode.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValidationMode.java similarity index 64% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValidationMode.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValidationMode.java index c850c63..206ac1d 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValidationMode.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValidationMode.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; public enum ValidationMode { EXACT, // Exact string match diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValueProvider.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValueProvider.java similarity index 93% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValueProvider.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValueProvider.java index 49c460e..2e6788a 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValueProvider.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValueProvider.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; import com.fasterxml.jackson.databind.JsonNode; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValueProviderType.java b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValueProviderType.java similarity index 81% rename from src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValueProviderType.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValueProviderType.java index 56123a0..8c2e510 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/annotations/ValueProviderType.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/annotations/ValueProviderType.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.annotations; +package com.github.jaksonlin.testcraft.domain.annotations; public enum ValueProviderType { GIT_AUTHOR, diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/context/CaseCheckContext.java b/src/main/java/com/github/jaksonlin/testcraft/domain/context/CaseCheckContext.java similarity index 82% rename from src/main/java/com/github/jaksonlin/testcraft/core/context/CaseCheckContext.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/context/CaseCheckContext.java index 58c0760..96f4577 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/context/CaseCheckContext.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/context/CaseCheckContext.java @@ -1,9 +1,9 @@ -package com.github.jaksonlin.testcraft.core.context; +package com.github.jaksonlin.testcraft.domain.context; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationParser; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationSchema; -import com.github.jaksonlin.testcraft.core.services.AnnotationConfigService; -import com.github.jaksonlin.testcraft.core.services.InvalidTestCaseConfigService; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationParser; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationSchema; +import com.github.jaksonlin.testcraft.infrastructure.services.config.AnnotationConfigService; +import com.github.jaksonlin.testcraft.infrastructure.services.config.InvalidTestCaseConfigService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/context/PitestContext.java b/src/main/java/com/github/jaksonlin/testcraft/domain/context/PitestContext.java similarity index 99% rename from src/main/java/com/github/jaksonlin/testcraft/core/context/PitestContext.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/context/PitestContext.java index dddbfa0..aede948 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/context/PitestContext.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/context/PitestContext.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.context; +package com.github.jaksonlin.testcraft.domain.context; import com.github.jaksonlin.testcraft.util.Mutation; import com.github.jaksonlin.testcraft.util.MutationReportParser; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/context/TestPoints.java b/src/main/java/com/github/jaksonlin/testcraft/domain/context/TestPoints.java similarity index 96% rename from src/main/java/com/github/jaksonlin/testcraft/core/context/TestPoints.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/context/TestPoints.java index 55ef18c..c909bf4 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/context/TestPoints.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/context/TestPoints.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.context; +package com.github.jaksonlin.testcraft.domain.context; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCase.java b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCase.java similarity index 94% rename from src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCase.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCase.java index f048d83..40a8745 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCase.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCase.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.context; +package com.github.jaksonlin.testcraft.domain.context; import java.util.Collections; import java.util.List; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCaseInfoContext.java b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCaseInfoContext.java similarity index 96% rename from src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCaseInfoContext.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCaseInfoContext.java index edeb48d..430ea77 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCaseInfoContext.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCaseInfoContext.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.core.context; +package com.github.jaksonlin.testcraft.domain.context; -import com.github.jaksonlin.testcraft.core.annotations.UnittestAnnotationConfig; +import com.github.jaksonlin.testcraft.domain.annotations.UnittestAnnotationConfig; import java.util.Collections; import java.util.List; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCaseStatus.java b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCaseStatus.java similarity index 56% rename from src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCaseStatus.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCaseStatus.java index 79a914d..98411cb 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestCaseStatus.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestCaseStatus.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.context; +package com.github.jaksonlin.testcraft.domain.context; public enum UnittestCaseStatus { TODO, DONE, BROKEN, DEPRECATED diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestMethodContext.java b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestMethodContext.java similarity index 88% rename from src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestMethodContext.java rename to src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestMethodContext.java index 145d704..20b3010 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/context/UnittestMethodContext.java +++ b/src/main/java/com/github/jaksonlin/testcraft/domain/context/UnittestMethodContext.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.context; +package com.github.jaksonlin.testcraft.domain.context; import java.util.List; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/CommandCancellationException.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/CommandCancellationException.java similarity index 70% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/CommandCancellationException.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/CommandCancellationException.java index 458175d..5af4d96 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/CommandCancellationException.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/CommandCancellationException.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.application.commands; +package com.github.jaksonlin.testcraft.infrastructure.commands; public class CommandCancellationException extends Exception{ diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/BuildPitestCommandCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/BuildPitestCommandCommand.java similarity index 95% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/BuildPitestCommandCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/BuildPitestCommandCommand.java index bf028d0..0378ca0 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/BuildPitestCommandCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/BuildPitestCommandCommand.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.application.commands.pitest; +package com.github.jaksonlin.testcraft.infrastructure.commands.pitest; -import com.github.jaksonlin.testcraft.core.context.PitestContext; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; import com.intellij.openapi.project.Project; import java.util.ArrayList; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/HandlePitestResultCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/HandlePitestResultCommand.java similarity index 95% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/HandlePitestResultCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/HandlePitestResultCommand.java index 124f782..d1d12d1 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/HandlePitestResultCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/HandlePitestResultCommand.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.application.commands.pitest; +package com.github.jaksonlin.testcraft.infrastructure.commands.pitest; -import com.github.jaksonlin.testcraft.core.context.PitestContext; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; import com.github.jaksonlin.testcraft.presentation.components.PitestOutputDialog; import com.github.jaksonlin.testcraft.util.ProcessResult; import com.intellij.openapi.application.ApplicationManager; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/PitestCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/PitestCommand.java similarity index 80% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/PitestCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/PitestCommand.java index e42206f..eae8eb7 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/PitestCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/PitestCommand.java @@ -1,19 +1,21 @@ -package com.github.jaksonlin.testcraft.application.commands.pitest; +package com.github.jaksonlin.testcraft.infrastructure.commands.pitest; -import com.github.jaksonlin.testcraft.application.commands.CommandCancellationException; -import com.github.jaksonlin.testcraft.core.context.PitestContext; -import com.github.jaksonlin.testcraft.core.services.RunHistoryManagerService; +import com.github.jaksonlin.testcraft.infrastructure.commands.CommandCancellationException; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; +import com.github.jaksonlin.testcraft.infrastructure.services.business.RunHistoryManagerService; import com.github.jaksonlin.testcraft.presentation.components.PitestOutputDialog; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; -import com.github.jaksonlin.testcraft.util.MyBundle; + import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + public abstract class PitestCommand { private final Project project; private final PitestContext context; @@ -22,7 +24,7 @@ public abstract class PitestCommand { public PitestCommand(Project project, PitestContext context) { this.project = project; this.context = context; - this.runHistoryManager = project.getService(RunHistoryManagerService.class); + this.runHistoryManager = RunHistoryManagerService.getInstance(); } public abstract void execute(); @@ -65,7 +67,7 @@ protected void showError(String message) { ApplicationManager.getApplication().invokeLater(() -> { String contextState = PitestContext.dumpPitestContext(context); String messageWithContextState = message + "\n\n" + contextState; - Messages.showErrorDialog(project, messageWithContextState, MyBundle.message("error.pitest.general.title")); + Messages.showErrorDialog(project, messageWithContextState, I18nService.getInstance().message("error.pitest.general.title")); }); } } diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/PrepareEnvironmentCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/PrepareEnvironmentCommand.java similarity index 94% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/PrepareEnvironmentCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/PrepareEnvironmentCommand.java index e4152d4..bb69a44 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/PrepareEnvironmentCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/PrepareEnvironmentCommand.java @@ -1,7 +1,7 @@ -package com.github.jaksonlin.testcraft.application.commands.pitest; +package com.github.jaksonlin.testcraft.infrastructure.commands.pitest; -import com.github.jaksonlin.testcraft.application.commands.CommandCancellationException; -import com.github.jaksonlin.testcraft.core.context.PitestContext; +import com.github.jaksonlin.testcraft.infrastructure.commands.CommandCancellationException; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; import com.github.jaksonlin.testcraft.util.*; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ReadAction; @@ -13,7 +13,7 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.github.jaksonlin.testcraft.util.MyBundle; + import java.io.File; import java.nio.file.Path; @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.List; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + public class PrepareEnvironmentCommand extends PitestCommand { private final JavaFileProcessor javaFileProcessor = new JavaFileProcessor(); @@ -144,7 +146,7 @@ private void collectResourceDirectories() { } private void collectTargetClassThatWeTest(List sourceRoots) { - String targetClass = showInputDialog(MyBundle.message("dialog.target.class.message"), MyBundle.message("dialog.target.class.title")); + String targetClass = showInputDialog(I18nService.getInstance().message("dialog.target.class.message"), I18nService.getInstance().message("dialog.target.class.title")); if (targetClass == null || targetClass.isEmpty()) { try { throw new CommandCancellationException("User cancelled the operation"); @@ -234,7 +236,7 @@ private void setupPitestLibDependencies(List resourceDirectories) { } dependencies.addAll(resourceDirectories); if (dependencies.isEmpty()) { - Messages.showErrorDialog(MyBundle.message("error.pitest.dependencies"), MyBundle.message("error.pitest.title")); + Messages.showErrorDialog(I18nService.getInstance().message("error.pitest.dependencies"), I18nService.getInstance().message("error.pitest.title")); throw new IllegalStateException("Cannot find pitest dependencies"); } getContext().setPitestDependencies(String.join(File.pathSeparator, dependencies)); diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/RunPitestCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/RunPitestCommand.java similarity index 94% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/RunPitestCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/RunPitestCommand.java index 36a29d2..46cc79a 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/RunPitestCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/RunPitestCommand.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.application.commands.pitest; +package com.github.jaksonlin.testcraft.infrastructure.commands.pitest; -import com.github.jaksonlin.testcraft.core.context.PitestContext; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; import com.github.jaksonlin.testcraft.util.Mutation; import com.github.jaksonlin.testcraft.util.ProcessExecutor; import com.github.jaksonlin.testcraft.util.ProcessResult; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/StoreHistoryCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/StoreHistoryCommand.java similarity index 69% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/StoreHistoryCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/StoreHistoryCommand.java index 9ccd93e..ec66496 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/pitest/StoreHistoryCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/pitest/StoreHistoryCommand.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.application.commands.pitest; +package com.github.jaksonlin.testcraft.infrastructure.commands.pitest; -import com.github.jaksonlin.testcraft.core.context.PitestContext; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; import com.intellij.openapi.project.Project; public class StoreHistoryCommand extends PitestCommand { diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/CollectScanCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/CollectScanCommand.java new file mode 100644 index 0000000..a1fc5ea --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/CollectScanCommand.java @@ -0,0 +1,4 @@ +package com.github.jaksonlin.testcraft.infrastructure.commands.testscan; + +public class CollectScanCommand { +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestCaseCheckCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestCaseCheckCommand.java similarity index 85% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestCaseCheckCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestCaseCheckCommand.java index a3b449f..4c83b36 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestCaseCheckCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestCaseCheckCommand.java @@ -1,9 +1,9 @@ -package com.github.jaksonlin.testcraft.application.commands.testscan; +package com.github.jaksonlin.testcraft.infrastructure.commands.testscan; -import com.github.jaksonlin.testcraft.util.MyBundle; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationSchema; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; -import com.github.jaksonlin.testcraft.core.context.UnittestCase; + +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationSchema; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.domain.context.UnittestCase; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.*; @@ -14,6 +14,8 @@ import java.util.List; import java.util.Map; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + public abstract class UnittestCaseCheckCommand { private final Project project; private final CaseCheckContext context; @@ -37,7 +39,7 @@ public void showSuccessMessage(Project project, String message) { Messages.showMessageDialog( project, message, - MyBundle.message("test.annotation.details.title"), + I18nService.getInstance().message("test.annotation.details.title"), Messages.getInformationIcon() ); } @@ -46,7 +48,7 @@ public void showErrorMessage(Project project, String message) { Messages.showMessageDialog( project, "Error parsing annotation: " + message, - MyBundle.message("test.file.action.title"), + I18nService.getInstance().message("test.file.action.title"), Messages.getErrorIcon() ); } @@ -55,7 +57,7 @@ public void showNoAnnotationMessage(Project project, String annotationName) { Messages.showMessageDialog( project, "No " + annotationName + " annotation found on this method", - MyBundle.message("test.file.action.title"), + I18nService.getInstance().message("test.file.action.title"), Messages.getWarningIcon() ); } @@ -64,7 +66,7 @@ public void showNotJunitTestMethodMessage(Project project) { Messages.showMessageDialog( project, "This method is not a JUnit test method", - MyBundle.message("test.annotation.generation.title"), + I18nService.getInstance().message("test.annotation.generation.title"), Messages.getWarningIcon() ); } @@ -73,7 +75,7 @@ public void showNoMethodMessage(Project project) { Messages.showMessageDialog( project, "No methods found in this class", - MyBundle.message("test.methods.not.found.title"), + I18nService.getInstance().message("test.methods.not.found.title"), Messages.getWarningIcon() ); } @@ -82,7 +84,7 @@ public void showNoTestMethodCanAddMessage(Project project) { Messages.showMessageDialog( project, "No test methods found in the class that can add annotation.", - MyBundle.message("test.methods.no.annotation.title"), + I18nService.getInstance().message("test.methods.no.annotation.title"), Messages.getInformationIcon() ); } @@ -91,7 +93,7 @@ public void showAnnotationAlreadyExistMessage(Project project, String annotation Messages.showMessageDialog( project, annotationName + " already exist on this method", - MyBundle.message("test.annotation.exists.title"), + I18nService.getInstance().message("test.annotation.exists.title"), Messages.getWarningIcon() ); } diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestFileBatchScanCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestFileBatchScanCommand.java similarity index 98% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestFileBatchScanCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestFileBatchScanCommand.java index 68f8c5b..80c8658 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestFileBatchScanCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestFileBatchScanCommand.java @@ -1,6 +1,6 @@ -package com.github.jaksonlin.testcraft.application.commands.testscan; +package com.github.jaksonlin.testcraft.infrastructure.commands.testscan; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.actionSystem.AnActionEvent; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestFileInspectorCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestFileInspectorCommand.java similarity index 95% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestFileInspectorCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestFileInspectorCommand.java index 24949bc..1cff768 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/testscan/UnittestFileInspectorCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/testscan/UnittestFileInspectorCommand.java @@ -1,8 +1,8 @@ -package com.github.jaksonlin.testcraft.application.commands.testscan; +package com.github.jaksonlin.testcraft.infrastructure.commands.testscan; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; -import com.github.jaksonlin.testcraft.core.services.AnnotationConfigService; -import com.github.jaksonlin.testcraft.core.services.InvalidTestCaseConfigService; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.services.config.AnnotationConfigService; +import com.github.jaksonlin.testcraft.infrastructure.services.config.InvalidTestCaseConfigService; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.application.ApplicationManager; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/CheckAnnotationCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/CheckAnnotationCommand.java similarity index 87% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/CheckAnnotationCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/CheckAnnotationCommand.java index a0d9d71..aa58be9 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/CheckAnnotationCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/CheckAnnotationCommand.java @@ -1,10 +1,10 @@ -package com.github.jaksonlin.testcraft.application.commands.unittestannotations; +package com.github.jaksonlin.testcraft.infrastructure.commands.unittestannotations; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationFieldType; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationSchema; -import com.github.jaksonlin.testcraft.application.commands.testscan.UnittestCaseCheckCommand; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; -import com.github.jaksonlin.testcraft.core.context.UnittestCase; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationFieldType; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationSchema; +import com.github.jaksonlin.testcraft.infrastructure.commands.testscan.UnittestCaseCheckCommand; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.domain.context.UnittestCase; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiComment; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/CheckMethodDataCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/CheckMethodDataCommand.java similarity index 84% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/CheckMethodDataCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/CheckMethodDataCommand.java index bb9ac4c..b05fbaf 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/CheckMethodDataCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/CheckMethodDataCommand.java @@ -1,7 +1,7 @@ -package com.github.jaksonlin.testcraft.application.commands.unittestannotations; +package com.github.jaksonlin.testcraft.infrastructure.commands.unittestannotations; -import com.github.jaksonlin.testcraft.application.commands.testscan.UnittestCaseCheckCommand; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.commands.testscan.UnittestCaseCheckCommand; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiComment; diff --git a/src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/GenerateAnnotationCommand.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/GenerateAnnotationCommand.java similarity index 95% rename from src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/GenerateAnnotationCommand.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/GenerateAnnotationCommand.java index f691945..3c0ad29 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/application/commands/unittestannotations/GenerateAnnotationCommand.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/commands/unittestannotations/GenerateAnnotationCommand.java @@ -1,14 +1,14 @@ -package com.github.jaksonlin.testcraft.application.commands.unittestannotations; +package com.github.jaksonlin.testcraft.infrastructure.commands.unittestannotations; import com.fasterxml.jackson.databind.node.ArrayNode; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationFieldConfig; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationFieldType; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationSchema; -import com.github.jaksonlin.testcraft.core.annotations.DefaultValue; -import com.github.jaksonlin.testcraft.application.commands.testscan.UnittestCaseCheckCommand; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; -import com.github.jaksonlin.testcraft.core.services.AnnotationConfigService; -import com.github.jaksonlin.testcraft.core.services.AnnotationValueProviderService; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationFieldConfig; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationFieldType; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationSchema; +import com.github.jaksonlin.testcraft.domain.annotations.DefaultValue; +import com.github.jaksonlin.testcraft.infrastructure.commands.testscan.UnittestCaseCheckCommand; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.infrastructure.services.config.AnnotationConfigService; +import com.github.jaksonlin.testcraft.infrastructure.services.business.AnnotationValueProviderService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.command.WriteCommandAction; diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/BaseEvent.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/BaseEvent.java new file mode 100644 index 0000000..35e456f --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/BaseEvent.java @@ -0,0 +1,27 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + +public abstract class BaseEvent { + private final String eventType; + private final Object payload; + + protected BaseEvent(String eventType, Object payload) { + this.eventType = eventType; + this.payload = payload; + } + + public String getEventType() { + return eventType; + } + + public Object getPayload() { + return payload; + } + + @Override + public String toString() { + return "BaseEvent{" + + "eventType='" + eventType + '\'' + + ", payload=" + payload + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/BasicEventObserver.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/BasicEventObserver.java new file mode 100644 index 0000000..296a8d6 --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/BasicEventObserver.java @@ -0,0 +1,16 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.BaseEvent; +import com.google.common.eventbus.Subscribe; + +public abstract class BasicEventObserver { + protected BasicEventObserver() { + } + + @Subscribe + public void onEvent(BaseEvent event) { + onEventHappen(event.getEventType(), event.getPayload()); + } + + public abstract void onEventHappen(String eventName, Object eventObj); +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/ChatEvent.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/ChatEvent.java new file mode 100644 index 0000000..2a467d4 --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/ChatEvent.java @@ -0,0 +1,17 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + +public class ChatEvent extends BaseEvent { + public static final String CLEAR_CHAT = "CLEAR_CHAT"; + public static final String CHAT_REQUEST = "CHAT_REQUEST"; + public static final String CHAT_RESPONSE = "CHAT_RESPONSE"; + public static final String START_LOADING = "START_LOADING"; + public static final String STOP_LOADING = "STOP_LOADING"; + public static final String REQUEST_COPY_CHAT_RESPONSE = "REQUEST_COPY_CHAT_RESPONSE"; + public static final String COPY_CHAT_RESPONSE = "COPY_CHAT_RESPONSE"; + public static final String DRY_RUN_PROMPT = "DRY_RUN_PROMPT"; + public static final String ERROR = "ERROR"; + + public ChatEvent(String eventType, Object payload) { + super(eventType, payload); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/EventHandler.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/EventHandler.java new file mode 100644 index 0000000..eb3aed6 --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/EventHandler.java @@ -0,0 +1,8 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + + +@FunctionalInterface +public interface EventHandler { + void handle(T event); +} + diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/LLMConfigEvent.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/LLMConfigEvent.java new file mode 100644 index 0000000..19408a3 --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/LLMConfigEvent.java @@ -0,0 +1,10 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + +public class LLMConfigEvent extends BaseEvent { + public static final String CONFIG_CHANGE = "CONFIG_CHANGE"; + public static final String CONFIG_CHANGE_COPY_AS_MARKDOWN = "CONFIG_CHANGE:copyAsMarkdown"; + + public LLMConfigEvent(String eventType, Object payload) { + super(eventType, payload); + } +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/MutationEvent.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/MutationEvent.java new file mode 100644 index 0000000..018bbae --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/MutationEvent.java @@ -0,0 +1,11 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + +public class MutationEvent extends BaseEvent { + public static final String MUTATION_RESULT = "MUTATION_RESULT"; + + public MutationEvent(String eventType, Object payload) { + super(eventType, payload); + } + + +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/RunHistoryEvent.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/RunHistoryEvent.java new file mode 100644 index 0000000..cce4d85 --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/RunHistoryEvent.java @@ -0,0 +1,10 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + +public class RunHistoryEvent extends BaseEvent { + public static final String RUN_HISTORY = "RUN_HISTORY"; + public static final String RUN_HISTORY_LIST = "RUN_HISTORY_LIST"; + + public RunHistoryEvent(String eventType, Object payload) { + super(eventType, payload); + } +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/TypedEventObserver.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/TypedEventObserver.java new file mode 100644 index 0000000..c67884c --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/events/TypedEventObserver.java @@ -0,0 +1,28 @@ +package com.github.jaksonlin.testcraft.infrastructure.messaging.events; + +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; +import com.google.common.eventbus.Subscribe; + +public abstract class TypedEventObserver { + private final Class eventType; + private final EventBusService eventBus; + + protected TypedEventObserver(Class eventType) { + this.eventType = eventType; + this.eventBus = EventBusService.getInstance(); + this.eventBus.register(this); + } + + @Subscribe + public void onEvent(BaseEvent event) { + if (eventType.isInstance(event)) { + onTypedEvent(eventType.cast(event)); + } + } + + protected abstract void onTypedEvent(T event); + + public void unregister() { + eventBus.unregister(this); + } +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/listeners/MyApplicationActivationListener.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/listeners/MyApplicationActivationListener.java similarity index 87% rename from src/main/java/com/github/jaksonlin/testcraft/messaging/listeners/MyApplicationActivationListener.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/listeners/MyApplicationActivationListener.java index 17822c2..c2addd0 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/listeners/MyApplicationActivationListener.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/listeners/MyApplicationActivationListener.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.messaging.listeners; +package com.github.jaksonlin.testcraft.infrastructure.messaging.listeners; import com.intellij.openapi.application.ApplicationActivationListener; import com.intellij.openapi.diagnostic.Logger; diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/ILLMChatClient.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/ILLMChatClient.java similarity index 59% rename from src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/ILLMChatClient.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/ILLMChatClient.java index 810ba34..e116486 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/ILLMChatClient.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/ILLMChatClient.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.messaging.mediators; +package com.github.jaksonlin.testcraft.infrastructure.messaging.mediators; public interface ILLMChatClient { diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/ILLMChatMediator.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/ILLMChatMediator.java similarity index 83% rename from src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/ILLMChatMediator.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/ILLMChatMediator.java index d6839dd..3d7199d 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/ILLMChatMediator.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/ILLMChatMediator.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.messaging.mediators; +package com.github.jaksonlin.testcraft.infrastructure.messaging.mediators; import com.github.jaksonlin.testcraft.util.Mutation; import com.github.jaksonlin.testcraft.util.OllamaClient; @@ -8,7 +8,6 @@ public interface ILLMChatMediator { void setOllamaClient(OllamaClient ollamaClient); void generateUnittestRequest(String testCodeFile, String sourceCodeFile, List mutationList); - void register(ILLMChatClient chatClient); String dryRunGetPrompt(String testClassName, String sourceClassName, List mutations); void handleChatMessage(String message); void clearChat(); diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/IMutationMediator.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/IMutationMediator.java similarity index 77% rename from src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/IMutationMediator.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/IMutationMediator.java index 90f1eea..596fa5d 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/IMutationMediator.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/IMutationMediator.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.messaging.mediators; +package com.github.jaksonlin.testcraft.infrastructure.messaging.mediators; import com.github.jaksonlin.testcraft.util.Mutation; diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/IMutationReportUI.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/IMutationReportUI.java similarity index 75% rename from src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/IMutationReportUI.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/IMutationReportUI.java index 110c68a..df1b928 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/IMutationReportUI.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/IMutationReportUI.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.messaging.mediators; +package com.github.jaksonlin.testcraft.infrastructure.messaging.mediators; import com.github.jaksonlin.testcraft.util.Pair; diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/LLMChatMediatorImpl.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/LLMChatMediatorImpl.java similarity index 82% rename from src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/LLMChatMediatorImpl.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/LLMChatMediatorImpl.java index 6647ef6..e685282 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/LLMChatMediatorImpl.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/LLMChatMediatorImpl.java @@ -1,12 +1,15 @@ -package com.github.jaksonlin.testcraft.messaging.mediators; +package com.github.jaksonlin.testcraft.infrastructure.messaging.mediators; -import com.github.jaksonlin.testcraft.util.MyBundle; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.ChatEvent; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; import com.github.jaksonlin.testcraft.util.Mutation; import com.github.jaksonlin.testcraft.util.OllamaClient; import com.intellij.openapi.diagnostic.Logger; import javax.swing.*; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; @@ -20,7 +23,7 @@ public class LLMChatMediatorImpl implements ILLMChatMediator { private static final Logger LOG = Logger.getInstance(LLMChatMediatorImpl.class); - private ILLMChatClient chatClient; + private final EventBusService eventBusService = EventBusService.getInstance(); private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private OllamaClient ollamaClient; private final List messageHistory = new ArrayList<>(); @@ -38,7 +41,6 @@ public String getChatHistory() { .map(message -> message.getRole() + ": " + message.getContent()) .collect(Collectors.joining("\n")); } - // generate unittest using mutation result, this will clear the chat history @Override public void generateUnittestRequest(String testCodeFile, String sourceCodeFile, List mutations) { @@ -46,31 +48,26 @@ public void generateUnittestRequest(String testCodeFile, String sourceCodeFile, try { // Test connection before attempting to send message if (!ollamaClient.testConnection()) { - if (chatClient != null) { - SwingUtilities.invokeLater(() -> chatClient.updateChatResponse("ERROR", - MyBundle.message("llm.error.connection"))); - } + eventBusService.post(new ChatEvent(ChatEvent.CHAT_RESPONSE, + I18nService.getInstance().message("llm.error.connection"))); return; } + List messages = createPromptOnly(testCodeFile, sourceCodeFile, mutations); if (messages.isEmpty()) { - if (chatClient != null) { - SwingUtilities.invokeLater(() -> chatClient.updateChatResponse("ERROR", - MyBundle.message("llm.error.no.mutations"))); - } + eventBusService.post(new ChatEvent(ChatEvent.CHAT_RESPONSE, + I18nService.getInstance().message("llm.error.no.mutations"))); return; } messageHistory.addAll(messages); String rawResponse = ollamaClient.chatCompletion(messageHistory); messageHistory.add(new OllamaClient.Message("assistant", rawResponse)); String formattedResponse = formatResponse(rawResponse); - SwingUtilities.invokeLater(() -> chatClient.updateChatResponse("UNIT_TEST_REQUEST", formattedResponse)); + eventBusService.post(new ChatEvent(ChatEvent.CHAT_RESPONSE, formattedResponse)); } catch (Exception e) { LOG.error("Failed to generate unit test suggestions", e); - if (chatClient != null) { - SwingUtilities.invokeLater(() -> chatClient.updateChatResponse("ERROR", "Error: " + e.toString())); - } + eventBusService.post(new ChatEvent(ChatEvent.CHAT_RESPONSE, "Error: " + e.toString())); } }); } @@ -82,10 +79,8 @@ public void handleChatMessage(String message) { try { // Test connection before attempting to send message if (!ollamaClient.testConnection()) { - if (chatClient != null) { - SwingUtilities.invokeLater(() -> chatClient.updateChatResponse("ERROR", - MyBundle.message("llm.error.connection"))); - } + eventBusService.post(new ChatEvent(ChatEvent.CHAT_RESPONSE, + I18nService.getInstance().message("llm.error.connection"))); return; } messageHistory.add(new OllamaClient.Message("user", message)); @@ -93,12 +88,10 @@ public void handleChatMessage(String message) { messageHistory.add(new OllamaClient.Message("assistant", rawResponse)); // Format the response String formattedResponse = formatResponse(rawResponse); - chatClient.updateChatResponse("CHAT_MESSAGE", formattedResponse); + eventBusService.post(new ChatEvent(ChatEvent.CHAT_RESPONSE, formattedResponse)); } catch (Exception e) { LOG.error("Failed to respond to chat message", e); - if (chatClient != null) { - SwingUtilities.invokeLater(() -> chatClient.updateChatResponse("ERROR", "Error: " + e.toString())); - } + eventBusService.post(new ChatEvent(ChatEvent.CHAT_RESPONSE, "Error: " + e.toString())); } }); } @@ -196,14 +189,14 @@ private List createPromptOnly(String testCodeFile, String .count(); // System message to set context - promptOnlyMessages.add(new OllamaClient.Message("system", MyBundle.message("llm.prompt.system"))); + promptOnlyMessages.add(new OllamaClient.Message("system", I18nService.getInstance().message("llm.prompt.system"))); // Read source files if needed - String sourceCode = Files.readString(Paths.get(sourceCodeFile)); - String testCode = Files.readString(Paths.get(testCodeFile)); + String sourceCode = readFileContent(sourceCodeFile); + String testCode = readFileContent(testCodeFile); // User message with the structured data - String prompt = String.format(MyBundle.message("llm.prompt.user"), + String prompt = String.format(I18nService.getInstance().message("llm.prompt.user"), sourceCode, testCode, totalMutations, @@ -234,10 +227,10 @@ private List createPromptOnlyWithoutCodeContent(String tes .count(); // System message to set context - promptOnlyMessages.add(new OllamaClient.Message("system", MyBundle.message("llm.prompt.system"))); + promptOnlyMessages.add(new OllamaClient.Message("system", I18nService.getInstance().message("llm.prompt.system"))); // User message with the structured data - String prompt = String.format(MyBundle.message("llm.prompt.user.compact"), + String prompt = String.format(I18nService.getInstance().message("llm.prompt.user.compact"), testClassName, sourceClassName, totalMutations, @@ -252,6 +245,18 @@ private List createPromptOnlyWithoutCodeContent(String tes return promptOnlyMessages; } + + private String readFileContent(String filePath) { + try { + return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException("Failed to read file: " + filePath, e); + } + } + + private String getSourceCode(String sourceCodeFile) { + return readFileContent(sourceCodeFile); + } @Override public String dryRunGetPrompt(String testClassName, String sourceClassName, List mutations) { try { @@ -293,12 +298,6 @@ public String dryRunGetPrompt(String testClassName, String sourceClassName, List } } - - - @Override - public void register(ILLMChatClient chatClient) { - this.chatClient = chatClient; - } } diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/MutationMediatorImpl.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/MutationMediatorImpl.java similarity index 84% rename from src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/MutationMediatorImpl.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/MutationMediatorImpl.java index d55029e..70cb27f 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/mediators/MutationMediatorImpl.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/messaging/mediators/MutationMediatorImpl.java @@ -1,5 +1,7 @@ -package com.github.jaksonlin.testcraft.messaging.mediators; +package com.github.jaksonlin.testcraft.infrastructure.messaging.mediators; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.MutationEvent; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; import com.github.jaksonlin.testcraft.util.Mutation; import com.github.jaksonlin.testcraft.util.Pair; @@ -14,13 +16,14 @@ public class MutationMediatorImpl implements IMutationMediator { protected IMutationReportUI clientUI; private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final EventBusService eventBusService = EventBusService.getInstance(); @Override public void processMutationResult(String mutationTargetClassFilePath, List mutations) { executorService.submit(() -> { Map> renderedFormat = convertResultToUIRenderFormat(mutations); if (clientUI != null) { - SwingUtilities.invokeLater(() -> clientUI.updateMutationResult(mutationTargetClassFilePath, renderedFormat)); + eventBusService.post(new MutationEvent(MutationEvent.MUTATION_RESULT, new Pair>>(mutationTargetClassFilePath, renderedFormat))); } }); } diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/services/AnnotationValueProviderService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/AnnotationValueProviderService.java similarity index 96% rename from src/main/java/com/github/jaksonlin/testcraft/core/services/AnnotationValueProviderService.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/AnnotationValueProviderService.java index ba27e81..9a0cf34 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/services/AnnotationValueProviderService.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/AnnotationValueProviderService.java @@ -1,8 +1,8 @@ -package com.github.jaksonlin.testcraft.core.services; +package com.github.jaksonlin.testcraft.infrastructure.services.business; -import com.github.jaksonlin.testcraft.core.annotations.ValueProvider; -import com.github.jaksonlin.testcraft.core.annotations.ValueProviderType; -import com.github.jaksonlin.testcraft.core.context.CaseCheckContext; +import com.github.jaksonlin.testcraft.domain.annotations.ValueProvider; +import com.github.jaksonlin.testcraft.domain.annotations.ValueProviderType; +import com.github.jaksonlin.testcraft.domain.context.CaseCheckContext; import com.github.jaksonlin.testcraft.util.GitUtil; import com.intellij.openapi.components.Service; import com.intellij.openapi.project.Project; diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/PitestService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/PitestService.java new file mode 100644 index 0000000..72ad64d --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/PitestService.java @@ -0,0 +1,9 @@ +package com.github.jaksonlin.testcraft.infrastructure.services.business; + +import com.intellij.openapi.components.Service; + +@Service(Service.Level.APP) +public final class PitestService { + + +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/services/RunHistoryManagerService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/RunHistoryManagerService.java similarity index 68% rename from src/main/java/com/github/jaksonlin/testcraft/core/services/RunHistoryManagerService.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/RunHistoryManagerService.java index 739e967..ac9c136 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/services/RunHistoryManagerService.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/business/RunHistoryManagerService.java @@ -1,15 +1,15 @@ -package com.github.jaksonlin.testcraft.core.services; +package com.github.jaksonlin.testcraft.infrastructure.services.business; -import com.github.jaksonlin.testcraft.core.context.PitestContext; -import com.github.jaksonlin.testcraft.messaging.observers.ObserverBase; -import com.github.jaksonlin.testcraft.messaging.observers.BasicEventObserver; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.RunHistoryEvent; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; import com.github.jaksonlin.testcraft.util.Pair; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.Service; -import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -24,30 +24,32 @@ import java.util.Map; import java.util.stream.Collectors; -@Service(Service.Level.PROJECT) -public final class RunHistoryManagerService extends ObserverBase { +@Service(Service.Level.APP) +public final class RunHistoryManagerService { private static final Logger log = LoggerFactory.getLogger(RunHistoryManagerService.class); - private final Project project; + private final EventBusService eventBusService = EventBusService.getInstance(); private final Gson gson = new Gson(); private final File historyFile; private final Map history; - public RunHistoryManagerService(@NotNull Project project) { - this.project = project; - this.historyFile = new File(PathManager.getConfigPath(), "run-" + project.getName() + "-history.json"); + public static RunHistoryManagerService getInstance() { + return ApplicationManager.getApplication().getService(RunHistoryManagerService.class); + } + + + public RunHistoryManagerService() { + this.historyFile = new File(PathManager.getConfigPath(), "run-history.json"); this.history = loadRunHistory(); } - @Override - public void addObserver(BasicEventObserver observer) { - super.addObserver(observer); + public void addObserver(Object observer) { + eventBusService.register(observer); // when observer is added, pass current value of history to observer, force it to update - // pass current value of history to observer, List> List> mappedHistory = history.entrySet().stream() .map(entry -> new Pair<>(entry.getValue().getTargetClassPackageName(), entry.getValue().getTargetClassName())) .collect(Collectors.toList()); - observer.onEventHappen("RUN_HISTORY", mappedHistory); - observer.onEventHappen("RUN_HISTORY_LIST", getRunHistory()); + eventBusService.post(new RunHistoryEvent(RunHistoryEvent.RUN_HISTORY, mappedHistory)); + eventBusService.post(new RunHistoryEvent(RunHistoryEvent.RUN_HISTORY_LIST, getRunHistory())); } @Nullable @@ -70,8 +72,8 @@ public void clearRunHistory() { if (historyFile.exists()) { historyFile.delete(); } - notifyObservers("RUN_HISTORY", null); - notifyObservers("RUN_HISTORY_LIST", null); + eventBusService.post(new RunHistoryEvent(RunHistoryEvent.RUN_HISTORY, null)); + eventBusService.post(new RunHistoryEvent(RunHistoryEvent.RUN_HISTORY_LIST, null)); } @NotNull @@ -85,8 +87,8 @@ public void saveRunHistory(@NotNull PitestContext entry) { String json = gson.toJson(history); Files.write(historyFile.toPath(), json.getBytes()); // this should be a Pair> - notifyObservers("RUN_HISTORY", new Pair(entry.getTargetClassPackageName(), entry.getTargetClassName())); - notifyObservers("RUN_HISTORY_LIST", getRunHistory()); + eventBusService.post(new RunHistoryEvent(RunHistoryEvent.RUN_HISTORY, new Pair(entry.getTargetClassPackageName(), entry.getTargetClassName()))); + eventBusService.post(new RunHistoryEvent(RunHistoryEvent.RUN_HISTORY_LIST, getRunHistory())); } catch (IOException e) { // Handle the exception appropriately, e.g., log an error log.error("Error saving run history", e); diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/services/AnnotationConfigService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/AnnotationConfigService.java similarity index 96% rename from src/main/java/com/github/jaksonlin/testcraft/core/services/AnnotationConfigService.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/AnnotationConfigService.java index 9425c28..dc40bda 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/services/AnnotationConfigService.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/AnnotationConfigService.java @@ -1,8 +1,8 @@ -package com.github.jaksonlin.testcraft.core.services; +package com.github.jaksonlin.testcraft.infrastructure.services.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; -import com.github.jaksonlin.testcraft.core.annotations.AnnotationSchema; +import com.github.jaksonlin.testcraft.domain.annotations.AnnotationSchema; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.Service; import com.intellij.openapi.components.State; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/services/InvalidTestCaseConfigService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/InvalidTestCaseConfigService.java similarity index 98% rename from src/main/java/com/github/jaksonlin/testcraft/core/services/InvalidTestCaseConfigService.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/InvalidTestCaseConfigService.java index 1d4c9e0..b3a1bda 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/services/InvalidTestCaseConfigService.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/InvalidTestCaseConfigService.java @@ -1,4 +1,4 @@ -package com.github.jaksonlin.testcraft.core.services; +package com.github.jaksonlin.testcraft.infrastructure.services.config; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.Service; diff --git a/src/main/java/com/github/jaksonlin/testcraft/core/services/LLMService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/LLMConfigService.java similarity index 70% rename from src/main/java/com/github/jaksonlin/testcraft/core/services/LLMService.java rename to src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/LLMConfigService.java index 3250c14..7530e2f 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/core/services/LLMService.java +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/config/LLMConfigService.java @@ -1,9 +1,8 @@ -package com.github.jaksonlin.testcraft.core.services; +package com.github.jaksonlin.testcraft.infrastructure.services.config; -import com.github.jaksonlin.testcraft.messaging.mediators.ILLMChatMediator; -import com.github.jaksonlin.testcraft.messaging.mediators.LLMChatMediatorImpl; -import com.github.jaksonlin.testcraft.messaging.observers.BasicEventObserver; -import com.github.jaksonlin.testcraft.messaging.observers.ObserverBase; +import com.github.jaksonlin.testcraft.infrastructure.messaging.mediators.ILLMChatMediator; +import com.github.jaksonlin.testcraft.infrastructure.messaging.mediators.LLMChatMediatorImpl; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; import com.github.jaksonlin.testcraft.util.Mutation; import com.github.jaksonlin.testcraft.util.OllamaClient; import com.intellij.openapi.components.Service; @@ -13,25 +12,32 @@ import java.util.Objects; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import com.github.jaksonlin.testcraft.messaging.mediators.ILLMChatClient; + +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.BasicEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.ChatEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.LLMConfigEvent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; @Service(Service.Level.APP) @State( - name = "com.github.jaksonlin.testcraft.core.services.LLMService", + name = "com.github.jaksonlin.testcraft.infrastructure.services.LLMService", storages = @Storage(value = "$APP_CONFIG$/LLMService.xml") ) -public final class LLMService - extends ObserverBase - implements ILLMChatClient, BasicEventObserver, PersistentStateComponent { +public final class LLMConfigService + extends BasicEventObserver + implements PersistentStateComponent { - private static final Logger LOG = Logger.getInstance(LLMService.class); + private static final Logger LOG = Logger.getInstance(LLMConfigService.class); private final ILLMChatMediator llmChatMediator = new LLMChatMediatorImpl(); + public static LLMConfigService getInstance() { + return ApplicationManager.getApplication().getService(LLMConfigService.class); + } - public LLMService() { - llmChatMediator.register(this); + public LLMConfigService() { + EventBusService.getInstance().register(this); } public static class State { @@ -78,7 +84,7 @@ public State getState() { public void loadState(@NotNull State state) { LOG.info("Loading LLMService state: " + state); myState = state; - notifyObservers("CONFIG_CHANGE:copyAsMarkdown", state.copyAsMarkdown); + EventBusService.getInstance().post(new LLMConfigEvent(LLMConfigEvent.CONFIG_CHANGE_COPY_AS_MARKDOWN, state.copyAsMarkdown)); } public void generateUnittestRequest(String testCodeFile, String sourceCodeFile, List mutationList) { @@ -95,15 +101,7 @@ public void generateUnittestRequest(String testCodeFile, String sourceCodeFile, llmChatMediator.generateUnittestRequest(testCodeFile, sourceCodeFile, mutationList); } - // the mediator is dedicated to talk to the LLM, and when the response is ready, the service will propagate the response to the observers - // so that on the UI layer, this is the place to notify all the observers - // the mediator is not responsible for the UI, so it does not know the UI is a Swing UI - @Override - public void updateChatResponse(String responseType, String chatResponse) { - LOG.info("Received chat response: " + chatResponse); - notifyObservers("CHAT_RESPONSE:" + responseType, chatResponse); - } - + public void handleChatMessage(String message) { LOG.info("Received chat message: " + message); llmChatMediator.setOllamaClient(new OllamaClient( @@ -121,10 +119,14 @@ public String dryRunGetPrompt(String testClassName, String sourceClassName, List return llmChatMediator.dryRunGetPrompt(testClassName, sourceClassName, mutations); } + @Override public void onEventHappen(String eventName, Object eventObj) { // Handle events from LLMChatMediator if needed switch (eventName) { - case "CLEAR_CHAT": + case ChatEvent.CHAT_REQUEST: + handleChatMessage(eventObj.toString()); + break; + case ChatEvent.CLEAR_CHAT: this.llmChatMediator.clearChat(); break; default: @@ -137,6 +139,6 @@ public String getChatHistory() { } public void propagateConfigChange() { - notifyObservers("CONFIG_CHANGE:copyAsMarkdown", myState.copyAsMarkdown); + EventBusService.getInstance().post(new LLMConfigEvent(LLMConfigEvent.CONFIG_CHANGE_COPY_AS_MARKDOWN, myState.copyAsMarkdown)); } } \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/system/EventBusService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/system/EventBusService.java new file mode 100644 index 0000000..f68ffeb --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/system/EventBusService.java @@ -0,0 +1,51 @@ +package com.github.jaksonlin.testcraft.infrastructure.services.system; + +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.BaseEvent; +import com.google.common.eventbus.EventBus; +import com.intellij.openapi.components.Service; +import com.intellij.openapi.application.ApplicationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Service(Service.Level.APP) +public final class EventBusService { + private final EventBus eventBus; + private final Logger logger = LoggerFactory.getLogger(EventBusService.class); + + public EventBusService() { + this.eventBus = new EventBus("TestCraftEventBus"); + } + + public void register(Object subscriber) { + try { + eventBus.register(subscriber); + logger.debug("Registered subscriber: {}", subscriber.getClass().getSimpleName()); + } catch (Exception e) { + logger.error("Failed to register subscriber: " + subscriber, e); + } + } + + public void unregister(Object subscriber) { + try { + eventBus.unregister(subscriber); + logger.debug("Unregistered subscriber: {}", subscriber.getClass().getSimpleName()); + } catch (Exception e) { + logger.error("Failed to unregister subscriber: " + subscriber, e); + } + } + + public void post(Object event) { + try { + if (event instanceof BaseEvent) { + logger.debug("Posting event: {}", ((BaseEvent) event).getEventType()); + } + eventBus.post(event); + } catch (Exception e) { + logger.error("Failed to post event: " + event, e); + } + } + + public static EventBusService getInstance() { + return ApplicationManager.getApplication().getService(EventBusService.class); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/system/I18nService.java b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/system/I18nService.java new file mode 100644 index 0000000..6c9c303 --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/infrastructure/services/system/I18nService.java @@ -0,0 +1,28 @@ +package com.github.jaksonlin.testcraft.infrastructure.services.system; + +import java.util.ResourceBundle; + +import org.jetbrains.annotations.PropertyKey; + +import com.intellij.AbstractBundle; +import com.intellij.openapi.components.Service; +import com.intellij.openapi.application.ApplicationManager; + +@Service(Service.Level.APP) +public final class I18nService { + private final String BUNDLE = "messages.MyBundle"; + private ResourceBundle ourBundle; + public String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { + return AbstractBundle.message(getBundle(), key, params); + } + private ResourceBundle getBundle() { + if (ourBundle == null) { + ourBundle = ResourceBundle.getBundle(BUNDLE); + } + return ourBundle; + } + + public static I18nService getInstance() { + return ApplicationManager.getApplication().getService(I18nService.class); + } +} diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/observers/BasicEventObserver.java b/src/main/java/com/github/jaksonlin/testcraft/messaging/observers/BasicEventObserver.java deleted file mode 100644 index 619c9da..0000000 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/observers/BasicEventObserver.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.jaksonlin.testcraft.messaging.observers; - -public interface BasicEventObserver { - void onEventHappen(String eventName, Object eventObj); -} diff --git a/src/main/java/com/github/jaksonlin/testcraft/messaging/observers/ObserverBase.java b/src/main/java/com/github/jaksonlin/testcraft/messaging/observers/ObserverBase.java deleted file mode 100644 index eb243a1..0000000 --- a/src/main/java/com/github/jaksonlin/testcraft/messaging/observers/ObserverBase.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.jaksonlin.testcraft.messaging.observers; - -import java.util.ArrayList; -import java.util.List; - -public class ObserverBase { - private final List observers = new ArrayList<>(); - - public void addObserver(BasicEventObserver observer) { - observers.add(observer); - } - - public void removeObserver(BasicEventObserver observer) { - observers.remove(observer); - } - - protected void notifyObservers(String eventName, Object eventObj) { - for (BasicEventObserver observer : observers) { - observer.onEventHappen(eventName, eventObj); - } - } -} diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunPitestAction.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunPitestAction.java deleted file mode 100644 index 1c3752b..0000000 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/actions/RunPitestAction.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.github.jaksonlin.testcraft.presentation.actions; - -import com.github.jaksonlin.testcraft.core.services.PitestService; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; - -public class RunPitestAction extends AnAction { - - private final PitestService pitestService; - - public RunPitestAction() { - pitestService = ApplicationManager.getApplication().getService(PitestService.class); - } - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - Project targetProject = e.getProject(); - if (targetProject == null) { - return; - } - - VirtualFile testVirtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); - if (testVirtualFile == null) { - return; - } - - pitestService.runPitest(targetProject, testVirtualFile.getPath()); - } -} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ChatPanel.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ChatPanel.java deleted file mode 100644 index faa5e40..0000000 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ChatPanel.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.github.jaksonlin.testcraft.presentation.components; - -import com.intellij.ui.components.JBScrollPane; -import com.intellij.util.ui.JBUI; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.KeyAdapter; -import java.util.ArrayList; -import java.util.List; - -public class ChatPanel extends JPanel { - private final JTextArea inputArea; - private final JButton sendButton; - private final List listeners = new ArrayList<>(); - private final JPanel inputPanel; - - public interface ChatMessageListener { - void onNewMessage(String message); - } - - public ChatPanel() { - setLayout(new BorderLayout()); - - // Input area - inputArea = new JTextArea(3, 40); - inputArea.setLineWrap(true); - inputArea.setWrapStyleWord(true); - JBScrollPane inputScrollPane = new JBScrollPane(inputArea); - - // Send button - sendButton = new JButton("Send"); - sendButton.addActionListener(e -> sendMessage()); - - // Input panel (input area + send button) - inputPanel = new JPanel(new BorderLayout()); - inputPanel.setBorder(JBUI.Borders.empty(5)); - inputPanel.add(inputScrollPane, BorderLayout.CENTER); - inputPanel.add(sendButton, BorderLayout.EAST); - - // Add key listener for Ctrl+Enter to send - inputArea.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER && e.isControlDown()) { - sendMessage(); - e.consume(); - } - } - }); - } - - public void addListener(ChatMessageListener listener) { - listeners.add(listener); - } - - public JPanel getInputPanel() { - return inputPanel; - } - - private void sendMessage() { - String message = inputArea.getText().trim(); - if (!message.isEmpty()) { - listeners.forEach(listener -> listener.onNewMessage(message)); - inputArea.setText(""); - inputArea.requestFocus(); - } - } - - public void clear() { - inputArea.setText(""); - } - - public void setInputEnabled(boolean enabled) { - inputArea.setEnabled(enabled); - sendButton.setEnabled(enabled); - if (enabled) { - inputArea.requestFocus(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ChatPanelComponent.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ChatPanelComponent.java new file mode 100644 index 0000000..82fe51d --- /dev/null +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ChatPanelComponent.java @@ -0,0 +1,102 @@ +package com.github.jaksonlin.testcraft.presentation.components; + +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.ChatEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.TypedEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; +import com.intellij.ui.components.JBScrollPane; +import com.intellij.util.ui.JBUI; + +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import java.awt.BorderLayout; +import java.awt.event.KeyEvent; +import java.awt.event.KeyAdapter; + +public class ChatPanelComponent { + + private final TypedEventObserver chatObserver = new TypedEventObserver(ChatEvent.class) { + @Override + protected void onTypedEvent(ChatEvent event) { + // Handle the chat event + switch (event.getEventType()) { + case ChatEvent.START_LOADING: + // disable input area and send button + setInputEnabled(false); + break; + case ChatEvent.STOP_LOADING: + case ChatEvent.CHAT_RESPONSE: + case ChatEvent.ERROR: + // enable input area and send button + setInputEnabled(true); + break; + } + } + }; + private final JTextArea inputArea; + private final JButton sendButton; + private final JPanel masterPanel; + + public ChatPanelComponent() { + + // Input area + inputArea = new JTextArea(3, 40); + inputArea.setLineWrap(true); + inputArea.setWrapStyleWord(true); + JBScrollPane inputScrollPane = new JBScrollPane(inputArea); + + // Send button + sendButton = new JButton(I18nService.getInstance().message("chat.send.button")); + sendButton.addActionListener(e -> sendMessage()); + + // Input panel (input area + send button) + masterPanel = new JPanel(new BorderLayout()); + masterPanel.setBorder(JBUI.Borders.empty(5)); + masterPanel.add(inputScrollPane, BorderLayout.CENTER); + masterPanel.add(sendButton, BorderLayout.EAST); + + // Add key listener for Ctrl+Enter to send + inputArea.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER && e.isControlDown()) { + sendMessage(); + e.consume(); + } + } + }); + + + } + + + public JPanel getInputPanel() { + return masterPanel; + } + + private void sendMessage() { + String message = inputArea.getText().trim(); + if (!message.isEmpty()) { + EventBusService.getInstance().post(new ChatEvent(ChatEvent.CHAT_REQUEST, message)); + inputArea.setText(""); + inputArea.requestFocus(); + } + } + + public void clear() { + inputArea.setText(""); + } + + public void setInputEnabled(boolean enabled) { + inputArea.setEnabled(enabled); + sendButton.setEnabled(enabled); + if (enabled) { + inputArea.requestFocus(); + } + } + + public void dispose() { + chatObserver.unregister(); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMResponsePanel.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMResponseComponent.java similarity index 66% rename from src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMResponsePanel.java rename to src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMResponseComponent.java index 457732c..176764a 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMResponsePanel.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMResponseComponent.java @@ -1,6 +1,10 @@ package com.github.jaksonlin.testcraft.presentation.components; -import com.github.jaksonlin.testcraft.messaging.observers.BasicEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.ChatEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.LLMConfigEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.TypedEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.ui.JBUI; import org.commonmark.node.Node; @@ -9,45 +13,82 @@ import com.intellij.ui.JBColor; import java.awt.datatransfer.StringSelection; import java.awt.Toolkit; -import com.intellij.AbstractBundle; -import org.jetbrains.annotations.PropertyKey; import javax.swing.*; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; import java.awt.*; -import java.util.ArrayList; import java.util.Timer; import java.util.TimerTask; -import java.util.List; -import java.util.ResourceBundle; import javax.swing.text.html.HTMLDocument; -public class LLMResponsePanel extends JPanel implements BasicEventObserver { - private static final String BUNDLE = "messages.MyBundle"; - private static ResourceBundle ourBundle; - - public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { - return AbstractBundle.message(getBundle(), key, params); - } - - private static ResourceBundle getBundle() { - if (ourBundle == null) { - ourBundle = ResourceBundle.getBundle(BUNDLE); +public class LLMResponseComponent { + private final TypedEventObserver eventObserver = new TypedEventObserver(ChatEvent.class) { + @Override + public void onTypedEvent(ChatEvent event) { + switch (event.getEventType()) { + case ChatEvent.START_LOADING: + startLoading(); + break; + case ChatEvent.STOP_LOADING: + stopLoading(); + break; + case ChatEvent.CHAT_REQUEST: + if (!isLoading) { + appendMarkdownToOutput(String.format(MESSAGE_TEMPLATE, "user", I18nService.getInstance().message("llm.user"), event.getPayload().toString())); + startLoading(); + } + break; + case ChatEvent.CHAT_RESPONSE: + stopLoading(); + appendMarkdownToOutput(String.format(MESSAGE_TEMPLATE, "assistant", I18nService.getInstance().message("llm.assistant"), event.getPayload().toString())); + break; + case ChatEvent.COPY_CHAT_RESPONSE: + copyToClipboard(event.getPayload()); + break; + case ChatEvent.DRY_RUN_PROMPT: + String dryRunPrompt = (String) event.getPayload(); + if (dryRunPrompt.isEmpty()){ + JOptionPane.showMessageDialog(masterPanel, I18nService.getInstance().message("llm.dry.run.prompt.empty"), I18nService.getInstance().message("llm.dry.run.prompt"), JOptionPane.INFORMATION_MESSAGE); + } else { + appendMarkdownToOutput(String.format(MESSAGE_TEMPLATE, "system", I18nService.getInstance().message("llm.system"), I18nService.getInstance().message("llm.dry.run.prompt") + "\n" + event.getPayload().toString())); + } + break; + case ChatEvent.ERROR: + JOptionPane.showMessageDialog(masterPanel, I18nService.getInstance().message("llm.error") + ": " + event.getPayload().toString(), I18nService.getInstance().message("llm.error"), JOptionPane.ERROR_MESSAGE); + break; + } } - return ourBundle; - } + }; + private final TypedEventObserver llmConfigObserver = new TypedEventObserver(LLMConfigEvent.class) { + @Override + public void onTypedEvent(LLMConfigEvent event) { + switch (event.getEventType()) { + case LLMConfigEvent.CONFIG_CHANGE_COPY_AS_MARKDOWN: + copyAsMarkdown = (boolean) event.getPayload(); + break; + } + } + }; private final JEditorPane outputArea; - private final ChatPanel chatPanel; private boolean isLoading = false; private boolean copyAsMarkdown = false; - private final StringBuilder chatHistory = new StringBuilder(); + private final HTMLEditorKit htmlKit; private final StyleSheet styleSheet; + private final JPanel masterPanel; private final JPanel loadingPanel; private final Timer loadingTimer; private final JLabel loadingLabel; + + + private final StringBuilder chatHistory = new StringBuilder(); + + public JPanel getMasterPanel() { + return masterPanel; + } + private static final String BASE_HTML_TEMPLATE = "\n" + @@ -71,37 +112,19 @@ private static ResourceBundle getBundle() { "\n" + "
"; - public interface ResponseActionListener { - void onClearButtonClick(); - void onCopyButtonClick(); - } - - private List responseActionListeners = new ArrayList<>(); - - public void addResponseActionListener(ResponseActionListener listener) { - responseActionListeners.add(listener); - } - - public void removeResponseActionListener(ResponseActionListener listener) { - responseActionListeners.remove(listener); - } - + public void notifyClearButtonClick() { - for (ResponseActionListener listener : responseActionListeners) { - listener.onClearButtonClick(); - } + EventBusService.getInstance().post(new ChatEvent(ChatEvent.CLEAR_CHAT, null)); } public void notifyCopyButtonClick() { - for (ResponseActionListener listener : responseActionListeners) { - listener.onCopyButtonClick(); - } + EventBusService.getInstance().post(new ChatEvent(ChatEvent.REQUEST_COPY_CHAT_RESPONSE, null)); } - public LLMResponsePanel(ChatPanel chatPanel) { - this.chatPanel = chatPanel; - setLayout(new BorderLayout()); - setBorder(JBUI.Borders.empty(10)); + public LLMResponseComponent(ChatPanelComponent chatPanelComponent) { + masterPanel = new JPanel(new BorderLayout()); + masterPanel.setBorder(JBUI.Borders.empty(10)); + // Setup improved JEditorPane for HTML rendering outputArea = new JEditorPane(); @@ -125,7 +148,7 @@ public LLMResponsePanel(ChatPanel chatPanel) { // Create loading panel loadingPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); loadingPanel.setVisible(false); - loadingLabel = new JLabel(message("llm.thinking")); + loadingLabel = new JLabel(I18nService.getInstance().message("llm.thinking")); loadingPanel.add(loadingLabel); loadingPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); loadingPanel.setBackground(JBColor.background()); @@ -140,13 +163,13 @@ public LLMResponsePanel(ChatPanel chatPanel) { toolbar.setFloatable(false); toolbar.setBorder(JBUI.Borders.empty(2, 2)); - JButton copyButton = new JButton(message("llm.copy.to.clipboard")); + JButton copyButton = new JButton(I18nService.getInstance().message("llm.copy.to.clipboard")); copyButton.addActionListener(e -> { notifyCopyButtonClick(); }); toolbar.add(copyButton); - JButton clearButton = new JButton(message("llm.clear")); + JButton clearButton = new JButton(I18nService.getInstance().message("llm.clear")); clearButton.addActionListener(e -> { clearOutput(); notifyClearButtonClick(); @@ -155,7 +178,7 @@ public LLMResponsePanel(ChatPanel chatPanel) { // Create input panel at the bottom JPanel inputPanel = new JPanel(new BorderLayout()); - inputPanel.add(chatPanel.getInputPanel(), BorderLayout.CENTER); + inputPanel.add(chatPanelComponent.getInputPanel(), BorderLayout.CENTER); // Create center panel to hold toolbar, output area, and loading panel JPanel centerPanel = new JPanel(new BorderLayout()); @@ -164,13 +187,9 @@ public LLMResponsePanel(ChatPanel chatPanel) { centerPanel.add(loadingPanel, BorderLayout.SOUTH); // Add components - add(centerPanel, BorderLayout.CENTER); - add(inputPanel, BorderLayout.SOUTH); + masterPanel.add(centerPanel, BorderLayout.CENTER); + masterPanel.add(inputPanel, BorderLayout.SOUTH); - // add the chatPanel to the responsePanel, and notify update on the responsePanel with user message - this.chatPanel.addListener(message -> { - onEventHappen("CHAT_REQUEST", message); - }); // Initialize with empty chat container updateOutputArea(); @@ -256,13 +275,11 @@ public void run() { } SwingUtilities.invokeLater(() -> { dots = (dots + 1) % 4; - loadingLabel.setText(message("llm.thinking") + repeatString(".", dots)); + loadingLabel.setText(I18nService.getInstance().message("llm.thinking") + repeatString(".", dots)); }); } }, 0, 500); - // Disable input while loading - chatPanel.setInputEnabled(false); } private void stopLoading() { @@ -272,9 +289,6 @@ private void stopLoading() { isLoading = false; loadingPanel.setVisible(false); loadingTimer.purge(); - - // Re-enable input after loading - chatPanel.setInputEnabled(true); } private void updateOutputArea() { @@ -324,53 +338,4 @@ private void copyToClipboard(Object eventObj) { StringSelection selection = new StringSelection(currentContentToCopy); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); } - - @Override - public void onEventHappen(String eventName, Object eventObj) { - switch (eventName) { - case "START_LOADING": - startLoading(); - break; - case "STOP_LOADING": - stopLoading(); - break; - case "COPY_CHAT_RESPONSE": - copyToClipboard(eventObj); - break; - case "CONFIG_CHANGE:copyAsMarkdown": - copyAsMarkdown = (boolean) eventObj; - break; - case "CHAT_REQUEST": - if (!isLoading) { - appendMarkdownToOutput(String.format(MESSAGE_TEMPLATE, "user", message("llm.user"), eventObj.toString())); - startLoading(); - } - break; - case "DRY_RUN_PROMPT": - String dryRunPrompt = (String) eventObj; - if (dryRunPrompt.isEmpty()){ - JOptionPane.showMessageDialog(this, message("llm.dry.run.prompt.empty"), message("llm.dry.run.prompt"), JOptionPane.INFORMATION_MESSAGE); - } else { - appendMarkdownToOutput(String.format(MESSAGE_TEMPLATE, "system", message("llm.system"), message("llm.dry.run.prompt") + "\n" + eventObj.toString())); - } - break; - default: - String[] responseType = eventName.split(":"); - if (responseType.length > 1 && responseType[0].equals("CHAT_RESPONSE")) { - switch (responseType[1]) { - case "CHAT_MESSAGE": - appendMarkdownToOutput(String.format(MESSAGE_TEMPLATE, "assistant", message("llm.assistant"), eventObj.toString())); - break; - case "ERROR": - JOptionPane.showMessageDialog(this, message("llm.error") + ": " + eventObj.toString(), message("llm.error"), JOptionPane.ERROR_MESSAGE); - break; - case "UNIT_TEST_REQUEST": - clearOutput(); - appendMarkdownToOutput(String.format(MESSAGE_TEMPLATE, "system", message("llm.system"), message("llm.new.unit.test.suggestion") + "\n" + eventObj.toString())); - break; - } - } - break; - } - } } diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMSuggestionUIComponent.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMSuggestionUIComponent.java index ea99077..3bf3a0b 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMSuggestionUIComponent.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/LLMSuggestionUIComponent.java @@ -1,97 +1,82 @@ package com.github.jaksonlin.testcraft.presentation.components; -import com.github.jaksonlin.testcraft.core.context.PitestContext; -import com.github.jaksonlin.testcraft.messaging.observers.BasicEventObserver; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.RunHistoryEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.ChatEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.TypedEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.github.jaksonlin.testcraft.presentation.viewmodels.LLMSuggestionUIComponentViewModel; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.ui.ComboBox; import com.intellij.util.ui.JBUI; -import com.intellij.AbstractBundle; -import org.jetbrains.annotations.PropertyKey; -import javax.swing.*; +import javax.swing.JPanel; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JComboBox; import javax.swing.plaf.basic.BasicComboBoxEditor; -import java.awt.*; +import javax.swing.DefaultComboBoxModel; +import javax.swing.ComboBoxEditor; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; + import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.ResourceBundle; -import com.github.jaksonlin.testcraft.core.services.LLMService; -public class LLMSuggestionUIComponent implements BasicEventObserver { - private static final String BUNDLE = "messages.MyBundle"; - private static ResourceBundle ourBundle; - - public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { - return AbstractBundle.message(getBundle(), key, params); - } - - private static ResourceBundle getBundle() { - if (ourBundle == null) { - ourBundle = ResourceBundle.getBundle(BUNDLE); +public class LLMSuggestionUIComponent { + + private final TypedEventObserver chatEventObserver = new TypedEventObserver(ChatEvent.class) { + @Override + public void onTypedEvent(ChatEvent event) { + switch (event.getEventType()) { + case ChatEvent.START_LOADING: + generateButton.setEnabled(false); + dryRunButton.setEnabled(false); + break; + case ChatEvent.STOP_LOADING: + case ChatEvent.CHAT_RESPONSE: + case ChatEvent.ERROR: + generateButton.setEnabled(true); + dryRunButton.setEnabled(true); + break; + } } - return ourBundle; - } + }; + private final TypedEventObserver runHistoryEventObserver = new TypedEventObserver(RunHistoryEvent.class) { + @Override + public void onTypedEvent(RunHistoryEvent event) { + switch (event.getEventType()) { + case RunHistoryEvent.RUN_HISTORY_LIST: + ApplicationManager.getApplication().invokeLater(() -> loadFileHistory(event.getPayload())); + break; + } + } + };; + - private final LLMSuggestionUIComponentViewModel viewModel; - private final ChatPanel chatPanel = new ChatPanel(); - private final LLMResponsePanel responsePanel = new LLMResponsePanel(chatPanel); + private final ChatPanelComponent chatPanel = new ChatPanelComponent(); + private final LLMResponseComponent responsePanel = new LLMResponseComponent(chatPanel); + + private final LLMSuggestionUIComponentViewModel viewModel = new LLMSuggestionUIComponentViewModel(); + private final JPanel mainPanel = new JPanel(new BorderLayout()); private final DefaultComboBoxModel fileListModel = new DefaultComboBoxModel<>(); private final JComboBox fileSelector = new ComboBox<>(fileListModel); - private final JButton generateButton = new JButton(message("llm.generate.suggestions")); - private final JButton dryRunButton = new JButton(message("llm.check.prompt")); + private final JButton generateButton = new JButton(I18nService.getInstance().message("llm.generate.suggestions")); + private final JButton dryRunButton = new JButton(I18nService.getInstance().message("llm.check.prompt")); private List allFileItems = new ArrayList<>(); - public LLMSuggestionUIComponent(LLMService llmService) { + public LLMSuggestionUIComponent() { setupUI(); - // setup message routing - viewModel = new LLMSuggestionUIComponentViewModel(llmService); - viewModel.addObserver(this); - viewModel.addObserver(responsePanel); - - // add the chatPanel to the mainPanel - chatPanel.addListener(message -> { - viewModel.handleChatMessage(message); - }); - - // add the reponse listener to the responsePanel - responsePanel.addResponseActionListener(new LLMResponsePanel.ResponseActionListener() { - @Override - public void onClearButtonClick() { - viewModel.clearChat(); - } - - @Override - public void onCopyButtonClick() { - viewModel.copyChat(); - } - }); - + // propagate the config change viewModel.propagateConfigChange(); - } - - @Override - public void onEventHappen(String eventName, Object eventObj) { - switch (eventName) { - case "START_LOADING": - generateButton.setEnabled(false); - dryRunButton.setEnabled(false); - break; - case "STOP_LOADING": - generateButton.setEnabled(true); - dryRunButton.setEnabled(true); - break; - case "RUN_HISTORY_LIST": - ApplicationManager.getApplication().invokeLater(() -> loadFileHistory(eventObj)); - break; - default: - break; - } - } public JPanel getPanel() { return this.mainPanel; @@ -145,14 +130,14 @@ public Component getEditorComponent() { // Add components to top panel JPanel selectorPanel = new JPanel(new BorderLayout()); - selectorPanel.add(new JLabel(message("llm.select.file") + ": "), BorderLayout.WEST); + selectorPanel.add(new JLabel(I18nService.getInstance().message("llm.select.file") + ": "), BorderLayout.WEST); selectorPanel.add(fileSelector, BorderLayout.CENTER); topPanel.add(selectorPanel, BorderLayout.CENTER); topPanel.add(buttonPanel, BorderLayout.EAST); // Add panels to main panel mainPanel.add(topPanel, BorderLayout.NORTH); - mainPanel.add(responsePanel, BorderLayout.CENTER); + mainPanel.add(responsePanel.getMasterPanel(), BorderLayout.CENTER); } diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/MutationToolWindowUIComponent.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/MutationToolWindowUIComponent.java index b6a7364..86eba29 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/MutationToolWindowUIComponent.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/MutationToolWindowUIComponent.java @@ -1,6 +1,6 @@ package com.github.jaksonlin.testcraft.presentation.components; -import com.github.jaksonlin.testcraft.util.MyBundle; + import com.github.jaksonlin.testcraft.presentation.viewmodels.MutationToolWindowViewModel; import com.intellij.openapi.project.Project; @@ -13,8 +13,10 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; + public class MutationToolWindowUIComponent { - private final JButton clearButton = new JButton(MyBundle.message("clear.button")); + private final JButton clearButton = new JButton(I18nService.getInstance().message("clear.button")); private final JTextField searchInput = new JTextField(20); protected final ObservableTree resultTree = new ObservableTree(); private final MutationToolWindowViewModel vm; @@ -24,7 +26,7 @@ public MutationToolWindowUIComponent(Project project) { this.vm = new MutationToolWindowViewModel(project, resultTree); this.toolWindowPanel = createToolWindowPanel(); registerListeners(); - searchInput.setToolTipText(MyBundle.message("search.placeholder")); + searchInput.setToolTipText(I18nService.getInstance().message("search.placeholder")); } private void registerListeners() { diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ObservableTree.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ObservableTree.java index b00182b..c296bde 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ObservableTree.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/ObservableTree.java @@ -1,7 +1,9 @@ package com.github.jaksonlin.testcraft.presentation.components; -import com.github.jaksonlin.testcraft.util.MyBundle; -import com.github.jaksonlin.testcraft.messaging.observers.BasicEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.RunHistoryEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.TypedEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.github.jaksonlin.testcraft.util.Pair; import org.jetbrains.annotations.NotNull; @@ -13,30 +15,34 @@ import java.util.List; import java.util.Objects; -public class ObservableTree extends JTree implements BasicEventObserver { +public class ObservableTree extends JTree { - @Override - public void onEventHappen(String eventName,Object eventObj) { - if (!eventName.equals("RUN_HISTORY")) { - return; - } - if (eventObj == null) { - initializeMutationTree(Collections.emptyList()); - } else if (eventObj instanceof Pair) { - Pair pair = (Pair) eventObj; - if (pair.getFirst() instanceof String && pair.getSecond() instanceof String) { - updateMutationTree(new Pair<>((String) pair.getFirst(), (String) pair.getSecond())); + private final TypedEventObserver eventObserver = new TypedEventObserver(RunHistoryEvent.class) { + @Override + public void onTypedEvent(RunHistoryEvent event) { + if (!event.getEventType().equals(RunHistoryEvent.RUN_HISTORY)) { + return; } - } else if (eventObj instanceof List) { - List list = (List) eventObj; - if (list.isEmpty()) { + if (event.getPayload() == null) { initializeMutationTree(Collections.emptyList()); - } else if (list.get(0) instanceof Pair) { - List> nodeList = (List>) list; - initializeMutationTree(nodeList); + } else if (event.getPayload() instanceof Pair) { + Pair pair = (Pair) event.getPayload(); + if (pair.getFirst() instanceof String && pair.getSecond() instanceof String) { + updateMutationTree(new Pair<>((String) pair.getFirst(), (String) pair.getSecond())); + } + } else if (event.getPayload() instanceof List) { + List list = (List) event.getPayload(); + if (list.isEmpty()) { + initializeMutationTree(Collections.emptyList()); + } else if (list.get(0) instanceof Pair) { + List> nodeList = (List>) list; + initializeMutationTree(nodeList); + } } } - } + }; + + private void initializeMutationTree(@NotNull List> nodeNameList) { DefaultTreeModel treeModel = buildTreeModel(nodeNameList); @@ -44,7 +50,7 @@ private void initializeMutationTree(@NotNull List> nodeName } private DefaultTreeModel buildTreeModel(@NotNull List> nodeNameList) { - DefaultMutableTreeNode root = new DefaultMutableTreeNode(MyBundle.message("mutation.tree.root")); + DefaultMutableTreeNode root = new DefaultMutableTreeNode(I18nService.getInstance().message("mutation.tree.root")); for (Pair pair : nodeNameList) { String packageName = pair.getFirst(); diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/PitestOutputDialog.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/PitestOutputDialog.java index eab3b29..0630102 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/components/PitestOutputDialog.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/components/PitestOutputDialog.java @@ -1,5 +1,6 @@ package com.github.jaksonlin.testcraft.presentation.components; +import com.github.jaksonlin.testcraft.infrastructure.services.system.I18nService; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -38,7 +39,7 @@ protected JComponent createCenterPanel() { panel.add(scrollPane, BorderLayout.CENTER); if (reportFile != null) { - JButton viewReportButton = new JButton("HTML Report"); + JButton viewReportButton = new JButton(I18nService.getInstance().message("pitest.view.report")); viewReportButton.addActionListener(e -> { try { Desktop.getDesktop().browse(reportFile.toURI()); diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/toolWindow/LLMSuggestionsToolWindowFactory.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/toolWindow/LLMSuggestionsToolWindowFactory.java index 94617eb..429b800 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/toolWindow/LLMSuggestionsToolWindowFactory.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/toolWindow/LLMSuggestionsToolWindowFactory.java @@ -1,8 +1,8 @@ package com.github.jaksonlin.testcraft.presentation.toolWindow; import com.github.jaksonlin.testcraft.presentation.components.LLMSuggestionUIComponent; -import com.github.jaksonlin.testcraft.core.services.LLMService; -import com.github.jaksonlin.testcraft.core.services.RunHistoryManagerService; +import com.github.jaksonlin.testcraft.infrastructure.services.config.LLMConfigService; +import com.github.jaksonlin.testcraft.infrastructure.services.business.RunHistoryManagerService; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; @@ -18,16 +18,14 @@ public class LLMSuggestionsToolWindowFactory implements ToolWindowFactory { @Override public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { // create a new LLMSuggestionUIComponent - LLMService llmService = ApplicationManager.getApplication().getService(LLMService.class); - LLMSuggestionUIComponent uiComponent = new LLMSuggestionUIComponent(llmService); + LLMSuggestionUIComponent uiComponent = new LLMSuggestionUIComponent(); // add the uiComponent to the toolWindow through the content manager JPanel toolWindowPanel = uiComponent.getPanel(); ContentManager contentManager = toolWindow.getContentManager(); Content content = new ContentImpl(toolWindowPanel, "TestCraft - LLM Suggestions Tool Window", false); // Directly create ContentImpl contentManager.addContent(content); // register the uiComponent to the runHistoryManagerService to sync the run history - RunHistoryManagerService runHistoryManagerService = project.getService(RunHistoryManagerService.class); - runHistoryManagerService.addObserver(uiComponent); + RunHistoryManagerService.getInstance().addObserver(uiComponent); } } \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/LLMSuggestionUIComponentViewModel.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/LLMSuggestionUIComponentViewModel.java index dbad525..52e95e5 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/LLMSuggestionUIComponentViewModel.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/LLMSuggestionUIComponentViewModel.java @@ -1,68 +1,52 @@ package com.github.jaksonlin.testcraft.presentation.viewmodels; -import com.github.jaksonlin.testcraft.core.context.PitestContext; -import com.github.jaksonlin.testcraft.messaging.observers.BasicEventObserver; -import com.github.jaksonlin.testcraft.messaging.observers.ObserverBase; -import com.github.jaksonlin.testcraft.core.services.LLMService; - -public class LLMSuggestionUIComponentViewModel extends ObserverBase implements BasicEventObserver { - - private final LLMService llmService; - - - public LLMSuggestionUIComponentViewModel(LLMService llmService) { - this.llmService = llmService; - llmService.addObserver(this); // as hub to forward events - this.addObserver(llmService); - } - - public void propagateConfigChange() { - llmService.propagateConfigChange(); - } - - public void clearChat() { - notifyObservers("CLEAR_CHAT", null); - } - - public void copyChat() { - String chatHistory = llmService.getChatHistory(); - // when chatHistory is empty, use the lastDryRunPrompt - if (chatHistory.isEmpty()) { - chatHistory = lastDryRunPrompt; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.ChatEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.TypedEventObserver; +import com.github.jaksonlin.testcraft.infrastructure.services.config.LLMConfigService; +import com.github.jaksonlin.testcraft.infrastructure.services.system.EventBusService; + + +public class LLMSuggestionUIComponentViewModel { + private final LLMConfigService llmConfigService = LLMConfigService.getInstance(); + private final EventBusService eventBusService = EventBusService.getInstance(); + + private final TypedEventObserver chatObserver = new TypedEventObserver(ChatEvent.class) { + @Override + public void onTypedEvent(ChatEvent event) { + switch (event.getEventType()) { + case ChatEvent.REQUEST_COPY_CHAT_RESPONSE: + String chatHistory = llmConfigService.getChatHistory(); + // when chatHistory is empty, use the lastDryRunPrompt + if (chatHistory.isEmpty()) { + chatHistory = lastDryRunPrompt; + } + eventBusService.post(new ChatEvent(ChatEvent.COPY_CHAT_RESPONSE, chatHistory)); + break; + default: + break; + } } - notifyObservers("COPY_CHAT_RESPONSE", chatHistory); - } - + }; - - @Override - public void onEventHappen(String eventName, Object eventObj) { - // Handle events from LLMService/UIComponent if needed - switch (eventName) { - default: - // if have chat response, stop loading - if (eventName.contains("CHAT_RESPONSE:")) { - notifyObservers("STOP_LOADING", null); - } - notifyObservers(eventName, eventObj); - break; - } + public void propagateConfigChange() { + llmConfigService.propagateConfigChange(); } public void generateSuggestions(PitestContext context) { - notifyObservers("START_LOADING", null); - llmService.generateUnittestRequest(context.getTestFilePath(), context.getTargetClassFilePath(), context.getMutationResults()); + eventBusService.post(new ChatEvent(ChatEvent.START_LOADING, null)); + llmConfigService.generateUnittestRequest(context.getTestFilePath(), context.getTargetClassFilePath(), context.getMutationResults()); } private String lastDryRunPrompt = ""; public void dryRunGetPrompt(PitestContext context) { - lastDryRunPrompt = llmService.dryRunGetPrompt(context.getFullyQualifiedTargetTestClassName(), context.getTargetClassFullyQualifiedName(), context.getMutationResults()); - notifyObservers("DRY_RUN_PROMPT", lastDryRunPrompt); + lastDryRunPrompt = llmConfigService.dryRunGetPrompt(context.getFullyQualifiedTargetTestClassName(), context.getTargetClassFullyQualifiedName(), context.getMutationResults()); + eventBusService.post(new ChatEvent(ChatEvent.DRY_RUN_PROMPT, lastDryRunPrompt)); } public void handleChatMessage(String message) { - llmService.handleChatMessage(message); + llmConfigService.handleChatMessage(message); } } diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationToolWindowViewModel.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationToolWindowViewModel.java index 38164ab..58eaba4 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationToolWindowViewModel.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationToolWindowViewModel.java @@ -1,8 +1,8 @@ package com.github.jaksonlin.testcraft.presentation.viewmodels; -import com.github.jaksonlin.testcraft.messaging.mediators.IMutationMediator; -import com.github.jaksonlin.testcraft.messaging.mediators.MutationMediatorImpl; -import com.github.jaksonlin.testcraft.core.services.RunHistoryManagerService; +import com.github.jaksonlin.testcraft.infrastructure.messaging.mediators.IMutationMediator; +import com.github.jaksonlin.testcraft.infrastructure.messaging.mediators.MutationMediatorImpl; +import com.github.jaksonlin.testcraft.infrastructure.services.business.RunHistoryManagerService; import com.github.jaksonlin.testcraft.presentation.components.ObservableTree; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.Nullable; @@ -12,12 +12,11 @@ import java.util.Enumeration; public class MutationToolWindowViewModel { - private final RunHistoryManagerService runHistoryManager; + private final RunHistoryManagerService runHistoryManager = RunHistoryManagerService.getInstance(); private final IMutationMediator mutationReportMediator = new MutationMediatorImpl(); private final MutationTreeMediatorViewModel mutationTreeMediatorVM; public MutationToolWindowViewModel(Project project, ObservableTree mutationTree) { - this.runHistoryManager = project.getService(RunHistoryManagerService.class); this.mutationTreeMediatorVM = new MutationTreeMediatorViewModel(project, mutationReportMediator); runHistoryManager.addObserver(mutationTree); } diff --git a/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationTreeMediatorViewModel.java b/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationTreeMediatorViewModel.java index bc48922..88e878a 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationTreeMediatorViewModel.java +++ b/src/main/java/com/github/jaksonlin/testcraft/presentation/viewmodels/MutationTreeMediatorViewModel.java @@ -1,9 +1,9 @@ package com.github.jaksonlin.testcraft.presentation.viewmodels; -import com.github.jaksonlin.testcraft.core.context.PitestContext; -import com.github.jaksonlin.testcraft.messaging.mediators.IMutationMediator; -import com.github.jaksonlin.testcraft.messaging.mediators.IMutationReportUI; -import com.github.jaksonlin.testcraft.core.services.RunHistoryManagerService; +import com.github.jaksonlin.testcraft.domain.context.PitestContext; +import com.github.jaksonlin.testcraft.infrastructure.messaging.mediators.IMutationMediator; +import com.github.jaksonlin.testcraft.infrastructure.messaging.mediators.IMutationReportUI; +import com.github.jaksonlin.testcraft.infrastructure.services.business.RunHistoryManagerService; import com.github.jaksonlin.testcraft.util.Mutation; import com.github.jaksonlin.testcraft.util.Pair; import com.intellij.icons.AllIcons; @@ -33,18 +33,28 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.MutationEvent; +import com.github.jaksonlin.testcraft.infrastructure.messaging.events.TypedEventObserver; public class MutationTreeMediatorViewModel implements IMutationReportUI { private static final Logger log = LoggerFactory.getLogger(MutationTreeMediatorViewModel.class); private final Project project; private final IMutationMediator mediator; - private final RunHistoryManagerService runHistoryManager; + private final RunHistoryManagerService runHistoryManager = RunHistoryManagerService.getInstance(); protected final HashMap annotatedNodes = new HashMap<>(); + private final TypedEventObserver mutationObserver = new TypedEventObserver(MutationEvent.class) { + @Override + public void onTypedEvent(MutationEvent event) { + if (event.getEventType().equals(MutationEvent.MUTATION_RESULT)) { + Pair>> payload = (Pair>>) event.getPayload(); + SwingUtilities.invokeLater(() -> updateMutationResult(payload.getFirst(), payload.getSecond())); + } + } + }; public MutationTreeMediatorViewModel(@NotNull Project project, @NotNull IMutationMediator mediator) { this.project = project; this.mediator = mediator; - this.runHistoryManager = project.getService(RunHistoryManagerService.class); mediator.register(this); registerEditorListener(project); } @@ -62,7 +72,6 @@ public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile f }); } - @Override public void updateMutationResult(String mutationClassFilePath, Map> mutationTestResult) { VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(mutationClassFilePath); if (virtualFile != null) { diff --git a/src/main/java/com/github/jaksonlin/testcraft/util/MyBundle.java b/src/main/java/com/github/jaksonlin/testcraft/util/MyBundle.java deleted file mode 100644 index 62d020a..0000000 --- a/src/main/java/com/github/jaksonlin/testcraft/util/MyBundle.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.jaksonlin.testcraft.util; - -import com.intellij.DynamicBundle; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.PropertyKey; - -import java.util.function.Supplier; - -public final class MyBundle extends DynamicBundle { - @NonNls - private static final String BUNDLE = "messages.MyBundle"; - private static final MyBundle INSTANCE = new MyBundle(); - - private MyBundle() { - super(BUNDLE); - } - - public static @NotNull String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { - return INSTANCE.getMessage(key, params); - } - - public static @NotNull Supplier messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { - return INSTANCE.getLazyMessage(key, params); - } - - public static MyBundle getInstance() { - return INSTANCE; - } -} \ No newline at end of file diff --git a/src/main/java/com/github/jaksonlin/testcraft/util/OllamaClient.java b/src/main/java/com/github/jaksonlin/testcraft/util/OllamaClient.java index 42dac18..ee49f25 100644 --- a/src/main/java/com/github/jaksonlin/testcraft/util/OllamaClient.java +++ b/src/main/java/com/github/jaksonlin/testcraft/util/OllamaClient.java @@ -2,13 +2,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.intellij.openapi.diagnostic.Logger; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,13 +21,12 @@ public class OllamaClient { private static final Logger LOG = Logger.getInstance(OllamaClient.class); private final String baseUrl; private final ObjectMapper objectMapper; - private final HttpClient httpClient; + private final CloseableHttpClient httpClient; private final int timeoutSeconds; private final String model; private final int maxTokens; private final float temperature; - public OllamaClient(String host, String model, int maxTokens, float temperature, int port, int timeoutSeconds) { this.baseUrl = String.format("http://%s:%d", host, port); this.objectMapper = new ObjectMapper(); @@ -31,28 +34,31 @@ public OllamaClient(String host, String model, int maxTokens, float temperature, this.model = model; this.maxTokens = maxTokens; this.temperature = temperature; - this.httpClient = HttpClient.newBuilder() - .connectTimeout(Duration.ofSeconds(timeoutSeconds)) + + RequestConfig config = RequestConfig.custom() + .setConnectTimeout(timeoutSeconds * 1000) + .setConnectionRequestTimeout(timeoutSeconds * 1000) + .setSocketTimeout(timeoutSeconds * 1000) + .build(); + + this.httpClient = HttpClients.custom() + .setDefaultRequestConfig(config) .build(); } public boolean testConnection() { try { - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(baseUrl)) - .timeout(Duration.ofSeconds(timeoutSeconds)) - .GET() - .build(); - - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - return response.statusCode() == 200; + HttpGet request = new HttpGet(baseUrl); + try (CloseableHttpResponse response = httpClient.execute(request)) { + return response.getStatusLine().getStatusCode() == 200; + } } catch (Exception e) { LOG.warn("Failed to test connection to Ollama server", e); return false; } } - public String chatCompletion(List messages) throws IOException, InterruptedException { + public String chatCompletion(List messages) throws IOException { Map requestBody = new HashMap<>(); requestBody.put("model", model); requestBody.put("messages", messages); @@ -60,22 +66,21 @@ public String chatCompletion(List messages) throws IOException, Interru requestBody.put("temperature", temperature); requestBody.put("num_predict", maxTokens); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(baseUrl + "/api/chat")) - .header("Content-Type", "application/json") - .timeout(Duration.ofSeconds(timeoutSeconds)) - .POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(requestBody))) - .build(); + HttpPost request = new HttpPost(baseUrl + "/api/chat"); + request.setHeader("Content-Type", "application/json"); + request.setEntity(new StringEntity(objectMapper.writeValueAsString(requestBody), "UTF-8")); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + try (CloseableHttpResponse response = httpClient.execute(request)) { + if (response.getStatusLine().getStatusCode() != 200) { + String errorBody = EntityUtils.toString(response.getEntity()); + LOG.error("Error from Ollama API: " + errorBody); + throw new IOException("Failed to get response from Ollama API: " + response.getStatusLine().getStatusCode()); + } - if (response.statusCode() != 200) { - LOG.error("Error from Ollama API: " + response.body()); - throw new IOException("Failed to get response from Ollama API: " + response.statusCode()); + String responseBody = EntityUtils.toString(response.getEntity()); + Map responseMap = objectMapper.readValue(responseBody, Map.class); + return ((Map) responseMap.get("message")).get("content"); } - - Map responseMap = objectMapper.readValue(response.body(), Map.class); - return ((Map) responseMap.get("message")).get("content"); } public static class Message { diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 008a892..924a4a6 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -104,36 +104,36 @@ + instance="com.github.jaksonlin.testcraft.application.settings.TestCraftSettingsConfigurable"/> - - - + + + + implementationClass="com.github.jaksonlin.testcraft.application.completions.AnnotationCompletionContributor"/> - + @@ -164,22 +164,22 @@ - - - diff --git a/src/main/resources/messages/MyBundle.properties b/src/main/resources/messages/MyBundle.properties index 85312a4..109ac78 100644 --- a/src/main/resources/messages/MyBundle.properties +++ b/src/main/resources/messages/MyBundle.properties @@ -142,4 +142,8 @@ test.annotation.exists.title=Annotation Already Exists # Pitest Run Messages pitest.run.canceled=Pitest run was canceled pitest.run.canceled.title=Canceled -pitest.run.error=Error executing Pitest command: %s +pitest.run.error=Error executing Pitest command: % +pitest.view.report=View HTML Report + +# Chat +chat.send.button=Send diff --git a/src/main/resources/messages/MyBundle_en_US.properties b/src/main/resources/messages/MyBundle_en_US.properties index 4e0dfc1..ada3552 100644 --- a/src/main/resources/messages/MyBundle_en_US.properties +++ b/src/main/resources/messages/MyBundle_en_US.properties @@ -142,3 +142,6 @@ test.annotation.exists.title=Annotation Already Exists pitest.run.canceled=Pitest run was canceled pitest.run.canceled.title=Canceled pitest.run.error=Error executing Pitest command: %s +pitest.view.report=View HTML Report +# Chat +chat.send.button=Send diff --git a/src/main/resources/messages/MyBundle_zh_CN.properties b/src/main/resources/messages/MyBundle_zh_CN.properties index 367b05f..1fd1b8a 100644 --- a/src/main/resources/messages/MyBundle_zh_CN.properties +++ b/src/main/resources/messages/MyBundle_zh_CN.properties @@ -150,3 +150,6 @@ test.annotation.exists.title=注解已存在 pitest.run.canceled=Pitest 运行已取消 pitest.run.canceled.title=已取消 pitest.run.error=执行 Pitest 命令时出错:%s +pitest.view.report=查看 HTML 报告 +# Chat +chat.send.button=发送