Skip to content
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

Fix compatibility issues + bugs #556

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion server/src/main/kotlin/org/javacs/kt/Configuration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,5 @@ public data class Configuration(
val indexing: IndexingConfiguration = IndexingConfiguration(),
val externalSources: ExternalSourcesConfiguration = ExternalSourcesConfiguration(),
val inlayHints: InlayHintsConfiguration = InlayHintsConfiguration(),
val formatting: FormattingConfiguration = FormattingConfiguration(),
val formatting: FormattingConfiguration = FormattingConfiguration()
)
2 changes: 2 additions & 0 deletions server/src/main/kotlin/org/javacs/kt/KotlinLanguageServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ class KotlinLanguageServer(
serverCapabilities.renameProvider = Either.forRight(RenameOptions(false))
}

workspaces.initialize(clientCapabilities)

@Suppress("DEPRECATION")
val folders = params.workspaceFolders?.takeIf { it.isNotEmpty() }
?: params.rootUri?.let(::WorkspaceFolder)?.let(::listOf)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import java.util.concurrent.CompletableFuture
import com.google.gson.JsonElement
import com.google.gson.Gson
import com.google.gson.JsonObject
import org.javacs.kt.symbols.symbolResolveSupport

class KotlinWorkspaceService(
private val sf: SourceFiles,
Expand All @@ -26,11 +27,16 @@ class KotlinWorkspaceService(
) : WorkspaceService, LanguageClientAware {
private val gson = Gson()
private var languageClient: LanguageClient? = null
private var clientCapabilities: ClientCapabilities? = null

override fun connect(client: LanguageClient): Unit {
languageClient = client
}

fun initialize(clientCapabilities: ClientCapabilities) {
this.clientCapabilities = clientCapabilities
}

override fun executeCommand(params: ExecuteCommandParams): CompletableFuture<Any> {
val args = params.arguments
LOG.info("Executing command: {} with {}", params.command, params.arguments)
Expand Down Expand Up @@ -189,7 +195,7 @@ class KotlinWorkspaceService(

@Suppress("DEPRECATION")
override fun symbol(params: WorkspaceSymbolParams): CompletableFuture<Either<List<SymbolInformation>, List<WorkspaceSymbol>>> {
val result = workspaceSymbols(params.query, sp)
val result = workspaceSymbols(params.query, sp, !clientCapabilities.symbolResolveSupport.enabled)

return CompletableFuture.completedFuture(Either.forRight(result))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.javacs.kt.symbols

import org.eclipse.lsp4j.ClientCapabilities

data class SymbolResolveSupport(
val enabled: Boolean = false,
val properties: List<String> = emptyList()
)

val ClientCapabilities?.symbolResolveSupport
get() = this?.workspace?.symbol?.resolveSupport?.properties?.let { properties ->
if (properties.size > 0) SymbolResolveSupport(true, properties) else null
} ?: SymbolResolveSupport(false, emptyList())
33 changes: 19 additions & 14 deletions server/src/main/kotlin/org/javacs/kt/symbols/Symbols.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package org.javacs.kt.symbols

import com.intellij.psi.PsiElement
import org.eclipse.lsp4j.Location
import org.eclipse.lsp4j.SymbolInformation
import org.eclipse.lsp4j.SymbolKind
import org.eclipse.lsp4j.DocumentSymbol
Expand All @@ -11,9 +12,9 @@ import org.eclipse.lsp4j.WorkspaceSymbolLocation
import org.eclipse.lsp4j.jsonrpc.messages.Either
import org.javacs.kt.SourcePath
import org.javacs.kt.position.range
import org.javacs.kt.position.toURIString
import org.javacs.kt.util.containsCharactersInOrder
import org.javacs.kt.util.preOrderTraversal
import org.javacs.kt.util.toPath
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents

Expand All @@ -33,10 +34,10 @@ private fun doDocumentSymbols(element: PsiElement): List<DocumentSymbol> {
} ?: children
}

fun workspaceSymbols(query: String, sp: SourcePath): List<WorkspaceSymbol> =
fun workspaceSymbols(query: String, sp: SourcePath, locationRequired: Boolean): List<WorkspaceSymbol> =
doWorkspaceSymbols(sp)
.filter { containsCharactersInOrder(it.name!!, query, false) }
.mapNotNull(::workspaceSymbol)
.mapNotNull { workspaceSymbol(it, locationRequired) }
.toList()

private fun doWorkspaceSymbols(sp: SourcePath): Sequence<KtNamedDeclaration> =
Expand All @@ -56,11 +57,22 @@ private fun pickImportantElements(node: PsiElement, includeLocals: Boolean): KtN
else -> null
}

private fun workspaceSymbol(d: KtNamedDeclaration): WorkspaceSymbol? {
val name = d.name ?: return null
private fun workspaceSymbol(d: KtNamedDeclaration, locationRequired: Boolean): WorkspaceSymbol? =
d.name?.let { name ->
val location: Either<Location, WorkspaceSymbolLocation>? = if (locationRequired) {
val content = d.containingFile?.text
val locationInContent = (d.nameIdentifier?.textRange ?: d.textRange)
if (content != null && locationInContent != null) {
Either.forLeft(Location(d.containingFile.toURIString(), range(content, locationInContent)))
} else {
null
}
} else {
d.containingFile?.let { Either.forRight(WorkspaceSymbolLocation(it.toURIString())) }
}

return WorkspaceSymbol(name, symbolKind(d), Either.forRight(workspaceLocation(d)), symbolContainer(d))
}
location?.let { WorkspaceSymbol(name, symbolKind(d), it, symbolContainer(d)) }
}

private fun symbolKind(d: KtNamedDeclaration): SymbolKind =
when (d) {
Expand All @@ -73,13 +85,6 @@ private fun symbolKind(d: KtNamedDeclaration): SymbolKind =
else -> throw IllegalArgumentException("Unexpected symbol $d")
}

private fun workspaceLocation(d: KtNamedDeclaration): WorkspaceSymbolLocation {
val file = d.containingFile
val uri = file.toPath().toUri().toString()

return WorkspaceSymbolLocation(uri)
}

private fun symbolContainer(d: KtNamedDeclaration): String? =
d.parents
.filterIsInstance<KtNamedDeclaration>()
Expand Down
29 changes: 29 additions & 0 deletions server/src/test/kotlin/org/javacs/kt/WorkspaceSymbolsTest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package org.javacs.kt

import org.eclipse.lsp4j.ClientCapabilities
import org.eclipse.lsp4j.SymbolCapabilities
import org.eclipse.lsp4j.SymbolKind
import org.eclipse.lsp4j.WorkspaceClientCapabilities
import org.eclipse.lsp4j.WorkspaceSymbolParams
import org.eclipse.lsp4j.WorkspaceSymbolResolveSupportCapabilities
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.hasItem
import org.hamcrest.Matchers.not
import org.junit.Assert.assertThat
Expand All @@ -21,4 +26,28 @@ class WorkspaceSymbolsTest : SingleFileTestFixture("symbols", "DocumentSymbols.k
assertThat(all, not(hasItem("aConstructorArg")))
assertThat(all, not(hasItem("otherFileLocalVariable")))
}

@Test fun `returns location information if resolve is not supported by the client`() {
languageServer.workspaceService.initialize(clientCapabilities(false))
val found = languageServer.workspaceService.symbol(WorkspaceSymbolParams("")).get().right
assertThat(found.all { s -> s.location.isLeft }, equalTo(true))
}

@Test fun `returns no location information if resolve is supported by the client`() {
languageServer.workspaceService.initialize(clientCapabilities(true))
val found = languageServer.workspaceService.symbol(WorkspaceSymbolParams("")).get().right
assertThat(found.all { s -> s.location.isRight }, equalTo(true))
}

private fun clientCapabilities(resolveSupported: Boolean): ClientCapabilities {
val properties = if (resolveSupported) listOf("location.range") else emptyList()

val workspaceClientCapabilities = WorkspaceClientCapabilities()
val symbolCapabilities = SymbolCapabilities()
val workspaceSymbolResolveSupportCapabilities = WorkspaceSymbolResolveSupportCapabilities()
workspaceSymbolResolveSupportCapabilities.properties = properties
symbolCapabilities.resolveSupport = workspaceSymbolResolveSupportCapabilities
workspaceClientCapabilities.symbol = symbolCapabilities
return ClientCapabilities(workspaceClientCapabilities, null, null)
}
}
3 changes: 1 addition & 2 deletions shared/src/main/kotlin/org/javacs/kt/Logger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.javacs.kt
import java.io.PrintWriter
import java.io.StringWriter
import java.util.*
import java.util.logging.Formatter
import java.util.logging.LogRecord
import java.util.logging.Handler
import java.util.logging.Level
Expand Down Expand Up @@ -136,7 +135,7 @@ class Logger {

fun connectStdioBackend() {
connectOutputBackend { println(it.formatted) }
connectOutputBackend { System.err.println(it.formatted) }
connectErrorBackend { System.err.println(it.formatted) }
}

private fun insertPlaceholders(msg: String, placeholders: Array<out Any?>): String {
Expand Down