-
Notifications
You must be signed in to change notification settings - Fork 251
feat(amazonq): add virtualFile -> URI util #5381
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
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
634de73
add virtualFile -> URI util
samgst-amazon 8f49353
add string function
samgst-amazon b4b831a
utility object instead of class
samgst-amazon 2e02eb6
Merge branch 'feature/q-lsp' into samgst/lsp-fileUtil
samgst-amazon 2010c90
tests
samgst-amazon d628c81
detekt
samgst-amazon 9c19631
Merge branch 'feature/q-lsp' into samgst/lsp-fileUtil
samgst-amazon d62d64d
detekt
samgst-amazon f7f55df
redhat impl
samgst-amazon 7c5c747
deteckt
samgst-amazon ddc4f07
missing license
samgst-amazon f51a293
Merge branch 'feature/q-lsp' into samgst/lsp-fileUtil
samgst-amazon b4eb1b8
fix tests
samgst-amazon 575e66c
detekt
samgst-amazon 90fbb91
Merge branch 'feature/q-lsp' into samgst/lsp-fileUtil
samgst-amazon 802379a
OS handling for tests
samgst-amazon b2c7fa8
detekt
samgst-amazon e090401
Merge branch 'feature/q-lsp' into samgst/lsp-fileUtil
samgst-amazon 43417c3
Merge branch 'feature/q-lsp' into samgst/lsp-fileUtil
samgst-amazon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
...ns-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/FileUriUtil.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// 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.vfs.VfsUtilCore | ||
import com.intellij.openapi.vfs.VirtualFile | ||
import software.aws.toolkits.core.utils.getLogger | ||
import software.aws.toolkits.core.utils.warn | ||
import java.io.File | ||
import java.net.URI | ||
|
||
import java.net.URISyntaxException | ||
|
||
object FileUriUtil { | ||
|
||
|
||
fun toUriString(virtualFile: VirtualFile): String? { | ||
val protocol = virtualFile.fileSystem.protocol | ||
val uri = when (protocol) { | ||
"jar" -> VfsUtilCore.convertToURL(virtualFile.url)?.toExternalForm() | ||
"jrt" -> virtualFile.url | ||
else -> toUri(VfsUtilCore.virtualToIoFile(virtualFile)).toASCIIString() | ||
} ?: return null | ||
|
||
return if (virtualFile.isDirectory) { | ||
uri.trimEnd('/', '\\') | ||
} else { | ||
uri | ||
} | ||
} | ||
|
||
private fun toUri(file: File): URI { | ||
try { | ||
// URI scheme specified by language server protocol | ||
return URI("file", "", file.absoluteFile.toURI().path, null) | ||
} catch (e: URISyntaxException) { | ||
LOG.warn { "${e.localizedMessage}: $e" } | ||
return file.absoluteFile.toURI() | ||
} | ||
} | ||
|
||
private val LOG = getLogger<FileUriUtil>() | ||
} |
150 changes: 150 additions & 0 deletions
150
...ommunity/tst/software/aws/toolkits/jetbrains/services/amazonq/lsp/util/FileUriUtilTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// 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.vfs.VirtualFile | ||
import com.intellij.testFramework.fixtures.BasePlatformTestCase | ||
import io.mockk.every | ||
import io.mockk.mockk | ||
import org.junit.Test | ||
|
||
class FileUriUtilTest : BasePlatformTestCase() { | ||
|
||
private fun createMockVirtualFile(path: String, protocol: String = "file", isDirectory: Boolean = false): VirtualFile = | ||
mockk<VirtualFile> { | ||
every { fileSystem } returns mockk { | ||
every { this@mockk.protocol } returns protocol | ||
} | ||
every { url } returns path | ||
every { this@mockk.isDirectory } returns isDirectory | ||
} | ||
|
||
private fun normalizeFileUri(uri: String): String { | ||
if (!System.getProperty("os.name").lowercase().contains("windows")) { | ||
return uri | ||
} | ||
|
||
if (!uri.startsWith("file:///")) { | ||
return uri | ||
} | ||
|
||
val path = uri.substringAfter("file:///") | ||
return "file:///C:/$path" | ||
} | ||
|
||
@Test | ||
fun `test basic unix path`() { | ||
val virtualFile = createMockVirtualFile("/path/to/file.txt") | ||
val uri = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("file:///path/to/file.txt") | ||
assertEquals(expected, uri) | ||
} | ||
|
||
@Test | ||
fun `test unix directory path`() { | ||
val virtualFile = createMockVirtualFile("/path/to/directory/", isDirectory = true) | ||
val uri = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("file:///path/to/directory") | ||
assertEquals(expected, uri) | ||
} | ||
|
||
@Test | ||
fun `test path with spaces`() { | ||
val virtualFile = createMockVirtualFile("/path/with spaces/file.txt") | ||
val uri = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("file:///path/with%20spaces/file.txt") | ||
assertEquals(expected, uri) | ||
} | ||
|
||
@Test | ||
fun `test root path`() { | ||
val virtualFile = createMockVirtualFile("/") | ||
val uri = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("file:///") | ||
assertEquals(expected, uri) | ||
} | ||
|
||
@Test | ||
fun `test path with multiple separators`() { | ||
val virtualFile = createMockVirtualFile("/path//to///file.txt") | ||
val uri = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("file:///path/to/file.txt") | ||
assertEquals(expected, uri) | ||
} | ||
|
||
@Test | ||
fun `test very long path`() { | ||
val longPath = "/a".repeat(256) + "/file.txt" | ||
val virtualFile = createMockVirtualFile(longPath) | ||
val uri = FileUriUtil.toUriString(virtualFile) | ||
if (uri != null) { | ||
assertTrue(uri.startsWith("file:///")) | ||
assertTrue(uri.endsWith("/file.txt")) | ||
} | ||
} | ||
|
||
@Test | ||
fun `test relative path`() { | ||
val virtualFile = createMockVirtualFile("./relative/path/file.txt") | ||
val uri = FileUriUtil.toUriString(virtualFile) | ||
if (uri != null) { | ||
assertTrue(uri.contains("file.txt")) | ||
assertTrue(uri.startsWith("file:///")) | ||
} | ||
} | ||
|
||
@Test | ||
fun `test jar protocol conversion`() { | ||
val virtualFile = createMockVirtualFile( | ||
"jar:file:///path/to/archive.jar!/com/example/Test.class", | ||
"jar" | ||
) | ||
val result = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("jar:file:///path/to/archive.jar!/com/example/Test.class") | ||
assertEquals(expected, result) | ||
} | ||
|
||
@Test | ||
fun `test jrt protocol conversion`() { | ||
val virtualFile = createMockVirtualFile( | ||
"jrt://java.base/java/lang/String.class", | ||
"jrt" | ||
) | ||
val result = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("jrt://java.base/java/lang/String.class") | ||
assertEquals(expected, result) | ||
} | ||
|
||
@Test | ||
fun `test invalid jar url returns null`() { | ||
val virtualFile = createMockVirtualFile( | ||
"invalid:url:format", | ||
"jar" | ||
) | ||
val result = FileUriUtil.toUriString(virtualFile) | ||
assertNull(result) | ||
} | ||
|
||
@Test | ||
fun `test jar protocol with directory`() { | ||
val virtualFile = createMockVirtualFile( | ||
"jar:file:///path/to/archive.jar!/com/example/", | ||
"jar", | ||
true | ||
) | ||
val result = FileUriUtil.toUriString(virtualFile) | ||
val expected = normalizeFileUri("jar:file:///path/to/archive.jar!/com/example") | ||
assertEquals(expected, result) | ||
} | ||
|
||
@Test | ||
fun `test empty url in jar protocol`() { | ||
val virtualFile = createMockVirtualFile( | ||
"", | ||
"jar", | ||
true | ||
) | ||
val result = FileUriUtil.toUriString(virtualFile) | ||
assertNull(result) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.