Skip to content

Commit 32834d9

Browse files
authored
fix(codewhisperer): show full reference in reference log (#3326)
1 parent d61acd8 commit 32834d9

File tree

2 files changed

+91
-20
lines changed

2 files changed

+91
-20
lines changed

jetbrains-core/src/software/aws/toolkits/jetbrains/services/codewhisperer/toolwindow/CodeWhispererCodeReferenceManager.kt

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Key
2323
import com.intellij.openapi.util.TextRange
2424
import com.intellij.openapi.wm.ToolWindowManager
2525
import com.intellij.ui.awt.RelativePoint
26+
import software.amazon.awssdk.services.codewhisperer.model.Recommendation
2627
import software.amazon.awssdk.services.codewhisperer.model.Reference
2728
import software.aws.toolkits.jetbrains.services.codewhisperer.editor.CodeWhispererEditorUtil.getPopupPositionAboveText
2829
import software.aws.toolkits.jetbrains.services.codewhisperer.editor.CodeWhispererEditorUtil.getRelativePathToContentRoot
@@ -66,34 +67,17 @@ class CodeWhispererCodeReferenceManager(private val project: Project) {
6667
val (requestContext, _, recommendationContext) = states
6768
val (_, editor, _, caretPosition) = requestContext
6869
val (_, detail, reformattedDetail) = recommendationContext.details[selectedIndex]
69-
val userInput = recommendationContext.userInputSinceInvocation
7070
val startOffset = caretPosition.offset
7171
val relativePath = getRelativePathToContentRoot(editor)
7272
reformattedDetail.references().forEachIndexed { i, reference ->
73-
// start and end could intersect with the userInput, we do not want to show reference for the
74-
// userInput part, so we truncate the range to exclude userInput here if there's an overlap.
75-
if (reference.recommendationContentSpan().end() <= userInput.length) return@forEachIndexed
76-
77-
// Now there's at least some valid range, truncate start if applicable
78-
val spanStartExcludeUserInput = maxOf(reference.recommendationContentSpan().start(), userInput.length)
79-
val start = startOffset + spanStartExcludeUserInput
73+
val start = startOffset + reference.recommendationContentSpan().start()
8074
val end = startOffset + reference.recommendationContentSpan().end()
81-
val startLine = editor.document.getLineNumber(start)
82-
val endLine = editor.document.getLineNumber(end)
83-
val lineNums = if (startLine == endLine) {
84-
(startLine + 1).toString()
85-
} else {
86-
"${startLine + 1} to ${endLine + 1}"
87-
}
88-
89-
val originalSpan = detail.references()[i].recommendationContentSpan()
75+
val lineNums = getReferenceLineNums(editor, start, end)
9076

9177
// There is an unformatted recommendation(directly from response) and reformatted one. We want to get
9278
// the line number, start/end offset of the reformatted one because it's the one inserted to the editor.
9379
// However, the one that shows in the tool window record should show the original recommendation, as below.
94-
val originalContentLines = detail.content().substring(
95-
maxOf(originalSpan.start(), userInput.length), originalSpan.end()
96-
).split("\n")
80+
val originalContentLines = getOriginalContentLines(detail, i)
9781

9882
codeReferenceComponents.contentPanel.apply {
9983
add(
@@ -115,6 +99,24 @@ class CodeWhispererCodeReferenceManager(private val project: Project) {
11599
}
116100
}
117101

102+
fun getReferenceLineNums(editor: Editor, start: Int, end: Int): String {
103+
val startLine = editor.document.getLineNumber(start)
104+
val endLine = editor.document.getLineNumber(end)
105+
val lineNums = if (startLine == endLine) {
106+
(startLine + 1).toString()
107+
} else {
108+
"${startLine + 1} to ${endLine + 1}"
109+
}
110+
return lineNums
111+
}
112+
113+
fun getOriginalContentLines(detail: Recommendation, i: Int): List<String> {
114+
val originalSpan = detail.references()[i].recommendationContentSpan()
115+
return detail.content()
116+
.substring(originalSpan.start(), originalSpan.end())
117+
.split("\n")
118+
}
119+
118120
private fun insertHighLightContext(editor: Editor, start: Int, end: Int, reference: Reference) {
119121
val codeContent = editor.document.getText(TextRange.create(start, end))
120122
val referenceContent = message(
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.codewhisperer
5+
6+
import com.intellij.openapi.project.Project
7+
import com.intellij.testFramework.DisposableRule
8+
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
9+
import com.intellij.testFramework.runInEdtAndWait
10+
import org.assertj.core.api.Assertions.assertThat
11+
import org.junit.Before
12+
import org.junit.Rule
13+
import org.junit.Test
14+
import software.amazon.awssdk.services.codewhisperer.model.Recommendation
15+
import software.amazon.awssdk.services.codewhisperer.model.Reference
16+
import software.amazon.awssdk.services.codewhisperer.model.Span
17+
import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager
18+
import software.aws.toolkits.jetbrains.utils.rules.PythonCodeInsightTestFixtureRule
19+
20+
class CodeWhispererReferenceManagerTest {
21+
@Rule
22+
@JvmField
23+
var projectRule = PythonCodeInsightTestFixtureRule()
24+
25+
@Rule
26+
@JvmField
27+
val disposableRule = DisposableRule()
28+
29+
private val documentContentContent = "012345678\n9"
30+
private lateinit var fixture: CodeInsightTestFixture
31+
private lateinit var project: Project
32+
private val originalReference = Reference.builder()
33+
.licenseName("test_license")
34+
.repository("test_repo")
35+
.recommendationContentSpan(
36+
Span.builder().start(0).end(14).build()
37+
)
38+
.build()
39+
40+
private val recommendation = Recommendation.builder()
41+
.references(originalReference)
42+
.content("test\nreference")
43+
.build()
44+
45+
@Before
46+
fun setup() {
47+
fixture = projectRule.fixture
48+
project = projectRule.project
49+
50+
fixture.configureByText("test.py", documentContentContent)
51+
runInEdtAndWait {
52+
fixture.editor.caretModel.moveToOffset(documentContentContent.length)
53+
}
54+
}
55+
56+
@Test
57+
fun `test getReferenceLineNums return expected line numbers`() {
58+
val referenceManager = CodeWhispererCodeReferenceManager(project)
59+
assertThat(referenceManager.getReferenceLineNums(fixture.editor, 0, 1)).isEqualTo("1")
60+
assertThat(referenceManager.getReferenceLineNums(fixture.editor, 0, 10)).isEqualTo("1 to 2")
61+
}
62+
63+
@Test
64+
fun `test getOriginalContent lines returns full reference lines`() {
65+
val referenceManager = CodeWhispererCodeReferenceManager(project)
66+
val expectedRecommendation = listOf<String>("test", "reference")
67+
assertThat(referenceManager.getOriginalContentLines(recommendation, 0)).isEqualTo(expectedRecommendation)
68+
}
69+
}

0 commit comments

Comments
 (0)