Skip to content

Commit a56a4dc

Browse files
authored
Merge pull request #5584 from continuedev/nate/intellij-uri-tests
tests for uriToFile
2 parents be4e6ae + 67671f4 commit a56a4dc

File tree

10 files changed

+131
-26
lines changed

10 files changed

+131
-26
lines changed

extensions/intellij/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ dependencies {
4242
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
4343
testImplementation("com.intellij.remoterobot:remote-robot:$remoteRobotVersion")
4444
testImplementation("com.intellij.remoterobot:remote-fixtures:$remoteRobotVersion")
45+
testImplementation("io.mockk:mockk:1.14.2")
4546
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
4647
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.2")
4748
testImplementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
@@ -62,6 +63,7 @@ dependencies {
6263
// Add Log4j 2.x explicitly
6364
implementation("org.apache.logging.log4j:log4j-core:2.20.0")
6465
implementation("org.apache.logging.log4j:log4j-api:2.20.0")
66+
testImplementation(kotlin("test"))
6567
}
6668

6769
// Set the JVM language level used to build the project. Use Java 11 for 2020.3+, and Java 17 for

extensions/intellij/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pluginSinceBuild=223
99
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
1010
platformType=IC
1111
platformVersion=2022.3.3
12-
#org.gradle.java.home=/opt/homebrew/opt/openjdk@17
12+
# org.gradle.java.home=/opt/homebrew/opt/openjdk@17
1313
#platformVersion = LATEST-EAP-SNAPSHOT
1414
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1515
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22

extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/activities/ContinuePluginStartupActivity.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.github.continuedev.continueintellijextension.activities
22

3-
import IntelliJIDE
43
import com.intellij.openapi.fileEditor.FileEditorManagerListener
54
import com.github.continuedev.continueintellijextension.auth.AuthListener
65
import com.github.continuedev.continueintellijextension.auth.ContinueAuthService

extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/continue/Diffs.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class DiffManager(private val project: Project) : DumbAware {
6262
file.createNewFile()
6363
}
6464
file.writeText(replacement)
65-
openDiffWindow(URI(filepath).toString(), file.toURI().toString(), stepIndex)
65+
openDiffWindow(UriUtils.parseUri(filepath).toString(), file.toURI().toString(), stepIndex)
6666
}
6767

