Skip to content

Commit 9868e35

Browse files
authored
Merge branch 'main' into aalpert/remove-telemetry
2 parents 246fd90 + 3f3726b commit 9868e35

File tree

22 files changed

+518
-495
lines changed

22 files changed

+518
-495
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "feature",
3+
"description" : "AmazonQ /dev and /doc: Add support for complex workspaces."
4+
}

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/common/session/SessionStateTypes.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
package software.aws.toolkits.jetbrains.common.session
55

66
import software.aws.toolkits.jetbrains.common.util.AmazonQCodeGenService
7-
import software.aws.toolkits.jetbrains.services.amazonq.FeatureDevSessionContext
7+
import software.aws.toolkits.jetbrains.services.amazonq.project.FeatureDevSessionContext
88

99
open class SessionStateConfig(
1010
open val conversationId: String,

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqDoc/controller/DocController.kt

+8-24
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ import com.intellij.diff.util.DiffUserDataKeys
1313
import com.intellij.ide.BrowserUtil
1414
import com.intellij.openapi.application.runInEdt
1515
import com.intellij.openapi.fileEditor.FileEditorManager
16-
import com.intellij.openapi.project.Project
17-
import com.intellij.openapi.roots.ProjectRootManager
18-
import com.intellij.openapi.vfs.LocalFileSystem
1916
import com.intellij.openapi.vfs.VfsUtil
2017
import com.intellij.openapi.wm.ToolWindowManager
2118
import com.intellij.testFramework.LightVirtualFile
@@ -31,9 +28,9 @@ import software.aws.toolkits.core.utils.info
3128
import software.aws.toolkits.core.utils.warn
3229
import software.aws.toolkits.jetbrains.common.util.selectFolder
3330
import software.aws.toolkits.jetbrains.core.coroutines.EDT
34-
import software.aws.toolkits.jetbrains.services.amazonq.RepoSizeError
3531
import software.aws.toolkits.jetbrains.services.amazonq.apps.AmazonQAppInitContext
3632
import software.aws.toolkits.jetbrains.services.amazonq.auth.AuthController
33+
import software.aws.toolkits.jetbrains.services.amazonq.project.RepoSizeError
3734
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindowFactory
3835
import software.aws.toolkits.jetbrains.services.amazonqDoc.DEFAULT_RETRY_LIMIT
3936
import software.aws.toolkits.jetbrains.services.amazonqDoc.DIAGRAM_SVG_EXT
@@ -81,7 +78,6 @@ import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.Cancellat
8178
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.QFeatureEvent
8279
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.broadcastQEvent
8380
import software.aws.toolkits.resources.message
84-
import java.nio.file.Paths
8581
import java.util.UUID
8682

8783
enum class DocGenerationStep {
@@ -308,7 +304,7 @@ class DocController(
308304
val session = getSessionInfo(tabId)
309305
val docGenerationTask = docGenerationTasks.getTask(tabId)
310306

311-
val currentSourceFolder = session.context.selectedSourceFolder
307+
val currentSourceFolder = session.context.selectionRoot
312308

313309
try {
314310
messenger.sendFolderConfirmationMessage(
@@ -405,7 +401,7 @@ class DocController(
405401
inMemoryFile.isWritable = false
406402
FileEditorManager.getInstance(context.project).openFile(inMemoryFile, true)
407403
} else {
408-
val existingFile = VfsUtil.findRelativeFile(message.filePath, session.context.selectedSourceFolder)
404+
val existingFile = VfsUtil.findRelativeFile(message.filePath, session.context.addressableRoot)
409405
val leftDiffContent = if (existingFile == null) {
410406
EmptyContent()
411407
} else {
@@ -945,19 +941,9 @@ class DocController(
945941
}
946942
}
947943

948-
private fun isFolderPathInProjectModules(project: Project, folderPath: String): Boolean {
949-
val path = Paths.get(folderPath)
950-
val virtualFile = LocalFileSystem.getInstance().findFileByIoFile(path.toFile()) ?: return false
951-
952-
val projectFileIndex = ProjectRootManager.getInstance(project).fileIndex
953-
954-
return projectFileIndex.isInProject(virtualFile)
955-
}
956-
957944
private suspend fun modifyDefaultSourceFolder(tabId: String) {
958945
val session = getSessionInfo(tabId)
959-
val currentSourceFolder = session.context.selectedSourceFolder
960-
val projectRoot = session.context.projectRoot
946+
val workspaceRoot = session.context.workspaceRoot
961947
val docGenerationTask = docGenerationTasks.getTask(tabId)
962948

963949
withContext(EDT) {
@@ -967,7 +953,7 @@ class DocController(
967953
message = message("amazonqDoc.prompt.choose_folder_to_continue")
968954
)
969955

970-
val selectedFolder = selectFolder(context.project, currentSourceFolder)
956+
val selectedFolder = selectFolder(context.project, workspaceRoot)
971957

972958
// No folder was selected
973959
if (selectedFolder == null) {
@@ -980,9 +966,7 @@ class DocController(
980966
return@withContext
981967
}
982968

983-
val isFolderPathInProject = isFolderPathInProjectModules(context.project, selectedFolder.path)
984-
985-
if (!isFolderPathInProject) {
969+
if (!selectedFolder.path.startsWith(workspaceRoot.path)) {
986970
logger.info { "Selected folder not in workspace: ${selectedFolder.path}" }
987971

988972
messenger.sendAnswer(
@@ -1004,15 +988,15 @@ class DocController(
1004988
return@withContext
1005989
}
1006990

1007-
if (selectedFolder.path == projectRoot.path) {
991+
if (selectedFolder.path == workspaceRoot.path) {
1008992
docGenerationTask.folderLevel = DocFolderLevel.ENTIRE_WORKSPACE
1009993
} else {
1010994
docGenerationTask.folderLevel = DocFolderLevel.SUB_FOLDER
1011995
}
1012996

1013997
logger.info { "Selected correct folder inside workspace: ${selectedFolder.path}" }
1014998

1015-
session.context.selectedSourceFolder = selectedFolder
999+
session.context.selectionRoot = selectedFolder
10161000

10171001
promptForDocTarget(tabId)
10181002

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqDoc/session/DocSession.kt

+5-7
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,12 @@ class DocSession(val tabID: String, val project: Project) {
107107
* Triggered by the Insert code follow-up button to apply code changes.
108108
*/
109109
fun insertChanges(filePaths: List<NewFileZipInfo>, deletedFiles: List<DeletedFileInfo>) {
110-
val selectedSourceFolder = context.selectedSourceFolder.toNioPath()
110+
filePaths.forEach { resolveAndCreateOrUpdateFile(context.addressableRoot.toNioPath(), it.zipFilePath, it.fileContent) }
111111

112-
filePaths.forEach { resolveAndCreateOrUpdateFile(selectedSourceFolder, it.zipFilePath, it.fileContent) }
113-
114-
deletedFiles.forEach { resolveAndDeleteFile(selectedSourceFolder, it.zipFilePath) }
112+
deletedFiles.forEach { resolveAndDeleteFile(context.addressableRoot.toNioPath(), it.zipFilePath) }
115113

116114
// Taken from https://intellij-support.jetbrains.com/hc/en-us/community/posts/206118439-Refresh-after-external-changes-to-project-structure-and-sources
117-
VfsUtil.markDirtyAndRefresh(true, true, true, context.selectedSourceFolder)
115+
VfsUtil.markDirtyAndRefresh(true, true, true, context.addressableRoot)
118116
}
119117

120118
private fun getFromReportedChanges(filePath: NewFileZipInfo): String? {
@@ -158,7 +156,7 @@ class DocSession(val tabID: String, val project: Project) {
158156
}
159157
} else {
160158
val sourceContent = reportedChange
161-
?: VfsUtil.findRelativeFile(filePath.zipFilePath, context.selectedSourceFolder)?.content()
159+
?: VfsUtil.findRelativeFile(filePath.zipFilePath, context.addressableRoot)?.content()
162160
.orEmpty()
163161
val diffMetrics = getDiffMetrics(sourceContent, content)
164162
totalAddedLines += diffMetrics.insertedLines
@@ -185,7 +183,7 @@ class DocSession(val tabID: String, val project: Project) {
185183
totalAddedChars += content.length
186184
totalAddedLines += content.split('\n').size
187185
} else {
188-
val existingFileContent = VfsUtil.findRelativeFile(filePath.zipFilePath, context.selectedSourceFolder)?.content()
186+
val existingFileContent = VfsUtil.findRelativeFile(filePath.zipFilePath, context.addressableRoot)?.content()
189187
val diffMetrics = getDiffMetrics(existingFileContent.orEmpty(), content)
190188
totalAddedLines += diffMetrics.insertedLines
191189
totalAddedChars += diffMetrics.insertedCharacters

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqDoc/session/DocSessionContext.kt

+2-26
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,6 @@
44
package software.aws.toolkits.jetbrains.services.amazonqDoc.session
55

66
import com.intellij.openapi.project.Project
7-
import com.intellij.openapi.vfs.VirtualFile
8-
import software.aws.toolkits.jetbrains.services.amazonq.FeatureDevSessionContext
9-
import software.aws.toolkits.jetbrains.services.amazonqDoc.SUPPORTED_DIAGRAM_EXT_SET
10-
import software.aws.toolkits.jetbrains.services.amazonqDoc.SUPPORTED_DIAGRAM_FILE_NAME_SET
7+
import software.aws.toolkits.jetbrains.services.amazonq.project.FeatureDevSessionContext
118

12-
class DocSessionContext(project: Project, maxProjectSizeBytes: Long? = null) : FeatureDevSessionContext(project, maxProjectSizeBytes) {
13-
14-
/**
15-
* Ensure diagram files are not ignored
16-
*/
17-
override fun getAdditionalGitIgnoreBinaryFilesRules(): Set<String> {
18-
val ignoreRules = super.getAdditionalGitIgnoreBinaryFilesRules()
19-
val diagramExtRulesInGitIgnoreFormatSet = SUPPORTED_DIAGRAM_EXT_SET.map { "*.$it" }.toSet()
20-
return ignoreRules - diagramExtRulesInGitIgnoreFormatSet
21-
}
22-
23-
/**
24-
* Ensure diagram files are not filtered
25-
*/
26-
override fun isFileExtensionAllowed(file: VirtualFile): Boolean {
27-
if (super.isFileExtensionAllowed(file)) {
28-
return true
29-
}
30-
31-
return file.extension != null && SUPPORTED_DIAGRAM_FILE_NAME_SET.contains(file.name)
32-
}
33-
}
9+
class DocSessionContext(project: Project, maxProjectSizeBytes: Long? = null) : FeatureDevSessionContext(project, maxProjectSizeBytes)

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevExceptions.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
package software.aws.toolkits.jetbrains.services.amazonqFeatureDev
55

6-
import software.aws.toolkits.jetbrains.services.amazonq.RepoSizeError
6+
import software.aws.toolkits.jetbrains.services.amazonq.project.RepoSizeError
77
import software.aws.toolkits.resources.message
88

99
/**

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevController.kt

+8-10
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ import software.aws.toolkits.core.utils.info
2929
import software.aws.toolkits.core.utils.warn
3030
import software.aws.toolkits.jetbrains.common.util.selectFolder
3131
import software.aws.toolkits.jetbrains.core.coroutines.EDT
32-
import software.aws.toolkits.jetbrains.services.amazonq.RepoSizeError
3332
import software.aws.toolkits.jetbrains.services.amazonq.apps.AmazonQAppInitContext
3433
import software.aws.toolkits.jetbrains.services.amazonq.auth.AuthController
3534
import software.aws.toolkits.jetbrains.services.amazonq.messages.MessagePublisher
35+
import software.aws.toolkits.jetbrains.services.amazonq.project.RepoSizeError
3636
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindowFactory
3737
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.CodeIterationLimitException
3838
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.DEFAULT_RETRY_LIMIT
@@ -249,7 +249,7 @@ class FeatureDevController(
249249
when (sessionState) {
250250
is PrepareCodeGenerationState -> {
251251
runInEdt {
252-
val existingFile = VfsUtil.findRelativeFile(message.filePath, session.context.selectedSourceFolder)
252+
val existingFile = VfsUtil.findRelativeFile(message.filePath, session.context.addressableRoot)
253253

254254
val leftDiffContent = if (existingFile == null) {
255255
EmptyContent()
@@ -336,7 +336,7 @@ class FeatureDevController(
336336
var pollAttempt = 0
337337
val pollDelayMs = 10L
338338
while (pollAttempt < 5) {
339-
val file = VfsUtil.findRelativeFile(message.filePath, session.context.selectedSourceFolder)
339+
val file = VfsUtil.findRelativeFile(message.filePath, session.context.addressableRoot)
340340
// Wait for the file to be created and/or updated to the new content:
341341
if (file != null && file.content() == filePaths.find { it.zipFilePath == fileToUpdate }?.fileContent) {
342342
// Open a diff, showing the changes have been applied and the file now has identical left/right state:
@@ -729,7 +729,7 @@ class FeatureDevController(
729729

730730
val codeWhispererSettings = CodeWhispererSettings.getInstance().getAutoBuildSetting()
731731
val hasDevFile = session.context.checkForDevFile()
732-
val isPromptedForAutoBuildFeature = codeWhispererSettings.containsKey(session.context.getWorkspaceRoot())
732+
val isPromptedForAutoBuildFeature = codeWhispererSettings.containsKey(session.context.workspaceRoot.path)
733733

734734
if (hasDevFile && !isPromptedForAutoBuildFeature) {
735735
promptAllowQCommandsConsent(messenger, tabId)
@@ -812,8 +812,7 @@ class FeatureDevController(
812812

813813
private suspend fun modifyDefaultSourceFolder(tabId: String) {
814814
val session = getSessionInfo(tabId)
815-
val currentSourceFolder = session.context.selectedSourceFolder
816-
val projectRoot = session.context.projectRoot
815+
val workspaceRoot = session.context.workspaceRoot
817816

818817
val modifyFolderFollowUp = FollowUp(
819818
pillText = message("amazonqFeatureDev.follow_up.modify_source_folder"),
@@ -825,7 +824,7 @@ class FeatureDevController(
825824
var reason: ModifySourceFolderErrorReason? = null
826825

827826
withContext(EDT) {
828-
val selectedFolder = selectFolder(context.project, currentSourceFolder)
827+
val selectedFolder = selectFolder(context.project, workspaceRoot)
829828
// No folder was selected
830829
if (selectedFolder == null) {
831830
logger.info { "Cancelled dialog and not selected any folder" }
@@ -839,8 +838,7 @@ class FeatureDevController(
839838
return@withContext
840839
}
841840

842-
// The folder is not in the workspace
843-
if (!selectedFolder.path.startsWith(projectRoot.path)) {
841+
if (!selectedFolder.path.startsWith(workspaceRoot.path)) {
844842
logger.info { "Selected folder not in workspace: ${selectedFolder.path}" }
845843

846844
messenger.sendAnswer(
@@ -860,7 +858,7 @@ class FeatureDevController(
860858

861859
logger.info { "Selected correct folder inside workspace: ${selectedFolder.path}" }
862860

863-
session.context.selectedSourceFolder = selectedFolder
861+
session.context.selectionRoot = selectedFolder
864862
result = Result.Succeeded
865863

866864
messenger.sendAnswer(

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationState.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class CodeGenerationState(
9696
var insertedCharacters = 0
9797
codeGenerationResult.newFiles.forEach { file ->
9898
// FIXME: Ideally, the before content should be read from the uploaded context instead of from disk, to avoid drift
99-
val before = config.repoContext.selectedSourceFolder
99+
val before = config.repoContext.addressableRoot
100100
.toNioPath()
101101
.resolve(file.zipFilePath)
102102
.toFile()

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationState.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class PrepareCodeGenerationState(
4949
messenger.sendAnswerPart(tabId = this.tabID, message = message("amazonqFeatureDev.chat_message.uploading_code"))
5050
messenger.sendUpdatePlaceholder(tabId = this.tabID, newPlaceholder = message("amazonqFeatureDev.chat_message.uploading_code"))
5151

52-
val isAutoBuildFeatureEnabled = CodeWhispererSettings.getInstance().isAutoBuildFeatureEnabled(this.config.repoContext.getWorkspaceRoot())
52+
val isAutoBuildFeatureEnabled = CodeWhispererSettings.getInstance().isAutoBuildFeatureEnabled(this.config.repoContext.workspaceRoot.path)
5353
val repoZipResult = config.repoContext.getProjectZip(isAutoBuildFeatureEnabled = isAutoBuildFeatureEnabled)
5454
val zipFileChecksum = repoZipResult.checksum
5555
zipFileLength = repoZipResult.contentLength

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/Session.kt

+5-10
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import com.intellij.openapi.project.Project
88
import com.intellij.openapi.vfs.VfsUtil
99
import software.aws.toolkits.jetbrains.common.util.resolveAndCreateOrUpdateFile
1010
import software.aws.toolkits.jetbrains.common.util.resolveAndDeleteFile
11-
import software.aws.toolkits.jetbrains.services.amazonq.FeatureDevSessionContext
1211
import software.aws.toolkits.jetbrains.services.amazonq.messages.MessagePublisher
12+
import software.aws.toolkits.jetbrains.services.amazonq.project.FeatureDevSessionContext
1313
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.CODE_GENERATION_RETRY_LIMIT
1414
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.ConversationIdNotFoundException
1515
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.FEATURE_NAME
@@ -130,14 +130,13 @@ class Session(val tabID: String, val project: Project) {
130130
) {
131131
val newFilePaths = filePaths.filter { !it.rejected && !it.changeApplied }
132132
val newDeletedFiles = deletedFiles.filter { !it.rejected && !it.changeApplied }
133-
val selectedSourceFolder = context.selectedSourceFolder.toNioPath()
134133

135134
runCatching {
136135
var insertedLines = 0
137136
var insertedCharacters = 0
138137
filePaths.forEach { file ->
139138
// FIXME: Ideally, the before content should be read from the uploaded context instead of from disk, to avoid drift
140-
val before = selectedSourceFolder
139+
val before = context.addressableRoot.toNioPath()
141140
.resolve(file.zipFilePath)
142141
.toFile()
143142
.let { f ->
@@ -174,18 +173,16 @@ class Session(val tabID: String, val project: Project) {
174173
ReferenceLogController.addReferenceLog(references, project)
175174

176175
// Taken from https://intellij-support.jetbrains.com/hc/en-us/community/posts/206118439-Refresh-after-external-changes-to-project-structure-and-sources
177-
VfsUtil.markDirtyAndRefresh(true, true, true, context.selectedSourceFolder)
176+
VfsUtil.markDirtyAndRefresh(true, true, true, context.addressableRoot)
178177
}
179178

180179
// Suppressing because insertNewFiles needs to be a suspend function in order to be tested
181180
@Suppress("RedundantSuspendModifier")
182181
suspend fun insertNewFiles(
183182
filePaths: List<NewFileZipInfo>,
184183
) {
185-
val selectedSourceFolder = context.selectedSourceFolder.toNioPath()
186-
187184
filePaths.forEach {
188-
resolveAndCreateOrUpdateFile(selectedSourceFolder, it.zipFilePath, it.fileContent)
185+
resolveAndCreateOrUpdateFile(context.addressableRoot.toNioPath(), it.zipFilePath, it.fileContent)
189186
it.changeApplied = true
190187
}
191188
}
@@ -195,10 +192,8 @@ class Session(val tabID: String, val project: Project) {
195192
suspend fun applyDeleteFiles(
196193
deletedFiles: List<DeletedFileInfo>,
197194
) {
198-
val selectedSourceFolder = context.selectedSourceFolder.toNioPath()
199-
200195
deletedFiles.forEach {
201-
resolveAndDeleteFile(selectedSourceFolder, it.zipFilePath)
196+
resolveAndDeleteFile(context.addressableRoot.toNioPath(), it.zipFilePath)
202197
it.changeApplied = true
203198
}
204199
}

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionStateTypes.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session
55

66
import com.fasterxml.jackson.annotation.JsonValue
7-
import software.aws.toolkits.jetbrains.services.amazonq.FeatureDevSessionContext
7+
import software.aws.toolkits.jetbrains.services.amazonq.project.FeatureDevSessionContext
88
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource
99
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FeatureDevService
1010
import software.aws.toolkits.jetbrains.services.cwc.messages.RecommendationContentSpan

0 commit comments

Comments
 (0)