Skip to content

Commit

Permalink
Fix compatibility issues + bugs
Browse files Browse the repository at this point in the history
1) From LSP spec 3.16 to 3.17, dropping the location attribute from the
   response to `workspace/symbol` is only permitted if the client
   capability `workspace.symbol.resolveSupport` is advertized. Without
   this setting, the `location` attribute should be present.
2) `findDeclarationCursorSite` constructs a location using a non-uri
   path in the uri property. This leads to document symbol rename
   for example to not work.
3) THe stdio backend for logging accidentally overrides the stdout
   backend with the one meant for stderr.
  • Loading branch information
Lorenz Bateman committed Feb 19, 2024
1 parent eee8afa commit 4056a8b
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 13 deletions.
3 changes: 2 additions & 1 deletion server/src/main/kotlin/org/javacs/kt/CompiledFile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.javacs.kt.position.changedRegion
import org.javacs.kt.position.location
import org.javacs.kt.position.position
import org.javacs.kt.position.range
import org.javacs.kt.position.toURIString
import org.javacs.kt.util.findParent
import org.javacs.kt.util.nullResult
import org.javacs.kt.util.toPath
Expand Down Expand Up @@ -214,7 +215,7 @@ class CompiledFile(

return declaration?.let {
Pair(it,
Location(it.containingFile.name,
Location(it.containingFile.toURIString(),
range(content, it.nameIdentifier?.textRange ?: return null)))
}
}
Expand Down
12 changes: 11 additions & 1 deletion server/src/main/kotlin/org/javacs/kt/Configuration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ public data class CompilerConfiguration(
val jvm: JVMConfiguration = JVMConfiguration()
)

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

public data class WorkspaceConfiguration(
var symbolResolveSupport: SymbolResolveSupport = SymbolResolveSupport()
)

public data class IndexingConfiguration(
/** Whether an index of global symbols should be built in the background. */
var enabled: Boolean = true
Expand Down Expand Up @@ -94,5 +103,6 @@ public data class Configuration(
val scripts: ScriptsConfiguration = ScriptsConfiguration(),
val indexing: IndexingConfiguration = IndexingConfiguration(),
val externalSources: ExternalSourcesConfiguration = ExternalSourcesConfiguration(),
val inlayHints: InlayHintsConfiguration = InlayHintsConfiguration()
val inlayHints: InlayHintsConfiguration = InlayHintsConfiguration(),
val workspace: WorkspaceConfiguration = WorkspaceConfiguration()
)
4 changes: 4 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,10 @@ class KotlinLanguageServer(
serverCapabilities.renameProvider = Either.forRight(RenameOptions(false))
}

config.workspace.symbolResolveSupport = clientCapabilities?.workspace?.symbol?.resolveSupport?.properties?.let { properties ->
if (properties.size > 0) SymbolResolveSupport(true, properties) else null
} ?: SymbolResolveSupport(false, emptyList())

@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 @@ -173,7 +173,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(!config.workspace.symbolResolveSupport.enabled, params.query, sp)

return CompletableFuture.completedFuture(Either.forRight(result))
}
Expand Down
33 changes: 25 additions & 8 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 Down Expand Up @@ -33,10 +34,10 @@ private fun doDocumentSymbols(element: PsiElement): List<DocumentSymbol> {
} ?: children
}

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

private fun doWorkspaceSymbols(sp: SourcePath): Sequence<KtNamedDeclaration> =
Expand All @@ -56,10 +57,18 @@ 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(locationRequired: Boolean): (KtNamedDeclaration) -> WorkspaceSymbol? {
return { d ->
d.name?.let { name ->
val location: Either<Location, WorkspaceSymbolLocation>? = if (locationRequired) {
location(d)?.let { l -> Either.forLeft(l) }
} else {
Either.forRight(workspaceSymbolLocation(d))
}

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 =
Expand All @@ -73,10 +82,18 @@ 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()
private fun location(d: KtNamedDeclaration): Location? {
val uri = d.containingFile.toPath().toUri().toString()
val (content, textRange) = try { d.containingFile?.text to d.nameIdentifier?.textRange } catch (e: Exception) { null to null }
return if (content != null && textRange != null) {
Location(uri, range(content, textRange))
} else {
null
}
}

private fun workspaceSymbolLocation(d: KtNamedDeclaration): WorkspaceSymbolLocation {
val uri = d.containingFile.toPath().toUri().toString()
return WorkspaceSymbolLocation(uri)
}

Expand Down
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

0 comments on commit 4056a8b

Please sign in to comment.