Skip to content

Commit 394c6a3

Browse files
authored
Merge pull request #337 from daplf/dependency-caching
Cache dependencies
2 parents 3f39416 + 8731d73 commit 394c6a3

File tree

17 files changed

+313
-21
lines changed

17 files changed

+313
-21
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ There is an extensive suite of behavioral [tests](server/src/test/kotlin/org/jav
8888

8989
The Kotlin language server supports some non-standard requests through LSP. See [KotlinProtocolExtensions](server/src/main/kotlin/org/javacs/kt/KotlinProtocolExtensions.kt) for a description of the interface. The general syntax for these methods is `kotlin/someCustomMethod`.
9090

91+
## Initialization Options
92+
93+
The Kotlin language server supports some custom initialization options via the `initializationOptions` property in the `initialize` request parameters. See `InitializationOptions` in [Configuration](server/src/main/kotlin/org/javacs/kt/Configuration.kt) for a list of supported properties.
94+
9195
## Features
9296

9397
### Autocomplete

gradle/platform/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ dependencies {
3939
api("org.jetbrains.kotlin:kotlin-scripting-jvm-host:$kotlinVersion")
4040
api("org.jetbrains.kotlin:kotlin-scripting-jvm-host:$kotlinVersion")
4141
api("org.openjdk.jmh:jmh-generator-annprocess:1.20")
42+
api("org.xerial:sqlite-jdbc:3.41.2.1")
4243
}
4344
}

