Skip to content

Commit 6340ef4

Browse files
authored
Merge branch 'main' into bugfix/amazon-q-doc-retry-button
2 parents 83a69b2 + 881398e commit 6340ef4

File tree

8 files changed

+166
-8
lines changed

8 files changed

+166
-8
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "Amazon Q Doc README diff will re-open when the README file is clicked after it has been closed"
4+
}s
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "Amazon Q /test: Fix for test generation payload creation to not filter out target file."
4+
}

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqCodeTest/controller/CodeTestChatController.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWh
7272
import software.aws.toolkits.jetbrains.services.codewhisperer.language.CodeWhispererProgrammingLanguage
7373
import software.aws.toolkits.jetbrains.services.codewhisperer.language.programmingLanguage
7474
import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager
75+
import software.aws.toolkits.jetbrains.services.codewhisperer.util.isWithin
7576
import software.aws.toolkits.jetbrains.services.cwc.ChatConstants
7677
import software.aws.toolkits.jetbrains.services.cwc.clients.chat.model.ChatRequestData
7778
import software.aws.toolkits.jetbrains.services.cwc.clients.chat.model.TriggerType
@@ -277,7 +278,7 @@ class CodeTestChatController(
277278

278279
val requestData = ChatRequestData(
279280
tabId = session.tabId,
280-
message = "Generate unit tests for the following part of my code: ${message.prompt}",
281+
message = "Generate unit tests for the following part of my code: ${message.prompt.ifBlank { fileInfo.fileName }}",
281282
activeFileContext = activeFileContext,
282283
userIntent = UserIntent.GENERATE_UNIT_TESTS,
283284
triggerType = TriggerType.ContextMenu,
@@ -1176,7 +1177,7 @@ class CodeTestChatController(
11761177
filePath = activeFile.path,
11771178
fileName = activeFile.name,
11781179
fileLanguage = programmingLanguage,
1179-
fileInWorkspace = activeFile.path.startsWith(projectRoot.path)
1180+
fileInWorkspace = activeFile.isWithin(projectRoot)
11801181
)
11811182
} catch (e: Exception) {
11821183
LOG.debug { "Error checking active file: $e" }

plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevSessionContextTest.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class FeatureDevSessionContextTest : FeatureDevTestBase(HeavyJavaCodeInsightTest
7575
@Test
7676
fun testZipProject() {
7777
addFilesToProjectModule(
78+
".gitignore",
7879
".gradle/cached.jar",
7980
"src/MyClass.java",
8081
"gradlew",
@@ -83,6 +84,19 @@ class FeatureDevSessionContextTest : FeatureDevTestBase(HeavyJavaCodeInsightTest
8384
"settings.gradle",
8485
"build.gradle",
8586
"gradle/wrapper/gradle-wrapper.properties",
87+
"builder/GetTestBuilder.java", // check for false positives
88+
".aws-sam/build/function1",
89+
".gem/specs.rb",
90+
"archive.zip",
91+
"output.bin",
92+
"images/logo.png",
93+
"assets/header.jpg",
94+
"icons/menu.svg",
95+
"license.txt",
96+
"License.md",
97+
"node_modules/express",
98+
"build/outputs",
99+
"dist/bundle.js"
86100
)
87101

88102
val zipResult = featureDevSessionContext.getProjectZip()
@@ -102,9 +116,10 @@ class FeatureDevSessionContextTest : FeatureDevTestBase(HeavyJavaCodeInsightTest
102116
"gradlew",
103117
"gradlew.bat",
104118
"README.md",
119+
"gradle/wrapper/gradle-wrapper.properties",
120+
"builder/GetTestBuilder.java",
105121
"settings.gradle",
106122
"build.gradle",
107-
"gradle/wrapper/gradle-wrapper.properties",
108123
)
109124

110125
assertTrue(zippedFiles == expectedFiles)

plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerTest.kt

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,121 @@ class FeatureDevControllerTest : FeatureDevTestBase() {
433433
}
434434
}
435435

436+
@Test
437+
fun `test handleChat onCodeGeneration sends correct add code messages`() = runTest {
438+
val totalIterations = 10
439+
440+
for (remainingIterations in 0 until totalIterations) {
441+
val message = if (remainingIterations > 2) {
442+
message("amazonqFeatureDev.code_generation.iteration_counts_ask_to_add_code_or_feedback")
443+
} else if (remainingIterations > 0) {
444+
message(
445+
"amazonqFeatureDev.code_generation.iteration_counts",
446+
remainingIterations,
447+
totalIterations,
448+
)
449+
} else {
450+
message(
451+
"amazonqFeatureDev.code_generation.iteration_counts_ask_to_add_code",
452+
remainingIterations,
453+
totalIterations,
454+
)
455+
}
456+
val mockSession = mock<Session>()
457+
val featureDevService = mockk<FeatureDevService>()
458+
val repoContext = mock<FeatureDevSessionContext>()
459+
val sessionStateConfig = SessionStateConfig(testConversationId, repoContext, featureDevService)
460+
val mockInteraction = mock<Interaction>()
461+
whenever(mockSession.send(userMessage)).thenReturn(mockInteraction)
462+
whenever(mockSession.sessionState).thenReturn(
463+
PrepareCodeGenerationState(
464+
testTabId,
465+
CancellationTokenSource(),
466+
"test-command",
467+
sessionStateConfig,
468+
newFileContents,
469+
deletedFiles,
470+
testReferences,
471+
testUploadId,
472+
1,
473+
messenger,
474+
remainingIterations,
475+
totalIterations,
476+
diffMetricsProcessed = DiffMetricsProcessed(HashSet(), HashSet()),
477+
),
478+
)
479+
480+
controller.onCodeGeneration(mockSession, userMessage, testTabId)
481+
482+
coVerify {
483+
messenger.sendAnswer(
484+
tabId = testTabId,
485+
messageType = FeatureDevMessageType.Answer,
486+
message = message
487+
)
488+
}
489+
}
490+
}
491+
492+
@Test
493+
fun `test handleChat onCodeGeneration sends correct messages after cancellation`() = runTest {
494+
val totalIterations = 10
495+
496+
for (remainingIterations in -1 until totalIterations) {
497+
// remainingIterations < 0 is to represent the null case
498+
val message = if (remainingIterations > 2 || remainingIterations < 0) {
499+
message("amazonqFeatureDev.code_generation.stopped_code_generation_no_iteration_count_display")
500+
} else if (remainingIterations > 0) {
501+
message(
502+
"amazonqFeatureDev.code_generation.stopped_code_generation",
503+
remainingIterations,
504+
totalIterations,
505+
)
506+
} else {
507+
message(
508+
"amazonqFeatureDev.code_generation.stopped_code_generation_no_iterations",
509+
remainingIterations,
510+
totalIterations,
511+
)
512+
}
513+
val mockSession = mock<Session>()
514+
val featureDevService = mockk<FeatureDevService>()
515+
val repoContext = mock<FeatureDevSessionContext>()
516+
val sessionStateConfig = SessionStateConfig(testConversationId, repoContext, featureDevService)
517+
val mockInteraction = mock<Interaction>()
518+
val token = CancellationTokenSource()
519+
token.cancel()
520+
whenever(mockSession.send(userMessage)).thenReturn(mockInteraction)
521+
whenever(mockSession.sessionState).thenReturn(
522+
PrepareCodeGenerationState(
523+
testTabId,
524+
token,
525+
"test-command",
526+
sessionStateConfig,
527+
newFileContents,
528+
deletedFiles,
529+
testReferences,
530+
testUploadId,
531+
1,
532+
messenger,
533+
(if (remainingIterations < 0) null else remainingIterations),
534+
totalIterations,
535+
diffMetricsProcessed = DiffMetricsProcessed(HashSet(), HashSet()),
536+
),
537+
)
538+
539+
controller.onCodeGeneration(mockSession, userMessage, testTabId)
540+
541+
coVerify {
542+
messenger.sendAnswer(
543+
tabId = testTabId,
544+
messageType = FeatureDevMessageType.Answer,
545+
message = message
546+
)
547+
}
548+
}
549+
}
550+
436551
@Test
437552
fun `test handleChat onCodeGeneration sends success metrics`() = runTest {
438553
val mockSession = mock<Session>()

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/codetest/sessionconfig/CodeTestSessionConfig.kt

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.language.programmi
3333
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.CODE_SCAN_CREATE_PAYLOAD_TIMEOUT_IN_SECONDS
3434
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.DEFAULT_CODE_SCAN_TIMEOUT_IN_SECONDS
3535
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.DEFAULT_PAYLOAD_LIMIT_IN_BYTES
36+
import software.aws.toolkits.jetbrains.services.codewhisperer.util.isWithin
3637
import software.aws.toolkits.resources.message
3738
import java.io.File
3839
import java.nio.file.Path
@@ -88,7 +89,10 @@ class CodeTestSessionConfig(
8889
LOG.debug { "Creating payload. File selected as root for the context truncation: ${projectRoot.path}" }
8990

9091
val payloadMetadata: PayloadMetadata = try {
91-
getProjectPayloadMetadata()
92+
when {
93+
!selectedFile.isWithin(projectRoot) -> cannotFindValidFile("Selected file is not within the project")
94+
else -> getProjectPayloadMetadata()
95+
}
9296
} catch (e: Exception) {
9397
val errorMessage = when {
9498
e.message?.contains("Illegal repetition near index") == true -> "Illegal repetition near index"
@@ -141,7 +145,7 @@ class CodeTestSessionConfig(
141145
}
142146

143147
// 2. Add the "utgRequiredArtifactsDir" directory
144-
val utgDir = "utgRequiredArtifactsDir"
148+
val utgDir = "utgRequiredArtifactsDir/" // Note the trailing slash which adds it as a directory and not a file
145149
LOG.debug { "Adding directory to ZIP: $utgDir" }
146150
val utgEntry = ZipEntry(utgDir)
147151
it.putNextEntry(utgEntry)
@@ -150,7 +154,7 @@ class CodeTestSessionConfig(
150154
val buildAndExecuteLogDir = "buildAndExecuteLogDir"
151155
val subDirs = listOf(buildAndExecuteLogDir, "repoMapData", "testCoverageDir")
152156
subDirs.forEach { subDir ->
153-
val subDirPathString = Path.of(utgDir, subDir).name
157+
val subDirPathString = Path.of(utgDir, subDir).toString() + "/" // Added trailing slash similar to utgRequiredArtifactsDir
154158
LOG.debug { "Adding empty directory to ZIP: $subDirPathString" }
155159
val zipEntry = ZipEntry(subDirPathString)
156160
it.putNextEntry(zipEntry)
@@ -168,6 +172,18 @@ class CodeTestSessionConfig(
168172
var currentTotalLines = 0L
169173
val languageCounts = mutableMapOf<CodeWhispererProgrammingLanguage, Int>()
170174

175+
// Adding Target File to make sure target file doesn't get filtered out.
176+
selectedFile?.let { selected ->
177+
files.add(selected.path)
178+
currentTotalFileSize += selected.length
179+
currentTotalLines += countLinesInVirtualFile(selected)
180+
selected.programmingLanguage().let { language ->
181+
if (language !is CodeWhispererUnknownLanguage) {
182+
languageCounts[language] = (languageCounts[language] ?: 0) + 1
183+
}
184+
}
185+
}
186+
171187
moduleLoop@ for (module in project.modules) {
172188
val changeListManager = ChangeListManager.getInstance(module.project)
173189
if (module.guessModuleDir() != null) {
@@ -176,7 +192,8 @@ class CodeTestSessionConfig(
176192
val current = stack.pop()
177193

178194
if (!current.isDirectory) {
179-
if (current.isFile && !changeListManager.isIgnoredFile(current) &&
195+
if (current.isFile && current.path != selectedFile?.path &&
196+
!changeListManager.isIgnoredFile(current) &&
180197
runBlocking { !featureDevSessionContext.ignoreFile(current) } &&
181198
runReadAction { !fileIndex.isInLibrarySource(current) }
182199
) {

plugins/amazonq/mynah-ui/src/mynah-ui/ui/connector.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,9 @@ export class Connector {
519519
case 'codetest':
520520
this.codeTestChatConnector.onFormButtonClick(tabID, messageId ?? '', {id: "utg_view_diff"})
521521
break
522+
case 'doc':
523+
this.docChatConnector.onOpenDiff(tabID, filePath, deleted)
524+
break
522525
}
523526
}
524527

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/FeatureDevSessionContext.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ class FeatureDevSessionContext(val project: Project, val maxProjectSizeBytes: Lo
256256
.replace(".", "\\.")
257257
.replace("*", ".*")
258258
.let { if (it.endsWith("/")) "$it.*" else "$it/.*" } // Add a trailing /* to all patterns. (we add a trailing / to all files when matching)
259-
260259
var selectedSourceFolder: VirtualFile
261260
set(newRoot) {
262261
_selectedSourceFolder = newRoot

0 commit comments

Comments
 (0)