Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(amazonq): implement workspace file messages #5377

Open
wants to merge 24 commits into
base: feature/q-lsp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
686fda2
add workspace handler
samgst-amazon Feb 13, 2025
a5250b5
break up repeat code
samgst-amazon Feb 14, 2025
0efb633
use serverInstance as messageBus disposable
samgst-amazon Feb 14, 2025
788e833
init starts listeners
samgst-amazon Feb 14, 2025
429f5e9
update listeners
samgst-amazon Feb 17, 2025
aababb6
fix init params
samgst-amazon Feb 17, 2025
c3d855a
didChangeWatchedFiles impl
samgst-amazon Feb 18, 2025
f826372
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 18, 2025
fad4467
detekt
samgst-amazon Feb 18, 2025
ffa167a
move executeIfRunning
samgst-amazon Feb 18, 2025
94c25e4
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 18, 2025
87817ea
private class
samgst-amazon Feb 18, 2025
d495450
null uri handling
samgst-amazon Feb 19, 2025
7cff72e
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 19, 2025
70b7e53
didChangeWorkspaceFolders
samgst-amazon Feb 20, 2025
eaa993a
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 24, 2025
d139dc4
detekt
samgst-amazon Feb 24, 2025
5458f0c
add tests for changeWorkspaceFolders
samgst-amazon Feb 24, 2025
0628cae
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 26, 2025
3f2a98d
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 28, 2025
401826d
fix test
samgst-amazon Feb 28, 2025
780395e
glob pattern matching
samgst-amazon Feb 28, 2025
8ee75f8
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 28, 2025
de16193
add didRename
samgst-amazon Mar 1, 2025
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
Expand Up @@ -37,7 +37,6 @@
import org.eclipse.lsp4j.SynchronizationCapabilities
import org.eclipse.lsp4j.TextDocumentClientCapabilities
import org.eclipse.lsp4j.WorkspaceClientCapabilities
import org.eclipse.lsp4j.WorkspaceFolder
import org.eclipse.lsp4j.jsonrpc.Launcher
import org.eclipse.lsp4j.launch.LSPLauncher
import org.slf4j.event.Level
Expand All @@ -48,14 +47,15 @@
import software.aws.toolkits.jetbrains.services.amazonq.lsp.auth.DefaultAuthCredentialsService
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.createExtendedClientMetadata
import software.aws.toolkits.jetbrains.services.amazonq.lsp.util.WorkspaceFolderUtil.createWorkspaceFolders
import software.aws.toolkits.jetbrains.services.amazonq.lsp.workspace.WorkspaceServiceHandler
import software.aws.toolkits.jetbrains.services.telemetry.ClientMetadata
import java.io.IOException
import java.io.OutputStreamWriter
import java.io.PipedInputStream
import java.io.PipedOutputStream
import java.io.PrintWriter
import java.io.StringWriter
import java.net.URI
import java.nio.charset.StandardCharsets
import java.util.concurrent.Future
import kotlin.time.Duration.Companion.seconds
Expand Down Expand Up @@ -215,17 +215,6 @@
}
}

// needs case handling when project's base path is null: default projects/unit tests
private fun createWorkspaceFolders(): List<WorkspaceFolder> =
project.basePath?.let { basePath ->
listOf(
WorkspaceFolder(
URI("file://$basePath").toString(),
project.name
)
)
}.orEmpty() // no folders to report or workspace not folder based

private fun createClientInfo(): ClientInfo {
val metadata = ClientMetadata.getDefault()
return ClientInfo().apply {
Expand All @@ -239,7 +228,7 @@
processId = ProcessHandle.current().pid().toInt()
capabilities = createClientCapabilities()
clientInfo = createClientInfo()
workspaceFolders = createWorkspaceFolders()
workspaceFolders = createWorkspaceFolders(project)

Check warning on line 231 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt#L231

Added line #L231 was not covered by tests
initializationOptions = createExtendedClientMetadata()
}

Expand Down Expand Up @@ -306,6 +295,7 @@
}

DefaultAuthCredentialsService(project, encryptionManager, this)
WorkspaceServiceHandler(project, this)

Check warning on line 298 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt#L298

Added line #L298 was not covered by tests
}

override fun dispose() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.amazonq.lsp.util

import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import org.eclipse.lsp4j.WorkspaceFolder

