Skip to content

Commit c3b2b47

Browse files
committed
tst
1 parent cdc4564 commit c3b2b47

File tree

3 files changed

+110
-60
lines changed

3 files changed

+110
-60
lines changed

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt

Lines changed: 14 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,6 @@ import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.auth.isFeature
117117
import software.aws.toolkits.jetbrains.services.codemodernizer.utils.isCodeTransformAvailable
118118
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanIssue
119119
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanManager
120-
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Description
121-
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Recommendation
122-
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.SuggestedFix
123120
import software.aws.toolkits.jetbrains.services.codewhisperer.settings.CodeWhispererConfigurable
124121
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
125122
import software.aws.toolkits.jetbrains.settings.MeetQSettings
@@ -583,48 +580,6 @@ class BrowserConnector(
583580
}
584581
}
585582

586-
/**
587-
* Solely used to extract the aggregated findings from the response
588-
*/
589-
// TODO: move to software.aws.toolkits.jetbrains.services.amazonq.lsp.model
590-
data class FlareAdditionalMessages(
591-
val additionalMessages: List<FlareAggregatedFindings>?,
592-
)
593-
594-
// TODO: move to software.aws.toolkits.jetbrains.services.amazonq.lsp.model
595-
data class FlareAggregatedFindings(
596-
val messageId: String,
597-
val body: List<AggregatedCodeScanIssue>,
598-
)
599-
600-
// TODO: move to software.aws.toolkits.jetbrains.services.amazonq.lsp.model
601-
data class FlareCodeScanIssue(
602-
val startLine: Int,
603-
val endLine: Int,
604-
val comment: String?,
605-
val title: String,
606-
val description: Description,
607-
val detectorId: String,
608-
val detectorName: String,
609-
val findingId: String,
610-
val ruleId: String?,
611-
val relatedVulnerabilities: List<String>,
612-
val severity: String,
613-
val recommendation: Recommendation,
614-
val suggestedFixes: List<SuggestedFix>,
615-
val scanJobId: String,
616-
val language: String,
617-
val autoDetected: Boolean,
618-
val filePath: String,
619-
val findingContext: String,
620-
)
621-
622-
// TODO: move to software.aws.toolkits.jetbrains.services.amazonq.lsp.model
623-
data class AggregatedCodeScanIssue(
624-
val filePath: String,
625-
val issues: List<FlareCodeScanIssue>,
626-
)
627-
628583
private fun showResult(
629584
result: CompletableFuture<String>,
630585
partialResultToken: String,
@@ -658,18 +613,23 @@ class BrowserConnector(
658613
}
659614
}
660615