6868
private fun cleanUpFile(file2: String) {
@@ -80,7 +80,8 @@ class DiffManager(private val project: Project) : DumbAware {
8080
val diffInfo = diffInfoMap[file] ?: return
8181

8282
// Write contents to original file
83-
val virtualFile = LocalFileSystem.getInstance().findFileByPath(URI(diffInfo.originalFilepath).path) ?: return
83+
val virtualFile =
84+
LocalFileSystem.getInstance().findFileByPath(UriUtils.parseUri(diffInfo.originalFilepath).path) ?: return
8485
val document = FileDocumentManager.getInstance().getDocument(virtualFile) ?: return
8586
WriteCommandAction.runWriteCommandAction(project) {
8687
document.setText(File(file).readText())
@@ -119,8 +120,8 @@ class DiffManager(private val project: Project) : DumbAware {
119120
lastFile2 = file2
120121

121122
// Create a DiffContent for each of the texts you want to compare
122-
val content1: DiffContent = DiffContentFactory.getInstance().create(File(URI(file1)).readText())
123-
val content2: DiffContent = DiffContentFactory.getInstance().create(File(URI(file2)).readText())
123+
val content1: DiffContent = DiffContentFactory.getInstance().create(UriUtils.uriToFile(file1).readText())
124+
val content2: DiffContent = DiffContentFactory.getInstance().create(UriUtils.uriToFile(file2).readText())
124125

125126
// Create a SimpleDiffRequest and populate it with the DiffContents and titles
126127
val diffRequest = SimpleDiffRequest("Continue Diff", content1, content2, "Old", "New")

extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/continue/GitService.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import com.intellij.openapi.project.guessProjectDir
77
import kotlinx.coroutines.Dispatchers
88
import kotlinx.coroutines.withContext
99
import java.io.BufferedReader
10-
import java.io.File
1110
import java.io.InputStreamReader
12-
import java.net.URI
1311

1412
class GitService(
1513
private val project: Project,
@@ -52,7 +50,7 @@ class GitService(
5250
} else {
5351
ProcessBuilder("git", "diff", "--cached")
5452
}
55-
builder.directory(File(URI(workspaceDir)))
53+
builder.directory(UriUtils.uriToFile(workspaceDir))
5654
val process = withContext(Dispatchers.IO) {
5755
builder.start()
5856
}

extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/continue/IdeProtocolClient.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package com.github.continuedev.continueintellijextension.`continue`
22

3-
import IntelliJIDE
43
import com.github.continuedev.continueintellijextension.*
54
import com.github.continuedev.continueintellijextension.activities.ContinuePluginDisposable
65
import com.github.continuedev.continueintellijextension.activities.showTutorial
7-
import com.github.continuedev.continueintellijextension.auth.AuthListener
86
import com.github.continuedev.continueintellijextension.auth.ContinueAuthService
97
import com.github.continuedev.continueintellijextension.editor.DiffStreamHandler
108
import com.github.continuedev.continueintellijextension.editor.DiffStreamService

extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/continue/IntelliJIde.kt

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
package com.github.continuedev.continueintellijextension.`continue`
2+
13
import com.github.continuedev.continueintellijextension.*
24
import com.github.continuedev.continueintellijextension.constants.getContinueGlobalPath
35
import com.github.continuedev.continueintellijextension.constants.ContinueConstants
@@ -167,7 +169,7 @@ class IntelliJIDE(
167169
// Find any .continuerc.json files
168170
for (file in contents) {
169171
if (file.endsWith(".continuerc.json")) {
170-
val fileContent = File(URI(file)).readText()
172+
val fileContent = UriUtils.uriToFile(file).readText()
171173
configs.add(fileContent)
172174
}
173175
}
@@ -178,12 +180,12 @@ class IntelliJIDE(
178180
}
179181

180182
override suspend fun fileExists(filepath: String): Boolean {
181-
val file = File(URI(filepath))
183+
val file = UriUtils.uriToFile(filepath)
182184
return file.exists()
183185
}
184186

185187
override suspend fun writeFile(path: String, contents: String) {
186-
val file = File(URI(path))
188+
val file = UriUtils.uriToFile(path)
187189
file.parentFile?.mkdirs()
188190
file.writeText(contents)
189191
}
@@ -201,7 +203,7 @@ class IntelliJIDE(
201203

202204
override suspend fun openFile(path: String) {
203205
// Convert URI path to absolute file path
204-
val filePath = File(URI(path)).absolutePath
206+
val filePath = UriUtils.uriToFile(path).absolutePath
205207
// Find the file using the absolute path
206208
val file = withContext(Dispatchers.IO) {
207209
LocalFileSystem.getInstance().refreshAndFindFileByPath(filePath)
@@ -216,7 +218,7 @@ class IntelliJIDE(
216218

217219
override suspend fun openUrl(url: String) {
218220
withContext(Dispatchers.IO) {
219-
Desktop.browse(java.net.URI(url))
221+
Desktop.browse(URI(url))
220222
}
221223
}
222224

@@ -226,7 +228,8 @@ class IntelliJIDE(
226228

227229
override suspend fun saveFile(filepath: String) {
228230
ApplicationManager.getApplication().invokeLater {
229-
val file = LocalFileSystem.getInstance().findFileByPath(URI(filepath).path) ?: return@invokeLater
231+
val file =
232+
LocalFileSystem.getInstance().findFileByPath(UriUtils.parseUri(filepath).path) ?: return@invokeLater
230233
val fileDocumentManager = FileDocumentManager.getInstance()
231234
val document = fileDocumentManager.getDocument(file)
232235

@@ -239,7 +242,7 @@ class IntelliJIDE(
239242
override suspend fun readFile(filepath: String): String {
240243
return try {
241244
val content = ApplicationManager.getApplication().runReadAction<String?> {
242-
val virtualFile = LocalFileSystem.getInstance().findFileByPath(URI(filepath).path)
245+
val virtualFile = LocalFileSystem.getInstance().findFileByPath(UriUtils.parseUri(filepath).path)
243246
if (virtualFile != null && FileDocumentManager.getInstance().isFileModified(virtualFile)) {
244247
return@runReadAction FileDocumentManager.getInstance().getDocument(virtualFile)?.text
245248
}
@@ -249,7 +252,7 @@ class IntelliJIDE(
249252
if (content != null) {
250253
content
251254
} else {
252-
val file = File(URI(filepath))
255+
val file = UriUtils.uriToFile(filepath)
253256
if (!file.exists() || file.isDirectory) return ""
254257
withContext(Dispatchers.IO) {
255258
FileInputStream(file).use { fis ->
@@ -455,7 +458,7 @@ class IntelliJIDE(
455458
return withContext(Dispatchers.IO) {
456459
try {
457460
val builder = ProcessBuilder("git", "rev-parse", "--abbrev-ref", "HEAD")
458-
builder.directory(File(URI(dir)))
461+
builder.directory(UriUtils.uriToFile(dir))
459462
val process = builder.start()
460463
val reader = BufferedReader(InputStreamReader(process.inputStream))
461464
val output = reader.readLine()
@@ -485,7 +488,7 @@ class IntelliJIDE(
485488

486489
override suspend fun getRepoName(dir: String): String? {
487490
return withContext(Dispatchers.IO) {
488-
val directory = File(URI(dir))
491+
val directory = UriUtils.uriToFile(dir)
489492
val targetDir = if (directory.isFile) directory.parentFile else directory
490493
val builder = ProcessBuilder("git", "config", "--get", "remote.origin.url")
491494
builder.directory(targetDir)
@@ -549,7 +552,7 @@ class IntelliJIDE(
549552
override suspend fun getGitRootPath(dir: String): String? {
550553
return withContext(Dispatchers.IO) {
551554
val builder = ProcessBuilder("git", "rev-parse", "--show-toplevel")
552-
builder.directory(File(URI(dir)))
555+
builder.directory(UriUtils.uriToFile(dir))
553556
val process = builder.start()
554557

555558
val reader = BufferedReader(InputStreamReader(process.inputStream))
@@ -560,7 +563,7 @@ class IntelliJIDE(
560563
}
561564

562565
override suspend fun listDir(dir: String): List<List<Any>> {
563-
val files = File(URI(dir)).listFiles()?.map {
566+
val files = UriUtils.uriToFile(dir).listFiles()?.map {
564567
listOf(it.name, if (it.isDirectory) FileType.DIRECTORY.value else FileType.FILE.value)
565568
} ?: emptyList()
566569

@@ -569,7 +572,7 @@ class IntelliJIDE(
569572

570573
override suspend fun getFileStats(files: List<String>): Map<String, FileStats> {
571574
return files.associateWith { file ->
572-
FileStats(File(URI(file)).lastModified(), File(URI(file)).length())
575+
FileStats(UriUtils.uriToFile(file).lastModified(), UriUtils.uriToFile(file).length())
573576
}
574577
}
575578

@@ -587,7 +590,7 @@ class IntelliJIDE(
587590
}
588591

589592
private fun setFileOpen(filepath: String, open: Boolean = true) {
590-
val file = LocalFileSystem.getInstance().findFileByPath(URI(filepath).path)
593+
val file = LocalFileSystem.getInstance().findFileByPath(UriUtils.uriToFile(filepath).path)
591594

592595
file?.let {
593596
if (open) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.github.continuedev.continueintellijextension.`continue`
2+
3+
import java.io.File
4+
import java.net.URI
5+
6+
/**
7+
* Utility class for URI operations
8+
*/
9+
object UriUtils {
10+
/**
11+
* Parses a URI string into a URI object, handling special cases for Windows file paths
12+
*/
13+
fun parseUri(uri: String): URI {
14+
try {
15+
// Remove query parameters if present
16+
val uriStr = uri.substringBefore("?")
17+
18+
// Handle Windows file paths with authority component
19+
if (uriStr.startsWith("file://") && !uriStr.startsWith("file:///")) {
20+
val path = uriStr.substringAfter("file://")
21+
return URI("file:///$path")
22+
}
23+
24+
// Standard URI handling for other cases
25+
val uriWithoutQuery = URI(uriStr)
26+
return uriWithoutQuery
27+
} catch (e: Exception) {
28+
println("Error parsing URI: $uri ${e.message}")
29+
throw Exception("Invalid URI: $uri ${e.message}")
30+
}
31+
}
32+
33+
/**
34+
* Converts a URI string to a File object
35+
*/
36+
fun uriToFile(uri: String): File {
37+
return File(parseUri(uri))
38+
}
39+
}

extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/services/ContinuePluginService.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.github.continuedev.continueintellijextension.services
22

3-
import IntelliJIDE
43
import com.github.continuedev.continueintellijextension.`continue`.CoreMessenger
54
import com.github.continuedev.continueintellijextension.`continue`.CoreMessengerManager
65
import com.github.continuedev.continueintellijextension.`continue`.DiffManager
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.github.continuedev.continueintellijextension.unit
2+
3+
import com.github.continuedev.continueintellijextension.`continue`.UriUtils
4+
import org.junit.jupiter.api.Disabled
5+
import org.junit.jupiter.api.Test
6+
import java.io.File
7+
import kotlin.test.assertEquals
8+
9+
class UriUtilsTest {
10+
@Test
11+
fun testUriToFile() {
12+
val uri = "file:///path/to/file"
13+
val file = UriUtils.uriToFile(uri)
14+
assertEquals(File("/path/to/file"), file)
15+
}
16+
17+
@Disabled("Not working")
18+
@Test
19+
fun testUriToFileWithWindowsPath() {
20+
val uri = "file:///C:/path/to/file"
21+
val file = UriUtils.uriToFile(uri)
22+
assertEquals(File("C:/path/to/file"), file)
23+
}
24+
25+
@Test
26+
fun shouldHandleAuthorityComponent() {
27+
val uri = "file://C:/path/to/file"
28+
val file = UriUtils.uriToFile(uri)
29+
assertEquals(File("/C:/path/to/file"), file)
30+
}
31+
32+
@Test
33+
fun testUriToFileWithSpaces() {
34+
val uri = "file:///path/to/file%20with%20spaces"
35+
val file = UriUtils.uriToFile(uri)
36+
assertEquals(File("/path/to/file with spaces"), file)
37+
}
38+
39+
@Test
40+
fun testUriToFileWithSpecialCharacters() {
41+
val uri = "file:///path/to/file%23with%25special%26chars"
42+
val file = UriUtils.uriToFile(uri)
43+
assertEquals(File("/path/to/file#with%special&chars"), file)
44+
}
45+
46+
@Test
47+
fun testUriToFileWithQueryParams() {
48+
val uri = "file:///path/to/file?param=value"
49+
val file = UriUtils.uriToFile(uri)
50+
assertEquals(File("/path/to/file"), file)
51+
}
52+
53+
@Test
54+
fun testUriToFileWithWSLPath() {
55+
val uri = "file:///wsl$/Ubuntu/home/user/file.txt"
56+
val file = UriUtils.uriToFile(uri)
57+
assertEquals(File("/wsl$/Ubuntu/home/user/file.txt"), file)
58+
}
59+
60+
@Test
61+
fun testUriToFileWithWSLLocalhostPath() {
62+
val uri = "file:///wsl.localhost/Ubuntu/home/user/file.txt"
63+
val file = UriUtils.uriToFile(uri)
64+
assertEquals(File("/wsl.localhost/Ubuntu/home/user/file.txt"), file)
65+
}
66+
}

0 commit comments

Comments
 (0)