From e9b2dedf3c6caae86cb099062774e7f9bda345c2 Mon Sep 17 00:00:00 2001 From: Zhiming Ma Date: Fri, 15 Nov 2024 18:07:46 +0800 Subject: [PATCH] feat(intellij): add kotlin language support for collecting declaration. (#3415) --- clients/intellij/build.gradle.kts | 7 +- .../KotlinLanguageSupportProvider.kt | 68 +++++++++++++++++++ .../main/resources/META-INF/plugin-kotlin.xml | 6 ++ .../src/main/resources/META-INF/plugin.xml | 2 +- 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/languageSupport/KotlinLanguageSupportProvider.kt create mode 100644 clients/intellij/src/main/resources/META-INF/plugin-kotlin.xml diff --git a/clients/intellij/build.gradle.kts b/clients/intellij/build.gradle.kts index 2174dec44519..c9cbd9795a60 100644 --- a/clients/intellij/build.gradle.kts +++ b/clients/intellij/build.gradle.kts @@ -18,7 +18,12 @@ repositories { dependencies { intellijPlatform { intellijIdeaCommunity("2023.1") - bundledPlugins(listOf("Git4Idea")) + bundledPlugins( + listOf( + "Git4Idea", + "org.jetbrains.kotlin", + ) + ) pluginVerifier() zipSigner() instrumentationTools() diff --git a/clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/languageSupport/KotlinLanguageSupportProvider.kt b/clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/languageSupport/KotlinLanguageSupportProvider.kt new file mode 100644 index 000000000000..11a50756bf2c --- /dev/null +++ b/clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/languageSupport/KotlinLanguageSupportProvider.kt @@ -0,0 +1,68 @@ +package com.tabbyml.intellijtabby.languageSupport + +import com.intellij.openapi.application.runReadAction +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.tabbyml.intellijtabby.languageSupport.LanguageSupportProvider.* +import io.ktor.util.* +import org.eclipse.lsp4j.SemanticTokenTypes +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType + +class KotlinLanguageSupportProvider : LanguageSupportProvider { + override fun provideSemanticTokensRange(project: Project, fileRange: FileRange): List? { + val psiFile = fileRange.file + if (psiFile.language.id.toUpperCasePreservingASCIIRules() != "KOTLIN") { + return null + } + return runReadAction { + val semanticTokens = mutableListOf() + psiFile.forEachDescendantOfType { element -> + if (element.children.isEmpty() && fileRange.range.contains(element.textRange)) { + val referenceTarget = + element.references.map { it.resolve() }.firstNotNullOfOrNull { it } ?: return@forEachDescendantOfType + val type = parseReferenceType(referenceTarget) + semanticTokens.add( + SemanticToken( + text = element.text, + range = element.textRange, + type = type, + ) + ) + } + } + semanticTokens.toList() + } + } + + override fun provideDeclaration(project: Project, filePosition: FilePosition): List? { + val psiFile = filePosition.file + if (psiFile.language.id.toUpperCasePreservingASCIIRules() != "KOTLIN") { + return null + } + return runReadAction { + val element = psiFile.findElementAt(filePosition.offset) + val referenceExpression = + element as? KtReferenceExpression ?: element?.parent as? KtReferenceExpression ?: return@runReadAction listOf() + val referenceTarget = + referenceExpression.references.map { it.resolve() }.firstNotNullOfOrNull { it } ?: return@runReadAction listOf() + val file = referenceTarget.containingFile ?: return@runReadAction listOf() + val range = referenceTarget.textRange + listOf(FileRange(file, range)) + } + } + + private fun parseReferenceType(referenceTarget: PsiElement): String { + return when (referenceTarget) { + is KtClassOrObject -> SemanticTokenTypes.Class + is KtFunction -> SemanticTokenTypes.Function + is KtProperty -> SemanticTokenTypes.Property + is KtParameter -> SemanticTokenTypes.Parameter + is KtVariableDeclaration -> SemanticTokenTypes.Variable + + // 1. Fallback to `Type` for other kotlin element declarations + // 2. The reference target may be declared in Java, fallback to `Type` for now + else -> SemanticTokenTypes.Type + } + } +} \ No newline at end of file diff --git a/clients/intellij/src/main/resources/META-INF/plugin-kotlin.xml b/clients/intellij/src/main/resources/META-INF/plugin-kotlin.xml new file mode 100644 index 000000000000..d4903d30c413 --- /dev/null +++ b/clients/intellij/src/main/resources/META-INF/plugin-kotlin.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/clients/intellij/src/main/resources/META-INF/plugin.xml b/clients/intellij/src/main/resources/META-INF/plugin.xml index 687523d2592b..4800ce9e0c04 100644 --- a/clients/intellij/src/main/resources/META-INF/plugin.xml +++ b/clients/intellij/src/main/resources/META-INF/plugin.xml @@ -29,7 +29,7 @@ Read more: https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html --> com.intellij.modules.platform Git4Idea - + org.jetbrains.kotlin