Skip to content

Commit 60b26c8

Browse files
authored
fix(amazonq): Prevents Q UriError : Validate file URI and fallback to Path.toUri() for WSL (#5960)
Fix repeated UriError when Amazon Q starts with a WSL-backed workspace. We now validate the constructed file: URI and fallback to JDK’s Path.toUri() if the URI violates Rule (no authority while the path begins with //, maybe RFC 3986). This keeps legacy behavior where it’s safe, and prevents Q from rejecting the workspace folder URI
1 parent ce3a4ed commit 60b26c8

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
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" : "Fix UriError when project is on WSL or a UNC path"
4+
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,25 @@ object LspEditorUtil {
4747
private fun toUri(file: File): URI {
4848
try {
4949
// URI scheme specified by language server protocol
50-
return URI("file", "", file.absoluteFile.toURI().path, null)
50+
val uri = URI("file", "", file.absoluteFile.toURI().path, null)
51+
val fallback = file.toPath().toAbsolutePath().normalize().toUri()
52+
return if (uri.isCompliant()) uri else fallback
5153
} catch (e: URISyntaxException) {
5254
LOG.warn { "${e.localizedMessage}: $e" }
5355
return file.absoluteFile.toURI()
5456
}
5557
}
5658

59+
private fun URI.isCompliant(): Boolean {
60+
if (!"file".equals(this.scheme, ignoreCase = true)) return true
61+
62+
val path = this.rawPath ?: this.path.orEmpty()
63+
val noAuthority = this.authority.isNullOrEmpty()
64+
65+
// If the authority component is empty, the path cannot begin with two slash characters ("//")
66+
return !(noAuthority && path.startsWith("//"))
67+
}
68+
5769
/**
5870
* Works but is divergent from [FocusAreaContextExtrator]
5971
*/

plugins/amazonq/shared/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/FileUriUtilTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import io.mockk.every
88
import io.mockk.mockk
99
import org.assertj.core.api.Assertions.assertThat
1010
import org.junit.jupiter.api.Test
11+
import org.junit.jupiter.api.condition.EnabledOnOs
12+
import org.junit.jupiter.api.condition.OS
1113
import org.junit.jupiter.api.extension.ExtendWith
1214

1315
@ExtendWith(ApplicationExtension::class)
@@ -96,6 +98,24 @@ class FileUriUtilTest {
9698
}
9799
}
98100

101+
@Test
102+
@EnabledOnOs(OS.WINDOWS)
103+
fun `test wsl-like path`() {
104+
val virtualFile = createMockVirtualFile("//wsl.localhost/Ubuntu/home/user/file.sh")
105+
val result = LspEditorUtil.toUriString(virtualFile)
106+
val expected = normalizeFileUri("file://wsl.localhost/Ubuntu/home/user/file.sh")
107+
assertThat(result).isEqualTo(expected)
108+
}
109+
110+
@Test
111+
@EnabledOnOs(OS.WINDOWS)
112+
fun `test UNC path`() {
113+
val virtualFile = createMockVirtualFile("//server/share/path/to/file.txt")
114+
val result = LspEditorUtil.toUriString(virtualFile)
115+
val expected = normalizeFileUri("file://server/share/path/to/file.txt")
116+
assertThat(result).isEqualTo(expected)
117+
}
118+
99119
@Test
100120
fun `test jar protocol conversion`() {
101121
val virtualFile = createMockVirtualFile(

0 commit comments

Comments
 (0)