diff --git a/CHANGELOG.md b/CHANGELOG.md index df0b840..b300058 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## Unreleased + +### Bug Fixes + +- Fix infinite indexing / intellisense blocked ([#66](https://github.com/biomejs/biome-intellij/issues/66)) + ## 1.0.0 ### Bug Fixes diff --git a/src/main/kotlin/com/github/biomejs/intellijbiome/lsp/BiomeLspServerSupportProvider.kt b/src/main/kotlin/com/github/biomejs/intellijbiome/lsp/BiomeLspServerSupportProvider.kt index 59f866f..df6b152 100644 --- a/src/main/kotlin/com/github/biomejs/intellijbiome/lsp/BiomeLspServerSupportProvider.kt +++ b/src/main/kotlin/com/github/biomejs/intellijbiome/lsp/BiomeLspServerSupportProvider.kt @@ -3,13 +3,21 @@ package com.github.biomejs.intellijbiome.lsp import com.github.biomejs.intellijbiome.BiomeBundle import com.github.biomejs.intellijbiome.BiomeIcons import com.github.biomejs.intellijbiome.BiomePackage -import com.github.biomejs.intellijbiome.extensions.runBiomeCLI +import com.github.biomejs.intellijbiome.extensions.isNodeScript import com.github.biomejs.intellijbiome.listeners.BIOME_CONFIG_RESOLVED_TOPIC import com.github.biomejs.intellijbiome.services.BiomeServerService import com.github.biomejs.intellijbiome.settings.BiomeConfigurable import com.github.biomejs.intellijbiome.settings.BiomeSettings import com.intellij.execution.ExecutionException import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.execution.process.OSProcessHandler +import com.intellij.javascript.nodejs.execution.NodeTargetRun +import com.intellij.javascript.nodejs.execution.NodeTargetRunOptions.Companion.of +import com.intellij.javascript.nodejs.execution.withInvisibleProgress +import com.intellij.javascript.nodejs.interpreter.NodeJsInterpreterManager +import com.intellij.javascript.nodejs.interpreter.local.NodeJsLocalInterpreter +import com.intellij.javascript.nodejs.interpreter.wsl.WslNodeInterpreter +import com.intellij.lang.javascript.JavaScriptBundle import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile @@ -17,6 +25,8 @@ import com.intellij.platform.lsp.api.* import com.intellij.platform.lsp.api.customization.LspFormattingSupport import com.intellij.platform.lsp.api.lsWidget.LspServerWidgetItem import com.intellij.util.SmartList +import java.io.File +import kotlin.io.path.Path @Suppress("UnstableApiUsage") @@ -38,16 +48,32 @@ class BiomeLspServerSupportProvider : LspServerSupportProvider { serverStarter.ensureServerStarted(BiomeLspServerDescriptor(project, executable, configPath)) } - override fun createLspServerWidgetItem(lspServer: LspServer, currentFile: VirtualFile?) = LspServerWidgetItem( + override fun createLspServerWidgetItem(lspServer: LspServer, + currentFile: VirtualFile?) = LspServerWidgetItem( lspServer, currentFile, BiomeIcons.BiomeIcon, BiomeConfigurable::class.java ) } @Suppress("UnstableApiUsage") -private class BiomeLspServerDescriptor(project: Project, val executable: String, val configPath: String?) : +private class BiomeLspServerDescriptor(project: Project, + val executable: String, + val configPath: String?) : ProjectWideLspServerDescriptor(project, "Biome") { private val biomePackage = BiomePackage(project) + private val executableFile = File(executable) + private val params: SmartList by lazy { + val params = SmartList("lsp-proxy") + if (!configPath.isNullOrEmpty()) { + params.add("--config-path") + params.add(configPath) + } + return@lazy params + } + + init { + biomePackage.versionNumber()?.let { project.messageBus.syncPublisher(BIOME_CONFIG_RESOLVED_TOPIC).resolved(it) } + } override fun isSupportedFile(file: VirtualFile): Boolean { val settings = BiomeSettings.getInstance(project) @@ -59,25 +85,44 @@ private class BiomeLspServerDescriptor(project: Project, val executable: String, } override fun createCommandLine(): GeneralCommandLine { - val params = SmartList("lsp-proxy") - - if (!configPath.isNullOrEmpty()) { - params.add("--config-path") - params.add(configPath) + // we're here only if we specify an executable file + return GeneralCommandLine().apply { + withExePath(executable) + withParentEnvironmentType(GeneralCommandLine.ParentEnvironmentType.CONSOLE) + project.basePath?.let { + withWorkingDirectory(Path(it)) + } + addParameters(params) } + } + + override fun startServerProcess(): OSProcessHandler { if (executable.isEmpty()) { throw ExecutionException(BiomeBundle.message("biome.language.server.not.found")) } - val version = biomePackage.versionNumber() + if (!(executableFile.isFile && executableFile.isNodeScript())) { + return super.startServerProcess() + } - version?.let { project.messageBus.syncPublisher(BIOME_CONFIG_RESOLVED_TOPIC).resolved(it) } + val interpreter = NodeJsInterpreterManager.getInstance(project).interpreter + if (interpreter !is NodeJsLocalInterpreter && interpreter !is WslNodeInterpreter) { + throw ExecutionException(JavaScriptBundle.message("lsp.interpreter.error")) + } - return GeneralCommandLine().runBiomeCLI(project, executable).apply { + val target = NodeTargetRun(interpreter, project, null, of(false)) + target.commandLineBuilder.apply { + project.basePath?.let { this.setWorkingDirectory(target.path(it)) } + addParameter(target.path(executable)) addParameters(params) - withWorkDirectory(configPath) + addParameter("--stdio") + charset = Charsets.UTF_8 } + + val process = withInvisibleProgress { target.startProcessEx() } + + return process.processHandler } override val lspGoToDefinitionSupport = false diff --git a/src/main/kotlin/com/github/biomejs/intellijbiome/settings/BiomeConfigurable.kt b/src/main/kotlin/com/github/biomejs/intellijbiome/settings/BiomeConfigurable.kt index 0556e13..37c1400 100644 --- a/src/main/kotlin/com/github/biomejs/intellijbiome/settings/BiomeConfigurable.kt +++ b/src/main/kotlin/com/github/biomejs/intellijbiome/settings/BiomeConfigurable.kt @@ -256,7 +256,8 @@ class BiomeConfigurable(internal val project: Project) : override fun get(): Boolean = getter() - override fun afterChange(parentDisposable: Disposable?, listener: (Boolean) -> Unit) { + override fun afterChange(parentDisposable: Disposable?, + listener: (Boolean) -> Unit) { fun emitChange(radio: JBRadioButton) { if (radio.isSelected) { listener(afterConfigModeChangeGetter())