Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type" : "bugfix",
"description" : "Fix handling of code review findings so they are properly sent to CodeIssues Panel"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -595,12 +593,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)
Expand All @@ -618,13 +616,10 @@ class BrowserConnector(
val additionalMessages = serializer.objectMapper.readValue<FlareAdditionalMessages>(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<VirtualFile>()
Expand Down Expand Up @@ -687,9 +682,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
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -55,10 +58,17 @@ data class AggregatedCodeScanIssue(
)

class FlareAggregatedFindingsDeserializer : JsonDeserializer<FlareAggregatedFindings>() {
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<JsonNode>()
val messageId = node.get("messageId")?.asText() ?: return null
val bodyNode = node.get("body") ?: return null

val body = objectMapper.readValue<List<AggregatedCodeScanIssue>>(bodyNode.asText())

FlareAggregatedFindings(messageId, body)
} catch (_: Exception) {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -256,6 +256,9 @@ class BrowserConnectorTest : AmazonQTestBase() {
{
"messageId": "test_codeReviewFindings",
"body": "invalid json"
},
{
"body": "invalid json"
}
]
}
Expand Down
Loading