diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index e20316b2..5a6b97ba 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -8,5 +8,5 @@ repositories { } dependencies { - implementation("org.jetbrains.intellij.plugins", "gradle-intellij-plugin", "1.15.0") + implementation("org.jetbrains.intellij.plugins", "gradle-intellij-plugin", "1.16.0") } diff --git a/buildSrc/src/main/kotlin/codegpt.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/codegpt.java-conventions.gradle.kts index 8c67a22f..755cef5d 100644 --- a/buildSrc/src/main/kotlin/codegpt.java-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/codegpt.java-conventions.gradle.kts @@ -18,7 +18,7 @@ intellij { } dependencies { - implementation("ee.carlrobert:llm-client:0.0.4") + implementation("ee.carlrobert:llm-client:0.0.5") } tasks { diff --git a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestHandler.java b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestHandler.java index 97372815..3ad285fe 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestHandler.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestHandler.java @@ -1,5 +1,7 @@ package ee.carlrobert.codegpt.completions; +import com.intellij.openapi.diagnostic.Logger; +import ee.carlrobert.codegpt.completions.you.YouUserManager; import ee.carlrobert.codegpt.conversations.Conversation; import ee.carlrobert.codegpt.conversations.message.Message; import ee.carlrobert.codegpt.settings.state.AzureSettingsState; @@ -20,6 +22,8 @@ import org.jetbrains.annotations.Nullable; public class CompletionRequestHandler { + private static final Logger LOG = Logger.getInstance(CompletionRequestHandler.class); + private final StringBuilder messageBuilder = new StringBuilder(); private SwingWorker swingWorker; private EventSource eventSource; @@ -77,8 +81,21 @@ public class CompletionRequestHandler { try { if (settings.isUseYouService()) { - return CompletionClientProvider.getYouClient("", "") - .getChatCompletion(requestProvider.buildYouCompletionRequest(message), eventListener); + var sessionId = ""; + var accessToken = ""; + var youUserManager = YouUserManager.getInstance(); + if (youUserManager.isAuthenticated()) { + var authenticationResponse = + youUserManager.getAuthenticationResponse().getData(); + sessionId = authenticationResponse.getSession().getSessionId(); + accessToken = authenticationResponse.getSessionJwt(); + } + var request = requestProvider.buildYouCompletionRequest(message); + LOG.info("Initiating completion request using model: " + + (request.isUseGPT4Model() ? "GPT-4" : "YouBot")); + + return CompletionClientProvider.getYouClient(sessionId, accessToken) + .getChatCompletion(request, eventListener); } if (settings.isUseAzureService()) { @@ -130,8 +147,8 @@ public class CompletionRequestHandler { message, isRetry, settings.isUseYouService() ? - getYouCompletionEventListener() : - getCompletionEventListener()); + new BaseCompletionEventListener() : + new YouRequestCompletionEventListener()); } catch (TotalUsageExceededException e) { if (tokensExceededListener != null) { tokensExceededListener.run(); @@ -152,66 +169,41 @@ public class CompletionRequestHandler { } } - private CompletionEventListener getCompletionEventListener() { - return new CompletionEventListener() { - @Override - public void onMessage(String message) { - publish(message); - } + class BaseCompletionEventListener implements CompletionEventListener { - @Override - public void onComplete(StringBuilder messageBuilder) { - if (completedListener != null) { - completedListener.accept(messageBuilder.toString()); - } - } + @Override + public void onMessage(String message) { + publish(message); + } - @Override - public void onError(ErrorDetails error, Throwable ex) { - try { - if (errorListener != null) { - errorListener.accept(error, ex); - } - } finally { - sendError(error, ex); - } + @Override + public void onComplete(StringBuilder messageBuilder) { + if (completedListener != null) { + completedListener.accept(messageBuilder.toString()); } - }; + } + + @Override + public void onError(ErrorDetails error, Throwable ex) { + try { + if (errorListener != null) { + errorListener.accept(error, ex); + } + } finally { + sendError(error, ex); + } + } } - // TODO: Refactor - private YouCompletionEventListener getYouCompletionEventListener() { - return new YouCompletionEventListener() { - @Override - public void onMessage(String message) { - publish(message); - } + class YouRequestCompletionEventListener extends BaseCompletionEventListener + implements YouCompletionEventListener { - @Override - public void onComplete(StringBuilder messageBuilder) { - if (completedListener != null) { - completedListener.accept(messageBuilder.toString()); - } + @Override + public void onSerpResults(List results) { + if (serpResultsListener != null) { + serpResultsListener.accept(results); } - - @Override - public void onError(ErrorDetails error, Throwable ex) { - try { - if (errorListener != null) { - errorListener.accept(error, ex); - } - } finally { - sendError(error, ex); - } - } - - @Override - public void onSerpResults(List results) { - if (serpResultsListener != null) { - serpResultsListener.accept(results); - } - } - }; + } } private void sendInfo(SettingsState settings) { diff --git a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java index ab1c501b..7e6e4902 100644 --- a/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java +++ b/src/main/java/ee/carlrobert/codegpt/completions/CompletionRequestProvider.java @@ -10,6 +10,7 @@ import ee.carlrobert.codegpt.conversations.ConversationsState; import ee.carlrobert.codegpt.conversations.message.Message; import ee.carlrobert.codegpt.settings.configuration.ConfigurationState; import ee.carlrobert.codegpt.settings.state.SettingsState; +import ee.carlrobert.codegpt.settings.state.YouSettingsState; import ee.carlrobert.embedding.EmbeddingsService; import ee.carlrobert.llm.client.openai.completion.chat.OpenAIChatCompletionModel; import ee.carlrobert.llm.client.openai.completion.chat.request.OpenAIChatCompletionMessage; @@ -55,6 +56,7 @@ public class CompletionRequestProvider { public YouCompletionRequest buildYouCompletionRequest(Message message) { return new YouCompletionRequest.Builder(message.getPrompt()) + .setUseGPT4Model(YouSettingsState.getInstance().isUseGPT4Model()) .setChatHistory(conversation.getMessages().stream() .map(prevMessage -> new YouCompletionRequestMessage(prevMessage.getPrompt(), prevMessage.getResponse())) .collect(toList())) diff --git a/src/main/java/ee/carlrobert/codegpt/settings/ServiceSelectionForm.java b/src/main/java/ee/carlrobert/codegpt/settings/ServiceSelectionForm.java index cb9de555..40039375 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/ServiceSelectionForm.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/ServiceSelectionForm.java @@ -19,6 +19,7 @@ import ee.carlrobert.codegpt.settings.state.OpenAISettingsState; import ee.carlrobert.codegpt.settings.state.SettingsState; import ee.carlrobert.codegpt.completions.you.YouUserManager; import ee.carlrobert.codegpt.completions.you.auth.AuthenticationNotifier; +import ee.carlrobert.codegpt.settings.state.YouSettingsState; import ee.carlrobert.codegpt.util.SwingUtils; import ee.carlrobert.llm.client.openai.completion.chat.OpenAIChatCompletionModel; import ee.carlrobert.llm.completion.CompletionModel; @@ -34,7 +35,7 @@ public class ServiceSelectionForm { private final Disposable parentDisposable; - private static final OpenAIChatCompletionModel[] DEFAULT_OPENAI_MODELS = new OpenAIChatCompletionModel[] { + private static final OpenAIChatCompletionModel[] DEFAULT_OPENAI_MODELS = new OpenAIChatCompletionModel[]{ OpenAIChatCompletionModel.GPT_3_5, OpenAIChatCompletionModel.GPT_3_5_16k, OpenAIChatCompletionModel.GPT_4, @@ -88,7 +89,8 @@ public class ServiceSelectionForm { azureActiveDirectoryTokenField = new JBPasswordField(); azureActiveDirectoryTokenField.setColumns(30); - azureActiveDirectoryTokenField.setText(AzureCredentialsManager.getInstance().getAzureActiveDirectoryToken()); + azureActiveDirectoryTokenField.setText( + AzureCredentialsManager.getInstance().getAzureActiveDirectoryToken()); azureActiveDirectoryTokenFieldPanel = UI.PanelFactory.panel(azureActiveDirectoryTokenField) .withLabel("Bearer token:") @@ -103,26 +105,37 @@ public class ServiceSelectionForm { azureSettings.isUseAzureActiveDirectoryAuthentication()); useOpenAIServiceRadioButton = new JBRadioButton( - CodeGPTBundle.get("settingsConfigurable.section.service.useOpenAIServiceRadioButtonLabel"), settings.isUseOpenAIService()); + CodeGPTBundle.get("settingsConfigurable.section.service.useOpenAIServiceRadioButtonLabel"), + settings.isUseOpenAIService()); useAzureServiceRadioButton = new JBRadioButton( - CodeGPTBundle.get("settingsConfigurable.section.service.useAzureServiceRadioButtonLabel"), settings.isUseAzureService()); + CodeGPTBundle.get("settingsConfigurable.section.service.useAzureServiceRadioButtonLabel"), + settings.isUseAzureService()); useYouServiceRadioButton = new JBRadioButton( - CodeGPTBundle.get("settingsConfigurable.section.service.useYouServiceRadioButtonLabel"), settings.isUseYouService()); + CodeGPTBundle.get("settingsConfigurable.section.service.useYouServiceRadioButtonLabel"), + settings.isUseYouService()); openAIBaseHostField = new JBTextField(openAISettings.getBaseHost(), 30); openAIPathField = new JBTextField(openAISettings.getPath(), 30); openAIOrganizationField = new JBTextField(openAISettings.getOrganization(), 30); - openAICompletionModelComboBox = new ModelComboBox(DEFAULT_OPENAI_MODELS, OpenAIChatCompletionModel.findByCode(openAISettings.getModel())); + openAICompletionModelComboBox = new ModelComboBox( + DEFAULT_OPENAI_MODELS, + OpenAIChatCompletionModel.findByCode(openAISettings.getModel())); azureBaseHostField = new JBTextField(azureSettings.getBaseHost(), 35); azurePathField = new JBTextField(azureSettings.getPath(), 35); azureResourceNameField = new JBTextField(azureSettings.getResourceName(), 35); azureDeploymentIdField = new JBTextField(azureSettings.getDeploymentId(), 35); azureApiVersionField = new JBTextField(azureSettings.getApiVersion(), 35); - azureCompletionModelComboBox = new ModelComboBox(DEFAULT_OPENAI_MODELS, OpenAIChatCompletionModel.findByCode(azureSettings.getModel())); - azureCompletionModelComboBox.getEditor().getEditorComponent().setMaximumSize(azureBaseHostField.getPreferredSize()); + azureCompletionModelComboBox = new ModelComboBox( + DEFAULT_OPENAI_MODELS, + OpenAIChatCompletionModel.findByCode(azureSettings.getModel())); + azureCompletionModelComboBox.getEditor() + .getEditorComponent() + .setMaximumSize(azureBaseHostField.getPreferredSize()); - displayWebSearchResultsCheckBox = new JBCheckBox("Display web search results", settings.isDisplayWebSearchResults()); + displayWebSearchResultsCheckBox = new JBCheckBox( + "Display web search results", + YouSettingsState.getInstance().isDisplayWebSearchResults()); displayWebSearchResultsCheckBox.setEnabled(YouUserManager.getInstance().isAuthenticated()); openAIServiceSectionPanel = createOpenAIServiceSectionPanel(); @@ -135,7 +148,8 @@ public class ServiceSelectionForm { ApplicationManager.getApplication() .getMessageBus() .connect() - .subscribe(AuthenticationNotifier.AUTHENTICATION_TOPIC, (AuthenticationNotifier) () -> displayWebSearchResultsCheckBox.setEnabled(true)); + .subscribe(AuthenticationNotifier.AUTHENTICATION_TOPIC, + (AuthenticationNotifier) () -> displayWebSearchResultsCheckBox.setEnabled(true)); } public JPanel getForm() { @@ -158,9 +172,11 @@ public class ServiceSelectionForm { private JPanel createOpenAIServiceSectionPanel() { var requestConfigurationPanel = UI.PanelFactory.grid() .add(UI.PanelFactory.panel(openAIOrganizationField) - .withLabel(CodeGPTBundle.get("settingsConfigurable.section.service.openai.organizationField.label")) + .withLabel(CodeGPTBundle.get( + "settingsConfigurable.section.service.openai.organizationField.label")) .resizeX(false) - .withComment(CodeGPTBundle.get("settingsConfigurable.section.service.openai.organizationField.comment"))) + .withComment(CodeGPTBundle.get( + "settingsConfigurable.section.service.openai.organizationField.comment"))) .add(UI.PanelFactory.panel(openAIBaseHostField) .withLabel("Base host:") .resizeX(false)) @@ -175,7 +191,8 @@ public class ServiceSelectionForm { var apiKeyFieldPanel = UI.PanelFactory.panel(openAIApiKeyField) .withLabel(CodeGPTBundle.get("settingsConfigurable.section.integration.apiKeyField.label")) .resizeX(false) - .withComment(CodeGPTBundle.get("settingsConfigurable.section.integration.apiKeyField.comment")) + .withComment( + CodeGPTBundle.get("settingsConfigurable.section.integration.apiKeyField.comment")) .withCommentHyperlinkListener(SwingUtils::handleHyperlinkClicked) .createPanel(); @@ -204,17 +221,23 @@ public class ServiceSelectionForm { var configPanel = withEmptyLeftBorder(UI.PanelFactory.grid() .add(UI.PanelFactory.panel(azureResourceNameField) - .withLabel(CodeGPTBundle.get("settingsConfigurable.section.service.azure.resourceNameField.label")) + .withLabel(CodeGPTBundle.get( + "settingsConfigurable.section.service.azure.resourceNameField.label")) .resizeX(false) - .withComment(CodeGPTBundle.get("settingsConfigurable.section.service.azure.resourceNameField.comment"))) + .withComment(CodeGPTBundle.get( + "settingsConfigurable.section.service.azure.resourceNameField.comment"))) .add(UI.PanelFactory.panel(azureDeploymentIdField) - .withLabel(CodeGPTBundle.get("settingsConfigurable.section.service.azure.deploymentIdField.label")) + .withLabel(CodeGPTBundle.get( + "settingsConfigurable.section.service.azure.deploymentIdField.label")) .resizeX(false) - .withComment(CodeGPTBundle.get("settingsConfigurable.section.service.azure.deploymentIdField.comment"))) + .withComment(CodeGPTBundle.get( + "settingsConfigurable.section.service.azure.deploymentIdField.comment"))) .add(UI.PanelFactory.panel(azureApiVersionField) - .withLabel(CodeGPTBundle.get("settingsConfigurable.section.service.azure.apiVersionField.label")) + .withLabel(CodeGPTBundle.get( + "settingsConfigurable.section.service.azure.apiVersionField.label")) .resizeX(false) - .withComment(CodeGPTBundle.get("settingsConfigurable.section.service.azure.apiVersionField.comment"))) + .withComment(CodeGPTBundle.get( + "settingsConfigurable.section.service.azure.apiVersionField.comment"))) .add(UI.PanelFactory.panel(azureBaseHostField) .withLabel("Base host:") .resizeX(false)) @@ -251,7 +274,8 @@ public class ServiceSelectionForm { openAIServiceSectionPanel.setVisible(settings.isUseOpenAIService()); azureServiceSectionPanel.setVisible(settings.isUseAzureService()); azureApiKeyFieldPanel.setVisible(azureSettings.isUseAzureApiKeyAuthentication()); - azureActiveDirectoryTokenFieldPanel.setVisible(azureSettings.isUseAzureActiveDirectoryAuthentication()); + azureActiveDirectoryTokenFieldPanel.setVisible( + azureSettings.isUseAzureActiveDirectoryAuthentication()); youServiceSectionPanel.setVisible(settings.isUseYouService()); } @@ -264,7 +288,8 @@ public class ServiceSelectionForm { registerRadioButtons( List.of( Map.entry(useAzureApiKeyAuthenticationRadioButton, azureApiKeyFieldPanel), - Map.entry(useAzureActiveDirectoryAuthenticationRadioButton, azureActiveDirectoryTokenFieldPanel))); + Map.entry(useAzureActiveDirectoryAuthenticationRadioButton, + azureActiveDirectoryTokenFieldPanel))); } private void registerRadioButtons(List> entries) { @@ -343,7 +368,9 @@ public class ServiceSelectionForm { } public String getOpenAIModel() { - return ((OpenAIChatCompletionModel) (openAICompletionModelComboBox.getModel().getSelectedItem())).getCode(); + return ((OpenAIChatCompletionModel) (openAICompletionModelComboBox.getModel() + .getSelectedItem())) + .getCode(); } public void setAzureActiveDirectoryAuthenticationSelected(boolean selected) { @@ -415,7 +442,9 @@ public class ServiceSelectionForm { } public String getAzureModel() { - return ((OpenAIChatCompletionModel) (azureCompletionModelComboBox.getModel().getSelectedItem())).getCode(); + return ((OpenAIChatCompletionModel) (azureCompletionModelComboBox.getModel() + .getSelectedItem())) + .getCode(); } public void setDisplayWebSearchResults(boolean displayWebSearchResults) { diff --git a/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java b/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java index f3cb1b4d..2a08dc51 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/SettingsConfigurable.java @@ -10,6 +10,7 @@ import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager; import ee.carlrobert.codegpt.settings.state.AzureSettingsState; import ee.carlrobert.codegpt.settings.state.OpenAISettingsState; import ee.carlrobert.codegpt.settings.state.SettingsState; +import ee.carlrobert.codegpt.settings.state.YouSettingsState; import ee.carlrobert.codegpt.telemetry.TelemetryAction; import ee.carlrobert.codegpt.toolwindow.chat.standard.StandardChatToolWindowContentManager; import ee.carlrobert.codegpt.util.ApplicationUtils; @@ -54,7 +55,8 @@ public class SettingsConfigurable implements Configurable { isServiceChanged(serviceSelectionForm, settings) || openAISettings.isModified(serviceSelectionForm) || azureSettings.isModified(serviceSelectionForm) || - serviceSelectionForm.isDisplayWebSearchResults() != settings.isDisplayWebSearchResults(); + serviceSelectionForm.isDisplayWebSearchResults() != + YouSettingsState.getInstance().isDisplayWebSearchResults(); } @Override @@ -76,7 +78,8 @@ public class SettingsConfigurable implements Configurable { settings.setUseOpenAIService(serviceSelectionForm.isOpenAIServiceSelected()); settings.setUseAzureService(serviceSelectionForm.isAzureServiceSelected()); settings.setUseYouService(serviceSelectionForm.isYouServiceSelected()); - settings.setDisplayWebSearchResults(serviceSelectionForm.isDisplayWebSearchResults()); + YouSettingsState.getInstance() + .setDisplayWebSearchResults(serviceSelectionForm.isDisplayWebSearchResults()); openAISettings.apply(serviceSelectionForm); azureSettings.apply(serviceSelectionForm); @@ -108,7 +111,8 @@ public class SettingsConfigurable implements Configurable { openAISettings.reset(serviceSelectionForm); azureSettings.reset(serviceSelectionForm); - serviceSelectionForm.setDisplayWebSearchResults(settings.isDisplayWebSearchResults()); + serviceSelectionForm.setDisplayWebSearchResults( + YouSettingsState.getInstance().isDisplayWebSearchResults()); } @Override diff --git a/src/main/java/ee/carlrobert/codegpt/settings/YouServiceSelectionPanel.java b/src/main/java/ee/carlrobert/codegpt/settings/YouServiceSelectionPanel.java index 181b6c52..2b8c4454 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/YouServiceSelectionPanel.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/YouServiceSelectionPanel.java @@ -9,6 +9,7 @@ import com.intellij.ui.TitledSeparator; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBPasswordField; import com.intellij.ui.components.JBTextField; +import com.intellij.ui.components.OnOffButton; import com.intellij.util.ui.AsyncProcessIcon; import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.JBFont; @@ -51,7 +52,8 @@ public class YouServiceSelectionPanel extends JPanel { if (!settings.getEmail().isEmpty()) { passwordField.setText(YouCredentialsManager.getInstance().getAccountPassword()); } - signInButton = new JButton(CodeGPTBundle.get("settingsConfigurable.section.userAuthentication.signIn.label")); + signInButton = new JButton( + CodeGPTBundle.get("settingsConfigurable.section.userAuthentication.signIn.label")); signUpTextPane = createSignUpTextPane(); loadingSpinner = new AsyncProcessIcon("sign_in_spinner"); loadingSpinner.setBorder(JBUI.Borders.emptyLeft(8)); @@ -63,11 +65,15 @@ public class YouServiceSelectionPanel extends JPanel { signInButton.addActionListener(e -> { emailValidator.revalidate(); passwordValidator.revalidate(); - if (emailValidator.getValidationInfo() == null && passwordValidator.getValidationInfo() == null) { + if (emailValidator.getValidationInfo() == null + && passwordValidator.getValidationInfo() == null) { loadingSpinner.resume(); loadingSpinner.setVisible(true); YouAuthenticationService.getInstance() - .signInAsync(emailField.getText(), new String(passwordField.getPassword()), new UserAuthenticationHandler()); + .signInAsync( + emailField.getText(), + new String(passwordField.getPassword()), + new UserAuthenticationHandler()); } }); @@ -91,14 +97,17 @@ public class YouServiceSelectionPanel extends JPanel { return new String(passwordField.getPassword()); } - private ComponentValidator createInputValidator(Disposable parentDisposable, JComponent component) { + private ComponentValidator createInputValidator( + Disposable parentDisposable, + JComponent component) { var validator = new ComponentValidator(parentDisposable) .withValidator(() -> { String value; if (component instanceof JBTextField) { value = ((JBTextField) component).getText(); if (!isValidEmail(value)) { - return new ValidationInfo("The email you entered is invalid.", component).withOKEnabled(); + return new ValidationInfo("The email you entered is invalid.", component) + .withOKEnabled(); } } else { value = new String(((JPasswordField) component).getPassword()); @@ -124,7 +133,8 @@ public class YouServiceSelectionPanel extends JPanel { } private JTextPane createSignUpTextPane() { - var textPane = createTextPane("Don't have an account? Sign up"); + var textPane = createTextPane( + "Don't have an account? Sign up"); textPane.setBorder(JBUI.Borders.emptyLeft(4)); return textPane; } @@ -148,7 +158,10 @@ public class YouServiceSelectionPanel extends JPanel { return panel; } - private JPanel createUserAuthenticationPanel(JBTextField emailAddressField, JBPasswordField passwordField, @Nullable YouAuthenticationError error) { + private JPanel createUserAuthenticationPanel( + JBTextField emailAddressField, + JBPasswordField passwordField, + @Nullable YouAuthenticationError error) { var contentPanelBuilder = FormBuilder.createFormBuilder() .addLabeledComponent("Email address:", emailAddressField) .addLabeledComponent("Password:", passwordField) @@ -160,12 +173,12 @@ public class YouServiceSelectionPanel extends JPanel { var invalidCredentialsLabel = new JBLabel(error.getErrorMessage()); invalidCredentialsLabel.setForeground(JBColor.red); invalidCredentialsLabel.setBorder(JBUI.Borders.emptyLeft(4)); - contentPanelBuilder.addComponentToRightColumn(invalidCredentialsLabel); } return FormBuilder.createFormBuilder() - .addComponent(new TitledSeparator(CodeGPTBundle.get("settingsConfigurable.section.userAuthentication.title"))) + .addComponent(new TitledSeparator( + CodeGPTBundle.get("settingsConfigurable.section.userAuthentication.title"))) .addComponent(JBUI.Panels .simplePanel(contentPanelBuilder.getPanel()) .withBorder(JBUI.Borders.emptyLeft(16))) @@ -175,7 +188,8 @@ public class YouServiceSelectionPanel extends JPanel { private JPanel createUserInformationPanel(YouUser user) { var userManager = YouUserManager.getInstance(); var contentPanelBuilder = FormBuilder.createFormBuilder() - .addLabeledComponent("Email address:", new JBLabel(user.getEmails().get(0).getEmail()).withFont(JBFont.label().asBold())); + .addLabeledComponent("Email address:", + new JBLabel(user.getEmails().get(0).getEmail()).withFont(JBFont.label().asBold())); var signOutButton = new JButton("Sign Out"); signOutButton.addActionListener(e -> { @@ -184,7 +198,8 @@ public class YouServiceSelectionPanel extends JPanel { }); return FormBuilder.createFormBuilder() - .addComponent(new TitledSeparator(CodeGPTBundle.get("settingsConfigurable.section.userInformation.title"))) + .addComponent(new TitledSeparator( + CodeGPTBundle.get("settingsConfigurable.section.userInformation.title"))) .addVerticalGap(8) .addComponent(JBUI.Panels .simplePanel(contentPanelBuilder.addVerticalGap(4) @@ -209,13 +224,18 @@ public class YouServiceSelectionPanel extends JPanel { @Override public void handleGenericError() { - SwingUtilities.invokeLater(() -> refreshView( - createUserAuthenticationPanel(emailField, passwordField, new YouAuthenticationError("unknown", "Something went wrong.")))); + SwingUtilities.invokeLater(() -> refreshView(createUserAuthenticationPanel( + emailField, + passwordField, + new YouAuthenticationError("unknown", "Something went wrong.")))); } @Override public void handleError(YouAuthenticationError error) { - SwingUtilities.invokeLater(() -> refreshView(createUserAuthenticationPanel(emailField, passwordField, error))); + SwingUtilities.invokeLater(() -> refreshView(createUserAuthenticationPanel( + emailField, + passwordField, + error))); } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/state/SettingsState.java b/src/main/java/ee/carlrobert/codegpt/settings/state/SettingsState.java index 2a99f4c1..b1b43fd1 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/state/SettingsState.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/state/SettingsState.java @@ -17,7 +17,6 @@ public class SettingsState implements PersistentStateComponent { private boolean useOpenAIService = true; private boolean useAzureService; private boolean useYouService; - private boolean displayWebSearchResults = true; public SettingsState() { } @@ -104,12 +103,4 @@ public class SettingsState implements PersistentStateComponent { public void setUseYouService(boolean useYouService) { this.useYouService = useYouService; } - - public boolean isDisplayWebSearchResults() { - return displayWebSearchResults; - } - - public void setDisplayWebSearchResults(boolean displayWebSearchResults) { - this.displayWebSearchResults = displayWebSearchResults; - } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/state/YouSettingsState.java b/src/main/java/ee/carlrobert/codegpt/settings/state/YouSettingsState.java new file mode 100644 index 00000000..d91201b4 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/settings/state/YouSettingsState.java @@ -0,0 +1,45 @@ +package ee.carlrobert.codegpt.settings.state; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.util.xmlb.XmlSerializerUtil; +import org.jetbrains.annotations.NotNull; + +@State(name = "CodeGPT_YouSettings", storages = @Storage("CodeGPT_YouSettings.xml")) +public class YouSettingsState implements PersistentStateComponent { + + private boolean displayWebSearchResults = true; + private boolean useGPT4Model; + + public static YouSettingsState getInstance() { + return ApplicationManager.getApplication().getService(YouSettingsState.class); + } + + @Override + public YouSettingsState getState() { + return this; + } + + @Override + public void loadState(@NotNull YouSettingsState state) { + XmlSerializerUtil.copyBean(state, this); + } + + public boolean isDisplayWebSearchResults() { + return displayWebSearchResults; + } + + public void setDisplayWebSearchResults(boolean displayWebSearchResults) { + this.displayWebSearchResults = displayWebSearchResults; + } + + public boolean isUseGPT4Model() { + return useGPT4Model; + } + + public void setUseGPT4Model(boolean useGPT4Model) { + this.useGPT4Model = useGPT4Model; + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/BaseChatToolWindowTabPanel.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/BaseChatToolWindowTabPanel.java index 197055fe..0055bc12 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/BaseChatToolWindowTabPanel.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/BaseChatToolWindowTabPanel.java @@ -5,12 +5,15 @@ import static ee.carlrobert.codegpt.util.ThemeUtils.getPanelBackgroundColor; import static java.lang.String.format; import static java.util.stream.Collectors.toList; +import com.intellij.ide.HelpTooltip; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel; import com.intellij.ui.JBColor; import com.intellij.ui.components.JBScrollPane; +import com.intellij.ui.components.OnOffButton; import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.JBUI.Borders; import ee.carlrobert.codegpt.actions.ActionType; import ee.carlrobert.codegpt.completions.CompletionRequestHandler; import ee.carlrobert.codegpt.completions.you.YouSerpResult; @@ -22,6 +25,7 @@ import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager; import ee.carlrobert.codegpt.settings.state.AzureSettingsState; import ee.carlrobert.codegpt.settings.state.OpenAISettingsState; import ee.carlrobert.codegpt.settings.state.SettingsState; +import ee.carlrobert.codegpt.settings.state.YouSettingsState; import ee.carlrobert.codegpt.telemetry.TelemetryAction; import ee.carlrobert.codegpt.toolwindow.ModelIconLabel; import ee.carlrobert.codegpt.toolwindow.chat.components.ChatMessageResponseBody; @@ -29,10 +33,9 @@ import ee.carlrobert.codegpt.toolwindow.chat.components.ResponsePanel; import ee.carlrobert.codegpt.toolwindow.chat.components.SmartScroller; import ee.carlrobert.codegpt.toolwindow.chat.components.UserMessagePanel; import ee.carlrobert.codegpt.toolwindow.chat.components.UserPromptTextArea; -import ee.carlrobert.codegpt.completions.you.YouUserManager; import ee.carlrobert.codegpt.util.EditorUtils; -import ee.carlrobert.codegpt.util.file.FileUtils; import ee.carlrobert.codegpt.util.OverlayUtils; +import ee.carlrobert.codegpt.util.file.FileUtils; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; @@ -131,10 +134,7 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan public void dispose() { } - private boolean isCredentialSet() { - if (SettingsState.getInstance().isUseYouService()) { - return YouUserManager.getInstance().isAuthenticated(); - } + private boolean isRequestAllowed() { if (SettingsState.getInstance().isUseAzureService()) { return AzureCredentialsManager.getInstance().isCredentialSet(); } @@ -148,7 +148,7 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan boolean isRetry) { ChatMessageResponseBody responseContainer = (ChatMessageResponseBody) responsePanel.getContent(); - if (!isCredentialSet()) { + if (!isRequestAllowed()) { responseContainer.displayMissingCredential(); return; } @@ -170,7 +170,7 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan var serpResults = serpResultsMapping.get(message.getId()); var containsResults = serpResults != null && !serpResults.isEmpty(); - if (SettingsState.getInstance().isDisplayWebSearchResults()) { + if (YouSettingsState.getInstance().isDisplayWebSearchResults()) { if (containsResults) { responseContainer.displaySerpResults(serpResults); } @@ -332,9 +332,10 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan gbc.gridy = 1; var model = getModel(); - var modelIconWrapper = JBUI.Panels.simplePanel( - new ModelIconLabel(getClientCode(), model)).withBorder(JBUI.Borders.empty(0, 0, 8, 4)); - modelIconWrapper.setBackground(getPanelBackgroundColor()); + var modelIconWrapper = JBUI.Panels + .simplePanel(new ModelIconLabel(getClientCode(), model)) + .withBorder(Borders.emptyRight(4)) + .withBackground(getPanelBackgroundColor()); var wrapper = new JPanel(new BorderLayout()); wrapper.setBorder(JBUI.Borders.compound( @@ -343,13 +344,46 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan wrapper.setBackground(getPanelBackgroundColor()); wrapper.add(userPromptTextArea, BorderLayout.SOUTH); if (model != null) { - wrapper.add(modelIconWrapper, BorderLayout.LINE_END); + var header = new JPanel(new BorderLayout()); + header.setBackground(getPanelBackgroundColor()); + header.setBorder(JBUI.Borders.emptyBottom(8)); + if ("YouCode".equals(model)) { + var gpt4ToggleButton = new OnOffButton(); + var useGPT4Model = YouSettingsState.getInstance().isUseGPT4Model(); + gpt4ToggleButton.setSelected(useGPT4Model); + gpt4ToggleButton.setOnText("GPT-4"); + gpt4ToggleButton.setOffText("GPT-4"); + gpt4ToggleButton.addActionListener( + actionEvent -> { + project.getMessageBus() + .syncPublisher(YouModelChangeNotifier.YOU_MODEL_CHANGE_NOTIFIER_TOPIC) + .modelChanged(gpt4ToggleButton.isSelected()); + YouSettingsState.getInstance().setUseGPT4Model(gpt4ToggleButton.isSelected()); + installHelpTooltip(gpt4ToggleButton.isSelected(), gpt4ToggleButton); + }); + project.getMessageBus() + .connect() + .subscribe( + YouModelChangeNotifier.YOU_MODEL_CHANGE_NOTIFIER_TOPIC, + (YouModelChangeNotifier) gpt4ToggleButton::setSelected); + + installHelpTooltip(useGPT4Model, gpt4ToggleButton); + header.add(gpt4ToggleButton, BorderLayout.LINE_START); + } + header.add(modelIconWrapper, BorderLayout.LINE_END); + wrapper.add(header); } rootPanel.add(wrapper, gbc); userPromptTextArea.requestFocusInWindow(); userPromptTextArea.requestFocus(); } + private void installHelpTooltip(boolean selected, JComponent component) { + new HelpTooltip() + .setDescription(selected ? "Turn off for faster responses" : "Turn on for complex queries") + .installOn(component); + } + private String getClientCode() { var settings = SettingsState.getInstance(); if (settings.isUseOpenAIService()) { diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java index 6d00d33b..a7b1d794 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java @@ -21,5 +21,6 @@ public interface ChatToolWindowTabPanel extends Disposable { void startNewConversation(Message message); void sendMessage(Message message); + void requestFocusForTextArea(); } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/YouModelChangeNotifier.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/YouModelChangeNotifier.java new file mode 100644 index 00000000..5bddfcef --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/YouModelChangeNotifier.java @@ -0,0 +1,11 @@ +package ee.carlrobert.codegpt.toolwindow.chat; + +import com.intellij.util.messages.Topic; + +public interface YouModelChangeNotifier { + + Topic YOU_MODEL_CHANGE_NOTIFIER_TOPIC = + Topic.create("youModelChangeTopic", YouModelChangeNotifier.class); + + void modelChanged(boolean selected); +} diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/components/ChatMessageResponseBody.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/components/ChatMessageResponseBody.java index af05d089..8aa4ad17 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/components/ChatMessageResponseBody.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/components/ChatMessageResponseBody.java @@ -102,9 +102,7 @@ public class ChatMessageResponseBody extends JPanel { } public void displayMissingCredential() { - var message = SettingsState.getInstance().isUseYouService() ? - "Please log in to access the chat feature." : - "API key not provided. Open Settings to set one."; + var message = "API key not provided. Open Settings to set one."; currentlyProcessedTextPane.setText( format("

%s

", message)); currentlyProcessedTextPane.addHyperlinkListener(e -> { diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditor.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditor.java index e664e51a..b22459b4 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditor.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/ResponseEditor.java @@ -1,24 +1,19 @@ package ee.carlrobert.codegpt.toolwindow.chat.editor; -import static ee.carlrobert.codegpt.util.file.FileUtils.findFileNameExtensionMapping; -import static java.lang.String.format; +import static ee.carlrobert.codegpt.util.file.FileUtils.findLanguageExtensionMapping; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DefaultActionGroup; -import com.intellij.openapi.application.PathManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.EditorKind; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.impl.ContextMenuPopupHandler; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; -import com.intellij.testFramework.LightVirtualFile; import com.intellij.ui.JBColor; import com.intellij.ui.components.JBLabel; import com.intellij.util.ui.JBUI; @@ -32,43 +27,26 @@ import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.ReplaceSelectionActi import ee.carlrobert.codegpt.util.EditorUtils; import java.awt.BorderLayout; import java.awt.FlowLayout; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import javax.swing.Box; import javax.swing.JPanel; public class ResponseEditor extends JPanel implements Disposable { private final Editor editor; - private final String fileName; - private final String fileExtension; + private final String language; + private final String extension; public ResponseEditor( Project project, String code, - String language, + String markdownLanguage, Disposable disposableParent) { super(new BorderLayout()); - var fileNameExtensionMapping = findFileNameExtensionMapping(language); - this.fileName = fileNameExtensionMapping.getKey(); - this.fileExtension = fileNameExtensionMapping.getValue(); - - var timestamp = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now()); - var fileName = "temp_" + timestamp + fileExtension; - var lightVirtualFile = new LightVirtualFile( - format("%s/%s", PathManager.getTempPath(), fileName), code); - var document = FileDocumentManager.getInstance().getDocument(lightVirtualFile); - if (document == null) { - document = EditorFactory.getInstance().createDocument(code); - } - EditorUtils.disableHighlighting(project, document); - editor = EditorFactory.getInstance().createEditor( - document, - project, - lightVirtualFile, - true, - EditorKind.UNTYPED); + var extensionMapping = findLanguageExtensionMapping(markdownLanguage); + language = extensionMapping.getKey(); + extension = extensionMapping.getValue(); + editor = EditorUtils.createEditor(project, extension, code); DefaultActionGroup group = new DefaultActionGroup(); group.add(new ReplaceCodeInMainEditorAction()); @@ -85,12 +63,14 @@ public class ResponseEditor extends JPanel implements Disposable { editorEx.installPopupHandler(new ContextMenuPopupHandler.Simple(group)); editorEx.setColorsScheme(EditorColorsManager.getInstance().getSchemeForCurrentUITheme()); - var settings = editor.getSettings(); + var settings = editorEx.getSettings(); settings.setAdditionalColumnsCount(0); settings.setAdditionalLinesCount(0); settings.setAdditionalPageAtBottom(false); settings.setVirtualSpace(false); settings.setUseSoftWraps(false); + settings.setLineMarkerAreaShown(true); + settings.setGutterIconsShown(true); add(createHeaderComponent(), BorderLayout.NORTH); add(editor.getComponent(), BorderLayout.SOUTH); @@ -112,7 +92,7 @@ public class ResponseEditor extends JPanel implements Disposable { headerComponent.setBorder(JBUI.Borders.compound( JBUI.Borders.customLine(JBColor.border(), 1, 1, 1, 1), JBUI.Borders.empty(8))); - headerComponent.add(new JBLabel(fileName), BorderLayout.LINE_START); + headerComponent.add(new JBLabel(language), BorderLayout.LINE_START); headerComponent.add(createHeaderActions(), BorderLayout.LINE_END); return headerComponent; } @@ -123,7 +103,7 @@ public class ResponseEditor extends JPanel implements Disposable { wrapper.add(Box.createHorizontalStrut(8)); wrapper.add(new IconActionButton(new EditAction(editor))); wrapper.add(Box.createHorizontalStrut(8)); - wrapper.add(new IconActionButton(new NewFileAction(editor, fileExtension))); + wrapper.add(new IconActionButton(new NewFileAction(editor, extension))); wrapper.add(Box.createHorizontalStrut(8)); wrapper.add(new IconActionButton(new CopyAction(editor))); wrapper.add(Box.createHorizontalStrut(8)); diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/standard/StandardChatToolWindowTabPanel.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/standard/StandardChatToolWindowTabPanel.java index f8a07ef7..188c7d2a 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/standard/StandardChatToolWindowTabPanel.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/standard/StandardChatToolWindowTabPanel.java @@ -7,6 +7,7 @@ import com.intellij.openapi.project.Project; import ee.carlrobert.codegpt.conversations.Conversation; import ee.carlrobert.codegpt.conversations.message.Message; import ee.carlrobert.codegpt.settings.state.SettingsState; +import ee.carlrobert.codegpt.settings.state.YouSettingsState; import ee.carlrobert.codegpt.toolwindow.chat.BaseChatToolWindowTabPanel; import ee.carlrobert.codegpt.toolwindow.chat.components.ChatMessageResponseBody; import ee.carlrobert.codegpt.toolwindow.chat.components.ResponsePanel; @@ -24,7 +25,8 @@ public class StandardChatToolWindowTabPanel extends BaseChatToolWindowTabPanel { this(project, null); } - public StandardChatToolWindowTabPanel(@NotNull Project project, @Nullable Conversation conversation) { + public StandardChatToolWindowTabPanel(@NotNull Project project, + @Nullable Conversation conversation) { super(project, false); if (conversation == null) { displayLandingView(); @@ -39,12 +41,14 @@ public class StandardChatToolWindowTabPanel extends BaseChatToolWindowTabPanel { var editor = EditorUtils.getSelectedEditor(project); if (editor == null || !editor.getSelectionModel().hasSelection()) { OverlayUtils.showWarningBalloon( - editor == null ? "Unable to locate a selected editor" : "Please select a target code before proceeding", + editor == null ? "Unable to locate a selected editor" + : "Please select a target code before proceeding", locationOnScreen); return; } - var fileExtension = FileUtils.getFileExtension(((EditorImpl) editor).getVirtualFile().getName()); + var fileExtension = FileUtils.getFileExtension( + ((EditorImpl) editor).getVirtualFile().getName()); var message = new Message(action.getPrompt().replace( "{{selectedCode}}", format("\n```%s\n%s\n```", fileExtension, editor.getSelectionModel().getSelectedText()))); @@ -66,7 +70,8 @@ public class StandardChatToolWindowTabPanel extends BaseChatToolWindowTabPanel { .withResponse(message.getResponse()); var serpResults = message.getSerpResults(); - if (SettingsState.getInstance().isDisplayWebSearchResults() && serpResults != null && !serpResults.isEmpty()) { + if (YouSettingsState.getInstance().isDisplayWebSearchResults() && + serpResults != null && !serpResults.isEmpty()) { messageResponseBody.displaySerpResults(serpResults); } diff --git a/src/main/java/ee/carlrobert/codegpt/util/EditorUtils.java b/src/main/java/ee/carlrobert/codegpt/util/EditorUtils.java index 83ba7186..0f05a152 100644 --- a/src/main/java/ee/carlrobert/codegpt/util/EditorUtils.java +++ b/src/main/java/ee/carlrobert/codegpt/util/EditorUtils.java @@ -1,18 +1,48 @@ package ee.carlrobert.codegpt.util; +import static java.lang.String.format; + import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.EditorKind; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; +import com.intellij.testFramework.LightVirtualFile; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public final class EditorUtils { + public static Editor createEditor(@NotNull Project project, String fileExtension, String code) { + var timestamp = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now()); + var fileName = "temp_" + timestamp + fileExtension; + var lightVirtualFile = new LightVirtualFile( + format("%s/%s", PathManager.getTempPath(), fileName), + code); + var existingDocument = FileDocumentManager.getInstance().getDocument(lightVirtualFile); + var document = existingDocument != null + ? existingDocument + : EditorFactory.getInstance().createDocument(code); + + disableHighlighting(project, document); + + return EditorFactory.getInstance().createEditor( + document, + project, + lightVirtualFile, + false, + EditorKind.MAIN_EDITOR); + } + public static boolean hasSelection(@Nullable Editor editor) { return editor != null && editor.getSelectionModel().hasSelection(); } diff --git a/src/main/java/ee/carlrobert/codegpt/util/file/FileUtils.java b/src/main/java/ee/carlrobert/codegpt/util/file/FileUtils.java index a26fef57..a276dba9 100644 --- a/src/main/java/ee/carlrobert/codegpt/util/file/FileUtils.java +++ b/src/main/java/ee/carlrobert/codegpt/util/file/FileUtils.java @@ -67,17 +67,17 @@ public class FileUtils { return ""; } - public static Map.Entry findFileNameExtensionMapping(String language) { + public static Map.Entry findLanguageExtensionMapping(String language) { var defaultValue = Map.entry("Text", ".txt"); var mapper = new ObjectMapper(); - List fileExtensionLanguageMappings; - List languageFileExtensionMappings; + List extensionToLanguageMappings; + List languageToExtensionMappings; try { - fileExtensionLanguageMappings = mapper.readValue( + extensionToLanguageMappings = mapper.readValue( getResourceContent("/fileExtensionLanguageMappings.json"), new TypeReference<>() { }); - languageFileExtensionMappings = mapper.readValue( + languageToExtensionMappings = mapper.readValue( getResourceContent("/languageFileExtensionMappings.json"), new TypeReference<>() { }); } catch (JsonProcessingException e) { @@ -85,11 +85,11 @@ public class FileUtils { return defaultValue; } - return findFirstExtension(languageFileExtensionMappings, language) - .orElseGet(() -> fileExtensionLanguageMappings.stream() + return findFirstExtension(languageToExtensionMappings, language) + .orElseGet(() -> extensionToLanguageMappings.stream() .filter(it -> it.getExtension().equalsIgnoreCase(language)) .findFirst() - .map(it -> findFirstExtension(languageFileExtensionMappings, it.getValue()) + .map(it -> findFirstExtension(languageToExtensionMappings, it.getValue()) .orElse(defaultValue)) .orElse(defaultValue)); } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 9b539d63..fddc2f3e 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -22,6 +22,7 @@ +