diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageClientImpl.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageClientImpl.java index 2856dd942..cda51ddc0 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageClientImpl.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageClientImpl.java @@ -4,15 +4,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.redhat.devtools.intellij.lsp4ij.operations.diagnostics.LSPDiagnosticHandler; -import org.eclipse.lsp4j.ApplyWorkspaceEditParams; -import org.eclipse.lsp4j.ApplyWorkspaceEditResponse; -import org.eclipse.lsp4j.MessageActionItem; -import org.eclipse.lsp4j.MessageParams; -import org.eclipse.lsp4j.PublishDiagnosticsParams; -import org.eclipse.lsp4j.RegistrationParams; -import org.eclipse.lsp4j.ShowMessageRequestParams; -import org.eclipse.lsp4j.UnregistrationParams; -import org.eclipse.lsp4j.WorkspaceFolder; +import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.services.LanguageClient; import org.eclipse.lsp4j.services.LanguageServer; @@ -30,6 +22,8 @@ public class LanguageClientImpl implements LanguageClient { private boolean disposed; + private Runnable didChangeConfigurationListener; + public LanguageClientImpl(Project project) { this.project = project; } @@ -109,4 +103,28 @@ public void dispose() { public boolean isDisposed() { return disposed; } + + protected Object createSettings() { + return null; + } + + protected synchronized Runnable getDidChangeConfigurationListener() { + if (didChangeConfigurationListener != null) { + return didChangeConfigurationListener; + } + didChangeConfigurationListener = () -> { + LanguageServer languageServer = getLanguageServer(); + if (languageServer == null) { + return; + } + Object settings = createSettings(); + if(settings == null) { + return; + } + DidChangeConfigurationParams params = new DidChangeConfigurationParams(settings); + languageServer.getWorkspaceService().didChangeConfiguration(params); + }; + return didChangeConfigurationListener; + } + } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java index 0dd5126d8..6745b32d0 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java @@ -18,6 +18,7 @@ import com.intellij.codeInsight.hints.presentation.MouseButton; import com.intellij.codeInsight.hints.presentation.PresentationFactory; import com.intellij.codeInsight.hints.presentation.SequencePresentation; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; @@ -27,13 +28,7 @@ import com.redhat.devtools.intellij.lsp4ij.AbstractLSPInlayProvider; import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; import com.redhat.devtools.intellij.lsp4ij.LanguageServiceAccessor; -import org.eclipse.lsp4j.InlayHint; -import org.eclipse.lsp4j.InlayHintLabelPart; -import org.eclipse.lsp4j.InlayHintParams; -import org.eclipse.lsp4j.InlayHintRegistrationOptions; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.services.LanguageServer; import org.jetbrains.annotations.NotNull; @@ -41,7 +36,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.awt.Component; +import java.awt.*; import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -69,10 +64,10 @@ public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @ try { URI docURI = LSPIJUtils.toUri(editor.getDocument()); if (docURI != null) { - Range viewPortRange = new Range(new Position(0, 0), new Position(0,0)); + Range viewPortRange = getViewPortRange(editor); InlayHintParams param = new InlayHintParams(new TextDocumentIdentifier(docURI.toString()), viewPortRange); BlockingDeque> pairs = new LinkedBlockingDeque<>(); - List>> inlayhints = new ArrayList<>(); + List>> inlayhints = new ArrayList<>(); CompletableFuture future = LanguageServiceAccessor.getInstance(psiElement.getProject()) .getLanguageServers(editor.getDocument(), capabilities -> capabilities.getInlayHintProvider() != null) .thenComposeAsync(languageServers -> CompletableFuture.allOf(languageServers.stream() @@ -93,8 +88,8 @@ public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @ inlayhints.add(Pair.create(offset, pair)); } } - Map>>> elements = inlayhints.stream().collect(Collectors.groupingBy(p -> p.first)); - elements.forEach((offset,list) -> inlayHintsSink.addInlineElement(offset, false, + Map>>> elements = inlayhints.stream().collect(Collectors.groupingBy(p -> p.first)); + elements.forEach((offset, list) -> inlayHintsSink.addInlineElement(offset, false, toPresentation(editor, offset, list, getFactory()), false)); } } catch (InterruptedException e) { @@ -106,6 +101,14 @@ public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @ }; } + @NotNull + private static Range getViewPortRange(Editor editor) { + Position start = new Position(0, 0); + Document document = editor.getDocument(); + Position end = LSPIJUtils.toPosition(document.getTextLength(), document); + return new Range(start, end); + } + private InlayPresentation toPresentation(Editor editor, int offset, List>> elements, PresentationFactory factory) { @@ -116,7 +119,7 @@ private InlayPresentation toPresentation(Editor editor, int offset, presentations.add(factory.smallText(label.getLeft())); } else { int index = 0; - for(InlayHintLabelPart part : label.getRight()) { + for (InlayHintLabelPart part : label.getRight()) { InlayPresentation presentation = factory.smallText(part.getValue()); if (part.getCommand() != null) { int finalIndex = index; @@ -156,7 +159,7 @@ private boolean isResolveSupported(Either private String getInlayHintString(InlayHint inlayHint) { Either> label = inlayHint.getLabel(); return label.map(Function.identity(), parts -> { - return parts==null?null:parts.stream().map(InlayHintLabelPart::getValue).collect(Collectors.joining()); + return parts == null ? null : parts.stream().map(InlayHintLabelPart::getValue).collect(Collectors.joining()); }); } } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/MicroProfileBundle.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/MicroProfileBundle.java new file mode 100644 index 000000000..bb013ac81 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/MicroProfileBundle.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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.lsp4mp4ij; + +import com.intellij.DynamicBundle; +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; + +/** + * MicroProfile messages bundle. + */ +public final class MicroProfileBundle extends DynamicBundle { + + @NonNls public static final String BUNDLE = "messages.MicroProfileBundle"; + private static final MicroProfileBundle INSTANCE = new MicroProfileBundle(); + + private MicroProfileBundle() { + 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/lsp4mp4ij/settings/MicroProfileConfigurable.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileConfigurable.java new file mode 100644 index 000000000..a81c51b59 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileConfigurable.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * 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.lsp4mp4ij.settings; + +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.ui.NamedConfigurable; +import com.intellij.openapi.util.NlsContexts; +import com.redhat.devtools.intellij.lsp4mp4ij.MicroProfileBundle; + +import javax.swing.*; + +/** + * MicroProfile configuration. + */ +public class MicroProfileConfigurable extends NamedConfigurable { + + private MicroProfileView myView; + + public MicroProfileConfigurable() { + } + + @Override + public UserDefinedMicroProfileSettings getEditableObject() { + return null; + } + + @Override + public @NlsContexts.DetailedDescription String getBannerSlogan() { + return null; + } + + @Override + public JComponent createOptionsPanel() { + if (myView == null) { + myView = new MicroProfileView(); + } + return myView.getComponent(); + } + + @Override + public void setDisplayName(String name) { + } + + @Override + public @NlsContexts.ConfigurableName String getDisplayName() { + return MicroProfileBundle.message("microprofile"); + } + + + @Override + public boolean isModified() { + if (myView == null) return false; + return false; + } + + @Override + public void apply() throws ConfigurationException { + // Do nothing + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileConfigurableProvider.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileConfigurableProvider.java new file mode 100644 index 000000000..ab60b91a8 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileConfigurableProvider.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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.lsp4mp4ij.settings; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableProvider; + +/** + * MicroProfile UI settings provider. + */ +public class MicroProfileConfigurableProvider extends ConfigurableProvider { + + @Override + public Configurable createConfigurable() { + return new MicroProfileConfigurable(); + } + + @Override + public boolean canCreateConfigurable() { + return true; + } + +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileView.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileView.java new file mode 100644 index 000000000..cc97fec87 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/MicroProfileView.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.lsp4mp4ij.settings; + +import com.intellij.openapi.Disposable; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UI; +import com.redhat.devtools.intellij.lsp4mp4ij.MicroProfileBundle; + +import javax.swing.*; +import javax.swing.border.TitledBorder; + +/** + * MicroProfile view. + */ +public class MicroProfileView implements Disposable { + + private final JPanel myMainPanel; + + public MicroProfileView() { + JComponent descriptionPanel = createDescription(MicroProfileBundle.message("microprofile.description")); + JPanel settingsPanel = createSettings(descriptionPanel); + TitledBorder title = IdeBorderFactory.createTitledBorder(MicroProfileBundle.message("microprofile.title")); + settingsPanel.setBorder(title); + this.myMainPanel = JBUI.Panels.simplePanel(10,10) + .addToLeft(JBUI.Panels.simplePanel()) + .addToCenter(settingsPanel); + } + + private JPanel createSettings(JComponent description) { + return FormBuilder.createFormBuilder() + .addComponentFillVertically(new JPanel(), 0) + .getPanel(); + } + + private JComponent createDescription(String description) { + /** + * Normally comments are below the controls. + * Here we want the comments to precede the controls, we therefore create an empty, 0-sized panel. + */ + JPanel titledComponent = UI.PanelFactory.grid().createPanel(); + titledComponent.setMinimumSize(JBUI.emptySize()); + titledComponent.setPreferredSize(JBUI.emptySize()); + if (description != null && !description.isBlank()) { + titledComponent = UI.PanelFactory.panel(titledComponent) + .withComment(description) + .resizeX(true) + .resizeY(true) + .createPanel(); + } + return titledComponent; + } + + public JComponent getComponent() { + return myMainPanel; + } + + @Override + public void dispose() { + + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/UserDefinedMicroProfileSettings.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/UserDefinedMicroProfileSettings.java new file mode 100644 index 000000000..3e85bec97 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/UserDefinedMicroProfileSettings.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * 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.lsp4mp4ij.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.containers.ContainerUtil; +import com.intellij.util.xmlb.annotations.Tag; +import com.jetbrains.jsonSchema.JsonSchemaCatalogProjectConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * User defined MicroProfile settings for: + * + *
    + *
  • properties files managed with the MicroProfile language server
  • + *
  • Java files managed with the MicroProfile language server
  • + *
+ */ +@State( + name = "MicroProfileSettingsState", + storages = {@Storage("microProfileSettings.xml")} +) +public class UserDefinedMicroProfileSettings implements PersistentStateComponent { + + public volatile MyState myState = new MyState(); + + private final List myChangeHandlers = ContainerUtil.createConcurrentList(); + + public static UserDefinedMicroProfileSettings getInstance() { + return ServiceManager.getService(UserDefinedMicroProfileSettings.class); + } + + public void addChangeHandler(Runnable runnable) { + myChangeHandlers.add(runnable); + } + + public void removeChangeHandler(Runnable runnable) { + myChangeHandlers.remove(runnable); + } + + public void fireStateChanged() { + for (Runnable handler : myChangeHandlers) { + handler.run(); + } + } + + // ---------- Properties + + public boolean isInlayHintEnabled() { + return myState.myInlayHintEnabled; + } + + public void setInlayHintEnabled(boolean inlayHintEnabled) { + myState.myInlayHintEnabled = inlayHintEnabled; + } + + // ---------- Java + + public boolean isUrlCodeLensEnabled() { + return myState.myUrlCodeLensEnabled; + } + + public void setUrlCodeLensEnabled(boolean urlCodeLensEnabled) { + myState.myUrlCodeLensEnabled = urlCodeLensEnabled; + } + + @Nullable + @Override + public MyState getState() { + return myState; + } + + @Override + public void loadState(@NotNull MyState state) { + myState = state; + for (Runnable handler : myChangeHandlers) { + handler.run(); + } + } + + /** + * Returns the proper settings expected by the MicroProfile language server. + * + * @return the proper settings expected by the MicroProfile language server. + */ + public Map toSettingsForMicroProfileLS() { + Map settings = new HashMap<>(); + Map microprofile = new HashMap<>(); + settings.put("microprofile", microprofile); + Map tools = new HashMap<>(); + microprofile.put("tools", tools); + + // Properties settings + // Inlay hint + Map inlayHint = new HashMap<>(); + inlayHint.put("enabled", isInlayHintEnabled()); + tools.put("inlayHint", inlayHint); + + // Java settings + // URL code lens + Map codeLens = new HashMap<>(); + codeLens.put("urlCodeLensEnabled", isUrlCodeLensEnabled()); + tools.put("codeLens", codeLens); + + return settings; + } + + static class MyState { + @Tag("inlayHintEnabled") + public boolean myInlayHintEnabled = true; + + @Tag("urlCodeLensEnabled") + public boolean myUrlCodeLensEnabled = true; + + MyState() { + } + + } + +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaConfigurable.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaConfigurable.java new file mode 100644 index 000000000..0aa24bf8c --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaConfigurable.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.lsp4mp4ij.settings.java; + +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.ui.NamedConfigurable; +import com.intellij.openapi.util.NlsContexts; +import com.redhat.devtools.intellij.lsp4mp4ij.MicroProfileBundle; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.properties.MicroProfilePropertiesView; + +import javax.swing.*; + +/** + * + */ +public class MicroProfileJavaConfigurable extends NamedConfigurable { + + private final UserDefinedMicroProfileSettings myMicroProfileSettings; + private MicroProfileJavaView myView; + private String myDisplayName; + + public MicroProfileJavaConfigurable(UserDefinedMicroProfileSettings microProfileSettings) { + this.myMicroProfileSettings = microProfileSettings; + } + + @Override + public UserDefinedMicroProfileSettings getEditableObject() { + return myMicroProfileSettings; + } + + @Override + public @NlsContexts.DetailedDescription String getBannerSlogan() { + return null; + } + + @Override + public JComponent createOptionsPanel() { + if (myView == null) { + myView = new MicroProfileJavaView(); + } + return myView.getComponent(); + } + + @Override + public void setDisplayName(String name) { + myDisplayName = name; + } + + @Override + public @NlsContexts.ConfigurableName String getDisplayName() { + return MicroProfileBundle.message("microprofile.java"); + } + + @Override + public void reset() { + if (myView == null) return; + UserDefinedMicroProfileSettings settings = UserDefinedMicroProfileSettings.getInstance(); + myView.setUrlCodeLensEnabled(settings.isUrlCodeLensEnabled()); + } + + @Override + public boolean isModified() { + if (myView == null) return false; + UserDefinedMicroProfileSettings settings = UserDefinedMicroProfileSettings.getInstance(); + if (settings == null) { + return true; + } + return !(myView.isUrlCodeLensEnabled()== settings.isUrlCodeLensEnabled()); + } + + @Override + public void apply() throws ConfigurationException { + if (myView == null) return; + UserDefinedMicroProfileSettings settings = UserDefinedMicroProfileSettings.getInstance(); + settings.setUrlCodeLensEnabled(myView.isUrlCodeLensEnabled()); + settings.fireStateChanged(); + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaConfigurableProvider.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaConfigurableProvider.java new file mode 100644 index 000000000..9cf64bf84 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaConfigurableProvider.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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.lsp4mp4ij.settings.java; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableProvider; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.java.MicroProfileJavaConfigurable; + +/** + * MicroProfile UI settings provider for Java file. + */ +public class MicroProfileJavaConfigurableProvider extends ConfigurableProvider { + + @Override + public Configurable createConfigurable() { + return new MicroProfileJavaConfigurable(UserDefinedMicroProfileSettings.getInstance()); + } + + @Override + public boolean canCreateConfigurable() { + return true; + } + +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaView.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaView.java new file mode 100644 index 000000000..1336c59ca --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/java/MicroProfileJavaView.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.lsp4mp4ij.settings.java; + +import com.intellij.openapi.Disposable; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UI; +import com.redhat.devtools.intellij.lsp4ij.LanguageServersRegistry; +import com.redhat.devtools.intellij.lsp4mp4ij.MicroProfileBundle; + +import javax.swing.*; +import javax.swing.border.TitledBorder; + +/** + * MicroProfile Java view. + */ +public class MicroProfileJavaView implements Disposable { + + private final JPanel myMainPanel; + + private JBCheckBox urlCodeLensEnabledCheckBox = new JBCheckBox(MicroProfileBundle.message("microprofile.java.codeLens.url.enabled")); + + public MicroProfileJavaView() { + JComponent descriptionPanel = createDescription(null); + JPanel settingsPanel = createSettings(descriptionPanel); + TitledBorder title = IdeBorderFactory.createTitledBorder(MicroProfileBundle.message("microprofile.java.title")); + settingsPanel.setBorder(title); + this.myMainPanel = JBUI.Panels.simplePanel(10, 10) + .addToLeft(JBUI.Panels.simplePanel()) + .addToCenter(settingsPanel); + } + + private JPanel createSettings(JComponent description) { + return FormBuilder.createFormBuilder() + .addComponent(description, 0) + .addComponent(urlCodeLensEnabledCheckBox, 5) + .addComponentFillVertically(new JPanel(), 0) + .getPanel(); + } + + private JComponent createDescription(String description) { + /** + * Normally comments are below the controls. + * Here we want the comments to precede the controls, we therefore create an empty, 0-sized panel. + */ + JPanel titledComponent = UI.PanelFactory.grid().createPanel(); + titledComponent.setMinimumSize(JBUI.emptySize()); + titledComponent.setPreferredSize(JBUI.emptySize()); + if (description != null && !description.isBlank()) { + titledComponent = UI.PanelFactory.panel(titledComponent) + .withComment(description) + .resizeX(true) + .resizeY(true) + .createPanel(); + } + return titledComponent; + } + + public JComponent getComponent() { + return myMainPanel; + } + + + public boolean isUrlCodeLensEnabled() { + return urlCodeLensEnabledCheckBox.isSelected(); + } + + public void setUrlCodeLensEnabled(boolean inlayHint) { + urlCodeLensEnabledCheckBox.setSelected(inlayHint); + } + + @Override + public void dispose() { + + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesConfigurable.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesConfigurable.java new file mode 100644 index 000000000..b2ff82d92 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesConfigurable.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.lsp4mp4ij.settings.properties; + +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.ui.NamedConfigurable; +import com.intellij.openapi.util.NlsContexts; +import com.redhat.devtools.intellij.lsp4ij.settings.UserDefinedLanguageServerSettings; +import com.redhat.devtools.intellij.lsp4mp4ij.MicroProfileBundle; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; + +import javax.swing.*; + +/** + * MicroProfile configuration for properties files. + */ +public class MicroProfilePropertiesConfigurable extends NamedConfigurable { + + private final UserDefinedMicroProfileSettings myMicroProfileSettings; + private MicroProfilePropertiesView myView; + private String myDisplayName; + + public MicroProfilePropertiesConfigurable(UserDefinedMicroProfileSettings microProfileSettings) { + this.myMicroProfileSettings = microProfileSettings; + } + + @Override + public UserDefinedMicroProfileSettings getEditableObject() { + return myMicroProfileSettings; + } + + @Override + public @NlsContexts.DetailedDescription String getBannerSlogan() { + return null; + } + + @Override + public JComponent createOptionsPanel() { + if (myView == null) { + myView = new MicroProfilePropertiesView(); + } + return myView.getComponent(); + } + + @Override + public void setDisplayName(String name) { + myDisplayName = name; + } + + @Override + public @NlsContexts.ConfigurableName String getDisplayName() { + return MicroProfileBundle.message("microprofile.properties"); + } + + @Override + public void reset() { + if (myView == null) return; + UserDefinedMicroProfileSettings settings = UserDefinedMicroProfileSettings.getInstance(); + myView.setInlayHintEnabled(settings.isInlayHintEnabled()); + } + + @Override + public boolean isModified() { + if (myView == null) return false; + UserDefinedMicroProfileSettings settings = UserDefinedMicroProfileSettings.getInstance(); + if (settings == null) { + return true; + } + return !(myView.isInlayHintEnabled()== settings.isInlayHintEnabled()); + } + + @Override + public void apply() throws ConfigurationException { + if (myView == null) return; + UserDefinedMicroProfileSettings settings = UserDefinedMicroProfileSettings.getInstance(); + settings.setInlayHintEnabled(myView.isInlayHintEnabled()); + settings.fireStateChanged(); + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesConfigurableProvider.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesConfigurableProvider.java new file mode 100644 index 000000000..d6039f829 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesConfigurableProvider.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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.lsp4mp4ij.settings.properties; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableProvider; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.properties.MicroProfilePropertiesConfigurable; + +/** + * MicroProfile UI settings provider for Properties file. + */ +public class MicroProfilePropertiesConfigurableProvider extends ConfigurableProvider { + + @Override + public Configurable createConfigurable() { + return new MicroProfilePropertiesConfigurable(UserDefinedMicroProfileSettings.getInstance()); + } + + @Override + public boolean canCreateConfigurable() { + return true; + } + +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesView.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesView.java new file mode 100644 index 000000000..83323b368 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/settings/properties/MicroProfilePropertiesView.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.lsp4mp4ij.settings.properties; + +import com.intellij.openapi.Disposable; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UI; +import com.redhat.devtools.intellij.lsp4mp4ij.MicroProfileBundle; + +import javax.swing.*; +import javax.swing.border.TitledBorder; + +/** + * MicroProfile Properties view. + */ +public class MicroProfilePropertiesView implements Disposable { + + private final JPanel myMainPanel; + + private JBCheckBox inlayHintCheckBox = new JBCheckBox(MicroProfileBundle.message("microprofile.properties.inlayHint.enabled")); + + public MicroProfilePropertiesView() { + JComponent descriptionPanel = createDescription(null); + JPanel settingsPanel = createSettings(descriptionPanel); + TitledBorder title = IdeBorderFactory.createTitledBorder(MicroProfileBundle.message("microprofile.properties.title")); + settingsPanel.setBorder(title); + this.myMainPanel = JBUI.Panels.simplePanel(10, 10) + .addToLeft(JBUI.Panels.simplePanel()) + .addToCenter(settingsPanel); + } + + private JPanel createSettings(JComponent description) { + return FormBuilder.createFormBuilder() + .addComponent(description, 0) + .addComponent(inlayHintCheckBox, 5) + .addComponentFillVertically(new JPanel(), 0) + .getPanel(); + } + + private JComponent createDescription(String description) { + /** + * Normally comments are below the controls. + * Here we want the comments to precede the controls, we therefore create an empty, 0-sized panel. + */ + JPanel titledComponent = UI.PanelFactory.grid().createPanel(); + titledComponent.setMinimumSize(JBUI.emptySize()); + titledComponent.setPreferredSize(JBUI.emptySize()); + if (description != null && !description.isBlank()) { + titledComponent = UI.PanelFactory.panel(titledComponent) + .withComment(description) + .resizeX(true) + .resizeY(true) + .createPanel(); + } + return titledComponent; + } + + + public JComponent getComponent() { + return myMainPanel; + } + + + public boolean isInlayHintEnabled() { + return inlayHintCheckBox.isSelected(); + } + + public void setInlayHintEnabled(boolean inlayHint) { + inlayHintCheckBox.setSelected(inlayHint); + } + + @Override + public void dispose() { + + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java index 1eabd43c6..2f0e9fd5b 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java @@ -21,6 +21,7 @@ import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.project.PsiMicroProfileProjectManager; import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; import com.redhat.devtools.intellij.lsp4ij.IndexAwareLanguageClient; import com.redhat.devtools.intellij.lsp4mp4ij.classpath.ClasspathResourceChangedManager; @@ -41,7 +42,6 @@ public class QuarkusLanguageClient extends IndexAwareLanguageClient implements MicroProfileLanguageClientAPI, ClasspathResourceChangedManager.Listener { - private static final Logger LOGGER = LoggerFactory.getLogger(QuarkusLanguageClient.class); private final MessageBusConnection connection; @@ -49,12 +49,20 @@ public QuarkusLanguageClient(Project project) { super(project); connection = project.getMessageBus().connect(project); connection.subscribe(ClasspathResourceChangedManager.TOPIC, this); + // Track MicroProfile settings changed to push them to the language server with LSP didChangeConfiguration. + UserDefinedMicroProfileSettings.getInstance().addChangeHandler(getDidChangeConfigurationListener()); } @Override public void dispose() { super.dispose(); connection.disconnect(); + UserDefinedMicroProfileSettings.getInstance().removeChangeHandler(getDidChangeConfigurationListener()); + } + + @Override + protected Object createSettings() { + return UserDefinedMicroProfileSettings.getInstance().toSettingsForMicroProfileLS(); } private void sendPropertiesChangeEvent(List scope, Set uris) { 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 3d77bc2bb..033bd8889 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 @@ -16,6 +16,7 @@ import com.redhat.devtools.intellij.quarkus.TelemetryService; import com.redhat.devtools.intellij.lsp4ij.server.JavaProcessCommandBuilder; import com.redhat.devtools.intellij.lsp4ij.server.ProcessStreamConnectionProvider; +import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; import java.io.File; import java.net.URI; @@ -46,19 +47,11 @@ public QuarkusServer() { @Override public Object getInitializationOptions(URI rootUri) { + Map root = new HashMap<>(); - Map settings = new HashMap<>(); - Map quarkus = new HashMap<>(); - Map tools = new HashMap<>(); - Map trace = new HashMap<>(); - trace.put("server", "verbose"); - tools.put("trace", trace); - Map codeLens = new HashMap<>(); - codeLens.put("urlCodeLensEnabled", "true"); - tools.put("codeLens", codeLens); - quarkus.put("tools", tools); - settings.put("microprofile", quarkus); + Map settings = UserDefinedMicroProfileSettings.getInstance().toSettingsForMicroProfileLS(); root.put("settings", settings); + Map extendedClientCapabilities = new HashMap<>(); Map commands = new HashMap<>(); Map commandsKind = new HashMap<>(); @@ -70,4 +63,5 @@ public Object getInitializationOptions(URI rootUri) { root.put("extendedClientCapabilities", extendedClientCapabilities); return root; } + } diff --git a/src/main/resources/META-INF/lsp4ij-quarkus.xml b/src/main/resources/META-INF/lsp4ij-quarkus.xml index e98482c4c..4f654592e 100644 --- a/src/main/resources/META-INF/lsp4ij-quarkus.xml +++ b/src/main/resources/META-INF/lsp4ij-quarkus.xml @@ -23,6 +23,18 @@ + + + + + + diff --git a/src/main/resources/messages/LanguageServerBundle.properties b/src/main/resources/messages/LanguageServerBundle.properties index 5829829a6..cf6b7fca0 100644 --- a/src/main/resources/messages/LanguageServerBundle.properties +++ b/src/main/resources/messages/LanguageServerBundle.properties @@ -27,5 +27,5 @@ lsp.console.actions.folding=Collapse/Expand All lsp.create.file.confirm.dialog.title=Create file? lsp.create.file.confirm.dialog.message=Unable to open file ''{0}''. Do you want to create it? lsp.create.file.error.dialog.title=Create file problem -lsp.create.file.error.dialog.message=Error while creating file ''{0}'' : ''{1}''. +lsp.create.file.error.dialog.message=Error while creating file ''{0}'' : ''{1}''. diff --git a/src/main/resources/messages/MicroProfileBundle.properties b/src/main/resources/messages/MicroProfileBundle.properties new file mode 100644 index 000000000..d9ce28630 --- /dev/null +++ b/src/main/resources/messages/MicroProfileBundle.properties @@ -0,0 +1,29 @@ +############################################################################### +# Copyright (c) 2023 Red Hat Inc. and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v2.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v20.html +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Red Hat Inc. - initial API and implementation +############################################################################### + +## MicroProfile UI settings page +microprofile=MicroProfile +microprofile.title=MicroProfile +microprofile.description=
    \ +
  • Configure MicroProfile in properties files
  • \ +
  • Configure MicroProfile in Java files
  • \ +
+## MicroProfile UI settings page for properties files +microprofile.properties=Properties +microprofile.properties.title=MicroProfile configuration in microprofile-config.properties +microprofile.properties.inlayHint.enabled=Show evaluated property expression as inlay hint? + +## MicroProfile UI settings page for Java files +microprofile.java=Java +microprofile.java.title=MicroProfile configuration in Java files +microprofile.java.codeLens.url.enabled=Show Rest endpoint URL as inlay hint?