From fbc77885fc90a6aa428457d8f268a722616d769d Mon Sep 17 00:00:00 2001 From: azerr Date: Fri, 5 May 2023 08:30:33 +0200 Subject: [PATCH] feat: Provide UI settings for Language Servers (#843) Fixes #843 Signed-off-by: azerr --- .../intellij/quarkus/lsp/QuarkusServer.java | 16 +-- .../quarkus/lsp4ij/LanguageServerBundle.java | 46 ++++++++ .../lsp4ij/LanguageServersRegistry.java | 31 +++++- .../lsp4ij/ServerExtensionPointBean.java | 4 + .../server/JavaProcessCommandBuilder.java | 103 +++++++++++++++++ .../JavaProcessStreamConnectionProvider.java | 43 -------- .../settings/LanguageServerConfigurable.java | 104 ++++++++++++++++++ .../LanguageServerListConfigurable.java | 103 +++++++++++++++++ ...anguageServerListConfigurableProvider.java | 41 +++++++ .../settings/LanguageServerSettingsState.java | 90 +++++++++++++++ .../lsp4ij/settings/LanguageServerView.java | 91 +++++++++++++++ .../intellij/qute/lsp/QuteServer.java | 14 +-- src/main/resources/META-INF/lsp.xml | 39 ++++++- .../messages/LanguageServerBundle.properties | 3 + 14 files changed, 662 insertions(+), 66 deletions(-) create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServerBundle.java create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/server/JavaProcessCommandBuilder.java delete mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/server/JavaProcessStreamConnectionProvider.java create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerConfigurable.java create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurable.java create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurableProvider.java create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerSettingsState.java create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerView.java create mode 100644 src/main/resources/messages/LanguageServerBundle.properties diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java index d7cbb607d..d4e79122a 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java @@ -14,7 +14,7 @@ import com.intellij.ide.plugins.PluginManager; import com.intellij.openapi.extensions.PluginId; import com.redhat.devtools.intellij.quarkus.TelemetryService; -import com.redhat.devtools.intellij.quarkus.lsp4ij.server.JavaProcessStreamConnectionProvider; +import com.redhat.devtools.intellij.quarkus.lsp4ij.server.JavaProcessCommandBuilder; import com.redhat.devtools.intellij.quarkus.lsp4ij.server.ProcessStreamConnectionProvider; import java.io.File; @@ -27,21 +27,17 @@ /** * Start the MicroProfile language server process with the Quarkus extension. */ -public class QuarkusServer extends JavaProcessStreamConnectionProvider { - - private static final String QUARKUS_DEBUG_PORT = "quarkus.debug.port"; +public class QuarkusServer extends ProcessStreamConnectionProvider { public QuarkusServer() { IdeaPluginDescriptor descriptor = PluginManager.getPlugin(PluginId.getId("com.redhat.devtools.intellij.quarkus")); File lsp4mpServerPath = new File(descriptor.getPath(), "lib/server/org.eclipse.lsp4mp.ls-uber.jar"); File quarkusServerPath = new File(descriptor.getPath(), "lib/server/com.redhat.quarkus.ls.jar"); - String debugPort = System.getProperty(QUARKUS_DEBUG_PORT); - List commands = createJavaCommands(debugPort); - commands.add("-jar"); - commands.add(lsp4mpServerPath.getAbsolutePath()); - commands.add("-cp"); - commands.add(quarkusServerPath.getAbsolutePath()); + List commands = new JavaProcessCommandBuilder("quarkus") + .setJar(lsp4mpServerPath.getAbsolutePath()) + .setCp(quarkusServerPath.getAbsolutePath()) + .create(); commands.add("-DrunAsync=true"); super.setCommands(commands); diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServerBundle.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServerBundle.java new file mode 100644 index 000000000..7a431c1a4 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServerBundle.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package com.redhat.devtools.intellij.quarkus.lsp4ij; + +import com.intellij.DynamicBundle; +import com.intellij.json.JsonBundle; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.PropertyKey; + +import java.util.function.Supplier; + +/** + * Language server messages bundle. + */ +public final class LanguageServerBundle extends DynamicBundle { + + @NonNls public static final String BUNDLE = "messages.LanguageServerBundle"; + private static final LanguageServerBundle INSTANCE = new LanguageServerBundle(); + + private LanguageServerBundle() { + super(BUNDLE); + } + + @NotNull + public static @Nls String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) { + return INSTANCE.getMessage(key, params); + } + + @NotNull + public static Supplier<@Nls String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) { + return INSTANCE.getLazyMessage(key, params); + } +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServersRegistry.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServersRegistry.java index f5022f58f..8248962b6 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServersRegistry.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/LanguageServersRegistry.java @@ -1,3 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2019 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, + * and is available at https://www.eclipse.org/legal/epl-v20.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ package com.redhat.devtools.intellij.quarkus.lsp4ij; import com.intellij.lang.Language; @@ -21,6 +31,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +/** + * Language server registry. + * + */ public class LanguageServersRegistry { private static final Logger LOGGER = LoggerFactory.getLogger(LanguageServersRegistry.class); @@ -29,10 +43,12 @@ public abstract static class LanguageServerDefinition { public final @Nonnull String label; public final boolean isSingleton; public final @Nonnull Map languageIdMappings; + public String description; - public LanguageServerDefinition(@Nonnull String id, @Nonnull String label, boolean isSingleton) { + public LanguageServerDefinition(@Nonnull String id, @Nonnull String label, String description, boolean isSingleton) { this.id = id; this.label = label; + this.description = description; this.isSingleton = isSingleton; this.languageIdMappings = new ConcurrentHashMap<>(); } @@ -41,6 +57,11 @@ public void registerAssociation(@Nonnull Language language, @Nonnull String lang this.languageIdMappings.put(language, languageId); } + @Nonnull + public String getDisplayName() { + return label != null ? label : id; + } + public abstract StreamConnectionProvider createConnectionProvider(); public LanguageClientImpl createLanguageClient(Project project) { @@ -57,7 +78,7 @@ static class ExtensionLanguageServerDefinition extends LanguageServerDefinition private ServerExtensionPointBean extension; public ExtensionLanguageServerDefinition(ServerExtensionPointBean element) { - super(element.id, element.label, element.singleton); + super(element.id, element.label, element.description, element.singleton); this.extension = element; } @@ -224,6 +245,12 @@ private Set getAvailableLSFor(Language language) { return res; } + public Set getAllDefinitions() { + return connections + .stream() + .map(definition -> definition.getValue()) + .collect(Collectors.toSet()); + } diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/ServerExtensionPointBean.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/ServerExtensionPointBean.java index 9364b6794..f7d31f222 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/ServerExtensionPointBean.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/ServerExtensionPointBean.java @@ -4,6 +4,7 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.serviceContainer.BaseKeyedLazyInstance; import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Tag; import com.redhat.devtools.intellij.quarkus.lsp4ij.server.StreamConnectionProvider; import org.jetbrains.annotations.Nullable; @@ -16,6 +17,9 @@ public class ServerExtensionPointBean extends BaseKeyedLazyInstance create() { + List commands = new ArrayList<>(); + commands.add(computeJavaPath()); + if (debugPort != null && !debugPort.isEmpty()) { + String suspend = debugSuspend ? "y" : "n"; + commands.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=" + suspend + ",address=" + debugPort); + } + if(jar != null) { + commands.add("-jar"); + commands.add(jar); + } + if(cp != null) { + commands.add("-cp"); + commands.add(cp); + } + return commands; + } + + private static String computeJavaPath() { + String javaPath = "java"; + boolean existsInPath = Stream.of(System.getenv("PATH").split(Pattern.quote(File.pathSeparator))).map(Paths::get) + .anyMatch(path -> Files.exists(path.resolve("java"))); + if (!existsInPath) { + File f = new File(System.getProperty("java.home"), + "bin/java" + (OS.current() == OS.WINDOWS ? ".exe" : "")); + javaPath = f.getAbsolutePath(); + } + return javaPath; + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/server/JavaProcessStreamConnectionProvider.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/server/JavaProcessStreamConnectionProvider.java deleted file mode 100644 index b437018fe..000000000 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/server/JavaProcessStreamConnectionProvider.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.redhat.devtools.intellij.quarkus.lsp4ij.server; - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -/** - * {@link ProcessStreamConnectionProvider} to start a language server written in Java. - */ -public class JavaProcessStreamConnectionProvider extends ProcessStreamConnectionProvider { - - /** - * Initialize Java commands with the 'java' path and debug port if it is filled. - * - * @param debugPort the debug port and null otherwise. - * @return the initialized Java commands. - */ - protected static List createJavaCommands(String debugPort) { - List commands = new ArrayList<>(); - commands.add(computeJavaPath()); - if (debugPort != null) { - commands.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + debugPort); - } - return commands; - } - - private static String computeJavaPath() { - String javaPath = "java"; - boolean existsInPath = Stream.of(System.getenv("PATH").split(Pattern.quote(File.pathSeparator))).map(Paths::get) - .anyMatch(path -> Files.exists(path.resolve("java"))); - if (!existsInPath) { - File f = new File(System.getProperty("java.home"), - "bin/java" + (OS.current() == OS.WINDOWS ? ".exe" : "")); - javaPath = f.getAbsolutePath(); - } - return javaPath; - } - -} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerConfigurable.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerConfigurable.java new file mode 100644 index 000000000..c018e431f --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerConfigurable.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package com.redhat.devtools.intellij.quarkus.lsp4ij.settings; + +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.ui.NamedConfigurable; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.NlsContexts; +import com.redhat.devtools.intellij.quarkus.lsp4ij.LanguageServersRegistry; + +import javax.swing.*; + +/** + * UI settings to configure a given language server: + * + *
    + *
  • Debug port
  • + *
  • Suspend and wait for a debugger
  • + *
+ */ +public class LanguageServerConfigurable extends NamedConfigurable { + + private final LanguageServersRegistry.LanguageServerDefinition languageServerDefinition; + + private LanguageServerView myView; + + public LanguageServerConfigurable(LanguageServersRegistry.LanguageServerDefinition languageServerDefinition, Runnable updater) { + super(false, updater); + this.languageServerDefinition = languageServerDefinition; + } + + @Override + public void setDisplayName(String name) { + // Do nothing: the language server name is nt editable. + } + + @Override + public LanguageServersRegistry.LanguageServerDefinition getEditableObject() { + return languageServerDefinition; + } + + @Override + public @NlsContexts.DetailedDescription String getBannerSlogan() { + return languageServerDefinition.getDisplayName(); + } + + @Override + public JComponent createOptionsPanel() { + if (myView == null) { + myView = new LanguageServerView(languageServerDefinition); + } + return myView.getComponent(); + } + + @Override + public @NlsContexts.ConfigurableName String getDisplayName() { + return languageServerDefinition.getDisplayName(); + } + + @Override + public boolean isModified() { + LanguageServerSettingsState.LanguageServerDefinitionSettings settings = LanguageServerSettingsState.getInstance() + .getLanguageServerSettings(languageServerDefinition.id); + if (settings == null) { + return true; + } + return !(myView.getDebugPort().equals(settings.getDebugPort()) + && myView.isDebugSuspend() == settings.isDebugSuspend()); + } + + @Override + public void apply() throws ConfigurationException { + LanguageServerSettingsState.LanguageServerDefinitionSettings settings = new LanguageServerSettingsState.LanguageServerDefinitionSettings(); + settings.setDebugPort(myView.getDebugPort()); + settings.setDebugSuspend(myView.isDebugSuspend()); + LanguageServerSettingsState.getInstance().setLanguageServerSettings(languageServerDefinition.id, settings); + } + + @Override + public void reset() { + LanguageServerSettingsState.LanguageServerDefinitionSettings settings = LanguageServerSettingsState.getInstance() + .getLanguageServerSettings(languageServerDefinition.id); + if (settings != null) { + myView.setDebugPort(settings.getDebugPort()); + myView.setDebugSuspend(settings.isDebugSuspend()); + } + } + + @Override + public void disposeUIResources() { + if (myView != null) Disposer.dispose(myView); + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurable.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurable.java new file mode 100644 index 000000000..ac4464353 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurable.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package com.redhat.devtools.intellij.quarkus.lsp4ij.settings; + +import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.ui.MasterDetailsComponent; +import com.intellij.openapi.util.NlsContexts; +import com.intellij.ui.TreeUIHelper; +import com.intellij.ui.speedSearch.SpeedSearchSupply; +import com.redhat.devtools.intellij.quarkus.lsp4ij.LanguageServerBundle; +import com.redhat.devtools.intellij.quarkus.lsp4ij.LanguageServersRegistry; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Objects; +import java.util.Set; + +/** + * UI settings which show: + * + *
    + *
  • list of language server as master on the left
  • + *
  • the settings detail of the selected language server on the right
  • + *
+ */ +public class LanguageServerListConfigurable extends MasterDetailsComponent implements SearchableConfigurable { + + @NonNls + private static final String ID = "LanguageServers"; + + private final Set languageServeDefinitions; + + private boolean isTreeInitialized; + + public LanguageServerListConfigurable(Set languageServeDefinitions) { + this.languageServeDefinitions = languageServeDefinitions; + } + + @Override + @NotNull + public JComponent createComponent() { + if (!isTreeInitialized) { + initTree(); + isTreeInitialized = true; + } + return super.createComponent(); + } + + @Override + public @NotNull @NonNls String getId() { + return ID; + } + + @Override + public @NlsContexts.ConfigurableName String getDisplayName() { + return LanguageServerBundle.message("language.servers"); + } + + @Nullable + @Override + public Runnable enableSearch(final String option) { + return () -> Objects.requireNonNull(SpeedSearchSupply.getSupply(myTree, true)).findAndSelectElement(option); + } + + @Override + protected void initTree() { + super.initTree(); + TreeUIHelper.getInstance() + .installTreeSpeedSearch(myTree, treePath -> ((MyNode) treePath.getLastPathComponent()).getDisplayName(), true); + } + + private MyNode addLanguageServerDefinitionNode(LanguageServersRegistry.LanguageServerDefinition languageServerDefinition) { + MyNode node = new MyNode(new LanguageServerConfigurable(languageServerDefinition, TREE_UPDATER)); + addNode(node, myRoot); + return node; + } + + private void reloadTree() { + myRoot.removeAllChildren(); + for (LanguageServersRegistry.LanguageServerDefinition languageServeDefinition : languageServeDefinitions) { + addLanguageServerDefinitionNode(languageServeDefinition); + } + } + + @Override + public void reset() { + reloadTree(); + super.reset(); + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurableProvider.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurableProvider.java new file mode 100644 index 000000000..dfbe986ea --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerListConfigurableProvider.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package com.redhat.devtools.intellij.quarkus.lsp4ij.settings; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableProvider; +import com.redhat.devtools.intellij.quarkus.lsp4ij.LanguageServersRegistry; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +/** + * Language server list UI settings provider. + */ +public class LanguageServerListConfigurableProvider extends ConfigurableProvider { + + @Override + public boolean canCreateConfigurable() { + return !getLanguageServeDefinitions().isEmpty(); + } + + @Override + public Configurable createConfigurable() { + return new LanguageServerListConfigurable(getLanguageServeDefinitions()); + } + + private static @NotNull Set getLanguageServeDefinitions() { + return LanguageServersRegistry.getInstance().getAllDefinitions(); + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerSettingsState.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerSettingsState.java new file mode 100644 index 000000000..b91f23cf9 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerSettingsState.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package com.redhat.devtools.intellij.quarkus.lsp4ij.settings; + +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.util.xmlb.XmlSerializerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** + * Settings for a given Language server definition + * + *
    + *
  • Debug port
  • + *
  • Suspend and wait for a debugger
  • + *
+ */ +@State( + name = "com.redhat.devtools.intellij.lsp4ij.settings.LanguageServerSettingsState", + storages = {@Storage("LanguageServersSettings.xml")} +) +public class LanguageServerSettingsState implements PersistentStateComponent { + + private Map languageServers = new HashMap<>(); + + public static LanguageServerSettingsState getInstance() { + return ServiceManager.getService(LanguageServerSettingsState.class); + } + + @Nullable + @Override + public LanguageServerSettingsState getState() { + return this; + } + + @Override + public void loadState(@NotNull LanguageServerSettingsState state) { + XmlSerializerUtil.copyBean(state, this); + } + + public LanguageServerDefinitionSettings getLanguageServerSettings(String languageSeverId) { + return languageServers.get(languageSeverId); + } + + public void setLanguageServerSettings(String languageSeverId, LanguageServerDefinitionSettings settings) { + languageServers.put(languageSeverId, settings); + } + + public static class LanguageServerDefinitionSettings { + + private String debugPort; + + private boolean debugSuspend; + + public String getDebugPort() { + return debugPort; + } + + public void setDebugPort(String debugPort) { + this.debugPort = debugPort; + } + + public boolean isDebugSuspend() { + return debugSuspend; + } + + public void setDebugSuspend(boolean debugSuspend) { + this.debugSuspend = debugSuspend; + } + } + + +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerView.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerView.java new file mode 100644 index 000000000..1ea528deb --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp4ij/settings/LanguageServerView.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package com.redhat.devtools.intellij.quarkus.lsp4ij.settings; + +import com.intellij.openapi.Disposable; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBTextField; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UI; +import com.redhat.devtools.intellij.quarkus.lsp4ij.LanguageServerBundle; +import com.redhat.devtools.intellij.quarkus.lsp4ij.LanguageServersRegistry; + +import javax.swing.*; +import java.awt.*; + +/** + * UI settings view to configure a given language server: + * + *
    + *
  • Debug port
  • + *
  • Suspend and wait for a debugger?
  • + *
+ */ +public class LanguageServerView implements Disposable { + + private final JPanel myMainPanel; + private JBTextField debugPortField = new JBTextField(); + + private JBCheckBox debugSuspendCheckBox = new JBCheckBox(LanguageServerBundle.message("language.server.debug.suspend")); + + public LanguageServerView(LanguageServersRegistry.LanguageServerDefinition languageServerDefinition) { + this.myMainPanel = FormBuilder.createFormBuilder() + .setFormLeftIndent(10) + .addComponent(createTitleComponent(languageServerDefinition), 1) + .addLabeledComponent(LanguageServerBundle.message("language.server.debug.port"), debugPortField, 1) + .addComponent(debugSuspendCheckBox, 1) + .addComponentFillVertically(new JPanel(), 0) + .getPanel(); + } + + private JComponent createTitleComponent(LanguageServersRegistry.LanguageServerDefinition languageServerDefinition) { + JLabel title = new JLabel(languageServerDefinition.getDisplayName()); + String description = languageServerDefinition.description; + if (description != null && description.length() > 0) { + // @See com.intellij.internal.ui.ComponentPanelTestAction for more details on how to create comment panels + return UI.PanelFactory.panel(title) + .withComment(description) + .createPanel(); + } + return title; + } + + public JComponent getComponent() { + return myMainPanel; + } + + public String getDebugPort() { + return debugPortField.getText(); + } + + public void setDebugPort(String debugPort) { + debugPortField.setText(debugPort); + } + + public boolean isDebugSuspend() { + return debugSuspendCheckBox.isSelected(); + } + + public void setDebugSuspend(boolean debugSuspend) { + debugSuspendCheckBox.setSelected(debugSuspend); + } + + @Override + public void dispose() { + + } + +} diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java index c13e591a1..cd792321e 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java @@ -14,7 +14,7 @@ import com.intellij.ide.plugins.PluginManager; import com.intellij.openapi.extensions.PluginId; import com.redhat.devtools.intellij.quarkus.TelemetryService; -import com.redhat.devtools.intellij.quarkus.lsp4ij.server.JavaProcessStreamConnectionProvider; +import com.redhat.devtools.intellij.quarkus.lsp4ij.server.JavaProcessCommandBuilder; import com.redhat.devtools.intellij.quarkus.lsp4ij.server.ProcessStreamConnectionProvider; import java.io.File; @@ -27,19 +27,15 @@ /** * Start the Qute language server process. */ -public class QuteServer extends JavaProcessStreamConnectionProvider { - - private static final String QUTE_DEBUG_PORT = "qute.debug.port"; +public class QuteServer extends ProcessStreamConnectionProvider { public QuteServer() { IdeaPluginDescriptor descriptor = PluginManager.getPlugin(PluginId.getId("com.redhat.devtools.intellij.quarkus")); File quteServerPath = new File(descriptor.getPath(), "lib/server/com.redhat.qute.ls-uber.jar"); - String debugPort = System.getProperty(QUTE_DEBUG_PORT); - - List commands = createJavaCommands(debugPort); - commands.add("-jar"); - commands.add(quteServerPath.getAbsolutePath()); + List commands = new JavaProcessCommandBuilder("qute") + .setJar(quteServerPath.getAbsolutePath()) + .create(); commands.add("-DrunAsync=true"); super.setCommands(commands); diff --git a/src/main/resources/META-INF/lsp.xml b/src/main/resources/META-INF/lsp.xml index 9a64c09ac..6b969fdb6 100644 --- a/src/main/resources/META-INF/lsp.xml +++ b/src/main/resources/META-INF/lsp.xml @@ -4,14 +4,49 @@ + + + + + - + + MicroProfile language server provides MicroProfile support in: +
    +
  • Java files.
  • +
  • and microprofile-config.properties files.
  • +
+ This language server is extended with Quakus extension to provide Quarkus support in application.properties file. + ]]> +
+
- + + Qute language server provides Qute support in: +
    +
  • Java files.
  • +
  • and *.html,*.txt,*.yml,*.json Qute template files.
  • +
+ ]]> +
+
diff --git a/src/main/resources/messages/LanguageServerBundle.properties b/src/main/resources/messages/LanguageServerBundle.properties new file mode 100644 index 000000000..1dc66547f --- /dev/null +++ b/src/main/resources/messages/LanguageServerBundle.properties @@ -0,0 +1,3 @@ +language.servers=Language Servers +language.server.debug.port=Debug port: +language.server.debug.suspend=Suspend and wait for a debugger?