diff --git a/gradle/productsReleases.txt b/gradle/productsReleases.txt index 7b32466..27efc33 100644 --- a/gradle/productsReleases.txt +++ b/gradle/productsReleases.txt @@ -1,3 +1,4 @@ +IU-2025.3.1 IU-2025.1.2 IU-2024.3.6 IU-2024.2.6 diff --git a/src/main/java/org/nixos/idea/lsp/NixLspServerDescriptor.java b/src/main/java/org/nixos/idea/lsp/NixLspServerDescriptor.java index b73bd6f..07a9d20 100644 --- a/src/main/java/org/nixos/idea/lsp/NixLspServerDescriptor.java +++ b/src/main/java/org/nixos/idea/lsp/NixLspServerDescriptor.java @@ -1,32 +1,51 @@ package org.nixos.idea.lsp; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.lsp.api.ProjectWideLspServerDescriptor; import com.intellij.util.execution.ParametersListUtil; +import org.eclipse.lsp4j.ClientCapabilities; +import org.eclipse.lsp4j.ConfigurationItem; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.nixos.idea.file.NixFileType; import java.util.List; +import java.util.Optional; @SuppressWarnings("UnstableApiUsage") final class NixLspServerDescriptor extends ProjectWideLspServerDescriptor { - private final String myCommand; - - NixLspServerDescriptor(@NotNull Project project, NixLspSettings settings) { + NixLspServerDescriptor(@NotNull Project project) { super(project, "Nix"); - myCommand = settings.getCommand(); + } + + @Override + public @NotNull ClientCapabilities getClientCapabilities() { + ClientCapabilities clientCapabilities = super.getClientCapabilities(); + clientCapabilities.getWorkspace().setConfiguration(true); + return clientCapabilities; } @Override public @NotNull GeneralCommandLine createCommandLine() throws ExecutionException { - List argv = ParametersListUtil.parse(myCommand, false, true); + List argv = ParametersListUtil.parse(NixLspSettings.getInstance(getProject()).getCommand(), false, true); return new GeneralCommandLine(argv); } + @Override + public @Nullable Object getWorkspaceConfiguration(@NotNull ConfigurationItem item) { + return Optional.ofNullable(NixLspSettings.getInstance(getProject()).getConfiguration()) + .map(JsonParser::parseString) + .map(JsonElement::getAsJsonObject) + .map(jsonObject -> jsonObject.get(item.getSection())) + .orElse(null); + } + @Override public boolean isSupportedFile(@NotNull VirtualFile virtualFile) { return virtualFile.getFileType() == NixFileType.INSTANCE; diff --git a/src/main/java/org/nixos/idea/lsp/NixLspServerSupportProvider.java b/src/main/java/org/nixos/idea/lsp/NixLspServerSupportProvider.java index 20d0d19..ff0cd05 100644 --- a/src/main/java/org/nixos/idea/lsp/NixLspServerSupportProvider.java +++ b/src/main/java/org/nixos/idea/lsp/NixLspServerSupportProvider.java @@ -15,9 +15,9 @@ public final class NixLspServerSupportProvider implements LspServerSupportProvid @Override public void fileOpened(@NotNull Project project, @NotNull VirtualFile virtualFile, @NotNull LspServerStarter lspServerStarter) { if (virtualFile.getFileType() == NixFileType.INSTANCE) { - NixLspSettings settings = NixLspSettings.getInstance(); + NixLspSettings settings = NixLspSettings.getInstance(project); if (settings.isEnabled()) { - lspServerStarter.ensureServerStarted(new NixLspServerDescriptor(project, settings)); + lspServerStarter.ensureServerStarted(new NixLspServerDescriptor(project)); } } } diff --git a/src/main/java/org/nixos/idea/lsp/NixLspSettings.kt b/src/main/java/org/nixos/idea/lsp/NixLspSettings.kt index 5b8b3c2..0e340e5 100644 --- a/src/main/java/org/nixos/idea/lsp/NixLspSettings.kt +++ b/src/main/java/org/nixos/idea/lsp/NixLspSettings.kt @@ -1,17 +1,19 @@ package org.nixos.idea.lsp -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.BaseState import com.intellij.openapi.components.RoamingType +import com.intellij.openapi.components.Service import com.intellij.openapi.components.SimplePersistentStateComponent import com.intellij.openapi.components.State import com.intellij.openapi.components.Storage +import com.intellij.openapi.project.Project import org.nixos.idea.settings.NixStoragePaths import org.nixos.idea.settings.SimplePersistentStateComponentHelper.delegate import java.util.ArrayDeque import java.util.Collections import java.util.Deque +@Service(Service.Level.PROJECT) @State(name = "NixLspSettings", storages = [Storage(value = NixStoragePaths.TOOLS, roamingType = RoamingType.LOCAL)]) class NixLspSettings : SimplePersistentStateComponent(State()) { @@ -19,17 +21,21 @@ class NixLspSettings : SimplePersistentStateComponent(Stat var enabled by property(false) var command by string() var history: Deque by property(ArrayDeque(), { it.isEmpty() }) + var configuration by string(DEFAULT_CONFIGURATION) } var isEnabled: Boolean by delegate(State::enabled) var command: String by delegate(State::command, State::history) val commandHistory: Collection get() = Collections.unmodifiableCollection(state.history) + var configuration: String? by delegate(State::configuration) companion object { + private const val DEFAULT_CONFIGURATION: String = "{}" + @JvmStatic - fun getInstance(): NixLspSettings { - return ApplicationManager.getApplication().getService(NixLspSettings::class.java) + fun getInstance(project: Project): NixLspSettings { + return project.getService(NixLspSettings::class.java) } } } diff --git a/src/main/java/org/nixos/idea/lsp/NixLspSettingsConfigurable.kt b/src/main/java/org/nixos/idea/lsp/NixLspSettingsConfigurable.kt index 1273061..c2edbf3 100644 --- a/src/main/java/org/nixos/idea/lsp/NixLspSettingsConfigurable.kt +++ b/src/main/java/org/nixos/idea/lsp/NixLspSettingsConfigurable.kt @@ -1,16 +1,22 @@ package org.nixos.idea.lsp +import com.intellij.json.JsonFileType +import com.intellij.openapi.editor.ex.EditorEx import com.intellij.openapi.options.BoundSearchableConfigurable import com.intellij.openapi.options.Configurable -import com.intellij.openapi.project.ProjectManager +import com.intellij.openapi.project.Project import com.intellij.platform.lsp.api.LspServerManager +import com.intellij.ui.EditorTextField import com.intellij.ui.RawCommandLineEditor import com.intellij.ui.components.JBCheckBox +import com.intellij.ui.dsl.builder.Align import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.Cell +import com.intellij.ui.dsl.builder.LabelPosition import com.intellij.ui.dsl.builder.bindSelected import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.selected +import com.intellij.ui.dsl.builder.toMutableProperty import org.nixos.idea.settings.ui.CommandSuggestionsPopup import org.nixos.idea.settings.ui.UiDslExtensions.bindText import org.nixos.idea.settings.ui.UiDslExtensions.placeholderText @@ -18,13 +24,14 @@ import org.nixos.idea.settings.ui.UiDslExtensions.suggestionsPopup import org.nixos.idea.settings.ui.UiDslExtensions.validateOnReset import org.nixos.idea.settings.ui.UiDslExtensions.validateWhenTextChanged import org.nixos.idea.settings.ui.UiDslExtensions.warnOnInput +import java.awt.Dimension -class NixLspSettingsConfigurable : +class NixLspSettingsConfigurable(val project: Project) : BoundSearchableConfigurable("Language Server (LSP)", "org.nixos.idea.lsp.NixLspSettingsConfigurable"), Configurable.Beta { override fun createPanel() = panel { - val settings = NixLspSettings.getInstance() + val settings = NixLspSettings.getInstance(project) lateinit var enabledCheckBox: Cell row { enabledCheckBox = checkBox("Enable language server") @@ -43,6 +50,15 @@ class NixLspSettingsConfigurable : it.text.isNullOrBlank() } } + row { + cell(createJsonEditorTextField()) + .align(Align.FILL) + .label("Workspace configuration:", LabelPosition.TOP) + .bind( + EditorTextField::getText, EditorTextField::setText, + settings::configuration.toMutableProperty() + ) + }.resizableRow() }.enabledIf(enabledCheckBox.selected) } @@ -50,9 +66,18 @@ class NixLspSettingsConfigurable : override fun apply() { super.apply() reset() // Update UI components to use normalized property values - for (project in ProjectManager.getInstance().openProjects) { - LspServerManager.getInstance(project).stopAndRestartIfNeeded(NixLspServerSupportProvider::class.java) + LspServerManager.getInstance(project).stopAndRestartIfNeeded(NixLspServerSupportProvider::class.java) + } + + private fun NixLspSettingsConfigurable.createJsonEditorTextField(): EditorTextField { + val editorTextField = object : EditorTextField(null, project, JsonFileType.INSTANCE, false, false) { + override fun createEditor(): EditorEx { + val editor = super.createEditor() + editor.settings.isUseSoftWraps = true + return editor + } } + return editorTextField } } diff --git a/src/main/resources/META-INF/nix-idea-ultimate.xml b/src/main/resources/META-INF/nix-idea-ultimate.xml index 1e1a0f1..2fb7d94 100644 --- a/src/main/resources/META-INF/nix-idea-ultimate.xml +++ b/src/main/resources/META-INF/nix-idea-ultimate.xml @@ -1,10 +1,8 @@ + com.intellij.modules.json - - -