object WorkspaceFolderUtil {
fun createWorkspaceFolders(project: Project): List<WorkspaceFolder> =
if (project.isDefault) {
emptyList()

Check warning on line 13 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/WorkspaceFolderUtil.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/WorkspaceFolderUtil.kt#L13

Added line #L13 was not covered by tests
} else {
ProjectRootManager.getInstance(project).contentRoots.map { contentRoot ->
WorkspaceFolder().apply {
name = contentRoot.name
this.uri = contentRoot.url
}

Check warning on line 19 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/WorkspaceFolderUtil.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/WorkspaceFolderUtil.kt#L15-L19

Added lines #L15 - L19 were not covered by tests
}
}

Check warning on line 21 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/WorkspaceFolderUtil.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/WorkspaceFolderUtil.kt#L21

Added line #L21 was not covered by tests
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.amazonq.lsp.workspace

import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ModuleRootEvent
import com.intellij.openapi.roots.ModuleRootListener
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.newvfs.BulkFileListener
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import org.eclipse.lsp4j.CreateFilesParams
import org.eclipse.lsp4j.DeleteFilesParams
import org.eclipse.lsp4j.DidChangeWatchedFilesParams
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams
import org.eclipse.lsp4j.FileChangeType
import org.eclipse.lsp4j.FileCreate
import org.eclipse.lsp4j.FileDelete
import org.eclipse.lsp4j.FileEvent
import org.eclipse.lsp4j.WorkspaceFolder
import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
import software.aws.toolkits.jetbrains.services.amazonq.lsp.util.WorkspaceFolderUtil.createWorkspaceFolders
import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread
import java.nio.file.FileSystems
import java.nio.file.Paths

class WorkspaceServiceHandler(
private val project: Project,

Check warning on line 33 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L32-L33

Added lines #L32 - L33 were not covered by tests
serverInstance: Disposable,
) : BulkFileListener,
ModuleRootListener {

private var lastSnapshot: List<WorkspaceFolder> = emptyList()
private val supportedFilePatterns = FileSystems.getDefault().getPathMatcher(
"glob:**/*.{ts,js,py,java}"

Check warning on line 40 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L38-L40

Added lines #L38 - L40 were not covered by tests
)
Comment on lines +42 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should read the patterns out from the server capabilities returned from the initialization message


init {
project.messageBus.connect(serverInstance).subscribe(
VirtualFileManager.VFS_CHANGES,
this

Check warning on line 46 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L43-L46

Added lines #L43 - L46 were not covered by tests
)

project.messageBus.connect(serverInstance).subscribe(
ModuleRootListener.TOPIC,
this

Check warning on line 51 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L49-L51

Added lines #L49 - L51 were not covered by tests
)
}

Check warning on line 53 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L53

Added line #L53 was not covered by tests

private fun didCreateFiles(events: List<VFileEvent>) {
AmazonQLspService.executeIfRunning(project) { languageServer ->
val validFiles = events.mapNotNull { event ->

Check warning on line 57 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L56-L57

Added lines #L56 - L57 were not covered by tests
val file = event.file?.takeIf { shouldHandleFile(it) } ?: return@mapNotNull null
file.toNioPath().toUri().toString().takeIf { it.isNotEmpty() }?.let { uri ->
FileCreate().apply {
this.uri = uri
}
}

Check warning on line 63 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L60-L63

Added lines #L60 - L63 were not covered by tests
}

if (validFiles.isNotEmpty()) {
languageServer.workspaceService.didCreateFiles(
CreateFilesParams().apply {
files = validFiles
}

Check warning on line 70 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L67-L70

Added lines #L67 - L70 were not covered by tests
)
}
}
}

Check warning on line 74 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L73-L74

Added lines #L73 - L74 were not covered by tests

private fun didDeleteFiles(events: List<VFileEvent>) {
AmazonQLspService.executeIfRunning(project) { languageServer ->
val validFiles = events.mapNotNull { event ->

Check warning on line 78 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L77-L78

Added lines #L77 - L78 were not covered by tests
val file = event.file?.takeIf { shouldHandleFile(it) } ?: return@mapNotNull null
file.toNioPath().toUri().toString().takeIf { it.isNotEmpty() }?.let { uri ->
FileDelete().apply {
this.uri = uri
}
}

Check warning on line 84 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L81-L84

Added lines #L81 - L84 were not covered by tests
}

if (validFiles.isNotEmpty()) {
languageServer.workspaceService.didDeleteFiles(
DeleteFilesParams().apply {
files = validFiles
}

Check warning on line 91 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L88-L91

Added lines #L88 - L91 were not covered by tests
)
}
}
}

Check warning on line 95 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L94-L95

Added lines #L94 - L95 were not covered by tests

private fun didChangeWatchedFiles(events: List<VFileEvent>) {
AmazonQLspService.executeIfRunning(project) { languageServer ->
val validChanges = events.mapNotNull { event ->

Check warning on line 99 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L98-L99

Added lines #L98 - L99 were not covered by tests
event.file?.toNioPath()?.toUri()?.toString()?.takeIf { it.isNotEmpty() }?.let { uri ->
FileEvent().apply {
this.uri = uri
type = when (event) {

Check warning on line 103 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L101-L103

Added lines #L101 - L103 were not covered by tests
is VFileCreateEvent -> FileChangeType.Created
is VFileDeleteEvent -> FileChangeType.Deleted
else -> FileChangeType.Changed

Check warning on line 106 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L106

Added line #L106 was not covered by tests
}
}
}

Check warning on line 109 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L108-L109

Added lines #L108 - L109 were not covered by tests
}

if (validChanges.isNotEmpty()) {
languageServer.workspaceService.didChangeWatchedFiles(
DidChangeWatchedFilesParams().apply {
changes = validChanges
}

Check warning on line 116 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L113-L116

Added lines #L113 - L116 were not covered by tests
)
}
}
}

Check warning on line 120 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L119-L120

Added lines #L119 - L120 were not covered by tests

override fun after(events: List<VFileEvent>) {
// since we are using synchronous FileListener
pluginAwareExecuteOnPooledThread {
didCreateFiles(events.filterIsInstance<VFileCreateEvent>())
didDeleteFiles(events.filterIsInstance<VFileDeleteEvent>())
didChangeWatchedFiles(events)
}
}

Check warning on line 129 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L124-L129

Added lines #L124 - L129 were not covered by tests

override fun beforeRootsChange(event: ModuleRootEvent) {
lastSnapshot = createWorkspaceFolders(project)
}

Check warning on line 133 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L132-L133

Added lines #L132 - L133 were not covered by tests

override fun rootsChanged(event: ModuleRootEvent) {
AmazonQLspService.executeIfRunning(project) { languageServer ->
val currentSnapshot = createWorkspaceFolders(project)
val addedFolders = currentSnapshot.filter { folder -> lastSnapshot.none { it.uri == folder.uri } }
val removedFolders = lastSnapshot.filter { folder -> currentSnapshot.none { it.uri == folder.uri } }

Check warning on line 139 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L136-L139

Added lines #L136 - L139 were not covered by tests

if (addedFolders.isNotEmpty() || removedFolders.isNotEmpty()) {
languageServer.workspaceService.didChangeWorkspaceFolders(
DidChangeWorkspaceFoldersParams().apply {
this.event = WorkspaceFoldersChangeEvent().apply {
added = addedFolders
removed = removedFolders
}
}

Check warning on line 148 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L142-L148

Added lines #L142 - L148 were not covered by tests
)
}

lastSnapshot = currentSnapshot
}
}

Check warning on line 154 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L152-L154

Added lines #L152 - L154 were not covered by tests

private fun shouldHandleFile(file: VirtualFile): Boolean {
if (file.isDirectory) {
return true // Matches "**/*" with matches: "folder"

Check warning on line 158 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L158

Added line #L158 was not covered by tests
}
val path = Paths.get(file.path)
val result = supportedFilePatterns.matches(path)
return result

Check warning on line 162 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/workspace/WorkspaceServiceHandler.kt#L160-L162

Added lines #L160 - L162 were not covered by tests
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.amazonq.lsp.util

import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.vfs.VirtualFile
import io.mockk.every
import io.mockk.mockk
import org.junit.Assert.assertEquals
import org.junit.Test

class WorkspaceFolderUtilTest {

@Test
fun `createWorkspaceFolders returns empty list when no workspace folders`() {
val mockProject = mockk<Project>()
every { mockProject.isDefault } returns true

val result = WorkspaceFolderUtil.createWorkspaceFolders(mockProject)

assertEquals(emptyList<VirtualFile>(), result)
}

@Test
fun `createWorkspaceFolders returns workspace folders for non-default project`() {
val mockProject = mockk<Project>()
val mockProjectRootManager = mockk<ProjectRootManager>()
val mockContentRoot1 = mockk<VirtualFile>()
val mockContentRoot2 = mockk<VirtualFile>()

every { mockProject.isDefault } returns false
every { ProjectRootManager.getInstance(mockProject) } returns mockProjectRootManager
every { mockProjectRootManager.contentRoots } returns arrayOf(mockContentRoot1, mockContentRoot2)

every { mockContentRoot1.name } returns "root1"
every { mockContentRoot1.url } returns "file:///path/to/root1"
every { mockContentRoot2.name } returns "root2"
every { mockContentRoot2.url } returns "file:///path/to/root2"

val result = WorkspaceFolderUtil.createWorkspaceFolders(mockProject)

assertEquals(2, result.size)
assertEquals("file:///path/to/root1", result[0].uri)
assertEquals("file:///path/to/root2", result[1].uri)
assertEquals("root1", result[0].name)
assertEquals("root2", result[1].name)
}

@Test
fun `reateWorkspaceFolders returns empty list when project has no content roots`() {
val mockProject = mockk<Project>()
val mockProjectRootManager = mockk<ProjectRootManager>()

every { mockProject.isDefault } returns false
every { ProjectRootManager.getInstance(mockProject) } returns mockProjectRootManager
every { mockProjectRootManager.contentRoots } returns emptyArray()

val result = WorkspaceFolderUtil.createWorkspaceFolders(mockProject)

assertEquals(emptyList<VirtualFile>(), result)
}
}
Loading
Loading