616+
fun deserializeFindings(@Language("JSON") responsePayload: String): List<FlareAggregatedFindings> {
617+
val additionalMessages = serializer.objectMapper.readValue<FlareAdditionalMessages>(responsePayload).additionalMessages
618+
?: return emptyList()
619+
620+
return additionalMessages.filter { message ->
621+
message.messageId.endsWith(CODE_REVIEW_FINDINGS_SUFFIX) ||
622+
message.messageId.endsWith(DISPLAY_FINDINGS_SUFFIX)
623+
}
624+
}
625+
661626
fun parseFindingsMessages(@Language("JSON") responsePayload: String) {
662627
try {
663-
val additionalMessages = serializer.objectMapper.readValue<FlareAdditionalMessages>(responsePayload).additionalMessages
664-
val findingsMessages = additionalMessages?.filter { message ->
665-
message.messageId.endsWith(CODE_REVIEW_FINDINGS_SUFFIX) ||
666-
message.messageId.endsWith(DISPLAY_FINDINGS_SUFFIX)
667-
} ?: return
668-
628+
val findings = deserializeFindings(responsePayload)
669629
val scannedFiles = mutableListOf<VirtualFile>()
670630
val mappedFindings = buildList {
671-
for (findingsMessage in findingsMessages) {
672-
for (aggregatedIssue in findingsMessage.body) {
631+
for (finding in findings) {
632+
for (aggregatedIssue in finding.body) {
673633
val file = LocalFileSystem.getInstance().findFileByIoFile(
674634
Path.of(aggregatedIssue.filePath).toFile()
675635
)
@@ -728,7 +688,7 @@ class BrowserConnector(
728688
CodeWhispererCodeScanManager.getInstance(project).showCodeScanUI()
729689
}
730690
} catch (e: Exception) {
731-
LOG.error { "Failed to parse findings message $e" }
691+
LOG.error(e) { "Failed to parse findings message" }
732692
}
733693
}
734694

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// TODO: move to software.aws.toolkits.jetbrains.services.amazonq.lsp.model
5+
package software.aws.toolkits.jetbrains.services.amazonq.webview
6+
7+
import com.fasterxml.jackson.annotation.JsonSetter
8+
import com.fasterxml.jackson.annotation.Nulls
9+
import com.fasterxml.jackson.core.JsonParser
10+
import com.fasterxml.jackson.databind.DeserializationContext
11+
import com.fasterxml.jackson.databind.JsonDeserializer
12+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
13+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Description
14+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Recommendation
15+
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.SuggestedFix
16+
17+
/**
18+
* Solely used to extract the aggregated findings from the response
19+
*/
20+
data class FlareAdditionalMessages(
21+
@get:JsonDeserialize(contentUsing = FlareAggregatedFindingsDeserializer::class)
22+
@get:JsonSetter(contentNulls = Nulls.SKIP)
23+
val additionalMessages: List<FlareAggregatedFindings>?,
24+
)
25+
26+
data class FlareAggregatedFindings(
27+
val messageId: String,
28+
val body: List<AggregatedCodeScanIssue>,
29+
)
30+
31+
data class FlareCodeScanIssue(
32+
val startLine: Int,
33+
val endLine: Int,
34+
val comment: String?,
35+
val title: String,
36+
val description: Description,
37+
val detectorId: String,
38+
val detectorName: String,
39+
val findingId: String,
40+
val ruleId: String?,
41+
val relatedVulnerabilities: List<String>,
42+
val severity: String,
43+
val recommendation: Recommendation,
44+
val suggestedFixes: List<SuggestedFix>,
45+
val scanJobId: String,
46+
val language: String,
47+
val autoDetected: Boolean,
48+
val filePath: String,
49+
val findingContext: String,
50+
)
51+
52+
data class AggregatedCodeScanIssue(
53+
val filePath: String,
54+
val issues: List<FlareCodeScanIssue>,
55+
)
56+
57+
class FlareAggregatedFindingsDeserializer : JsonDeserializer<FlareAggregatedFindings>() {
58+
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): FlareAggregatedFindings? =
59+
// drop values that do not look like FlareAggregatedFindings
60+
try {
61+
ctxt.readValue(p, FlareAggregatedFindings::class.java)
62+
} catch (_: Exception) {
63+
null
64+
}
65+
}

plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnectorTest.kt

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Descripti
3030
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.Recommendation
3131
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.SuggestedFix
3232
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
33+
import software.aws.toolkits.jetbrains.utils.satisfiesKt
3334

3435
class BrowserConnectorTest : AmazonQTestBase() {
3536
private lateinit var browserConnector: BrowserConnector
@@ -102,7 +103,15 @@ class BrowserConnectorTest : AmazonQTestBase() {
102103
}
103104
""".trimIndent()
104105

105-
browserConnector.parseFindingsMessages(findingsMessage)
106+
assertThat(browserConnector.deserializeFindings(findingsMessage))
107+
.singleElement()
108+
.satisfiesKt {
109+
assertThat(it.messageId).isEqualTo("test_codeReviewFindings")
110+
assertThat(it.body).singleElement()
111+
.satisfiesKt { finding ->
112+
assertThat(finding.filePath).isEqualTo("/test/file.kt")
113+
}
114+
}
106115
}
107116

108117
@Test
@@ -122,7 +131,15 @@ class BrowserConnectorTest : AmazonQTestBase() {
122131
}
123132
""".trimIndent()
124133

125-
browserConnector.parseFindingsMessages(findingsMessage)
134+
assertThat(browserConnector.deserializeFindings(findingsMessage))
135+
.singleElement()
136+
.satisfiesKt {
137+
assertThat(it.messageId).isEqualTo("test_displayFindings")
138+
assertThat(it.body).singleElement()
139+
.satisfiesKt { finding ->
140+
assertThat(finding.filePath).isEqualTo("/test/file.kt")
141+
}
142+
}
126143
}
127144

128145
@Test
@@ -145,7 +162,7 @@ class BrowserConnectorTest : AmazonQTestBase() {
145162
whenever(mockFileDocumentManager.getDocument(mockVirtualFile)) doReturn mockDocument
146163
whenever(mockCodeScanManager.isIgnoredIssue(any(), any(), any(), any())) doReturn false
147164

148-
val issue = BrowserConnector.FlareCodeScanIssue(
165+
val issue = FlareCodeScanIssue(
149166
startLine = 1, endLine = 1, comment = "Test comment", title = "Test Issue",
150167
description = Description("Test description", "Test text"), detectorId = "test-detector",
151168
detectorName = "Test Detector", findingId = "test-finding-id", ruleId = "test-rule",
@@ -156,13 +173,17 @@ class BrowserConnectorTest : AmazonQTestBase() {
156173
filePath = "/test/file.kt", findingContext = "test context"
157174
)
158175

159-
val aggregatedIssue = BrowserConnector.AggregatedCodeScanIssue("/test/file.kt", listOf(issue))
176+
val aggregatedIssue = AggregatedCodeScanIssue("/test/file.kt", listOf(issue))
160177
val findingsMessage = """
161178
{
162179
"additionalMessages": [
163180
{
164181
"messageId": "test_codeReviewFindings",
165182
"body": ${jacksonObjectMapper().writeValueAsString(listOf(aggregatedIssue))}
183+
},
184+
{
185+
"messageId": "other_message",
186+
"body": "other content"
166187
}
167188
]
168189
}
@@ -191,7 +212,7 @@ class BrowserConnectorTest : AmazonQTestBase() {
191212
localFileSystemMock.`when`<LocalFileSystem> { LocalFileSystem.getInstance() } doReturn mockLocalFileSystem
192213
whenever(mockLocalFileSystem.findFileByIoFile(any())) doReturn mockDirectoryFile
193214

194-
val issue = BrowserConnector.FlareCodeScanIssue(
215+
val issue = FlareCodeScanIssue(
195216
startLine = 1, endLine = 1, comment = null, title = "Test Issue",
196217
description = Description("Test description", "Test text"), detectorId = "test-detector",
197218
detectorName = "Test Detector", findingId = "test-finding-id", ruleId = null,
@@ -201,13 +222,17 @@ class BrowserConnectorTest : AmazonQTestBase() {
201222
filePath = "/test/directory", findingContext = "test context"
202223
)
203224

204-
val aggregatedIssue = BrowserConnector.AggregatedCodeScanIssue("/test/directory", listOf(issue))
225+
val aggregatedIssue = AggregatedCodeScanIssue("/test/directory", listOf(issue))
205226
val findingsMessage = """
206227
{
207228
"additionalMessages": [
208229
{
209230
"messageId": "test_displayFindings",
210231
"body": ${jacksonObjectMapper().writeValueAsString(listOf(aggregatedIssue))}
232+
},
233+
{
234+
"messageId": "other_message",
235+
"body": "other content"
211236
}
212237
]
213238
}

0 commit comments

Comments
 (0)