From c15cad40f117a53322d5c0d35b3efaf2a733e4a1 Mon Sep 17 00:00:00 2001 From: Blake Lazarine Date: Wed, 10 Sep 2025 16:28:32 -0700 Subject: [PATCH 1/3] fix(amazonq): fix handling of code review tool findings --- .../amazonq/webview/BrowserConnector.kt | 19 ++++++++++++------- .../webview/FlareAdditionalFindings.kt | 14 ++++++++++++-- .../amazonq/webview/BrowserConnectorTest.kt | 11 +++++++---- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt index ae40e384071..2e225899a23 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt @@ -595,12 +595,12 @@ class BrowserConnector( } chatCommunicationManager.removePartialChatMessage(partialResultToken) val decryptedMessage = value?.let { encryptionManager?.decrypt(it) }.orEmpty() - parseFindingsMessages(decryptedMessage) + val filteredMessage = parseFindingsMessages(decryptedMessage) val messageToChat = ChatCommunicationManager.convertToJsonToSendToChat( SEND_CHAT_COMMAND_PROMPT, tabId, - decryptedMessage, + filteredMessage, isPartialResult = false ) browser.postChat(messageToChat) @@ -618,13 +618,10 @@ class BrowserConnector( val additionalMessages = serializer.objectMapper.readValue(responsePayload).additionalMessages ?: return emptyList() - return additionalMessages.filter { message -> - message.messageId.endsWith(CODE_REVIEW_FINDINGS_SUFFIX) || - message.messageId.endsWith(DISPLAY_FINDINGS_SUFFIX) - } + return additionalMessages } - fun parseFindingsMessages(@Language("JSON") responsePayload: String) { + fun parseFindingsMessages(@Language("JSON") responsePayload: String): String { try { val findings = deserializeFindings(responsePayload) val scannedFiles = mutableListOf() @@ -687,9 +684,17 @@ class BrowserConnector( CodeWhispererConstants.CodeAnalysisScope.AGENTIC ) CodeWhispererCodeScanManager.getInstance(project).showCodeScanUI() + + // Remove findings messages from response payload + val rootNode = serializer.objectMapper.readTree(responsePayload) as ObjectNode + rootNode.remove("additionalMessages") + return serializer.objectMapper.writeValueAsString(rootNode) } + + return responsePayload } catch (e: Exception) { LOG.error(e) { "Failed to parse findings message" } + return responsePayload } } diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/FlareAdditionalFindings.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/FlareAdditionalFindings.kt index 66ae2e10722..a497bf5a59f 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/FlareAdditionalFindings.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/FlareAdditionalFindings.kt @@ -9,7 +9,10 @@ import com.fasterxml.jackson.annotation.Nulls import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Description import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Recommendation import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.SuggestedFix @@ -55,10 +58,17 @@ data class AggregatedCodeScanIssue( ) class FlareAggregatedFindingsDeserializer : JsonDeserializer() { + private val objectMapper = jacksonObjectMapper() + override fun deserialize(p: JsonParser, ctxt: DeserializationContext): FlareAggregatedFindings? = - // drop values that do not look like FlareAggregatedFindings try { - ctxt.readValue(p, FlareAggregatedFindings::class.java) + val node = p.readValueAsTree() + val messageId = node.get("messageId")?.asText() ?: return null + val bodyNode = node.get("body") ?: return null + + val body = objectMapper.readValue>(bodyNode.asText()) + + FlareAggregatedFindings(messageId, body) } catch (_: Exception) { null } diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnectorTest.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnectorTest.kt index 7d4f7cd81bc..5b3922b961f 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnectorTest.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnectorTest.kt @@ -93,7 +93,7 @@ class BrowserConnectorTest : AmazonQTestBase() { "additionalMessages": [ { "messageId": "test_codeReviewFindings", - "body": [{"filePath": "/test/file.kt", "issues": []}] + "body": "[{\"filePath\": \"/test/file.kt\", \"issues\": []}]" }, { "messageId": "other_message", @@ -121,7 +121,7 @@ class BrowserConnectorTest : AmazonQTestBase() { "additionalMessages": [ { "messageId": "test_displayFindings", - "body": [{"filePath": "/test/file.kt", "issues": []}] + "body": "[{\"filePath\": \"/test/file.kt\", \"issues\": []}]" }, { "messageId": "other_message", @@ -179,7 +179,7 @@ class BrowserConnectorTest : AmazonQTestBase() { "additionalMessages": [ { "messageId": "test_codeReviewFindings", - "body": ${jacksonObjectMapper().writeValueAsString(listOf(aggregatedIssue))} + "body": "${jacksonObjectMapper().writeValueAsString(listOf(aggregatedIssue)).replace("\"", "\\\"")}" }, { "messageId": "other_message", @@ -228,7 +228,7 @@ class BrowserConnectorTest : AmazonQTestBase() { "additionalMessages": [ { "messageId": "test_displayFindings", - "body": ${jacksonObjectMapper().writeValueAsString(listOf(aggregatedIssue))} + "body": "${jacksonObjectMapper().writeValueAsString(listOf(aggregatedIssue)).replace("\"", "\\\"")}" }, { "messageId": "other_message", @@ -256,6 +256,9 @@ class BrowserConnectorTest : AmazonQTestBase() { { "messageId": "test_codeReviewFindings", "body": "invalid json" + }, + { + "body": "invalid json" } ] } From a924166b325fd0d827df2704e0e57b47bbc4b23f Mon Sep 17 00:00:00 2001 From: Blake Lazarine Date: Wed, 10 Sep 2025 16:39:40 -0700 Subject: [PATCH 2/3] fix(amazonq): include changelog --- .../bugfix-2cc32b84-5755-4e7c-99ff-965850ff3c7e.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changes/next-release/bugfix-2cc32b84-5755-4e7c-99ff-965850ff3c7e.json diff --git a/.changes/next-release/bugfix-2cc32b84-5755-4e7c-99ff-965850ff3c7e.json b/.changes/next-release/bugfix-2cc32b84-5755-4e7c-99ff-965850ff3c7e.json new file mode 100644 index 00000000000..14d102fdf9b --- /dev/null +++ b/.changes/next-release/bugfix-2cc32b84-5755-4e7c-99ff-965850ff3c7e.json @@ -0,0 +1,4 @@ +{ + "type" : "bugfix", + "description" : "Fix handling of code review findings so they are properly sent to CodeIssues Panel" +} \ No newline at end of file From e84bc5292ba6192a4f2a48e9c0a6c3e309656da2 Mon Sep 17 00:00:00 2001 From: Blake Lazarine Date: Wed, 10 Sep 2025 16:40:59 -0700 Subject: [PATCH 3/3] fix(amazonq): fix detekt failures --- .../jetbrains/services/amazonq/webview/BrowserConnector.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt index 2e225899a23..93df86fdad5 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt @@ -77,8 +77,6 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_BAR_ACTIONS import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_CHANGE import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_TAB_REMOVE -import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CODE_REVIEW_FINDINGS_SUFFIX -import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.DISPLAY_FINDINGS_SUFFIX import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.EncryptedChatParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.EncryptedQuickActionChatParams import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GET_SERIALIZED_CHAT_REQUEST_METHOD @@ -684,13 +682,13 @@ class BrowserConnector( CodeWhispererConstants.CodeAnalysisScope.AGENTIC ) CodeWhispererCodeScanManager.getInstance(project).showCodeScanUI() - + // Remove findings messages from response payload val rootNode = serializer.objectMapper.readTree(responsePayload) as ObjectNode rootNode.remove("additionalMessages") return serializer.objectMapper.writeValueAsString(rootNode) } - + return responsePayload } catch (e: Exception) { LOG.error(e) { "Failed to parse findings message" }