server/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ dependencies {
5454
implementation("com.h2database:h2")
5555
implementation("com.github.fwcd.ktfmt:ktfmt")
5656
implementation("com.beust:jcommander")
57+
implementation("org.xerial:sqlite-jdbc")
5758

5859
testImplementation("org.hamcrest:hamcrest-all")
5960
testImplementation("junit:junit")

server/src/main/kotlin/org/javacs/kt/CompilerClassPath.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.javacs.kt
33
import org.javacs.kt.classpath.ClassPathEntry
44
import org.javacs.kt.classpath.defaultClassPathResolver
55
import org.javacs.kt.compiler.Compiler
6+
import org.javacs.kt.database.DatabaseService
67
import org.javacs.kt.util.AsyncExecutor
78
import java.io.Closeable
89
import java.io.File
@@ -14,7 +15,7 @@ import java.nio.file.Path
1415
* Manages the class path (compiled JARs, etc), the Java source path
1516
* and the compiler. Note that Kotlin sources are stored in SourcePath.
1617
*/
17-
class CompilerClassPath(private val config: CompilerConfiguration) : Closeable {
18+
class CompilerClassPath(private val config: CompilerConfiguration, private val databaseService: DatabaseService) : Closeable {
1819
val workspaceRoots = mutableSetOf<Path>()
1920

2021
private val javaSourcePath = mutableSetOf<Path>()
@@ -39,7 +40,7 @@ class CompilerClassPath(private val config: CompilerConfiguration) : Closeable {
3940
updateJavaSourcePath: Boolean = true
4041
): Boolean {
4142
// TODO: Fetch class path and build script class path concurrently (and asynchronously)
42-
val resolver = defaultClassPathResolver(workspaceRoots)
43+
val resolver = defaultClassPathResolver(workspaceRoots, databaseService.db)
4344
var refreshCompiler = updateJavaSourcePath
4445

4546
if (updateClassPath) {

server/src/main/kotlin/org/javacs/kt/Configuration.kt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
package org.javacs.kt
22

3+
import com.google.gson.GsonBuilder
4+
import com.google.gson.JsonDeserializationContext
5+
import com.google.gson.JsonDeserializer
6+
import com.google.gson.JsonElement
7+
import com.google.gson.JsonParseException
8+
import org.eclipse.lsp4j.InitializeParams
9+
import java.lang.reflect.Type
10+
import java.nio.file.InvalidPathException
11+
import java.nio.file.Path
12+
import java.nio.file.Paths
13+
314
public data class SnippetsConfiguration(
415
/** Whether code completion should return VSCode-style snippets. */
516
var enabled: Boolean = true
@@ -35,6 +46,36 @@ public data class ExternalSourcesConfiguration(
3546
var autoConvertToKotlin: Boolean = false
3647
)
3748

49+
50+
fun getStoragePath(params: InitializeParams): Path? {
51+
params.initializationOptions?.let { initializationOptions ->
52+
val gson = GsonBuilder().registerTypeHierarchyAdapter(Path::class.java, GsonPathConverter()).create()
53+
val options = gson.fromJson(initializationOptions as JsonElement, InitializationOptions::class.java)
54+
55+
return options?.storagePath
56+
}
57+
58+
return null
59+
}
60+
61+
data class InitializationOptions(
62+
// A path to a directory used by the language server to store data. Used for caching purposes.
63+
val storagePath: Path?
64+
)
65+
66+
class GsonPathConverter : JsonDeserializer<Path?> {
67+
68+
@Throws(JsonParseException::class)
69+
override fun deserialize(json: JsonElement, type: Type?, context: JsonDeserializationContext?): Path? {
70+
return try {
71+
Paths.get(json.asString)
72+
} catch (ex: InvalidPathException) {
73+
LOG.printStackTrace(ex)
74+
null
75+
}
76+
}
77+
}
78+
3879
public data class Configuration(
3980
val compiler: CompilerConfiguration = CompilerConfiguration(),
4081
val completion: CompletionConfiguration = CompletionConfiguration(),

server/src/main/kotlin/org/javacs/kt/KotlinLanguageServer.kt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,28 @@ import org.eclipse.lsp4j.services.LanguageClientAware
88
import org.eclipse.lsp4j.services.LanguageServer
99
import org.eclipse.lsp4j.services.NotebookDocumentService
1010
import org.javacs.kt.command.ALL_COMMANDS
11-
import org.javacs.kt.externalsources.*
11+
import org.javacs.kt.database.DatabaseService
12+
import org.javacs.kt.progress.LanguageClientProgress
13+
import org.javacs.kt.progress.Progress
14+
import org.javacs.kt.semantictokens.semanticTokensLegend
1215
import org.javacs.kt.util.AsyncExecutor
1316
import org.javacs.kt.util.TemporaryDirectory
1417
import org.javacs.kt.util.parseURI
15-
import org.javacs.kt.progress.Progress
16-
import org.javacs.kt.progress.LanguageClientProgress
17-
import org.javacs.kt.semantictokens.semanticTokensLegend
18+
import org.javacs.kt.externalsources.*
19+
import org.javacs.kt.index.SymbolIndex
1820
import java.io.Closeable
1921
import java.nio.file.Paths
2022
import java.util.concurrent.CompletableFuture
2123
import java.util.concurrent.CompletableFuture.completedFuture
2224

2325
class KotlinLanguageServer : LanguageServer, LanguageClientAware, Closeable {
2426
val config = Configuration()
25-
val classPath = CompilerClassPath(config.compiler)
27+
val databaseService = DatabaseService()
28+
val classPath = CompilerClassPath(config.compiler, databaseService)
2629

2730
private val tempDirectory = TemporaryDirectory()
2831
private val uriContentProvider = URIContentProvider(ClassContentProvider(config.externalSources, classPath, tempDirectory, CompositeSourceArchiveProvider(JdkSourceArchiveProvider(classPath), ClassPathSourceArchiveProvider(classPath))))
29-
val sourcePath = SourcePath(classPath, uriContentProvider, config.indexing)
32+
val sourcePath = SourcePath(classPath, uriContentProvider, config.indexing, databaseService)
3033
val sourceFiles = SourceFiles(sourcePath, uriContentProvider)
3134

3235
private val textDocuments = KotlinTextDocumentService(sourceFiles, sourcePath, config, tempDirectory, uriContentProvider, classPath)
@@ -89,6 +92,9 @@ class KotlinLanguageServer : LanguageServer, LanguageClientAware, Closeable {
8992
serverCapabilities.executeCommandProvider = ExecuteCommandOptions(ALL_COMMANDS)
9093
serverCapabilities.documentHighlightProvider = Either.forLeft(true)
9194

95+
val storagePath = getStoragePath(params)
96+
databaseService.setup(storagePath)
97+
9298
val clientCapabilities = params.capabilities
9399
config.completion.snippets.enabled = clientCapabilities?.textDocument?.completion?.completionItem?.snippetSupport ?: false
94100

server/src/main/kotlin/org/javacs/kt/SourcePath.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.javacs.kt.util.describeURI
88
import org.javacs.kt.index.SymbolIndex
99
import org.javacs.kt.progress.Progress
1010
import com.intellij.lang.Language
11+
import org.javacs.kt.database.DatabaseService
1112
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
1213
import org.jetbrains.kotlin.psi.KtFile
1314
import org.jetbrains.kotlin.resolve.BindingContext
@@ -22,14 +23,15 @@ import java.util.concurrent.locks.ReentrantLock
2223
class SourcePath(
2324
private val cp: CompilerClassPath,
2425
private val contentProvider: URIContentProvider,
25-
private val indexingConfig: IndexingConfiguration
26+
private val indexingConfig: IndexingConfiguration,
27+
private val databaseService: DatabaseService
2628
) {
2729
private val files = mutableMapOf<URI, SourceFile>()
2830
private val parseDataWriteLock = ReentrantLock()
2931

3032
private val indexAsync = AsyncExecutor()
3133
var indexEnabled: Boolean by indexingConfig::enabled
32-
val index = SymbolIndex()
34+
val index = SymbolIndex(databaseService)
3335

3436
var beforeCompileCallback: () -> Unit = {}
3537

server/src/main/kotlin/org/javacs/kt/index/SymbolIndex.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
77
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
88
import org.jetbrains.kotlin.name.FqName
99
import org.javacs.kt.LOG
10+
import org.javacs.kt.database.DatabaseService
1011
import org.javacs.kt.progress.Progress
1112
import org.jetbrains.exposed.dao.IntEntity
1213
import org.jetbrains.exposed.dao.IntEntityClass
@@ -80,14 +81,18 @@ class PositionEntity(id: EntityID<Int>) : IntEntity(id) {
8081
/**
8182
* A global view of all available symbols across all packages.
8283
*/
83-
class SymbolIndex {
84-
private val db = Database.connect("jdbc:h2:mem:symbolindex;DB_CLOSE_DELAY=-1", "org.h2.Driver")
84+
class SymbolIndex(
85+
private val databaseService: DatabaseService
86+
) {
87+
private val db: Database by lazy {
88+
databaseService.db ?: Database.connect("jdbc:h2:mem:symbolindex;DB_CLOSE_DELAY=-1", "org.h2.Driver")
89+
}
8590

8691
var progressFactory: Progress.Factory = Progress.Factory.None
8792

8893
init {
8994
transaction(db) {
90-
SchemaUtils.create(Symbols, Locations, Ranges, Positions)
95+
SchemaUtils.createMissingTablesAndColumns(Symbols, Locations, Ranges, Positions)
9196
}
9297
}
9398

@@ -99,6 +104,9 @@ class SymbolIndex {
99104
progressFactory.create("Indexing").thenApplyAsync { progress ->
100105
try {
101106
transaction(db) {
107+
// Remove everything first.
108+
Symbols.deleteAll()
109+
// Add new ones.
102110
addDeclarations(allDescriptors(module, exclusions))
103111

104112
val finished = System.currentTimeMillis()

server/src/test/kotlin/org/javacs/kt/CompiledFileTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package org.javacs.kt
22

33
import org.hamcrest.Matchers.equalTo
44
import org.javacs.kt.compiler.Compiler
5+
import org.javacs.kt.database.DatabaseService
56
import org.junit.AfterClass
67
import org.junit.Assert.assertThat
78
import org.junit.Test
@@ -29,7 +30,7 @@ class CompiledFileTest {
2930
val file = testResourcesRoot().resolve("compiledFile/CompiledFileExample.kt")
3031
val content = Files.readAllLines(file).joinToString("\n")
3132
val parse = compiler.createKtFile(content, file)
32-
val classPath = CompilerClassPath(CompilerConfiguration())
33+
val classPath = CompilerClassPath(CompilerConfiguration(), DatabaseService())
3334
val sourcePath = listOf(parse)
3435
val (context, container) = compiler.compileKtFiles(sourcePath, sourcePath)
3536
CompiledFile(content, parse, context, container, sourcePath, classPath)

shared/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ dependencies {
1515
implementation(platform("dev.fwcd.kotlin-language-server:platform"))
1616

1717
implementation(kotlin("stdlib"))
18+
implementation("org.jetbrains.exposed:exposed-core")
19+
implementation("org.jetbrains.exposed:exposed-dao")
1820
testImplementation("org.hamcrest:hamcrest-all")
1921
testImplementation("junit:junit")
2022
}

0 commit comments

Comments
 (0)