From 8a9799b738d7630f35e142aad8b46165c131b29a Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Wed, 8 May 2024 17:04:38 +0000 Subject: [PATCH 01/25] Support LSP4IJ, which is a third-party LSP server integration --- build.gradle.kts | 18 +++++++- gradle.properties | 2 +- gradle/libs.versions.toml | 2 + resources/META-INF/plugin.xml | 14 ++++++ src/com/koxudaxi/ruff/RuffLanguageClient.kt | 6 +++ src/com/koxudaxi/ruff/RuffLanguageServer.kt | 44 +++++++++++++++++++ .../ruff/RuffLanguageServerFactory.kt | 16 +++++++ .../ruff/RuffLspServerSupportProvider.kt | 2 + 8 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/com/koxudaxi/ruff/RuffLanguageClient.kt create mode 100644 src/com/koxudaxi/ruff/RuffLanguageServer.kt create mode 100644 src/com/koxudaxi/ruff/RuffLanguageServerFactory.kt diff --git a/build.gradle.kts b/build.gradle.kts index de1efc0a..ac3f596a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,6 +19,11 @@ version = properties("pluginVersion").get() // Configure project's dependencies repositories { mavenCentral() + maven { url = uri("https://repository.jboss.org/nexus/content/repositories/snapshots") } + maven { url = uri("https://repository.jboss.org/nexus/content/groups/public") } + maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-snapshots") } + maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-releases") } + maven { url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") } } // Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog @@ -27,6 +32,14 @@ dependencies { compileOnly(libs.ini4j) compileOnly(libs.kotlinxSerialization) testImplementation(kotlin("test")) +// implementation("com.redhat.devtools:lsp4ij:0.10.0") + implementation("org.eclipse.lsp4mp:org.eclipse.lsp4mp.ls:0.10.0") { + exclude("org.eclipse.lsp4j") + } + // Exclude all lsp4j dependencies to use LSP4J from LSP4IJ + implementation("com.redhat.microprofile:com.redhat.qute.ls:0.17.0") { + exclude("org.eclipse.lsp4j") + } } // Set the JVM language level used to build the project. Use Java 11 for 2020.3+, and Java 17 for 2022.2+. @@ -46,6 +59,7 @@ intellij { // Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file. plugins.set(properties("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) }) + plugins.add(libs.plugins.lsp4ij) } // Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin @@ -107,7 +121,9 @@ tasks { } } } - + runIde { + systemProperties["com.redhat.devtools.intellij.telemetry.mode"] = "disabled" + } // Configure UI tests plugin // Read more: https://github.com/JetBrains/intellij-ui-test-robot runIdeForUiTests { diff --git a/gradle.properties b/gradle.properties index a49cc244..df9844a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,7 @@ platformVersion = 2024.1 # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 -platformPlugins = python +platformPlugins = python,com.redhat.devtools.intellij.telemetry:1.1.0.52 # Gradle Releases -> https://github.com/gradle/gradle/releases gradleVersion = 8.6 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 936021c1..15ae1330 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,6 +11,7 @@ changelog = "2.2.0" gradleIntelliJPlugin = "1.17.3" qodana = "0.1.13" kover = "0.7.6" +lsp4ij = "0.0.1-20240508-011803@nightly" [libraries] annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } @@ -25,3 +26,4 @@ kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } qodana = { id = "org.jetbrains.qodana", version.ref = "qodana" } kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +lsp4ij = { id = "com.redhat.devtools.lsp4ij", version.ref = "lsp4ij"} \ No newline at end of file diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 60d676b8..e7f5984e 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -6,6 +6,8 @@ com.intellij.modules.lang com.intellij.modules.python com.intellij.modules.platform + com.redhat.devtools.lsp4ij + com.redhat.devtools.intellij.telemetry com.intellij.modules.ultimate @@ -31,4 +33,16 @@ description="Run ruff with fix option"> + + + + + + + diff --git a/src/com/koxudaxi/ruff/RuffLanguageClient.kt b/src/com/koxudaxi/ruff/RuffLanguageClient.kt new file mode 100644 index 00000000..0191a657 --- /dev/null +++ b/src/com/koxudaxi/ruff/RuffLanguageClient.kt @@ -0,0 +1,6 @@ +package com.koxudaxi.ruff + +import com.intellij.openapi.project.Project +import com.redhat.devtools.lsp4ij.client.LanguageClientImpl + +class RuffLanguageClient(project: Project?) : LanguageClientImpl(project) \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/RuffLanguageServer.kt b/src/com/koxudaxi/ruff/RuffLanguageServer.kt new file mode 100644 index 00000000..7d1f6cad --- /dev/null +++ b/src/com/koxudaxi/ruff/RuffLanguageServer.kt @@ -0,0 +1,44 @@ +package com.koxudaxi.ruff + +import com.intellij.codeInspection.ex.InspectionToolRegistrar +import com.intellij.openapi.project.Project +import com.intellij.profile.codeInspection.ProjectInspectionProfileManager +import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider +import java.io.File + + +class RuffLanguageServer(project: Project) : ProcessStreamConnectionProvider() { + init { + val ruffConfigService = RuffConfigService.getInstance(project) + val commands = createCommand(project, ruffConfigService) + if (commands != null) { + if (ruffConfigService.useRuffFormat) { + super.setUserEnvironmentVariables(mapOf("RUFF_EXPERIMENTAL_FORMATTER" to "1")) + } + super.setCommands(commands) + } + + + } + + private fun createCommand(project: Project, ruffConfigService: RuffConfigService): List? { + if (!ruffConfigService.useRuffLsp) return null + if (!isInspectionEnabled(project)) return null + val executable = + ruffConfigService.ruffLspExecutablePath?.let { File(it) }?.takeIf { it.exists() } + ?: detectRuffExecutable( + project, ruffConfigService, true + ) ?: return null + // TODO Support Configuration + return listOf(executable.absolutePath) + } + + // TODO: move the function to new ruff lsp class + private fun isInspectionEnabled(project: Project): Boolean { + val inspectionProfileManager = ProjectInspectionProfileManager.getInstance(project) + + val toolWrapper = InspectionToolRegistrar.getInstance().createTools() + .find { it.shortName == RuffInspection.INSPECTION_SHORT_NAME } ?: return false + return inspectionProfileManager.currentProfile.isToolEnabled(toolWrapper.displayKey) + } +} \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/RuffLanguageServerFactory.kt b/src/com/koxudaxi/ruff/RuffLanguageServerFactory.kt new file mode 100644 index 00000000..846f33dd --- /dev/null +++ b/src/com/koxudaxi/ruff/RuffLanguageServerFactory.kt @@ -0,0 +1,16 @@ +package com.koxudaxi.ruff +import com.intellij.openapi.project.Project +import com.redhat.devtools.lsp4ij.LanguageServerFactory +import com.redhat.devtools.lsp4ij.client.LanguageClientImpl +import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider + +class RuffLanguageServerFactory : LanguageServerFactory { + override fun createConnectionProvider(project: Project): StreamConnectionProvider { + return RuffLanguageServer(project) + } + + //If you need to provide client specific features + override fun createLanguageClient(project: Project): LanguageClientImpl { + return RuffLanguageClient(project) + } +} \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/RuffLspServerSupportProvider.kt b/src/com/koxudaxi/ruff/RuffLspServerSupportProvider.kt index d0ad2ca3..14069363 100644 --- a/src/com/koxudaxi/ruff/RuffLspServerSupportProvider.kt +++ b/src/com/koxudaxi/ruff/RuffLspServerSupportProvider.kt @@ -19,6 +19,8 @@ class RuffLspServerSupportProvider : LspServerSupportProvider { file: VirtualFile, serverStarter: LspServerSupportProvider.LspServerStarter ) { + // Debugging + return val ruffConfigService = RuffConfigService.getInstance(project) if (!ruffConfigService.useRuffLsp) return if (!isInspectionEnabled(project)) return From ff3511836cb682239f5b9cf2a5593f7a68d72b0c Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Tue, 28 May 2024 09:21:29 +0900 Subject: [PATCH 02/25] Update config panel --- resources/META-INF/plugin.xml | 2 +- src/com/koxudaxi/ruff/Ruff.kt | 14 +++--- src/com/koxudaxi/ruff/RuffConfigPanel.form | 43 +++++++++++++++++-- src/com/koxudaxi/ruff/RuffConfigPanel.kt | 21 +++++---- src/com/koxudaxi/ruff/RuffConfigService.kt | 2 + src/com/koxudaxi/ruff/RuffConfigurable.kt | 30 ++++++++----- .../ruff/RuffPackageManagerListener.kt | 9 +++- .../koxudaxi/ruff/RuffProjectInitializer.kt | 13 +++--- src/com/koxudaxi/ruff/lsp/RuffLspClient.kt | 13 ++++++ .../koxudaxi/ruff/lsp/RuffLspClientManager.kt | 18 ++++++++ .../lsp/intellij/RuffIntellijLspClient.kt | 32 ++++++++++++++ .../intellij}/RuffLspServerSupportProvider.kt | 3 +- .../{ => lsp/lsp4ij}/RuffLanguageClient.kt | 2 +- .../{ => lsp/lsp4ij}/RuffLanguageServer.kt | 6 ++- .../lsp4ij}/RuffLanguageServerFactory.kt | 2 +- 15 files changed, 166 insertions(+), 44 deletions(-) create mode 100644 src/com/koxudaxi/ruff/lsp/RuffLspClient.kt create mode 100644 src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt create mode 100644 src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt rename src/com/koxudaxi/ruff/{ => lsp/intellij}/RuffLspServerSupportProvider.kt (98%) rename src/com/koxudaxi/ruff/{ => lsp/lsp4ij}/RuffLanguageClient.kt (82%) rename src/com/koxudaxi/ruff/{ => lsp/lsp4ij}/RuffLanguageServer.kt (89%) rename src/com/koxudaxi/ruff/{ => lsp/lsp4ij}/RuffLanguageServerFactory.kt (94%) diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index e7f5984e..b3c85813 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -36,7 +36,7 @@ + factoryClass="com.koxudaxi.ruff.lsp.lsp4ij.RuffLanguageServerFactory"> diff --git a/src/com/koxudaxi/ruff/Ruff.kt b/src/com/koxudaxi/ruff/Ruff.kt index edb63169..1a3a56ca 100644 --- a/src/com/koxudaxi/ruff/Ruff.kt +++ b/src/com/koxudaxi/ruff/Ruff.kt @@ -16,7 +16,6 @@ import com.intellij.openapi.editor.Document import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.Task -import com.intellij.openapi.progress.progressStep import com.intellij.openapi.project.Project import com.intellij.openapi.project.modules import com.intellij.openapi.projectRoots.Sdk @@ -37,7 +36,6 @@ import com.jetbrains.python.sdk.flavors.conda.CondaEnvSdkFlavor import com.jetbrains.python.target.PyTargetAwareAdditionalData import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json -import org.jetbrains.annotations.SystemDependent import java.io.File import java.io.IOError import java.io.IOException @@ -121,19 +119,19 @@ val Sdk.wslIsSupported: Boolean }.also { wslSdkIsSupported = it } } -private var lspIsSupportedValue: Boolean? = null -val lspIsSupported: Boolean +private var intellijLspClientSupportedValue: Boolean? = null +val intellijLspClientSupported: Boolean get() { - if (lspIsSupportedValue is Boolean) { - return lspIsSupportedValue as Boolean + if (intellijLspClientSupportedValue is Boolean) { + return intellijLspClientSupportedValue as Boolean } return try { @Suppress("UnstableApiUsage") LspServerSupportProvider - lspIsSupportedValue = true + intellijLspClientSupportedValue = true true } catch (e: NoClassDefFoundError) { - lspIsSupportedValue = false + intellijLspClientSupportedValue = false false } } diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.form b/src/com/koxudaxi/ruff/RuffConfigPanel.form index 3f6c527e..14f4eb44 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.form +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.form @@ -10,7 +10,7 @@ - + @@ -69,17 +69,48 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -224,4 +255,10 @@ + + + + + + diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.kt b/src/com/koxudaxi/ruff/RuffConfigPanel.kt index 8fe5df3b..edd729d4 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.kt +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.kt @@ -10,11 +10,7 @@ import com.jetbrains.python.sdk.pythonSdk import com.koxudaxi.ruff.RuffConfigService.Companion.getInstance import org.jetbrains.annotations.SystemDependent import java.io.File - -import javax.swing.JButton -import javax.swing.JCheckBox -import javax.swing.JLabel -import javax.swing.JPanel +import javax.swing.* class RuffConfigPanel(project: Project) { @@ -37,6 +33,8 @@ class RuffConfigPanel(project: Project) { private lateinit var clearRuffConfigPathButton: JButton private lateinit var disableOnSaveOutsideOfProjectCheckBox: JCheckBox private lateinit var useRuffLspCheckBox: JCheckBox + private lateinit var useIntellijLspClientRadioButton: JRadioButton + private lateinit var useLsp4ijRadioButton: JRadioButton private lateinit var useRuffFormatCheckBox: JCheckBox init { val ruffConfigService = getInstance(project) @@ -49,8 +47,10 @@ class RuffConfigPanel(project: Project) { alwaysUseGlobalRuffCheckBox.isEnabled = true alwaysUseGlobalRuffCheckBox.isSelected = ruffConfigService.alwaysUseGlobalRuff disableOnSaveOutsideOfProjectCheckBox.isEnabled = ruffConfigService.runRuffOnSave - useRuffLspCheckBox.isEnabled = lspIsSupported useRuffLspCheckBox.isSelected = ruffConfigService.useRuffLsp + useIntellijLspClientRadioButton.isEnabled = intellijLspClientSupported + useIntellijLspClientRadioButton.isSelected = ruffConfigService.useIntellijLspClient + useLsp4ijRadioButton.isSelected = ruffConfigService.useLsp4ij useRuffFormatCheckBox.isEnabled = true useRuffFormatCheckBox.isSelected = ruffConfigService.useRuffFormat disableOnSaveOutsideOfProjectCheckBox.isSelected = ruffConfigService.disableOnSaveOutsideOfProject @@ -120,7 +120,7 @@ class RuffConfigPanel(project: Project) { } private fun updateLspExecutableFields() { - val enabled = lspIsSupported && useRuffLspCheckBox.isSelected + val enabled = intellijLspClientSupported && useRuffLspCheckBox.isSelected globalRuffLspExecutablePathField.isEnabled = enabled globalRuffLspLabel.isEnabled = enabled setAutodetectedRuffLspButton.isEnabled = enabled @@ -133,7 +133,7 @@ class RuffConfigPanel(project: Project) { val enabled = !alwaysUseGlobalRuffCheckBox.isSelected projectRuffExecutablePathField.isEnabled = enabled projectRuffLabel.isEnabled = enabled - if (lspIsSupported && useRuffLspCheckBox.isSelected) { + if (intellijLspClientSupported && useRuffLspCheckBox.isSelected) { projectRuffLspExecutablePathField.isEnabled = enabled projectRuffLspLabel.isEnabled = enabled } @@ -178,7 +178,10 @@ class RuffConfigPanel(project: Project) { get() = disableOnSaveOutsideOfProjectCheckBox.isSelected val useRuffLsp: Boolean get() = useRuffLspCheckBox.isSelected - + val useIntellijLspClient: Boolean + get() = useIntellijLspClientRadioButton.isSelected + val useLsp4ij: Boolean + get() = useLsp4ijRadioButton.isSelected val useRuffFormat: Boolean get() = useRuffFormatCheckBox.isSelected diff --git a/src/com/koxudaxi/ruff/RuffConfigService.kt b/src/com/koxudaxi/ruff/RuffConfigService.kt index 965bcdff..fd098344 100644 --- a/src/com/koxudaxi/ruff/RuffConfigService.kt +++ b/src/com/koxudaxi/ruff/RuffConfigService.kt @@ -22,6 +22,8 @@ class RuffConfigService : PersistentStateComponent { var ruffConfigPath: @SystemDependent String? = null var disableOnSaveOutsideOfProject: Boolean = true var useRuffLsp: Boolean = false + var useIntellijLspClient: Boolean = intellijLspClientSupported + var useLsp4ij: Boolean = !useIntellijLspClient var useRuffFormat: Boolean = false override fun getState(): RuffConfigService { diff --git a/src/com/koxudaxi/ruff/RuffConfigurable.kt b/src/com/koxudaxi/ruff/RuffConfigurable.kt index 3c0621b4..51d53194 100644 --- a/src/com/koxudaxi/ruff/RuffConfigurable.kt +++ b/src/com/koxudaxi/ruff/RuffConfigurable.kt @@ -36,6 +36,8 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.ruffConfigPath != configPanel.ruffConfigPath || ruffConfigService.disableOnSaveOutsideOfProject != configPanel.disableOnSaveOutsideOfProject || ruffConfigService.useRuffLsp != configPanel.useRuffLsp || + ruffConfigService.useIntellijLspClient != configPanel.useIntellijLspClient || + ruffConfigService.useLsp4ij != configPanel.useLsp4ij || ruffConfigService.useRuffFormat != configPanel.useRuffFormat } @@ -52,19 +54,25 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.useRuffFormat = configPanel.useRuffFormat ruffCacheService.setVersion() if (ruffConfigService.useRuffLsp != configPanel.useRuffLsp) { - @Suppress("UnstableApiUsage") - val lspServerManager = if (lspIsSupported) LspServerManager.getInstance(project) else null - if (lspServerManager != null) { - if (configPanel.useRuffLsp) { - @Suppress("UnstableApiUsage") - lspServerManager.startServersIfNeeded(RuffLspServerSupportProvider::class.java) - } else { - @Suppress("UnstableApiUsage") - lspServerManager.stopServers(RuffLspServerSupportProvider::class.java) - } + + } + if (configPanel.ruffConfigPath != configPanel.ruffConfigPath) {} + } + + + private fun startIntellijLspClient() { + @Suppress("UnstableApiUsage") + val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null + if (lspServerManager != null) { + if (configPanel.useRuffLsp) { + @Suppress("UnstableApiUsage") + lspServerManager.startServersIfNeeded(RuffLspServerSupportProvider::class.java) + } else { + @Suppress("UnstableApiUsage") + lspServerManager.stopServers(RuffLspServerSupportProvider::class.java) } - ruffConfigService.useRuffLsp = configPanel.useRuffLsp } + ruffConfigService.useRuffLsp = configPanel.useRuffLsp } override fun disposeUIResources() { diff --git a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt index 0f4c7395..080e9f56 100644 --- a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt +++ b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt @@ -5,22 +5,27 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.platform.lsp.api.LspServerManager import com.jetbrains.python.packaging.PyPackageManager +import com.redhat.devtools.lsp4ij.LanguageServersRegistry class RuffPackageManagerListener(project: Project) : PyPackageManager.Listener { private val ruffConfigService = RuffConfigService.getInstance(project) private val ruffCacheService = RuffCacheService.getInstance(project) @Suppress("UnstableApiUsage") - private val lspServerManager = if (lspIsSupported) LspServerManager.getInstance(project) else null + private val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null override fun packagesRefreshed(sdk: Sdk) { ruffConfigService.projectRuffExecutablePath = findRuffExecutableInSDK(sdk, false)?.absolutePath ruffConfigService.projectRuffLspExecutablePath = findRuffExecutableInSDK(sdk, true)?.absolutePath ruffCacheService.setVersion() - if (lspServerManager != null && ruffConfigService.useRuffLsp) { + if (!ruffConfigService.useRuffLsp) return + if (lspServerManager != null && ruffConfigService.useIntellijLspClient) { try { @Suppress("UnstableApiUsage") lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) } catch (_: Exception) { } } + if (ruffConfigService.useLsp4ij) { + // TODO: Restart lsp4ij + } } } \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/RuffProjectInitializer.kt b/src/com/koxudaxi/ruff/RuffProjectInitializer.kt index aec9432c..2772bae1 100644 --- a/src/com/koxudaxi/ruff/RuffProjectInitializer.kt +++ b/src/com/koxudaxi/ruff/RuffProjectInitializer.kt @@ -23,7 +23,7 @@ class RuffProjectInitializer : ProjectActivity { if (ruffCacheService.getVersion() == null) { ruffCacheService.setVersion() } - if (lspIsSupported) { + if (intellijLspClientSupported) { setUpPyProjectTomlLister(project) } } catch (_: AlreadyDisposedException) { @@ -57,10 +57,13 @@ class RuffProjectInitializer : ProjectActivity { ApplicationManager.getApplication().invokeLater { if (project.isDisposed) return@invokeLater if (!ruffConfigService.useRuffLsp) return@invokeLater - lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) - - LspServerManager.getInstance(project) - .stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) + if (ruffConfigService.useIntellijLspClient) { + @Suppress("UnstableApiUsage") + lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) + @Suppress("UnstableApiUsage") + LspServerManager.getInstance(project) + .stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) + } } } catch (_: AlreadyDisposedException) { } diff --git a/src/com/koxudaxi/ruff/lsp/RuffLspClient.kt b/src/com/koxudaxi/ruff/lsp/RuffLspClient.kt new file mode 100644 index 00000000..81acbc49 --- /dev/null +++ b/src/com/koxudaxi/ruff/lsp/RuffLspClient.kt @@ -0,0 +1,13 @@ +package com.koxudaxi.ruff.lsp + +import com.intellij.openapi.extensions.ExtensionPointName + +interface RuffLspClient { + companion object { + val EP_NAME = ExtensionPointName.create("com.koxudaxi.ruff.lsp.client") + } + fun getRuffLspClientId(): String + fun start() + fun stop() + fun restart() +} \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt new file mode 100644 index 00000000..3c898fb6 --- /dev/null +++ b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt @@ -0,0 +1,18 @@ +package com.koxudaxi.ruff.lsp + +import com.intellij.openapi.components.Service +import com.intellij.openapi.project.Project + + +@Service(Service.Level.PROJECT) +class RuffLspClientManager { + private fun getLspClient(): List { + return RuffLspClient.EP_NAME.extensionList + } + private val lspClient: List = getLspClient() + companion object { + fun getInstance(project: Project): RuffLspClientManager { + return project.getService(RuffLspClientManager::class.java) + } + } +} \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt b/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt new file mode 100644 index 00000000..8cab8581 --- /dev/null +++ b/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt @@ -0,0 +1,32 @@ +package com.koxudaxi.ruff.lsp.intellij + +import RuffLspServerSupportProvider +import com.intellij.openapi.project.Project +import com.intellij.platform.lsp.api.LspServerManager +import com.koxudaxi.ruff.intellijLspClientSupported +import com.koxudaxi.ruff.lsp.RuffLspClient + +class RuffIntellijLspClient(val project: Project) : RuffLspClient { + @Suppress("UnstableApiUsage") + private val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null + override fun getRuffLspClientId(): String = RUFF_INTELLIJ_LSP_CLIENT_ID + + override fun start() { + restart() + } + + override fun stop() { +// if (lspServerManager == null) return +// @Suppress("UnstableApiUsage") +// lspServerManager.stopServer(RuffLspServerSupportProvider::class.java) + } + + override fun restart() { + if (lspServerManager == null) return + @Suppress("UnstableApiUsage") + lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) + } + companion object { + const val RUFF_INTELLIJ_LSP_CLIENT_ID = "ruff-intellij-lsp-client" + } +} \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/RuffLspServerSupportProvider.kt b/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt similarity index 98% rename from src/com/koxudaxi/ruff/RuffLspServerSupportProvider.kt rename to src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt index 14069363..a59b45de 100644 --- a/src/com/koxudaxi/ruff/RuffLspServerSupportProvider.kt +++ b/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt @@ -19,10 +19,9 @@ class RuffLspServerSupportProvider : LspServerSupportProvider { file: VirtualFile, serverStarter: LspServerSupportProvider.LspServerStarter ) { - // Debugging - return val ruffConfigService = RuffConfigService.getInstance(project) if (!ruffConfigService.useRuffLsp) return + if (!ruffConfigService.useIntellijLspClient) return if (!isInspectionEnabled(project)) return if (file.extension != "py") return val executable = diff --git a/src/com/koxudaxi/ruff/RuffLanguageClient.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageClient.kt similarity index 82% rename from src/com/koxudaxi/ruff/RuffLanguageClient.kt rename to src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageClient.kt index 0191a657..da994388 100644 --- a/src/com/koxudaxi/ruff/RuffLanguageClient.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageClient.kt @@ -1,4 +1,4 @@ -package com.koxudaxi.ruff +package com.koxudaxi.ruff.lsp.lsp4ij import com.intellij.openapi.project.Project import com.redhat.devtools.lsp4ij.client.LanguageClientImpl diff --git a/src/com/koxudaxi/ruff/RuffLanguageServer.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt similarity index 89% rename from src/com/koxudaxi/ruff/RuffLanguageServer.kt rename to src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt index 7d1f6cad..7ff9efd9 100644 --- a/src/com/koxudaxi/ruff/RuffLanguageServer.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt @@ -1,8 +1,11 @@ -package com.koxudaxi.ruff +package com.koxudaxi.ruff.lsp.lsp4ij import com.intellij.codeInspection.ex.InspectionToolRegistrar import com.intellij.openapi.project.Project import com.intellij.profile.codeInspection.ProjectInspectionProfileManager +import com.koxudaxi.ruff.RuffConfigService +import com.koxudaxi.ruff.RuffInspection +import com.koxudaxi.ruff.detectRuffExecutable import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider import java.io.File @@ -23,6 +26,7 @@ class RuffLanguageServer(project: Project) : ProcessStreamConnectionProvider() { private fun createCommand(project: Project, ruffConfigService: RuffConfigService): List? { if (!ruffConfigService.useRuffLsp) return null + if (!ruffConfigService.useLsp4ij) return null if (!isInspectionEnabled(project)) return null val executable = ruffConfigService.ruffLspExecutablePath?.let { File(it) }?.takeIf { it.exists() } diff --git a/src/com/koxudaxi/ruff/RuffLanguageServerFactory.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt similarity index 94% rename from src/com/koxudaxi/ruff/RuffLanguageServerFactory.kt rename to src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt index 846f33dd..2f76b670 100644 --- a/src/com/koxudaxi/ruff/RuffLanguageServerFactory.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt @@ -1,4 +1,4 @@ -package com.koxudaxi.ruff +package com.koxudaxi.ruff.lsp.lsp4ij import com.intellij.openapi.project.Project import com.redhat.devtools.lsp4ij.LanguageServerFactory import com.redhat.devtools.lsp4ij.client.LanguageClientImpl From 3fcae65b83e68aeb495dbe7a15f5bdc4ccf18dec Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 30 May 2024 01:00:43 +0900 Subject: [PATCH 03/25] Remove unnecessary dependency --- build.gradle.kts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ac3f596a..2ab90f81 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,11 +19,6 @@ version = properties("pluginVersion").get() // Configure project's dependencies repositories { mavenCentral() - maven { url = uri("https://repository.jboss.org/nexus/content/repositories/snapshots") } - maven { url = uri("https://repository.jboss.org/nexus/content/groups/public") } - maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-snapshots") } - maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-releases") } - maven { url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") } } // Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog @@ -32,14 +27,6 @@ dependencies { compileOnly(libs.ini4j) compileOnly(libs.kotlinxSerialization) testImplementation(kotlin("test")) -// implementation("com.redhat.devtools:lsp4ij:0.10.0") - implementation("org.eclipse.lsp4mp:org.eclipse.lsp4mp.ls:0.10.0") { - exclude("org.eclipse.lsp4j") - } - // Exclude all lsp4j dependencies to use LSP4J from LSP4IJ - implementation("com.redhat.microprofile:com.redhat.qute.ls:0.17.0") { - exclude("org.eclipse.lsp4j") - } } // Set the JVM language level used to build the project. Use Java 11 for 2020.3+, and Java 17 for 2022.2+. From 1c988cce1b79770f0dfaf1137527f435f8f104c9 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 30 May 2024 01:05:17 +0900 Subject: [PATCH 04/25] Update github action --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 719c121a..aeeb71d2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,7 +61,7 @@ jobs: # Setup Gradle - name: Setup Gradle - uses: gradle/actions/setup-gradle@v321 + uses: gradle/gradle-build-action@v3 with: gradle-home-cache-cleanup: true From e79d6c2c45e73bc83604268db59faa0a56cb789f Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 30 May 2024 02:39:47 +0900 Subject: [PATCH 05/25] Update lsp clients --- resources/META-INF/plugin.xml | 25 ++++++++-------- src/com/koxudaxi/ruff/RuffConfigurable.kt | 8 +++++ src/com/koxudaxi/ruff/lsp/RuffLspClient.kt | 6 ---- .../koxudaxi/ruff/lsp/RuffLspClientManager.kt | 29 ++++++++++++++++--- .../lsp/intellij/RuffIntellijLspClient.kt | 4 +-- .../ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt | 27 +++++++++++++++++ 6 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index b3c85813..f23d6c6c 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -7,7 +7,6 @@ com.intellij.modules.python com.intellij.modules.platform com.redhat.devtools.lsp4ij - com.redhat.devtools.intellij.telemetry com.intellij.modules.ultimate @@ -33,16 +32,16 @@ description="Run ruff with fix option"> - - - - - - - + + + + + + + + + + + + diff --git a/src/com/koxudaxi/ruff/RuffConfigurable.kt b/src/com/koxudaxi/ruff/RuffConfigurable.kt index 51d53194..b4aaead8 100644 --- a/src/com/koxudaxi/ruff/RuffConfigurable.kt +++ b/src/com/koxudaxi/ruff/RuffConfigurable.kt @@ -4,6 +4,8 @@ import RuffLspServerSupportProvider import com.intellij.openapi.options.Configurable import com.intellij.openapi.project.Project import com.intellij.platform.lsp.api.LspServerManager +import com.koxudaxi.ruff.lsp.RuffLspClientManager +import com.koxudaxi.ruff.lsp.lsp4ij.RuffLsp4IntellijClient import javax.swing.JComponent @@ -54,7 +56,13 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.useRuffFormat = configPanel.useRuffFormat ruffCacheService.setVersion() if (ruffConfigService.useRuffLsp != configPanel.useRuffLsp) { + val ruffLspClientManager = RuffLspClientManager.getInstance(project) + if (configPanel.useRuffLsp) { + ruffLspClientManager.startRuffLsp4IntellijClient() + } else { + ruffLspClientManager.stopAll() + } } if (configPanel.ruffConfigPath != configPanel.ruffConfigPath) {} } diff --git a/src/com/koxudaxi/ruff/lsp/RuffLspClient.kt b/src/com/koxudaxi/ruff/lsp/RuffLspClient.kt index 81acbc49..9a27ff39 100644 --- a/src/com/koxudaxi/ruff/lsp/RuffLspClient.kt +++ b/src/com/koxudaxi/ruff/lsp/RuffLspClient.kt @@ -1,12 +1,6 @@ package com.koxudaxi.ruff.lsp -import com.intellij.openapi.extensions.ExtensionPointName - interface RuffLspClient { - companion object { - val EP_NAME = ExtensionPointName.create("com.koxudaxi.ruff.lsp.client") - } - fun getRuffLspClientId(): String fun start() fun stop() fun restart() diff --git a/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt index 3c898fb6..7cbf2aac 100644 --- a/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt +++ b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt @@ -2,17 +2,38 @@ package com.koxudaxi.ruff.lsp import com.intellij.openapi.components.Service import com.intellij.openapi.project.Project +import com.koxudaxi.ruff.lsp.intellij.RuffIntellijLspClient +import com.koxudaxi.ruff.lsp.lsp4ij.RuffLsp4IntellijClient @Service(Service.Level.PROJECT) -class RuffLspClientManager { - private fun getLspClient(): List { - return RuffLspClient.EP_NAME.extensionList +class RuffLspClientManager(private val project: Project) { + private val ruffLsp4IntellijClient = RuffLsp4IntellijClient(project) + private val ruffIntellijLspClient = RuffIntellijLspClient(project) + + fun startRuffLsp4IntellijClient() { + ruffLsp4IntellijClient.start() + } + fun stopRuffLsp4IntellijClient() { + ruffLsp4IntellijClient.stop() + } + fun startRuffIntellijLspClient() { + ruffIntellijLspClient.start() } - private val lspClient: List = getLspClient() + fun stopRuffIntellijLspClient() { + ruffIntellijLspClient.stop() + } + + fun stopAll() { + stopRuffIntellijLspClient() + stopRuffLsp4IntellijClient() + } + companion object { fun getInstance(project: Project): RuffLspClientManager { return project.getService(RuffLspClientManager::class.java) } } + + } \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt b/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt index 8cab8581..de6c0bd7 100644 --- a/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt +++ b/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt @@ -9,13 +9,13 @@ import com.koxudaxi.ruff.lsp.RuffLspClient class RuffIntellijLspClient(val project: Project) : RuffLspClient { @Suppress("UnstableApiUsage") private val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null - override fun getRuffLspClientId(): String = RUFF_INTELLIJ_LSP_CLIENT_ID override fun start() { restart() } override fun stop() { + // TODO: stop server // if (lspServerManager == null) return // @Suppress("UnstableApiUsage") // lspServerManager.stopServer(RuffLspServerSupportProvider::class.java) @@ -27,6 +27,6 @@ class RuffIntellijLspClient(val project: Project) : RuffLspClient { lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) } companion object { - const val RUFF_INTELLIJ_LSP_CLIENT_ID = "ruff-intellij-lsp-client" + const val RUFF_LSP_CLIENT_ID = "ruff-intellij-lsp-client" } } \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt new file mode 100644 index 00000000..d06d85cb --- /dev/null +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt @@ -0,0 +1,27 @@ +package com.koxudaxi.ruff.lsp.lsp4ij + +import com.intellij.openapi.project.Project +import com.koxudaxi.ruff.lsp.RuffLspClient + +class RuffLsp4IntellijClient(val project: Project): RuffLspClient { + private val lspServer get() = RuffLanguageServerFactory().createConnectionProvider(project) + override fun start() { + lspServer.start() + } + + override fun stop() { + if (lspServer.isAlive) { + lspServer.stop() + } + } + + override fun restart() { + if (lspServer.isAlive) { + lspServer.stop() + } + lspServer.start() + } + companion object { + const val RUFF_LSP_CLIENT_ID = "ruff-lsp4-intellij-client" + } +} \ No newline at end of file From 4406488a6dc0c87fbd2598169f65e01d4a76b23e Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 15 Aug 2024 03:55:52 +0000 Subject: [PATCH 06/25] Update libs --- build.gradle.kts | 3 +++ gradle/libs.versions.toml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 244fe275..3261c7d1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,7 @@ fun environment(key: String) = providers.environmentVariable(key) plugins { alias(libs.plugins.kotlin) // Kotlin support alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin + alias(libs.plugins.lsp4ij) alias(libs.plugins.changelog) // Gradle Changelog Plugin alias(libs.plugins.qodana) // Gradle Qodana Plugin alias(libs.plugins.kover) // Gradle Kover Plugin @@ -19,6 +20,8 @@ version = properties("pluginVersion").get() // Configure project's dependencies repositories { mavenCentral() + maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-snapshots") } + maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-releases") } intellijPlatform { defaultRepositories() snapshots() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 04125ed5..261e0202 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ changelog = "2.2.1" gradleIntelliJPlugin = "2.0.0-rc1" qodana = "0.1.13" kover = "0.7.6" -lsp4ij = "0.0.1-20240508-011803@nightly" +lsp4ij = "0.4.0-20240815-013110@nightly" [libraries] annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } From 7f66d7b2592a49a02f11b5cf1ea115ce71be4bc1 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 15 Aug 2024 06:48:48 +0000 Subject: [PATCH 07/25] Fix libs --- build.gradle.kts | 13 ++++++--- gradle.properties | 4 +-- gradle/libs.versions.toml | 4 +-- src/com/koxudaxi/ruff/RuffConfigPanel.kt | 4 +-- src/com/koxudaxi/ruff/RuffConfigurable.kt | 17 ++++++----- .../ruff/RuffPackageManagerListener.kt | 29 ++++++++++--------- 6 files changed, 40 insertions(+), 31 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3261c7d1..cbbbc1e4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,8 @@ import org.jetbrains.changelog.Changelog import org.jetbrains.changelog.markdownToHTML +import org.jetbrains.intellij.platform.gradle.TestFrameworkType +import org.jetbrains.intellij.platform.gradle.extensions.intellijPlatform + fun properties(key: String) = providers.gradleProperty(key) fun environment(key: String) = providers.environmentVariable(key) @@ -7,7 +10,6 @@ fun environment(key: String) = providers.environmentVariable(key) plugins { alias(libs.plugins.kotlin) // Kotlin support alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin - alias(libs.plugins.lsp4ij) alias(libs.plugins.changelog) // Gradle Changelog Plugin alias(libs.plugins.qodana) // Gradle Qodana Plugin alias(libs.plugins.kover) // Gradle Kover Plugin @@ -20,11 +22,11 @@ version = properties("pluginVersion").get() // Configure project's dependencies repositories { mavenCentral() - maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-snapshots") } - maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-releases") } intellijPlatform { defaultRepositories() - snapshots() +// snapshots() +// nightly() + marketplace() } } @@ -40,6 +42,9 @@ dependencies { val bundledPlugins = properties("platformBundledPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) } create(type, version, useInstaller = false) bundledPlugins(bundledPlugins) + val lsp4ij = libs.plugins.lsp4ij.get() + plugin(lsp4ij.pluginId, lsp4ij.version.requiredVersion) + instrumentationTools() testFramework(TestFrameworkType.Bundled) pluginVerifier() diff --git a/gradle.properties b/gradle.properties index f04928b1..be36ea9a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,11 +12,11 @@ pluginUntilBuild = 242.* # IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension platformType = PY -platformVersion = 242-EAP-SNAPSHOT +platformVersion = 2024.2 # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 -platformBundledPlugins = org.toml.lang,Pythonid,com.redhat.devtools.intellij.telemetry:1.1.0.52 +platformBundledPlugins = org.toml.lang,Pythonid # Gradle Releases -> https://github.com/gradle/gradle/releases gradleVersion = 8.6 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 261e0202..c0316b54 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,10 +8,10 @@ kotlinxSerialization = "1.6.3" # plugins kotlin = "1.9.23" changelog = "2.2.1" -gradleIntelliJPlugin = "2.0.0-rc1" +gradleIntelliJPlugin = "2.0.1" qodana = "0.1.13" kover = "0.7.6" -lsp4ij = "0.4.0-20240815-013110@nightly" +lsp4ij = "0.3.0" [libraries] annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.kt b/src/com/koxudaxi/ruff/RuffConfigPanel.kt index 7ed6a3ca..78719aaa 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.kt +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.kt @@ -123,7 +123,7 @@ class RuffConfigPanel(project: Project) { } private fun updateLspExecutableFields() { - val enabled = lspIsSupported && useRuffLspCheckBox.isSelected + val enabled = intellijLspClientSupported && useRuffLspCheckBox.isSelected globalRuffLspExecutablePathField.isEnabled = enabled globalRuffLspLabel.isEnabled = enabled setAutodetectedRuffLspButton.isEnabled = enabled @@ -136,7 +136,7 @@ class RuffConfigPanel(project: Project) { val enabled = !alwaysUseGlobalRuffCheckBox.isSelected projectRuffExecutablePathField.isEnabled = enabled projectRuffLabel.isEnabled = enabled - if (lspIsSupported && useRuffLspCheckBox.isSelected) { + if (intellijLspClientSupported && useRuffLspCheckBox.isSelected) { projectRuffLspExecutablePathField.isEnabled = enabled projectRuffLspLabel.isEnabled = enabled } diff --git a/src/com/koxudaxi/ruff/RuffConfigurable.kt b/src/com/koxudaxi/ruff/RuffConfigurable.kt index 6d5713b2..984523f6 100644 --- a/src/com/koxudaxi/ruff/RuffConfigurable.kt +++ b/src/com/koxudaxi/ruff/RuffConfigurable.kt @@ -60,7 +60,7 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable if (ruffConfigService.useRuffLsp != configPanelUseRuffLsp || ruffConfigService.useRuffServer != configPanelUseRuffServer) { ruffCacheService.setVersion{ @Suppress("UnstableApiUsage") - val lspServerManager = if (lspIsSupported) LspServerManager.getInstance(project) else null + val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null if (lspServerManager != null) { if (configPanelUseRuffLsp || configPanelUseRuffServer) { @Suppress("UnstableApiUsage") @@ -77,14 +77,15 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.useRuffLsp = configPanel.useRuffLsp ruffConfigService.useRuffServer = configPanel.useRuffServer - ruffCacheService.setVersion() - if (ruffConfigService.useRuffLsp != configPanel.useRuffLsp) { - val ruffLspClientManager = RuffLspClientManager.getInstance(project) + ruffCacheService.setVersion { + if (ruffConfigService.useRuffLsp != configPanel.useRuffLsp) { + val ruffLspClientManager = RuffLspClientManager.getInstance(project) - if (configPanel.useRuffLsp) { - ruffLspClientManager.startRuffLsp4IntellijClient() - } else { - ruffLspClientManager.stopAll() + if (configPanel.useRuffLsp) { + ruffLspClientManager.startRuffLsp4IntellijClient() + } else { + ruffLspClientManager.stopAll() + } } } if (configPanel.ruffConfigPath != configPanel.ruffConfigPath) {} diff --git a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt index 8738ac92..c1051f05 100644 --- a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt +++ b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt @@ -9,25 +9,28 @@ import com.jetbrains.python.packaging.PyPackageManager class RuffPackageManagerListener(project: Project) : PyPackageManager.Listener { private val ruffConfigService = RuffConfigService.getInstance(project) private val ruffCacheService = RuffCacheService.getInstance(project) + @Suppress("UnstableApiUsage") private val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null override fun packagesRefreshed(sdk: Sdk) { ruffConfigService.projectRuffExecutablePath = findRuffExecutableInSDK(sdk, false)?.absolutePath ruffConfigService.projectRuffLspExecutablePath = findRuffExecutableInSDK(sdk, true)?.absolutePath - ruffCacheService.setVersion() - if (!ruffConfigService.useRuffLsp) return - if (lspServerManager != null && ruffConfigService.useIntellijLspClient) { - ruffCacheService.setVersion{ - if (lspServerManager != null && (ruffConfigService.useRuffLsp || ruffConfigService.useRuffServer)) { - try { - @Suppress("UnstableApiUsage") - lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) - } catch (_: Exception) { + ruffCacheService.setVersion { + if (!ruffConfigService.useRuffLsp) return@setVersion + if (lspServerManager != null && ruffConfigService.useIntellijLspClient) { + ruffCacheService.setVersion { + if (lspServerManager != null && (ruffConfigService.useRuffLsp || ruffConfigService.useRuffServer)) { + try { + @Suppress("UnstableApiUsage") + lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) + } catch (_: Exception) { + } + } + if (ruffConfigService.useLsp4ij) { + // TODO: Restart lsp4ij + } + } } - } - if (ruffConfigService.useLsp4ij) { - // TODO: Restart lsp4ij - } } } } \ No newline at end of file From 65f2992225cb30e99f1cd8db06f36f171c20760c Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 15 Aug 2024 07:05:19 +0000 Subject: [PATCH 08/25] Fix libs --- build.gradle.kts | 11 +++++++---- gradle/libs.versions.toml | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index cbbbc1e4..8debae15 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,11 +22,14 @@ version = properties("pluginVersion").get() // Configure project's dependencies repositories { mavenCentral() +// maven { url = uri("https://repository.jboss.org/nexus/content/repositories/snapshots") } +// maven { url = uri("https://repository.jboss.org/nexus/content/groups/public") } + maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-snapshots") } + maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-releases") } +// maven { url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") } intellijPlatform { defaultRepositories() -// snapshots() -// nightly() - marketplace() + nightly() } } @@ -43,7 +46,7 @@ dependencies { create(type, version, useInstaller = false) bundledPlugins(bundledPlugins) val lsp4ij = libs.plugins.lsp4ij.get() - plugin(lsp4ij.pluginId, lsp4ij.version.requiredVersion) + plugin("${lsp4ij.pluginId}:${lsp4ij.version.requiredVersion}@nightly") instrumentationTools() testFramework(TestFrameworkType.Bundled) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0316b54..5a8f73fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ changelog = "2.2.1" gradleIntelliJPlugin = "2.0.1" qodana = "0.1.13" kover = "0.7.6" -lsp4ij = "0.3.0" +lsp4ij = "0.4.0-20240815-013110" [libraries] annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } From db04902219c0eb38b60d4d62d02fecb9b78a58a6 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 15 Aug 2024 14:06:59 +0000 Subject: [PATCH 09/25] Remove deps --- build.gradle.kts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8debae15..09c9b3c8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,11 +22,6 @@ version = properties("pluginVersion").get() // Configure project's dependencies repositories { mavenCentral() -// maven { url = uri("https://repository.jboss.org/nexus/content/repositories/snapshots") } -// maven { url = uri("https://repository.jboss.org/nexus/content/groups/public") } - maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-snapshots") } - maven { url = uri("https://repo.eclipse.org/content/repositories/lsp4mp-releases") } -// maven { url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") } intellijPlatform { defaultRepositories() nightly() From ff9a1aaaf1e8f2e568b5340d7be7afef5cbb9e0c Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 15 Aug 2024 14:17:55 +0000 Subject: [PATCH 10/25] Enable lsp server feature --- resources/META-INF/plugin.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index f23d6c6c..4c15db81 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -32,16 +32,16 @@ description="Run ruff with fix option"> - - - - - - - - - - - - + + + + + + + From ee85e089767de7ad4809c6210cbe7e28c6ee4bd6 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Fri, 16 Aug 2024 16:01:57 +0000 Subject: [PATCH 11/25] Fix config panel --- src/com/koxudaxi/ruff/RuffConfigPanel.form | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.form b/src/com/koxudaxi/ruff/RuffConfigPanel.form index 356a6b3c..90f63d53 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.form +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.form @@ -10,7 +10,7 @@ - + @@ -91,7 +91,7 @@ - + From 6ec0b79966be39bfc49760eb572dd67c342725f8 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 22 Aug 2024 01:59:50 +0900 Subject: [PATCH 12/25] Implement lsp clients --- resources/META-INF/plugin.xml | 16 +-- src/com/koxudaxi/ruff/Ruff.kt | 23 ++++ src/com/koxudaxi/ruff/RuffConfigPanel.form | 103 ++++++++++++------ src/com/koxudaxi/ruff/RuffConfigurable.kt | 76 +++++-------- .../ruff/RuffPackageManagerListener.kt | 33 +++--- .../koxudaxi/ruff/lsp/RuffLspClientManager.kt | 68 ++++++++---- .../lsp/intellij/RuffIntellijLspClient.kt | 10 +- .../intellij/RuffLspServerSupportProvider.kt | 24 +--- .../ruff/lsp/lsp4ij/RuffLanguageServer.kt | 39 +++---- .../ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt | 30 +++-- 10 files changed, 238 insertions(+), 184 deletions(-) diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 4c15db81..28fce851 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -33,14 +33,14 @@ - - - - + + + + + + + + diff --git a/src/com/koxudaxi/ruff/Ruff.kt b/src/com/koxudaxi/ruff/Ruff.kt index aa965bae..87f005a8 100644 --- a/src/com/koxudaxi/ruff/Ruff.kt +++ b/src/com/koxudaxi/ruff/Ruff.kt @@ -1,5 +1,6 @@ package com.koxudaxi.ruff +import com.intellij.codeInspection.ex.InspectionToolRegistrar import com.intellij.credentialStore.toByteArrayAndClear import com.intellij.execution.ExecutionException import com.intellij.execution.RunCanceledByUserException @@ -24,6 +25,7 @@ import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.platform.lsp.api.LspServerSupportProvider +import com.intellij.profile.codeInspection.ProjectInspectionProfileManager import com.intellij.psi.PsiComment import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiFile @@ -207,6 +209,27 @@ val PsiFile.isApplicableTo: Boolean else -> language.isKindOf(PythonLanguage.getInstance()) } +fun getRuffExecutable(project: Project, ruffConfigService: RuffConfigService, lsp: Boolean): File? { + return when { + lsp -> ruffConfigService.ruffLspExecutablePath + else -> ruffConfigService.ruffExecutablePath + }?.let { File(it) }?.takeIf { it.exists() } ?: detectRuffExecutable( + project, ruffConfigService, lsp + ) +} + +fun getConfigArgs(ruffConfigService: RuffConfigService): List? { + val config = ruffConfigService.ruffConfigPath?.let { File(it) }?.takeIf { it.exists() } ?: return null + return listOf(CONFIG_ARG, config.absolutePath) +} + +fun isInspectionEnabled(project: Project): Boolean { + val inspectionProfileManager = ProjectInspectionProfileManager.getInstance(project) + + val toolWrapper = InspectionToolRegistrar.getInstance().createTools() + .find { it.shortName == RuffInspection.INSPECTION_SHORT_NAME } ?: return false + return inspectionProfileManager.currentProfile.isToolEnabled(toolWrapper.displayKey) +} fun runCommand( commandArgs: CommandArgs ): String? = runCommand( diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.form b/src/com/koxudaxi/ruff/RuffConfigPanel.form index 90f63d53..0c98d6fc 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.form +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.form @@ -10,7 +10,7 @@ - + @@ -64,59 +64,94 @@ - - - - - - - - - + - - - - - - - - - + - + - + - + + - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/koxudaxi/ruff/RuffConfigurable.kt b/src/com/koxudaxi/ruff/RuffConfigurable.kt index 984523f6..cdd96c43 100644 --- a/src/com/koxudaxi/ruff/RuffConfigurable.kt +++ b/src/com/koxudaxi/ruff/RuffConfigurable.kt @@ -1,10 +1,9 @@ package com.koxudaxi.ruff -import RuffLspServerSupportProvider import com.intellij.openapi.options.Configurable import com.intellij.openapi.project.Project -import com.intellij.platform.lsp.api.LspServerManager -import com.koxudaxi.ruff.lsp.RuffLspClientManager +import com.koxudaxi.ruff.lsp.intellij.RuffIntellijLspClient +import com.koxudaxi.ruff.lsp.lsp4ij.RuffLsp4IntellijClient import javax.swing.JComponent @@ -12,6 +11,7 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable private val ruffConfigService: RuffConfigService = RuffConfigService.getInstance(project) private val configPanel: RuffConfigPanel = RuffConfigPanel(project) private val ruffCacheService: RuffCacheService = RuffCacheService.getInstance(project) + private val ruffLspClientManager = RuffLspClientManager.getInstance(project) override fun getDisplayName(): String { return "Ruff" } @@ -39,8 +39,6 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.useRuffLsp != configPanel.useRuffLsp || ruffConfigService.useIntellijLspClient != configPanel.useIntellijLspClient || ruffConfigService.useLsp4ij != configPanel.useLsp4ij || - ruffConfigService.useRuffFormat != configPanel.useRuffFormat - ruffConfigService.useRuffFormat != configPanel.useRuffFormat || ruffConfigService.useRuffServer != configPanel.useRuffServer } @@ -52,59 +50,43 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.alwaysUseGlobalRuff = configPanel.alwaysUseGlobalRuff ruffConfigService.globalRuffExecutablePath = configPanel.globalRuffExecutablePath ruffConfigService.globalRuffLspExecutablePath = configPanel.globalRuffLspExecutablePath - ruffConfigService.ruffConfigPath = configPanel.ruffConfigPath ruffConfigService.disableOnSaveOutsideOfProject = configPanel.disableOnSaveOutsideOfProject ruffConfigService.useRuffFormat = configPanel.useRuffFormat - val configPanelUseRuffLsp = configPanel.useRuffLsp - val configPanelUseRuffServer = configPanel.useRuffServer - if (ruffConfigService.useRuffLsp != configPanelUseRuffLsp || ruffConfigService.useRuffServer != configPanelUseRuffServer) { - ruffCacheService.setVersion{ - @Suppress("UnstableApiUsage") - val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null - if (lspServerManager != null) { - if (configPanelUseRuffLsp || configPanelUseRuffServer) { - @Suppress("UnstableApiUsage") - lspServerManager.startServersIfNeeded(RuffLspServerSupportProvider::class.java) - } else { - @Suppress("UnstableApiUsage") - lspServerManager.stopServers(RuffLspServerSupportProvider::class.java) - } - } - } - } else { - ruffCacheService.setVersion{} - } - + val ruffConfigPathChanged = configPanel.ruffConfigPath != configPanel.ruffConfigPath + val useRuffLspChanged = ruffConfigService.useRuffLsp != configPanel.useRuffLsp + val useRuffServerChanged = ruffConfigService.useRuffServer != configPanel.useRuffServer + val lspClientChanged = ruffConfigService.useIntellijLspClient != configPanel.useIntellijLspClient + ruffConfigService.ruffConfigPath = configPanel.ruffConfigPath ruffConfigService.useRuffLsp = configPanel.useRuffLsp ruffConfigService.useRuffServer = configPanel.useRuffServer + ruffConfigService.useIntellijLspClient = configPanel.useIntellijLspClient + ruffConfigService.useLsp4ij = configPanel.useLsp4ij ruffCacheService.setVersion { - if (ruffConfigService.useRuffLsp != configPanel.useRuffLsp) { - val ruffLspClientManager = RuffLspClientManager.getInstance(project) - - if (configPanel.useRuffLsp) { - ruffLspClientManager.startRuffLsp4IntellijClient() + val startLsp = ruffConfigService.useRuffLsp || ruffConfigService.useRuffServer + var started = false + if (lspClientChanged) { + if (ruffConfigService.useLsp4ij) { + ruffLspClientManager.setClient(RuffLsp4IntellijClient::class, startLsp) } else { - ruffLspClientManager.stopAll() + ruffLspClientManager.setClient(RuffIntellijLspClient::class, startLsp) + } + started = startLsp + } else { + if (useRuffLspChanged || useRuffServerChanged) { + if (startLsp) { + ruffLspClientManager.start() + started = true + } else { + ruffLspClientManager.stop() + } } } - } - if (configPanel.ruffConfigPath != configPanel.ruffConfigPath) {} - } - - private fun startIntellijLspClient() { - @Suppress("UnstableApiUsage") - val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null - if (lspServerManager != null) { - if (configPanel.useRuffLsp) { - @Suppress("UnstableApiUsage") - lspServerManager.startServersIfNeeded(RuffLspServerSupportProvider::class.java) - } else { - @Suppress("UnstableApiUsage") - lspServerManager.stopServers(RuffLspServerSupportProvider::class.java) + if (!started && ruffConfigPathChanged && startLsp) { + ruffLspClientManager.restart() } + // TODO: support ruff global executable path changed pattern } - ruffConfigService.useRuffLsp = configPanel.useRuffLsp } override fun disposeUIResources() { diff --git a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt index c1051f05..501b81b4 100644 --- a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt +++ b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt @@ -1,36 +1,39 @@ package com.koxudaxi.ruff -import RuffLspServerSupportProvider +import RuffLspClientManager +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk -import com.intellij.platform.lsp.api.LspServerManager import com.jetbrains.python.packaging.PyPackageManager +import com.koxudaxi.ruff.lsp.intellij.RuffIntellijLspClient +import com.koxudaxi.ruff.lsp.lsp4ij.RuffLsp4IntellijClient class RuffPackageManagerListener(project: Project) : PyPackageManager.Listener { private val ruffConfigService = RuffConfigService.getInstance(project) private val ruffCacheService = RuffCacheService.getInstance(project) + private val ruffLspClientManager = RuffLspClientManager.getInstance(project) - @Suppress("UnstableApiUsage") - private val lspServerManager = if (intellijLspClientSupported) LspServerManager.getInstance(project) else null override fun packagesRefreshed(sdk: Sdk) { ruffConfigService.projectRuffExecutablePath = findRuffExecutableInSDK(sdk, false)?.absolutePath ruffConfigService.projectRuffLspExecutablePath = findRuffExecutableInSDK(sdk, true)?.absolutePath + if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return ruffCacheService.setVersion { - if (!ruffConfigService.useRuffLsp) return@setVersion - if (lspServerManager != null && ruffConfigService.useIntellijLspClient) { - ruffCacheService.setVersion { - if (lspServerManager != null && (ruffConfigService.useRuffLsp || ruffConfigService.useRuffServer)) { - try { - @Suppress("UnstableApiUsage") - lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) - } catch (_: Exception) { + ApplicationManager.getApplication().invokeLater { + ApplicationManager.getApplication().runWriteAction { + when { + ruffLspClientManager.hasClient() -> ruffLspClientManager.restart() + else -> { + val clientClass = when { + ruffConfigService.useLsp4ij -> RuffLsp4IntellijClient::class + else -> RuffIntellijLspClient::class + } + ruffLspClientManager.setClient(clientClass) } } - if (ruffConfigService.useLsp4ij) { - // TODO: Restart lsp4ij - } + } } + } } } \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt index 7cbf2aac..c7cbd209 100644 --- a/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt +++ b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt @@ -1,32 +1,64 @@ -package com.koxudaxi.ruff.lsp - +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.Service import com.intellij.openapi.project.Project +import com.koxudaxi.ruff.lsp.RuffLspClient import com.koxudaxi.ruff.lsp.intellij.RuffIntellijLspClient import com.koxudaxi.ruff.lsp.lsp4ij.RuffLsp4IntellijClient - +import kotlin.reflect.KClass @Service(Service.Level.PROJECT) -class RuffLspClientManager(private val project: Project) { - private val ruffLsp4IntellijClient = RuffLsp4IntellijClient(project) - private val ruffIntellijLspClient = RuffIntellijLspClient(project) +class RuffLspClientManager(project: Project) { + + private val clients: Map, RuffLspClient> = mapOf( + RuffLsp4IntellijClient::class to RuffLsp4IntellijClient(project), + RuffIntellijLspClient::class to RuffIntellijLspClient(project) + ) + + @Volatile + private var enabledClient: RuffLspClient? = null - fun startRuffLsp4IntellijClient() { - ruffLsp4IntellijClient.start() + fun hasClient(): Boolean { + return enabledClient != null } - fun stopRuffLsp4IntellijClient() { - ruffLsp4IntellijClient.stop() + + fun setClient(client: KClass, start: Boolean = true) { + ApplicationManager.getApplication().invokeLater { + val newClient = clients[client] ?: error("Client for key $client not found") + ApplicationManager.getApplication().runWriteAction { + if (enabledClient?.javaClass == client.java) { + return@runWriteAction + } + enabledClient?.stop() + if (start) { + newClient.start() + } + enabledClient = newClient + } + } } - fun startRuffIntellijLspClient() { - ruffIntellijLspClient.start() + + fun start() { + ApplicationManager.getApplication().invokeLater { + ApplicationManager.getApplication().runWriteAction { + enabledClient?.start() + } + } } - fun stopRuffIntellijLspClient() { - ruffIntellijLspClient.stop() + + fun stop() { + ApplicationManager.getApplication().invokeLater { + ApplicationManager.getApplication().runWriteAction { + enabledClient?.stop() + } + } } - fun stopAll() { - stopRuffIntellijLspClient() - stopRuffLsp4IntellijClient() + fun restart() { + ApplicationManager.getApplication().invokeLater { + ApplicationManager.getApplication().runWriteAction { + enabledClient?.restart() + } + } } companion object { @@ -34,6 +66,4 @@ class RuffLspClientManager(private val project: Project) { return project.getService(RuffLspClientManager::class.java) } } - - } \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt b/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt index de6c0bd7..462a13c7 100644 --- a/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt +++ b/src/com/koxudaxi/ruff/lsp/intellij/RuffIntellijLspClient.kt @@ -15,10 +15,9 @@ class RuffIntellijLspClient(val project: Project) : RuffLspClient { } override fun stop() { - // TODO: stop server -// if (lspServerManager == null) return -// @Suppress("UnstableApiUsage") -// lspServerManager.stopServer(RuffLspServerSupportProvider::class.java) + if (lspServerManager == null) return + @Suppress("UnstableApiUsage") + lspServerManager.stopServers(RuffLspServerSupportProvider::class.java) } override fun restart() { @@ -26,7 +25,4 @@ class RuffIntellijLspClient(val project: Project) : RuffLspClient { @Suppress("UnstableApiUsage") lspServerManager.stopAndRestartIfNeeded(RuffLspServerSupportProvider::class.java) } - companion object { - const val RUFF_LSP_CLIENT_ID = "ruff-intellij-lsp-client" - } } \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt b/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt index bb1936b2..1eeb7c09 100644 --- a/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt +++ b/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt @@ -1,11 +1,9 @@ -import com.intellij.codeInspection.ex.InspectionToolRegistrar import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.platform.lsp.api.LspServerSupportProvider import com.intellij.platform.lsp.api.ProjectWideLspServerDescriptor import com.intellij.platform.lsp.api.customization.LspCompletionSupport -import com.intellij.profile.codeInspection.ProjectInspectionProfileManager import com.koxudaxi.ruff.* import kotlinx.serialization.Serializable import java.io.File @@ -21,7 +19,6 @@ class RuffLspServerSupportProvider : LspServerSupportProvider { ) { val ruffConfigService = RuffConfigService.getInstance(project) if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return - if (!ruffConfigService.useRuffLsp) return if (!ruffConfigService.useIntellijLspClient) return if (!isInspectionEnabled(project)) return if (file.extension != "py") return @@ -35,23 +32,6 @@ class RuffLspServerSupportProvider : LspServerSupportProvider { } ?: return serverStarter.ensureServerStarted(descriptor) } - - private fun getRuffExecutable(project: Project, ruffConfigService: RuffConfigService, lsp: Boolean): File? { - return when { - lsp -> ruffConfigService.ruffLspExecutablePath - else -> ruffConfigService.ruffExecutablePath - }?.let { File(it) }?.takeIf { it.exists() } ?: detectRuffExecutable( - project, ruffConfigService, lsp - ) - } - - private fun isInspectionEnabled(project: Project): Boolean { - val inspectionProfileManager = ProjectInspectionProfileManager.getInstance(project) - - val toolWrapper = InspectionToolRegistrar.getInstance().createTools() - .find { it.shortName == RuffInspection.INSPECTION_SHORT_NAME } ?: return false - return inspectionProfileManager.currentProfile.isToolEnabled(toolWrapper.displayKey) - } } @Suppress("UnstableApiUsage") @@ -76,8 +56,8 @@ abstract class RuffLspServerDescriptorBase(project: Project, val executable: Fil override fun isSupportedFile(file: VirtualFile) = file.extension == "py" abstract override fun createCommandLine(): GeneralCommandLine override fun createInitializationOptions(): Any? { - val config = ruffConfig.ruffConfigPath?.let { File(it) }?.takeIf { it.exists() } ?: return null - return InitOptions(Settings(listOf(CONFIG_ARG, config.absolutePath))) + val configArgs = getConfigArgs(ruffConfig) ?: return null + return InitOptions(Settings(configArgs)) } override val lspGoToDefinitionSupport: Boolean = false diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt index 7ff9efd9..806a3cb1 100644 --- a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt @@ -1,13 +1,8 @@ package com.koxudaxi.ruff.lsp.lsp4ij -import com.intellij.codeInspection.ex.InspectionToolRegistrar import com.intellij.openapi.project.Project -import com.intellij.profile.codeInspection.ProjectInspectionProfileManager -import com.koxudaxi.ruff.RuffConfigService -import com.koxudaxi.ruff.RuffInspection -import com.koxudaxi.ruff.detectRuffExecutable +import com.koxudaxi.ruff.* import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider -import java.io.File class RuffLanguageServer(project: Project) : ProcessStreamConnectionProvider() { @@ -25,24 +20,24 @@ class RuffLanguageServer(project: Project) : ProcessStreamConnectionProvider() { } private fun createCommand(project: Project, ruffConfigService: RuffConfigService): List? { - if (!ruffConfigService.useRuffLsp) return null + if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return null if (!ruffConfigService.useLsp4ij) return null if (!isInspectionEnabled(project)) return null - val executable = - ruffConfigService.ruffLspExecutablePath?.let { File(it) }?.takeIf { it.exists() } - ?: detectRuffExecutable( - project, ruffConfigService, true - ) ?: return null - // TODO Support Configuration - return listOf(executable.absolutePath) - } - // TODO: move the function to new ruff lsp class - private fun isInspectionEnabled(project: Project): Boolean { - val inspectionProfileManager = ProjectInspectionProfileManager.getInstance(project) - - val toolWrapper = InspectionToolRegistrar.getInstance().createTools() - .find { it.shortName == RuffInspection.INSPECTION_SHORT_NAME } ?: return false - return inspectionProfileManager.currentProfile.isToolEnabled(toolWrapper.displayKey) + val ruffCacheService = RuffCacheService.getInstance(project) + if (ruffCacheService.getVersion() == null) return null + val executable = + when { + ruffConfigService.useRuffServer && ruffCacheService.hasLsp() == true -> { + getRuffExecutable(project, ruffConfigService, false) + } + + else -> getRuffExecutable(project, ruffConfigService, true) + } ?: return null + val executableCommandArgs = listOf(executable.absolutePath) + LSP_PREVIEW_ARGS + + return getConfigArgs(ruffConfigService)?.let { + executableCommandArgs + it + } ?: executableCommandArgs } } \ No newline at end of file diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt index d06d85cb..0415481a 100644 --- a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt @@ -2,26 +2,36 @@ package com.koxudaxi.ruff.lsp.lsp4ij import com.intellij.openapi.project.Project import com.koxudaxi.ruff.lsp.RuffLspClient +import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider class RuffLsp4IntellijClient(val project: Project): RuffLspClient { - private val lspServer get() = RuffLanguageServerFactory().createConnectionProvider(project) + private var provider: StreamConnectionProvider? = null override fun start() { - lspServer.start() + provider?.let { + if (!it.isAlive) { + it.start() + } + } ?: run { + val newProvider = RuffLanguageServerFactory().createConnectionProvider(project) + newProvider.start() + provider = newProvider + } } override fun stop() { - if (lspServer.isAlive) { - lspServer.stop() + provider?.let { + if (it.isAlive) { + it.stop() + } } } override fun restart() { - if (lspServer.isAlive) { - lspServer.stop() + provider?.let { + if (it.isAlive) { + it.stop() + } } - lspServer.start() - } - companion object { - const val RUFF_LSP_CLIENT_ID = "ruff-lsp4-intellij-client" + start() } } \ No newline at end of file From c21b40b1e57fe96e4e46eb232605bca37bab19ca Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 22 Aug 2024 02:02:30 +0900 Subject: [PATCH 13/25] Update lsp4ij version --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5a8f73fc..e5885967 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ changelog = "2.2.1" gradleIntelliJPlugin = "2.0.1" qodana = "0.1.13" kover = "0.7.6" -lsp4ij = "0.4.0-20240815-013110" +lsp4ij = "0.4.0" [libraries] annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } From 795cc3e525204bac9dfba965178d570b1acd5d6d Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 22 Aug 2024 02:04:09 +0900 Subject: [PATCH 14/25] Fix ci --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6c4a6712..e226741e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,7 +82,7 @@ jobs: echo "$CHANGELOG" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - ./gradlew listProductsReleases # prepare list of IDEs for Plugin Verifier + ./gradlew printProductsReleases # prepare list of IDEs for Plugin Verifier # Build plugin - name: Build plugin @@ -233,7 +233,7 @@ jobs: uses: actions/cache@v4 with: path: ${{ needs.build.outputs.pluginVerifierHomeDir }}/ides - key: plugin-verifier-${{ hashFiles('build/listProductsReleases.txt') }} + key: plugin-verifier-${{ hashFiles('build/printProductsReleases.txt') }} # Run Verify Plugin task and IntelliJ Plugin Verifier tool - name: Run Plugin Verification tasks From 55e81834f6a27c6224e9435ef7fa04a851b5395e Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 22 Aug 2024 02:22:15 +0900 Subject: [PATCH 15/25] Fix lsp server --- gradle/libs.versions.toml | 2 +- resources/META-INF/plugin.xml | 16 +++++++-------- .../lsp/lsp4ij/RuffLanguageServerFactory.kt | 20 ++++++++++++++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e5885967..5a8f73fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ changelog = "2.2.1" gradleIntelliJPlugin = "2.0.1" qodana = "0.1.13" kover = "0.7.6" -lsp4ij = "0.4.0" +lsp4ij = "0.4.0-20240815-013110" [libraries] annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 28fce851..4c15db81 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -33,14 +33,14 @@ - - - - - - - - + + + + diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt index 2f76b670..0c9ad23b 100644 --- a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt @@ -1,10 +1,15 @@ package com.koxudaxi.ruff.lsp.lsp4ij import com.intellij.openapi.project.Project +import com.koxudaxi.ruff.RuffCacheService +import com.koxudaxi.ruff.RuffConfigService +import com.koxudaxi.ruff.isInspectionEnabled +import com.redhat.devtools.lsp4ij.LanguageServerEnablementSupport import com.redhat.devtools.lsp4ij.LanguageServerFactory import com.redhat.devtools.lsp4ij.client.LanguageClientImpl import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider -class RuffLanguageServerFactory : LanguageServerFactory { +class RuffLanguageServerFactory : LanguageServerFactory, LanguageServerEnablementSupport { + override fun createConnectionProvider(project: Project): StreamConnectionProvider { return RuffLanguageServer(project) } @@ -13,4 +18,17 @@ class RuffLanguageServerFactory : LanguageServerFactory { override fun createLanguageClient(project: Project): LanguageClientImpl { return RuffLanguageClient(project) } + + override fun isEnabled(project: Project): Boolean { + val ruffConfigService = RuffConfigService.getInstance(project) + if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return false + if (!ruffConfigService.useLsp4ij) return false + if (!isInspectionEnabled(project)) return false + + val ruffCacheService = RuffCacheService.getInstance(project) + return ruffCacheService.getVersion() != null + } + + override fun setEnabled(p0: Boolean, project: Project) { + } } \ No newline at end of file From 70ac3ad3b179ab3e2d9d05970692a7abdc4b49c9 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Thu, 22 Aug 2024 02:37:56 +0900 Subject: [PATCH 16/25] Fix lsp server --- .../lsp/lsp4ij/RuffLanguageServerFactory.kt | 1 + .../ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt | 42 ++++++++++--------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt index 0c9ad23b..b4910be4 100644 --- a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt @@ -12,6 +12,7 @@ class RuffLanguageServerFactory : LanguageServerFactory, LanguageServerEnablemen override fun createConnectionProvider(project: Project): StreamConnectionProvider { return RuffLanguageServer(project) + } //If you need to provide client specific features diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt index 0415481a..a39d615d 100644 --- a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLsp4IntellijClient.kt @@ -2,36 +2,38 @@ package com.koxudaxi.ruff.lsp.lsp4ij import com.intellij.openapi.project.Project import com.koxudaxi.ruff.lsp.RuffLspClient -import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider +import com.redhat.devtools.lsp4ij.LanguageServerManager +import com.redhat.devtools.lsp4ij.ServerStatus + +class RuffLsp4IntellijClient(project: Project) : RuffLspClient { + private val languageServerManager: LanguageServerManager = LanguageServerManager.getInstance(project) + private val isRunning: Boolean + get() { + val status = languageServerManager.getServerStatus(LANGUAGE_SERVER_ID) + return status == ServerStatus.started || status == ServerStatus.starting + } -class RuffLsp4IntellijClient(val project: Project): RuffLspClient { - private var provider: StreamConnectionProvider? = null override fun start() { - provider?.let { - if (!it.isAlive) { - it.start() - } - } ?: run { - val newProvider = RuffLanguageServerFactory().createConnectionProvider(project) - newProvider.start() - provider = newProvider + if (!isRunning) { + languageServerManager.start(LANGUAGE_SERVER_ID) } } + override fun stop() { - provider?.let { - if (it.isAlive) { - it.stop() - } + if (isRunning) { + languageServerManager.stop(LANGUAGE_SERVER_ID) } } override fun restart() { - provider?.let { - if (it.isAlive) { - it.stop() - } + if (isRunning) { + languageServerManager.stop(LANGUAGE_SERVER_ID) } - start() + languageServerManager.start(LANGUAGE_SERVER_ID) + } + companion object { + const val LANGUAGE_SERVER_ID = "ruffLanguageServer" + } } \ No newline at end of file From 0fe96640dab1f37fafd22f856507b944cf6fe455 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 31 Aug 2024 14:58:51 +0900 Subject: [PATCH 17/25] Update config panel --- src/com/koxudaxi/ruff/RuffConfigPanel.form | 31 +++++++++-------- src/com/koxudaxi/ruff/RuffConfigPanel.kt | 33 +++++++++++++------ .../koxudaxi/ruff/lsp/RuffLspClientManager.kt | 12 ++++--- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.form b/src/com/koxudaxi/ruff/RuffConfigPanel.form index 0c98d6fc..c0db5307 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.form +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.form @@ -80,7 +80,7 @@ - + @@ -88,34 +88,33 @@ - + - + - + + - + - + - + - + - + + - - - - - @@ -303,5 +302,9 @@ + + + + diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.kt b/src/com/koxudaxi/ruff/RuffConfigPanel.kt index 78719aaa..aac86aaa 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.kt +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.kt @@ -32,11 +32,11 @@ class RuffConfigPanel(project: Project) { private lateinit var ruffConfigPathField: TextFieldWithBrowseButton private lateinit var clearRuffConfigPathButton: JButton private lateinit var disableOnSaveOutsideOfProjectCheckBox: JCheckBox - private lateinit var useRuffLspCheckBox: JCheckBox + private lateinit var useRuffLspRadioButton: JRadioButton private lateinit var useIntellijLspClientRadioButton: JRadioButton private lateinit var useLsp4ijRadioButton: JRadioButton private lateinit var useRuffFormatCheckBox: JCheckBox - private lateinit var useRuffServerCheckBox: JCheckBox + private lateinit var useRuffServerRadioButton: JRadioButton init { val ruffConfigService = getInstance(project) runRuffOnSaveCheckBox.isSelected = ruffConfigService.runRuffOnSave @@ -48,14 +48,14 @@ class RuffConfigPanel(project: Project) { alwaysUseGlobalRuffCheckBox.isEnabled = true alwaysUseGlobalRuffCheckBox.isSelected = ruffConfigService.alwaysUseGlobalRuff disableOnSaveOutsideOfProjectCheckBox.isEnabled = ruffConfigService.runRuffOnSave - useRuffLspCheckBox.isSelected = ruffConfigService.useRuffLsp + useRuffLspRadioButton.isSelected = ruffConfigService.useRuffLsp useIntellijLspClientRadioButton.isEnabled = intellijLspClientSupported useIntellijLspClientRadioButton.isSelected = ruffConfigService.useIntellijLspClient useLsp4ijRadioButton.isSelected = ruffConfigService.useLsp4ij useRuffFormatCheckBox.isEnabled = true useRuffFormatCheckBox.isSelected = ruffConfigService.useRuffFormat - useRuffServerCheckBox.isEnabled = true - useRuffServerCheckBox.isSelected = ruffConfigService.useRuffServer + useRuffServerRadioButton.isEnabled = true + useRuffServerRadioButton.isSelected = ruffConfigService.useRuffServer disableOnSaveOutsideOfProjectCheckBox.isSelected = ruffConfigService.disableOnSaveOutsideOfProject runRuffOnSaveCheckBox.addActionListener { disableOnSaveOutsideOfProjectCheckBox.isEnabled = runRuffOnSaveCheckBox.isSelected @@ -92,7 +92,20 @@ class RuffConfigPanel(project: Project) { setAutodetectedRuffLspButton.addActionListener { setAutodetectedRuffLsp() } - useRuffLspCheckBox.addActionListener { updateLspExecutableFields() } + fun updateLspClientCheckBoxes() { + val useLspClient = useRuffLspRadioButton.isSelected || useRuffServerRadioButton.isSelected + useIntellijLspClientRadioButton.isEnabled = useLspClient + useLsp4ijRadioButton.isEnabled = useLspClient + } + + useRuffLspRadioButton.addActionListener { + updateLspClientCheckBoxes() + updateLspExecutableFields() + } + useRuffServerRadioButton.addActionListener { + updateLspClientCheckBoxes() + updateLspExecutableFields() + } alwaysUseGlobalRuffCheckBox.addActionListener { updateProjectExecutableFields() } when (val projectRuffExecutablePath = ruffConfigService.projectRuffExecutablePath?.takeIf { File(it).exists() } ?: getProjectRuffExecutablePath(project, false)) { @@ -123,7 +136,7 @@ class RuffConfigPanel(project: Project) { } private fun updateLspExecutableFields() { - val enabled = intellijLspClientSupported && useRuffLspCheckBox.isSelected + val enabled = intellijLspClientSupported && useRuffLspRadioButton.isSelected globalRuffLspExecutablePathField.isEnabled = enabled globalRuffLspLabel.isEnabled = enabled setAutodetectedRuffLspButton.isEnabled = enabled @@ -136,7 +149,7 @@ class RuffConfigPanel(project: Project) { val enabled = !alwaysUseGlobalRuffCheckBox.isSelected projectRuffExecutablePathField.isEnabled = enabled projectRuffLabel.isEnabled = enabled - if (intellijLspClientSupported && useRuffLspCheckBox.isSelected) { + if (intellijLspClientSupported && useRuffLspRadioButton.isSelected) { projectRuffLspExecutablePathField.isEnabled = enabled projectRuffLspLabel.isEnabled = enabled } @@ -180,13 +193,13 @@ class RuffConfigPanel(project: Project) { val disableOnSaveOutsideOfProject: Boolean get() = disableOnSaveOutsideOfProjectCheckBox.isSelected val useRuffLsp: Boolean - get() = useRuffLspCheckBox.isSelected + get() = useRuffLspRadioButton.isSelected val useIntellijLspClient: Boolean get() = useIntellijLspClientRadioButton.isSelected val useLsp4ij: Boolean get() = useLsp4ijRadioButton.isSelected val useRuffServer: Boolean - get() = useRuffServerCheckBox.isSelected + get() = useRuffServerRadioButton.isSelected val useRuffFormat: Boolean get() = useRuffFormatCheckBox.isSelected diff --git a/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt index c7cbd209..2b8032be 100644 --- a/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt +++ b/src/com/koxudaxi/ruff/lsp/RuffLspClientManager.kt @@ -9,10 +9,13 @@ import kotlin.reflect.KClass @Service(Service.Level.PROJECT) class RuffLspClientManager(project: Project) { - private val clients: Map, RuffLspClient> = mapOf( - RuffLsp4IntellijClient::class to RuffLsp4IntellijClient(project), - RuffIntellijLspClient::class to RuffIntellijLspClient(project) - ) + private val clients: Map, RuffLspClient>? = when { + project.isDefault -> null + else -> mapOf( + RuffLsp4IntellijClient::class to RuffLsp4IntellijClient(project), + RuffIntellijLspClient::class to RuffIntellijLspClient(project) + ) + } @Volatile private var enabledClient: RuffLspClient? = null @@ -22,6 +25,7 @@ class RuffLspClientManager(project: Project) { } fun setClient(client: KClass, start: Boolean = true) { + if (clients == null) return ApplicationManager.getApplication().invokeLater { val newClient = clients[client] ?: error("Client for key $client not found") ApplicationManager.getApplication().runWriteAction { From c2ae984ce88d1742cf6d51fd65a69ebe0c4dc5ba Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 2 Sep 2024 01:37:14 +0900 Subject: [PATCH 18/25] Fix gradle action version --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e226741e..e243470d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -140,7 +140,7 @@ jobs: # Setup Gradle - name: Setup Gradle - uses: gradle/actions/setup-gradle@v321 + uses: gradle/actions/setup-gradle@v4 with: gradle-home-cache-cleanup: true @@ -224,7 +224,7 @@ jobs: # Setup Gradle - name: Setup Gradle - uses: gradle/actions/setup-gradle@v321 + uses: gradle/actions/setup-gradle@v4 with: gradle-home-cache-cleanup: true From b23a90638521995ab9fe09cf4e1df7857f691e3a Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 2 Sep 2024 16:58:59 +0900 Subject: [PATCH 19/25] Fix verifyPlugin task in CI --- .github/workflows/build.yml | 4 ++-- .run/Run Verifications.run.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e243470d..b675dcac 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,7 @@ # - Run 'test' and 'verifyPlugin' tasks. # - Run Qodana inspections. # - Run the 'buildPlugin' task and prepare artifact for further tests. -# - Run the 'runPluginVerifier' task. +# - Run the 'verifyPlugin' task. # - Create a draft release. # # The workflow is triggered on push and pull_request events. @@ -237,7 +237,7 @@ jobs: # Run Verify Plugin task and IntelliJ Plugin Verifier tool - name: Run Plugin Verification tasks - run: ./gradlew runPluginVerifier -Dplugin.verifier.home.dir=${{ needs.build.outputs.pluginVerifierHomeDir }} + run: ./gradlew verifyPlugin -Dplugin.verifier.home.dir=${{ needs.build.outputs.pluginVerifierHomeDir }} # Collect Plugin Verifier Result - name: Collect Plugin Verifier Result diff --git a/.run/Run Verifications.run.xml b/.run/Run Verifications.run.xml index 3a8d6885..3fd5c43c 100644 --- a/.run/Run Verifications.run.xml +++ b/.run/Run Verifications.run.xml @@ -11,7 +11,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -117,13 +117,13 @@ - + - + @@ -151,6 +151,14 @@ + + + + + + + + diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.kt b/src/com/koxudaxi/ruff/RuffConfigPanel.kt index aac86aaa..6d93791f 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.kt +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.kt @@ -37,6 +37,7 @@ class RuffConfigPanel(project: Project) { private lateinit var useLsp4ijRadioButton: JRadioButton private lateinit var useRuffFormatCheckBox: JCheckBox private lateinit var useRuffServerRadioButton: JRadioButton + private lateinit var enableLspCheckBox: JCheckBox init { val ruffConfigService = getInstance(project) runRuffOnSaveCheckBox.isSelected = ruffConfigService.runRuffOnSave @@ -57,6 +58,7 @@ class RuffConfigPanel(project: Project) { useRuffServerRadioButton.isEnabled = true useRuffServerRadioButton.isSelected = ruffConfigService.useRuffServer disableOnSaveOutsideOfProjectCheckBox.isSelected = ruffConfigService.disableOnSaveOutsideOfProject + enableLspCheckBox.isSelected = ruffConfigService.enableLsp runRuffOnSaveCheckBox.addActionListener { disableOnSaveOutsideOfProjectCheckBox.isEnabled = runRuffOnSaveCheckBox.isSelected } @@ -107,6 +109,21 @@ class RuffConfigPanel(project: Project) { updateLspExecutableFields() } + enableLspCheckBox.addActionListener { + if (enableLspCheckBox.isSelected) { + useLsp4ijRadioButton.isEnabled = true + useIntellijLspClientRadioButton.isEnabled = intellijLspClientSupported + useRuffLspRadioButton.isEnabled = true + useRuffServerRadioButton.isEnabled = true + } else { + updateLspClientCheckBoxes() + updateLspExecutableFields() + useLsp4ijRadioButton.isEnabled = false + useIntellijLspClientRadioButton.isEnabled = false + useRuffLspRadioButton.isEnabled = false + useRuffServerRadioButton.isEnabled = false + } + } alwaysUseGlobalRuffCheckBox.addActionListener { updateProjectExecutableFields() } when (val projectRuffExecutablePath = ruffConfigService.projectRuffExecutablePath?.takeIf { File(it).exists() } ?: getProjectRuffExecutablePath(project, false)) { is String -> projectRuffExecutablePathField.text = projectRuffExecutablePath @@ -202,6 +219,8 @@ class RuffConfigPanel(project: Project) { get() = useRuffServerRadioButton.isSelected val useRuffFormat: Boolean get() = useRuffFormatCheckBox.isSelected + val enableLsp: Boolean + get() = enableLspCheckBox.isSelected companion object { const val RUFF_EXECUTABLE_NOT_FOUND = "Ruff executable not found" diff --git a/src/com/koxudaxi/ruff/RuffConfigService.kt b/src/com/koxudaxi/ruff/RuffConfigService.kt index b9400908..32e0073e 100644 --- a/src/com/koxudaxi/ruff/RuffConfigService.kt +++ b/src/com/koxudaxi/ruff/RuffConfigService.kt @@ -26,6 +26,7 @@ class RuffConfigService : PersistentStateComponent { var useLsp4ij: Boolean = !useIntellijLspClient var useRuffServer: Boolean = false var useRuffFormat: Boolean = false + var enableLsp: Boolean = true override fun getState(): RuffConfigService { return this diff --git a/src/com/koxudaxi/ruff/RuffConfigurable.kt b/src/com/koxudaxi/ruff/RuffConfigurable.kt index cdd96c43..8f9c40c3 100644 --- a/src/com/koxudaxi/ruff/RuffConfigurable.kt +++ b/src/com/koxudaxi/ruff/RuffConfigurable.kt @@ -40,7 +40,8 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.useIntellijLspClient != configPanel.useIntellijLspClient || ruffConfigService.useLsp4ij != configPanel.useLsp4ij || ruffConfigService.useRuffFormat != configPanel.useRuffFormat || - ruffConfigService.useRuffServer != configPanel.useRuffServer + ruffConfigService.useRuffServer != configPanel.useRuffServer || + ruffConfigService.enableLsp != configPanel.enableLsp } override fun apply() { @@ -61,8 +62,9 @@ class RuffConfigurable internal constructor(val project: Project) : Configurable ruffConfigService.useRuffServer = configPanel.useRuffServer ruffConfigService.useIntellijLspClient = configPanel.useIntellijLspClient ruffConfigService.useLsp4ij = configPanel.useLsp4ij + ruffConfigService.enableLsp = configPanel.enableLsp ruffCacheService.setVersion { - val startLsp = ruffConfigService.useRuffLsp || ruffConfigService.useRuffServer + val startLsp = ruffConfigService.enableLsp var started = false if (lspClientChanged) { if (ruffConfigService.useLsp4ij) { diff --git a/src/com/koxudaxi/ruff/RuffExternalAnnotator.kt b/src/com/koxudaxi/ruff/RuffExternalAnnotator.kt index b81058fc..e212a187 100644 --- a/src/com/koxudaxi/ruff/RuffExternalAnnotator.kt +++ b/src/com/koxudaxi/ruff/RuffExternalAnnotator.kt @@ -38,6 +38,7 @@ class RuffExternalAnnotator : if (file !is PyFile) return null val project = file.project val config = RuffConfigService.getInstance(project) + if (config.enableLsp) return null if (config.useRuffLsp && config.ruffLspExecutablePath is String) return null if (config.useRuffServer && RuffCacheService.hasLsp(project) == true) return null if (!file.isApplicableTo) return null diff --git a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt index 501b81b4..4f16abbc 100644 --- a/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt +++ b/src/com/koxudaxi/ruff/RuffPackageManagerListener.kt @@ -16,7 +16,7 @@ class RuffPackageManagerListener(project: Project) : PyPackageManager.Listener { override fun packagesRefreshed(sdk: Sdk) { ruffConfigService.projectRuffExecutablePath = findRuffExecutableInSDK(sdk, false)?.absolutePath ruffConfigService.projectRuffLspExecutablePath = findRuffExecutableInSDK(sdk, true)?.absolutePath - if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return + if (!ruffConfigService.enableLsp) return ruffCacheService.setVersion { ApplicationManager.getApplication().invokeLater { ApplicationManager.getApplication().runWriteAction { diff --git a/src/com/koxudaxi/ruff/RuffProjectInitializer.kt b/src/com/koxudaxi/ruff/RuffProjectInitializer.kt index 50174f73..3c8607d8 100644 --- a/src/com/koxudaxi/ruff/RuffProjectInitializer.kt +++ b/src/com/koxudaxi/ruff/RuffProjectInitializer.kt @@ -56,6 +56,7 @@ class RuffProjectInitializer : ProjectActivity { ) return ApplicationManager.getApplication().invokeLater { if (project.isDisposed) return@invokeLater + if (!ruffConfigService.enableLsp) return@invokeLater if (!ruffConfigService.useRuffLsp) return@invokeLater if (ruffConfigService.useIntellijLspClient) { @Suppress("UnstableApiUsage") diff --git a/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt b/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt index ebbf05d2..e84c91ab 100644 --- a/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt +++ b/src/com/koxudaxi/ruff/lsp/intellij/RuffLspServerSupportProvider.kt @@ -18,6 +18,7 @@ class RuffLspServerSupportProvider : LspServerSupportProvider { serverStarter: LspServerSupportProvider.LspServerStarter ) { val ruffConfigService = RuffConfigService.getInstance(project) + if (!ruffConfigService.enableLsp) return if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return if (!ruffConfigService.useIntellijLspClient) return if (!isInspectionEnabled(project)) return diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt index a9ce9d3f..6af13f4e 100644 --- a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServer.kt @@ -21,6 +21,7 @@ class RuffLanguageServer(project: Project) : ProcessStreamConnectionProvider() { } private fun createCommand(project: Project, ruffConfigService: RuffConfigService): List? { + if (!ruffConfigService.enableLsp) return null if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return null if (!ruffConfigService.useLsp4ij) return null if (!isInspectionEnabled(project)) return null diff --git a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt index b4910be4..3ba74ba6 100644 --- a/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt +++ b/src/com/koxudaxi/ruff/lsp/lsp4ij/RuffLanguageServerFactory.kt @@ -22,6 +22,7 @@ class RuffLanguageServerFactory : LanguageServerFactory, LanguageServerEnablemen override fun isEnabled(project: Project): Boolean { val ruffConfigService = RuffConfigService.getInstance(project) + if (!ruffConfigService.enableLsp) return false if (!ruffConfigService.useRuffLsp && !ruffConfigService.useRuffServer) return false if (!ruffConfigService.useLsp4ij) return false if (!isInspectionEnabled(project)) return false From 17c32dad5d585e6300a905804f6e761cee71fb53 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 2 Sep 2024 23:09:32 +0900 Subject: [PATCH 23/25] Update config panel --- src/com/koxudaxi/ruff/RuffConfigPanel.kt | 41 +++++++++++++----------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/com/koxudaxi/ruff/RuffConfigPanel.kt b/src/com/koxudaxi/ruff/RuffConfigPanel.kt index 6d93791f..2119300f 100644 --- a/src/com/koxudaxi/ruff/RuffConfigPanel.kt +++ b/src/com/koxudaxi/ruff/RuffConfigPanel.kt @@ -94,11 +94,6 @@ class RuffConfigPanel(project: Project) { setAutodetectedRuffLspButton.addActionListener { setAutodetectedRuffLsp() } - fun updateLspClientCheckBoxes() { - val useLspClient = useRuffLspRadioButton.isSelected || useRuffServerRadioButton.isSelected - useIntellijLspClientRadioButton.isEnabled = useLspClient - useLsp4ijRadioButton.isEnabled = useLspClient - } useRuffLspRadioButton.addActionListener { updateLspClientCheckBoxes() @@ -110,20 +105,9 @@ class RuffConfigPanel(project: Project) { } enableLspCheckBox.addActionListener { - if (enableLspCheckBox.isSelected) { - useLsp4ijRadioButton.isEnabled = true - useIntellijLspClientRadioButton.isEnabled = intellijLspClientSupported - useRuffLspRadioButton.isEnabled = true - useRuffServerRadioButton.isEnabled = true - } else { - updateLspClientCheckBoxes() - updateLspExecutableFields() - useLsp4ijRadioButton.isEnabled = false - useIntellijLspClientRadioButton.isEnabled = false - useRuffLspRadioButton.isEnabled = false - useRuffServerRadioButton.isEnabled = false - } + updateLspFields() } + updateLspFields() alwaysUseGlobalRuffCheckBox.addActionListener { updateProjectExecutableFields() } when (val projectRuffExecutablePath = ruffConfigService.projectRuffExecutablePath?.takeIf { File(it).exists() } ?: getProjectRuffExecutablePath(project, false)) { is String -> projectRuffExecutablePathField.text = projectRuffExecutablePath @@ -151,7 +135,26 @@ class RuffConfigPanel(project: Project) { ruffConfigPathField.text = "" } } - + private fun updateLspClientCheckBoxes() { + val useLspClient = useRuffLspRadioButton.isSelected || useRuffServerRadioButton.isSelected + useIntellijLspClientRadioButton.isEnabled = useLspClient + useLsp4ijRadioButton.isEnabled = useLspClient + } + private fun updateLspFields() { + if (enableLspCheckBox.isSelected) { + useLsp4ijRadioButton.isEnabled = true + useIntellijLspClientRadioButton.isEnabled = intellijLspClientSupported + useRuffLspRadioButton.isEnabled = true + useRuffServerRadioButton.isEnabled = true + } else { + updateLspClientCheckBoxes() + updateLspExecutableFields() + useLsp4ijRadioButton.isEnabled = false + useIntellijLspClientRadioButton.isEnabled = false + useRuffLspRadioButton.isEnabled = false + useRuffServerRadioButton.isEnabled = false + } + } private fun updateLspExecutableFields() { val enabled = intellijLspClientSupported && useRuffLspRadioButton.isSelected globalRuffLspExecutablePathField.isEnabled = enabled From b0875a04d45e4bb1a1b7c9b943a3c1423cf6d378 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 2 Sep 2024 23:20:32 +0900 Subject: [PATCH 24/25] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 852c4487..d336d023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## [Unreleased] +- Support LSP4IJ, which is a third-party LSP server integration [[#437](https://github.com/koxudaxi/pydantic-pycharm-plugin/pull/#437)] ## [0.0.35] - 2024-07-24 From 841203e59d86f3efd7e7c2e7c7db695eea024696 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 2 Sep 2024 23:33:18 +0900 Subject: [PATCH 25/25] Update lsp4ij plugin version --- build.gradle.kts | 3 +-- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 09c9b3c8..abc94512 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,6 @@ repositories { mavenCentral() intellijPlatform { defaultRepositories() - nightly() } } @@ -41,7 +40,7 @@ dependencies { create(type, version, useInstaller = false) bundledPlugins(bundledPlugins) val lsp4ij = libs.plugins.lsp4ij.get() - plugin("${lsp4ij.pluginId}:${lsp4ij.version.requiredVersion}@nightly") + plugin("${lsp4ij.pluginId}:${lsp4ij.version.requiredVersion}") instrumentationTools() testFramework(TestFrameworkType.Bundled) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5a8f73fc..e5885967 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ changelog = "2.2.1" gradleIntelliJPlugin = "2.0.1" qodana = "0.1.13" kover = "0.7.6" -lsp4ij = "0.4.0-20240815-013110" +lsp4ij = "0.4.0" [libraries] annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" }