Skip to content

Commit 4192bb7

Browse files
authored
Support reading source files from jars (#588)
* Support reading source files from jars * Close test FileSystems and add changelog entry * Apply spotless --------- Co-authored-by: hfhbd <[email protected]>
1 parent 41c651b commit 4192bb7

File tree

14 files changed

+165
-39
lines changed

14 files changed

+165
-39
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
## Unreleased
44

5-
- Change visibility on CreateTableElementType https://github.com/sqldelight/sql-psi/pull/691
5+
- Change visibility on CreateTableElementType (https://github.com/sqldelight/sql-psi/pull/691)
6+
- Support reading jar files (https://github.com/sqldelight/sql-psi/pull/588)
67

78

89
## [0.6.0] - 2025-08-08

core/src/test/kotlin/com/alecstrong/sql/psi/core/PassingPredefinedTablesTest.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ package com.alecstrong.sql.psi.core
33
import com.alecstrong.sql.psi.test.fixtures.TestHeadlessParser
44
import org.junit.Assert.fail
55
import org.junit.Test
6-
import java.io.File
76
import java.nio.file.Files
7+
import kotlin.io.path.div
8+
import kotlin.io.path.writeText
89

910
class PassingPredefinedTablesTest {
1011
@Test
1112
fun mirrorSqlDelight() {
12-
val temp = Files.createTempDirectory("predefinedTest").toFile()
13-
File(temp, "Test.s").writeText(
13+
val temp = Files.createTempDirectory("predefinedTest")
14+
(temp / "Test.s").writeText(
1415
"""
1516
SELECT * FROM dual;
1617
SELECT name FROM dual;

core/src/testFixtures/kotlin/com/alecstrong/sql/psi/test/fixtures/CompileFile.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ package com.alecstrong.sql.psi.test.fixtures
22

33
import com.alecstrong.sql.psi.core.SqlFileBase
44
import com.intellij.core.CoreApplicationEnvironment
5-
import java.io.File
65
import java.nio.file.Files
6+
import kotlin.io.path.div
7+
import kotlin.io.path.writeText
78

89
fun compileFile(
910
// language=sql
@@ -23,9 +24,9 @@ fun compileFiles(
2324
predefined: List<String> = emptyList(),
2425
action: (List<SqlFileBase>) -> Unit,
2526
) {
26-
val directory = Files.createTempDirectory("sql-psi").toFile()
27+
val directory = Files.createTempDirectory("sql-psi")
2728
for ((index, content) in files.withIndex()) {
28-
val file = File(directory, "$index.s")
29+
val file = directory / "$index.s"
2930
file.writeText(content)
3031
}
3132

core/src/testFixtures/kotlin/com/alecstrong/sql/psi/test/fixtures/FixturesTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ abstract class FixturesTest(
3333
}
3434

3535
val environment = TestHeadlessParser.build(
36-
root = newRoot.path,
36+
root = newRoot.toPath(),
3737
customInit = {
3838
setupDialect()
3939
},

core/src/testFixtures/kotlin/com/alecstrong/sql/psi/test/fixtures/TestHeadlessParser.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ import com.intellij.openapi.fileTypes.LanguageFileType
1111
import com.intellij.psi.FileViewProvider
1212
import com.intellij.psi.PsiFileFactory
1313
import com.intellij.psi.tree.IFileElementType
14-
import java.io.File
14+
import java.nio.file.Path
1515

1616
object TestHeadlessParser {
1717
fun build(
18-
root: String,
18+
root: Path,
1919
annotator: SqlAnnotationHolder,
2020
predefinedTables: List<String> = emptyList(),
2121
customInit: CoreApplicationEnvironment.() -> Unit = { },
2222
): SqlCoreEnvironment {
23-
return build(listOf(File(root)), annotator, predefinedTables, customInit)
23+
return build(listOf(root), annotator, predefinedTables, customInit)
2424
}
2525

2626
fun build(
27-
sourceFolders: List<File>,
27+
sourceFolders: List<Path>,
2828
annotator: SqlAnnotationHolder,
2929
predefinedTables: List<String> = emptyList(),
3030
customInit: CoreApplicationEnvironment.() -> Unit = { },

environment/src/main/kotlin/com/alecstrong/sql/psi/core/SqlCoreEnvironment.kt

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import com.intellij.openapi.roots.impl.ProjectRootManagerImpl
2121
import com.intellij.openapi.util.Disposer
2222
import com.intellij.openapi.vfs.StandardFileSystems
2323
import com.intellij.openapi.vfs.VirtualFile
24-
import com.intellij.openapi.vfs.VirtualFileManager
2524
import com.intellij.openapi.vfs.VirtualFileSystem
2625
import com.intellij.psi.PsiElement
2726
import com.intellij.psi.PsiErrorElement
@@ -33,7 +32,8 @@ import com.intellij.psi.util.PsiTreeUtil
3332
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndex
3433
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndexContributor
3534
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl
36-
import java.io.File
35+
import java.nio.file.Path
36+
import kotlin.io.path.pathString
3737
import kotlin.reflect.KClass
3838

3939
private class ApplicationEnvironment {
@@ -65,8 +65,8 @@ private class ApplicationEnvironment {
6565
}
6666

6767
open class SqlCoreEnvironment(
68-
sourceFolders: List<File>,
69-
dependencies: List<File>,
68+
sourceFolders: List<Path>,
69+
dependencies: List<Path>,
7070
) : AutoCloseable {
7171
private val fileIndex: CoreFileIndex
7272

@@ -76,9 +76,8 @@ open class SqlCoreEnvironment(
7676
env.coreApplicationEnvironment,
7777
)
7878

79-
protected val localFileSystem: VirtualFileSystem = VirtualFileManager.getInstance().getFileSystem(
80-
StandardFileSystems.FILE_PROTOCOL,
81-
)
79+
private val localFileSystem: VirtualFileSystem = StandardFileSystems.local()
80+
private val jarFileSystem: VirtualFileSystem = StandardFileSystems.jar()
8281

8382
init {
8483
projectEnvironment.registerProjectComponent(
@@ -94,10 +93,20 @@ open class SqlCoreEnvironment(
9493
DirectoryIndexImpl(projectEnvironment.project),
9594
)
9695

97-
fileIndex = CoreFileIndex(sourceFolders, localFileSystem, projectEnvironment.project)
96+
fileIndex = CoreFileIndex(
97+
sourceFolders,
98+
localFileSystem,
99+
jarFileSystem,
100+
project = projectEnvironment.project,
101+
)
98102
projectEnvironment.project.registerService(ProjectFileIndex::class.java, fileIndex)
99103

100-
val contributorIndex = CoreFileIndex(sourceFolders + dependencies, localFileSystem, projectEnvironment.project)
104+
val contributorIndex = CoreFileIndex(
105+
sourceFolders + dependencies,
106+
localFileSystem,
107+
jarFileSystem,
108+
project = projectEnvironment.project,
109+
)
101110
projectEnvironment.project.registerService(
102111
SchemaContributorIndex::class.java,
103112
object : SchemaContributorIndex {
@@ -204,16 +213,27 @@ open class SqlCoreEnvironment(
204213
}
205214

206215
private class CoreFileIndex(
207-
val sourceFolders: List<File>,
208-
private val localFileSystem: VirtualFileSystem,
216+
val sourceFolders: List<Path>,
217+
val localFileSystems: VirtualFileSystem,
218+
val jarFileSystem: VirtualFileSystem,
209219
project: Project,
210220
) : ProjectFileIndexImpl(project) {
211221
override fun iterateContent(iterator: ContentIterator): Boolean {
212-
return sourceFolders.all {
213-
val file = localFileSystem.findFileByPath(it.absolutePath)
214-
?: throw NullPointerException("File ${it.absolutePath} not found")
215-
iterateContentUnderDirectory(file, iterator)
222+
for (file in sourceFolders) {
223+
val vFile = when (val schema = file.fileSystem.provider().scheme) {
224+
StandardFileSystems.JAR_PROTOCOL -> {
225+
val jarFilePath = file.toUri().toString().removePrefix("jar:file://")
226+
jarFileSystem.findFileByPath(jarFilePath)
227+
}
228+
StandardFileSystems.FILE_PROTOCOL -> localFileSystems.findFileByPath(file.pathString)
229+
else -> error("Not supported schema $schema")
230+
} ?: throw NullPointerException("File ${file.pathString} not found")
231+
232+
if (!iterateContentUnderDirectory(vFile, iterator)) {
233+
return false
234+
}
216235
}
236+
return true
217237
}
218238

219239
override fun iterateContentUnderDirectory(file: VirtualFile, iterator: ContentIterator): Boolean {

sample-core/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
alias(libs.plugins.kotlinJvm)
33
alias(libs.plugins.grammarKitComposer)
4+
id("java-test-fixtures")
45
}
56

67
grammarKit {
@@ -9,6 +10,7 @@ grammarKit {
910

1011
dependencies {
1112
compileOnly libs.bundles.intelliJ
13+
testFixturesCompileOnly libs.bundles.intelliJ
1214

1315
implementation projects.core
1416
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import com.alecstrong.sql.psi.sample.core.SampleFileType
2+
import java.net.URI
3+
import java.nio.file.FileSystem
4+
import java.nio.file.FileSystemNotFoundException
5+
import java.nio.file.FileSystems
6+
import java.nio.file.Path
7+
import kotlin.io.path.toPath
8+
import kotlin.properties.ReadOnlyProperty
9+
import kotlin.reflect.KProperty
10+
11+
class SqliteTestFixtures : ReadOnlyProperty<Nothing?, Path>, AutoCloseable {
12+
val jarFile: Path get() = SqliteTestFixtures::class.java.getResource("/SqliteTestFixtures.class")!!.toURI().toJarPath().parent
13+
14+
override operator fun getValue(thisRef: Nothing?, property: KProperty<*>): Path {
15+
val uri =
16+
SqliteTestFixtures::class.java.getResource("/${property.name}.${SampleFileType.defaultExtension}")!!.toURI()
17+
return uri.toJarPath()
18+
}
19+
20+
private val openFileSystems = mutableSetOf<FileSystem>()
21+
22+
override fun close() {
23+
for (openFileSystem in openFileSystems) {
24+
openFileSystem.close()
25+
}
26+
}
27+
28+
private fun URI.toJarPath(): Path {
29+
val fileSystem = try {
30+
FileSystems.getFileSystem(this)
31+
} catch (_: FileSystemNotFoundException) {
32+
val env = mapOf("create" to "true")
33+
FileSystems.newFileSystem(this, env)
34+
}
35+
openFileSystems.add(fileSystem)
36+
return toPath()
37+
}
38+
}
File renamed without changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CREATE TABLE test2 (
2+
sample_column 42 TEXT AS "java.util.List" NOT NULL
3+
);
4+
5+
SELECT *
6+
FROM test, test2
7+
WHERE test.sample_column = "foo";
8+
9+
SELECT * FROM test2 WHERE (1 = 1) FOO 13;
10+
SELECT * FROM test2 WHERE (1 = 1);

0 commit comments

Comments
 (0)