diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt index a7dad74b179..5cb296926f4 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClient.kt @@ -11,6 +11,8 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ChatU import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GET_SERIALIZED_CHAT_REQUEST_METHOD import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSerializedChatParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSerializedChatResult +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OPEN_FILE_DIFF +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenFileDiffParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenTabParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenTabResult import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SHOW_SAVE_FILE_DIALOG_REQUEST_METHOD @@ -38,4 +40,7 @@ interface AmazonQLanguageClient : LanguageClient { @JsonNotification(CHAT_SEND_UPDATE) fun sendChatUpdate(params: ChatUpdateParams): CompletableFuture + + @JsonNotification(OPEN_FILE_DIFF) + fun openFileDiff(params: OpenFileDiffParams): CompletableFuture } diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt index f389e8b9b77..f9ba4b44bd1 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt @@ -4,6 +4,9 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp import com.google.gson.Gson +import com.intellij.diff.DiffContentFactory +import com.intellij.diff.DiffManager +import com.intellij.diff.requests.SimpleDiffRequest import com.intellij.notification.NotificationType import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.fileChooser.FileChooserFactory @@ -34,6 +37,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ChatU import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GET_SERIALIZED_CHAT_REQUEST_METHOD import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSerializedChatParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSerializedChatResult +import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenFileDiffParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenTabParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenTabResult import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ShowSaveFileDialogParams @@ -42,6 +46,9 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credential import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.SsoProfileData import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererModelConfigurator import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings +import software.aws.toolkits.resources.message +import java.io.File +import java.nio.file.Paths import java.util.UUID import java.util.concurrent.CompletableFuture import java.util.concurrent.TimeUnit @@ -262,6 +269,45 @@ class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageC return CompletableFuture.completedFuture(Unit) } + override fun openFileDiff(params: OpenFileDiffParams): CompletableFuture = + CompletableFuture.supplyAsync( + { + try { + val contentFactory = DiffContentFactory.getInstance() + val fileName = Paths.get(params.originalFileUri).fileName.toString() + + val originalContent = params.originalFileContent ?: run { + val file = File(params.originalFileUri) + if (file.exists()) file.readText() else "" + } + val (leftContent, rightContent) = when { + params.isDeleted -> { + // For deleted files, show original on left, empty on right + contentFactory.create(originalContent) to + contentFactory.createEmpty() + } + else -> { + // For new or modified files + val newContent = params.fileContent.orEmpty() + contentFactory.create(originalContent) to + contentFactory.create(newContent) + } + } + val diffRequest = SimpleDiffRequest( + "$fileName ${message("aws.q.lsp.client.diff_message")}", + leftContent, + rightContent, + "Original", + if (params.isDeleted) "Deleted" else "Modified" + ) + DiffManager.getInstance().showDiff(project, diffRequest) + } catch (e: Exception) { + LOG.warn { "Failed to open file diff: ${e.message}" } + } + }, + ApplicationManager.getApplication()::invokeLater + ) + companion object { private val LOG = getLogger() } diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt index 614385a7abc..8c8b830a07e 100644 --- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/FlareChatCommands.kt @@ -31,4 +31,5 @@ const val CHAT_SEND_UPDATE = "aws/chat/sendChatUpdate" const val CHAT_CREATE_PROMPT = "aws/chat/createPrompt" const val SHOW_SAVE_FILE_DIALOG_REQUEST_METHOD = "aws/showSaveFileDialog" const val GET_SERIALIZED_CHAT_REQUEST_METHOD = "aws/chat/getSerializedChat" +const val OPEN_FILE_DIFF = "aws/openFileDiff" const val STOP_CHAT_RESPONSE = "stopChatResponse" diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/OpenFileDiffParams.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/OpenFileDiffParams.kt new file mode 100644 index 00000000000..e0eb4870bf4 --- /dev/null +++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/chat/OpenFileDiffParams.kt @@ -0,0 +1,11 @@ +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat + +data class OpenFileDiffParams( + val originalFileUri: String, + val originalFileContent: String? = null, + val isDeleted: Boolean, + val fileContent: String? = null, +) diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index 74c794110a4..40e26a283d1 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -253,6 +253,7 @@ aws.onboarding.getstarted.panel.login_with_iam=Use Professional License aws.onboarding.getstarted.panel.share_feedback=Share Feedback aws.onboarding.getstarted.panel.signup_iam_text=Sign up for free aws.onboarding.getstarted.panel.title=Authenticate with AWS Toolkit +aws.q.lsp.client.diff_message=(Generated by Amazon Q) aws.q.migration.action.install.text=Install aws.q.migration.action.manage_plugins.text=Manage plugins aws.q.migration.action.read_more.text=Read more