Skip to content

Commit ad21d27

Browse files
committed
implemented codelens and codelens resolution
1 parent 69d6201 commit ad21d27

File tree

3 files changed

+134
-4
lines changed

3 files changed

+134
-4
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class KotlinLanguageServer(
9494
serverCapabilities.executeCommandProvider = ExecuteCommandOptions(ALL_COMMANDS)
9595
serverCapabilities.documentHighlightProvider = Either.forLeft(true)
9696
serverCapabilities.implementationProvider = Either.forLeft(true)
97+
serverCapabilities.codeLensProvider = CodeLensOptions(true)
9798

9899
val storagePath = getStoragePath(params)
99100
databaseService.setup(storagePath)

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

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import java.nio.file.Path
3535
import java.time.Duration
3636
import java.util.concurrent.CompletableFuture
3737
import org.javacs.kt.implementation.findImplementation
38+
import org.javacs.kt.codelens.findCodeLenses
3839

3940
class KotlinTextDocumentService(
4041
private val sf: SourceFiles,
@@ -145,8 +146,14 @@ class KotlinTextDocumentService(
145146
))
146147
}
147148

148-
override fun codeLens(params: CodeLensParams): CompletableFuture<List<CodeLens>> {
149-
TODO("not implemented")
149+
override fun codeLens(params: CodeLensParams): CompletableFuture<List<CodeLens>> = async.compute {
150+
reportTime {
151+
LOG.info("Finding code lenses in {}", describeURI(params.textDocument.uri))
152+
153+
val uri = parseURI(params.textDocument.uri)
154+
val file = sp.currentVersion(uri)
155+
return@compute findCodeLenses(file)
156+
}
150157
}
151158

152159
override fun rename(params: RenameParams) = async.compute {
@@ -264,8 +271,66 @@ class KotlinTextDocumentService(
264271
}
265272
}
266273

267-
override fun resolveCodeLens(unresolved: CodeLens): CompletableFuture<CodeLens> {
268-
TODO("not implemented")
274+
override fun resolveCodeLens(unresolved: CodeLens): CompletableFuture<CodeLens> = async.compute {
275+
reportTime {
276+
LOG.info("Resolving code lens {}", unresolved.command?.command)
277+
278+
val command = unresolved.command
279+
if (command == null) {
280+
return@compute unresolved
281+
}
282+
283+
val args = command.arguments as List<*>
284+
if (args.size != 3) {
285+
return@compute unresolved
286+
}
287+
288+
val uri = args[0] as String
289+
val line = args[1] as Int
290+
val character = args[2] as Int
291+
292+
val file = sp.currentVersion(parseURI(uri))
293+
val content = sp.content(parseURI(uri))
294+
val offset = offset(content, line, character)
295+
296+
when (command.command) {
297+
"kotlin.showImplementations" -> {
298+
val implementations = findImplementation(sp, sf, file, offset)
299+
if (implementations.isNotEmpty()) {
300+
unresolved.command = Command(
301+
command.title,
302+
command.command,
303+
listOf(uri, line, character, implementations)
304+
)
305+
}
306+
}
307+
"kotlin.showSubclasses" -> {
308+
val implementations = findImplementation(sp, sf, file, offset)
309+
if (implementations.isNotEmpty()) {
310+
unresolved.command = Command(
311+
command.title,
312+
command.command,
313+
listOf(uri, line, character, implementations)
314+
)
315+
}
316+
}
317+
"kotlin.showReferences" -> {
318+
val filePath = parseURI(uri).filePath
319+
if (filePath != null) {
320+
val references = findReferences(filePath, offset, sp)
321+
if (references.isNotEmpty()) {
322+
unresolved.command = Command(
323+
command.title,
324+
command.command,
325+
listOf(uri, line, character, references)
326+
)
327+
}
328+
}
329+
}
330+
}
331+
332+
return@compute unresolved
333+
}
269334
}
270335

271336
override fun implementation(params: ImplementationParams): CompletableFuture<Either<List<Location>, List<LocationLink>>> = async.compute {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.javacs.kt.codelens
2+
3+
import org.eclipse.lsp4j.CodeLens
4+
import org.eclipse.lsp4j.Command
5+
import org.eclipse.lsp4j.Range
6+
import org.javacs.kt.CompiledFile
7+
import org.javacs.kt.LOG
8+
import org.javacs.kt.position.location
9+
import org.jetbrains.kotlin.descriptors.ClassDescriptor
10+
import org.jetbrains.kotlin.descriptors.ClassKind
11+
import org.jetbrains.kotlin.psi.KtClassOrObject
12+
import org.jetbrains.kotlin.psi.KtNamedFunction
13+
import org.jetbrains.kotlin.resolve.BindingContext
14+
import java.nio.file.Paths
15+
16+
fun findCodeLenses(file: CompiledFile): List<CodeLens> {
17+
val codeLenses = mutableListOf<CodeLens>()
18+
val parsedFile = file.parse
19+
val filePath = Paths.get(parsedFile.containingFile.virtualFile.path)
20+
val uri = filePath.toUri().toString()
21+
22+
// Add code lenses for classes and interfaces
23+
parsedFile.declarations.filterIsInstance<KtClassOrObject>().forEach { ktClass ->
24+
val classDesc = file.compile.get(BindingContext.CLASS, ktClass)
25+
if (classDesc != null) {
26+
when (classDesc.kind) {
27+
ClassKind.INTERFACE -> {
28+
// Add "Show Implementations" code lens for interfaces
29+
location(ktClass)?.let { loc ->
30+
codeLenses.add(CodeLens(
31+
loc.range,
32+
Command("Show Implementations", "kotlin.showImplementations", listOf(uri, loc.range.start.line, loc.range.start.character)),
33+
null
34+
))
35+
}
36+
}
37+
ClassKind.CLASS -> {
38+
// Add "Show Subclasses" code lens for classes
39+
location(ktClass)?.let { loc ->
40+
codeLenses.add(CodeLens(
41+
loc.range,
42+
Command("Show Subclasses", "kotlin.showSubclasses", listOf(uri, loc.range.start.line, loc.range.start.character)),
43+
null
44+
))
45+
}
46+
}
47+
else -> {}
48+
}
49+
}
50+
}
51+
52+
// Add code lenses for functions
53+
parsedFile.declarations.filterIsInstance<KtNamedFunction>().forEach { ktFunction ->
54+
location(ktFunction)?.let { loc ->
55+
codeLenses.add(CodeLens(
56+
loc.range,
57+
Command("Show References", "kotlin.showReferences", listOf(uri, loc.range.start.line, loc.range.start.character)),
58+
null
59+
))
60+
}
61+
}
62+
63+
return codeLenses
64+
}

0 commit comments

Comments
 (0)