From da27ab555ade2881a3075a79340e7a903d7f8b59 Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Mon, 4 Sep 2023 10:56:27 +0200 Subject: [PATCH] feat: add command to update microprofile configuration from LSP4MP Signed-off-by: Fred Bricon --- .../lsp4ij/AbstractLSPInlayProvider.java | 6 +- .../devtools/intellij/lsp4ij/LSPIJUtils.java | 13 ++ .../lsp4ij/LanguageServiceAccessor.java | 2 +- .../CommandExecutor.java | 88 ++++++------- .../LSPLazyCodeActionIntentionAction.java | 39 ++---- .../completion/LSPCompletionProposal.java | 14 +- .../command/MicroprofileOpenURIAction.java | 4 +- ...MicroprofileUpdateConfigurationAction.java | 124 ++++++++++++++++++ ...rofilePropertiesExpressionsInspection.java | 2 +- .../intellij/quarkus/lsp/QuarkusServer.java | 2 +- .../qute/psi/core/command/QuteAction.java | 4 +- .../command/QuteGenerateTemplateAction.java | 4 +- .../command/QuteJavaDefinitionAction.java | 6 +- src/main/resources/META-INF/plugin.xml | 4 +- 14 files changed, 215 insertions(+), 97 deletions(-) rename src/main/java/com/redhat/devtools/intellij/lsp4ij/{command/internal => commands}/CommandExecutor.java (76%) create mode 100644 src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileUpdateConfigurationAction.java diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/AbstractLSPInlayProvider.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/AbstractLSPInlayProvider.java index de4f38294..25ad680ee 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/AbstractLSPInlayProvider.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/AbstractLSPInlayProvider.java @@ -22,21 +22,19 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.impl.SimpleDataContext; import com.intellij.ui.layout.LCFlags; import com.intellij.ui.layout.LayoutKt; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; import org.eclipse.lsp4j.Command; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.JComponent; import java.awt.Component; -import java.util.Map; public abstract class AbstractLSPInlayProvider implements InlayHintsProvider { - public static final DataKey LSP_COMMAND = DataKey.create("com.redhat.devtools.intellij.quarkus.lsp4ij.command"); private SettingsKey key = new SettingsKey<>("LSP.hints"); @@ -92,7 +90,7 @@ protected void executeClientCommand(Component source, Command command) { if (command != null) { AnAction action = ActionManager.getInstance().getAction(command.getCommand()); if (action != null) { - DataContext context = SimpleDataContext.getSimpleContext(DataKey.create(LSP_COMMAND.getName()), command, DataManager.getInstance().getDataContext(source)); + DataContext context = SimpleDataContext.getSimpleContext(CommandExecutor.LSP_COMMAND, command, DataManager.getInstance().getDataContext(source)); action.actionPerformed(new AnActionEvent(null, context, ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(), 0)); diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LSPIJUtils.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LSPIJUtils.java index 3b7d8f2de..707a729e1 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LSPIJUtils.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LSPIJUtils.java @@ -145,6 +145,19 @@ public static Document getDocument(VirtualFile docFile) { return FileDocumentManager.getInstance().getDocument(docFile); } + /** + * Returns the @{@link Document} associated to the given @{@link URI}, or null if there's no match. + * @param documentUri the uri of the Document to return + * @return the @{@link Document} associated to documentUri, or null + */ + public static @Nullable Document getDocument(URI documentUri) { + if (documentUri == null) { + return null; + } + VirtualFile documentFile = findResourceFor(documentUri.toASCIIString()); + return getDocument(documentFile); + } + public static @Nullable Module getProject(@Nullable VirtualFile file) { if (file == null) { return null; diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java index 53c3981c2..7ef4e79ad 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java @@ -120,7 +120,7 @@ public CompletableFuture getInitializedLanguageServer(Document d throws IOException { URI initialPath = LSPIJUtils.toUri(document); LanguageServerWrapper wrapper = getLSWrapperForConnection(document, lsDefinition, initialPath); - if (capabilitiesComply(wrapper, capabilitiesPredicate)) { + if (wrapper != null && capabilitiesComply(wrapper, capabilitiesPredicate)) { wrapper.connect(document); return wrapper.getInitializedServer(); } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/command/internal/CommandExecutor.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/commands/CommandExecutor.java similarity index 76% rename from src/main/java/com/redhat/devtools/intellij/lsp4ij/command/internal/CommandExecutor.java rename to src/main/java/com/redhat/devtools/intellij/lsp4ij/commands/CommandExecutor.java index 73697a941..bbb044bbe 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/command/internal/CommandExecutor.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/commands/CommandExecutor.java @@ -9,18 +9,15 @@ * Red Hat, Inc. - initial API and implementation * Fraunhofer FOKUS ******************************************************************************/ -package com.redhat.devtools.intellij.lsp4ij.command.internal; - +package com.redhat.devtools.intellij.lsp4ij.commands; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionUtil; +import com.intellij.openapi.actionSystem.impl.SimpleDataContext; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; @@ -36,7 +33,6 @@ import org.eclipse.lsp4j.WorkspaceEdit; import org.eclipse.lsp4j.services.LanguageServer; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,14 +51,14 @@ public class CommandExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(CommandExecutor.class); - private static final String LSP_COMMAND_CATEGORY_ID = "org.eclipse.lsp4e.commandCategory"; //$NON-NLS-1$ - private static final String LSP_COMMAND_PARAMETER_TYPE_ID = "org.eclipse.lsp4e.commandParameterType"; //$NON-NLS-1$ - private static final String LSP_PATH_PARAMETER_TYPE_ID = "org.eclipse.lsp4e.pathParameterType"; //$NON-NLS-1$ + public static final DataKey LSP_COMMAND = DataKey.create("com.redhat.devtools.intellij.quarkus.lsp4ij.command"); + + public static final DataKey LSP_COMMAND_DOCUMENT_URI = DataKey.create("com.redhat.devtools.intellij.quarkus.lsp4ij.command.documentUri"); /** * Will execute the given {@code command} either on a language server, - * supporting the command, or on the client, if an {@link IHandler} is - * registered for the ID of the command (see {@link LSPCommandHandler}). If + * supporting the command, or on the client, if an {@link AnAction} is + * registered for the ID of the command. If * {@code command} is {@code null}, then this method will do nothing. If neither * the server, nor the client are able to handle the command explicitly, a * heuristic method will try to interpret the command locally. @@ -70,33 +66,36 @@ public class CommandExecutor { * @param command * the LSP Command to be executed. If {@code null} this method will * do nothing. - * @param document - * the document for which the command was created + * @param documentUri + * the URI of the document for which the command was created * @param languageServerId * the ID of the language server for which the {@code command} is * applicable. If {@code null}, the command will not be executed on * the language server. */ - public static void executeCommand(Project project, Command command, Document document, + public static void executeCommand(Project project, Command command, URI documentUri, String languageServerId) { if (command == null) { return; } - if (executeCommandServerSide(project, command, languageServerId, document)) { + if (executeCommandServerSide(project, command, documentUri, languageServerId)) { return; } - if (executeCommandClientSide(command, document)) { + if (executeCommandClientSide(project, command, documentUri)) { return; } // tentative fallback - if (command.getArguments() != null) { - WorkspaceEdit edit = createWorkspaceEdit(command.getArguments(), document); - LSPIJUtils.applyWorkspaceEdit(edit); + if (documentUri != null && command.getArguments() != null) { + Document document = LSPIJUtils.getDocument(documentUri); + if (document != null) { + WorkspaceEdit edit = createWorkspaceEdit(command.getArguments(), document); + LSPIJUtils.applyWorkspaceEdit(edit); + } } } - private static boolean executeCommandServerSide(Project project, Command command, String languageServerId, - Document document) { + private static boolean executeCommandServerSide(Project project, Command command, + URI documentUri, String languageServerId) { if (languageServerId == null) { return false; } @@ -107,7 +106,7 @@ private static boolean executeCommandServerSide(Project project, Command command } try { - CompletableFuture languageServerFuture = getLanguageServerForCommand(project, command, document, + CompletableFuture languageServerFuture = getLanguageServerForCommand(project, command, documentUri, languageServerDefinition); if (languageServerFuture == null) { return false; @@ -130,33 +129,34 @@ private static boolean executeCommandServerSide(Project project, Command command private static CompletableFuture getLanguageServerForCommand(Project project, Command command, - Document document, LanguageServersRegistry.LanguageServerDefinition languageServerDefinition) throws IOException { - CompletableFuture languageServerFuture = LanguageServiceAccessor.getInstance(project) + URI documentUri, LanguageServersRegistry.LanguageServerDefinition languageServerDefinition) throws IOException { + Document document = LSPIJUtils.getDocument(documentUri); + if (document == null) { + return null; + } + return LanguageServiceAccessor.getInstance(project) + //TODO pass documentUri instead of document, but looks like that implies non-trivial refactoring .getInitializedLanguageServer(document, languageServerDefinition, serverCapabilities -> { ExecuteCommandOptions provider = serverCapabilities.getExecuteCommandProvider(); return provider != null && provider.getCommands().contains(command.getCommand()); }); - return languageServerFuture; } - @SuppressWarnings("unused") // ECJ compiler for some reason thinks handlerService == null is always false - private static boolean executeCommandClientSide(Command command, Document document) { + private static boolean executeCommandClientSide(Project project, Command command, URI documentUri) { Application workbench = ApplicationManager.getApplication(); if (workbench == null) { return false; } - URI context = LSPIJUtils.toUri(document); - AnAction parameterizedCommand = createEclipseCoreCommand(command, context, workbench); + AnAction parameterizedCommand = createIDEACoreCommand(command); if (parameterizedCommand == null) { return false; } - DataContext dataContext = createDataContext(command, context, workbench); + DataContext dataContext = createDataContext(project, command, documentUri); ActionUtil.invokeAction(parameterizedCommand, dataContext, ActionPlaces.UNKNOWN, null, null); return true; } - private static AnAction createEclipseCoreCommand(Command command, URI context, - Application workbench) { + private static AnAction createIDEACoreCommand(Command command) { // Usually commands are defined via extension point, but we synthesize one on // the fly for the command ID, since we do not want downstream users // having to define them. @@ -164,21 +164,13 @@ private static AnAction createEclipseCoreCommand(Command command, URI context, return ActionManager.getInstance().getAction(commandId); } - private static DataContext createDataContext(Command command, URI context, - Application workbench) { + private static DataContext createDataContext(Project project, Command command, URI documentUri) { - return new DataContext() { - @Nullable - @Override - public Object getData(@NotNull String dataId) { - if (LSP_COMMAND_PARAMETER_TYPE_ID.equals(dataId)) { - return command; - } else if (LSP_PATH_PARAMETER_TYPE_ID.equals(dataId)) { - return context; - } - return null; - } - }; + SimpleDataContext.Builder contextBuilder = SimpleDataContext.builder(); + contextBuilder.add(CommonDataKeys.PROJECT, project) + .add(LSP_COMMAND, command) + .add(LSP_COMMAND_DOCUMENT_URI, documentUri); + return contextBuilder.build(); } // TODO consider using Entry/SimpleEntry instead @@ -197,7 +189,7 @@ private static final class Pair { * Very empirical and unsafe heuristic to turn unknown command arguments into a * workspace edit... */ - private static WorkspaceEdit createWorkspaceEdit(List commandArguments, Document document) { + private static WorkspaceEdit createWorkspaceEdit(List commandArguments, @NotNull Document document) { WorkspaceEdit res = new WorkspaceEdit(); Map> changes = new HashMap<>(); res.setChanges(changes); diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codeactions/LSPLazyCodeActionIntentionAction.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codeactions/LSPLazyCodeActionIntentionAction.java index f89aa0063..2c9a81afc 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codeactions/LSPLazyCodeActionIntentionAction.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codeactions/LSPLazyCodeActionIntentionAction.java @@ -24,8 +24,12 @@ import com.intellij.util.IncorrectOperationException; import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; import com.redhat.devtools.intellij.lsp4ij.LanguageServerWrapper; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; import org.apache.commons.lang.StringUtils; -import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionOptions; +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.ServerCapabilities; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.jetbrains.annotations.NotNull; @@ -71,6 +75,7 @@ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + String serverId = getLanguageServerWrapper().serverDefinition.id; if (codeAction != null) { if (codeAction.getEdit() == null && codeAction.getCommand() == null && isCodeActionResolveSupported()) { // Unresolved code action "edit" property. Resolve it. @@ -80,52 +85,34 @@ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws .thenAccept(resolved -> { ApplicationManager.getApplication().invokeLater(() -> { DocumentUtil.writeInRunUndoTransparentAction(() -> { - apply(resolved != null ? resolved : codeAction, project); + apply(resolved != null ? resolved : codeAction, project, file, serverId); }); }); }) ); } else { - apply(codeAction, project); + apply(codeAction, project, file, serverId); } } else if (command != null) { - executeCommand(command, project); + executeCommand(command, project, file, serverId); } else { // Should never get here } } - private void apply(CodeAction codeaction, @NotNull Project project) { + private void apply(CodeAction codeaction, @NotNull Project project, PsiFile file, String serverId ) { if (codeaction != null) { if (codeaction.getEdit() != null) { LSPIJUtils.applyWorkspaceEdit(codeaction.getEdit(), codeaction.getTitle()); } if (codeaction.getCommand() != null) { - executeCommand(codeaction.getCommand(), project); + executeCommand(codeaction.getCommand(), project, file, serverId); } } } - private void executeCommand(Command command, @NotNull Project project) { - if (!canSupportCommand(command)) { - return; - } - ExecuteCommandParams params = new ExecuteCommandParams(); - params.setCommand(command.getCommand()); - params.setArguments(command.getArguments()); - getLanguageServerWrapper() - .getInitializedServer() - .thenApply(ls -> ls.getWorkspaceService().executeCommand(params) - ); - } - - private boolean canSupportCommand(Command command) { - ServerCapabilities capabilities = getLanguageServerWrapper().getServerCapabilities(); - if (capabilities != null) { - ExecuteCommandOptions provider = capabilities.getExecuteCommandProvider(); - return (provider != null && provider.getCommands().contains(command.getCommand())); - } - return false; + private void executeCommand(Command command, @NotNull Project project, PsiFile file, String serverId) { + CommandExecutor.executeCommand(project, command, LSPIJUtils.toUri(file), serverId); } private LanguageServerWrapper getLanguageServerWrapper() { diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionProposal.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionProposal.java index 5f7f3b184..6a8a61efb 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionProposal.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSPCompletionProposal.java @@ -27,7 +27,7 @@ import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; import com.redhat.devtools.intellij.lsp4ij.LanguageServerItem; import com.redhat.devtools.intellij.lsp4ij.LanguageServiceAccessor; -import com.redhat.devtools.intellij.lsp4ij.command.internal.CommandExecutor; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; import com.redhat.devtools.intellij.lsp4ij.operations.completion.snippet.LspSnippetIndentOptions; import org.apache.commons.lang.StringUtils; import org.eclipse.lsp4j.*; @@ -37,6 +37,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.net.URI; import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; @@ -265,25 +266,26 @@ protected void apply(Document document, char trigger, int stateMask, int offset) // Execute custom command of the completion item if needed Command command = item.getCommand(); if (command != null) { - executeCustomCommand(command, document); + executeCustomCommand(command, LSPIJUtils.toUri(document)); } } catch (RuntimeException ex) { LOGGER.warn(ex.getLocalizedMessage(), ex); } } + /** * Execute custom command of the completion item. - * - * @param document + * @param command + * @param documentUri */ - private void executeCustomCommand(@NotNull Command command, Document document) { + private void executeCustomCommand(@NotNull Command command, URI documentUri) { Project project = editor.getProject(); // Execute custom command of the completion item. LanguageServiceAccessor.getInstance(project) .resolveServerDefinition(languageServer.getServer()).map(definition -> definition.id) .ifPresent(id -> { - CommandExecutor.executeCommand(project, command, document, id); + CommandExecutor.executeCommand(project, command, documentUri, id); }); } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileOpenURIAction.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileOpenURIAction.java index 6d540499e..6478e4783 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileOpenURIAction.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileOpenURIAction.java @@ -4,7 +4,7 @@ import com.intellij.ide.BrowserUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.redhat.devtools.intellij.lsp4ij.operations.codelens.LSPCodelensInlayProvider; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; import java.util.List; @@ -20,7 +20,7 @@ public void actionPerformed(AnActionEvent e) { private String getURL(AnActionEvent e) { String url = null; - List arguments = e.getData(LSPCodelensInlayProvider.LSP_COMMAND).getArguments(); + List arguments = e.getData(CommandExecutor.LSP_COMMAND).getArguments(); if (!arguments.isEmpty()) { Object arg = arguments.get(0); if (arg instanceof JsonPrimitive) { diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileUpdateConfigurationAction.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileUpdateConfigurationAction.java new file mode 100644 index 000000000..238bbd9de --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/command/MicroprofileUpdateConfigurationAction.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * 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.psi.core.command; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.ex.InspectionToolWrapper; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.profile.codeInspection.InspectionProfileManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.impl.FakePsiElement; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.inspections.AbstractDelegateInspectionWithExcludedProperties; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.inspections.MicroProfilePropertiesUnassignedInspection; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.inspections.MicroProfilePropertiesUnknownInspection; +import org.eclipse.lsp4j.Command; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Action for updating the Microprofile configuration, typically requested by LSP4MP. + */ +public class MicroprofileUpdateConfigurationAction extends AnAction { + private final Map updaters = new HashMap<>(); + + public MicroprofileUpdateConfigurationAction() { + //TODO potentially load those from an extension point? + updaters.put("microprofile.tools.validation.unknown.excluded", new InspectionConfigurationUpdater(MicroProfilePropertiesUnknownInspection.ID)); + updaters.put("microprofile.tools.validation.unassigned.excluded", new InspectionConfigurationUpdater(MicroProfilePropertiesUnassignedInspection.ID)); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + JsonObject configUpdate = getConfigUpdate(e); + if (configUpdate != null && e.getProject() != null) { + String section = configUpdate.get("section").getAsString(); + ConfigurationUpdater updater = updaters.get(section); + if (updater == null) { + throw new UnsupportedOperationException("Updating "+section+" is not supported yet!"); + } + JsonElement value = configUpdate.get("value"); + updater.updateConfiguration(e.getProject(), value); + } + } + + private @Nullable JsonObject getConfigUpdate(@NotNull AnActionEvent e) { + @Nullable Command command = e.getData(CommandExecutor.LSP_COMMAND); + if (command == null) { + return null; + } + List arguments = command.getArguments(); + if (arguments != null && !arguments.isEmpty()) { + Object arg = arguments.get(0); + if (arg instanceof JsonObject) { + return (JsonObject) arg; + } + } + return null; + } + + interface ConfigurationUpdater { + void updateConfiguration(Project project, JsonElement value); + } + + private static class InspectionConfigurationUpdater implements ConfigurationUpdater { + + private final String inspectionId; + + InspectionConfigurationUpdater(String inspectionId) { + this.inspectionId = inspectionId; + } + + @Override + public void updateConfiguration(Project project, JsonElement value) { + if (value != null) { + updateConfiguration(project, value.getAsString()); + } + } + + private void updateConfiguration(Project project, @NotNull String value) { + InspectionProfile profile = InspectionProfileManager.getInstance(project).getCurrentProfile(); + InspectionToolWrapper toolWrapper = profile.getInspectionTool(inspectionId, project); + if (toolWrapper != null && toolWrapper.getTool() instanceof AbstractDelegateInspectionWithExcludedProperties) { + Key key = new Key<>(inspectionId); + profile.modifyToolSettings(key, getPsiElement(project), (tool) -> { + tool.excludeList.add(value); + }); + } + } + + private PsiElement getPsiElement(Project project) { + return new FakePsiElement() { + @Override + public PsiElement getParent() { + return null; + } + + @Override + public @NotNull Project getProject() { + return project; + } + }; + } + } +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/inspections/MicroProfilePropertiesExpressionsInspection.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/inspections/MicroProfilePropertiesExpressionsInspection.java index a7a896780..7b2949fda 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/inspections/MicroProfilePropertiesExpressionsInspection.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/inspections/MicroProfilePropertiesExpressionsInspection.java @@ -16,6 +16,6 @@ /** * Dummy inspection for expression values in Microprofile properties files */ -public class MicroProfilePropertiesExpressionsInspection extends AbstractDelegateInspectionWithExcludedProperties { +public class MicroProfilePropertiesExpressionsInspection extends AbstractDelegateInspection { public static final String ID = getShortName(MicroProfilePropertiesExpressionsInspection.class.getSimpleName()); } 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 8854529ec..94e6c0688 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 @@ -59,7 +59,7 @@ public Object getInitializationOptions(URI rootUri) { Map extendedClientCapabilities = new HashMap<>(); Map commands = new HashMap<>(); Map commandsKind = new HashMap<>(); - commandsKind.put("valueSet", Arrays.asList(/* TODO support "microprofile.command.configuration.update",*/ "microprofile.command.open.uri")); + commandsKind.put("valueSet", Arrays.asList("microprofile.command.configuration.update", "microprofile.command.open.uri")); commands.put("commandsKind", commandsKind); extendedClientCapabilities.put("commands", commands); extendedClientCapabilities.put("completion", new HashMap<>()); diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteAction.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteAction.java index 4d6637475..45fdd6465 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteAction.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteAction.java @@ -13,14 +13,14 @@ import com.google.gson.JsonPrimitive; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.redhat.devtools.intellij.lsp4ij.operations.codelens.LSPCodelensInlayProvider; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; import java.util.List; public abstract class QuteAction extends AnAction { protected String getURL(AnActionEvent e) { String url = null; - List arguments = e.getData(LSPCodelensInlayProvider.LSP_COMMAND).getArguments(); + List arguments = e.getData(CommandExecutor.LSP_COMMAND).getArguments(); if (!arguments.isEmpty()) { Object arg = arguments.get(0); if (arg instanceof JsonPrimitive) { diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteGenerateTemplateAction.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteGenerateTemplateAction.java index 956d1535b..37c038aed 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteGenerateTemplateAction.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteGenerateTemplateAction.java @@ -17,7 +17,7 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.redhat.devtools.intellij.lsp4ij.LanguageServiceAccessor; -import com.redhat.devtools.intellij.lsp4ij.operations.codelens.LSPCodelensInlayProvider; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; import org.eclipse.lsp4j.Command; import org.eclipse.lsp4j.ExecuteCommandOptions; import org.eclipse.lsp4j.ExecuteCommandParams; @@ -45,7 +45,7 @@ private LanguageServer getFirstServer(AnActionEvent e) { @Override public void actionPerformed(AnActionEvent e) { - Command command = e.getData(LSPCodelensInlayProvider.LSP_COMMAND); + Command command = e.getData(CommandExecutor.LSP_COMMAND); LanguageServer server = getFirstServer(e); try { if (server != null) { diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteJavaDefinitionAction.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteJavaDefinitionAction.java index dbcea0a08..c553008e9 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteJavaDefinitionAction.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/core/command/QuteJavaDefinitionAction.java @@ -14,10 +14,10 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.project.Project; +import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; +import com.redhat.devtools.intellij.lsp4ij.commands.CommandExecutor; 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.lsp4ij.LSPIJUtils; -import com.redhat.devtools.intellij.lsp4ij.operations.codelens.LSPCodelensInlayProvider; import com.redhat.devtools.intellij.qute.psi.QuteSupportForTemplate; import com.redhat.qute.commons.QuteJavaDefinitionParams; import org.eclipse.lsp4j.Command; @@ -36,7 +36,7 @@ public class QuteJavaDefinitionAction extends QuteAction { @Override public void actionPerformed(AnActionEvent e) { - Command command = e.getData(LSPCodelensInlayProvider.LSP_COMMAND); + Command command = e.getData(CommandExecutor.LSP_COMMAND); QuteJavaDefinitionParams params = getQuteJavaDefinitionParams(command.getArguments()); if (params != null) { Project project = e.getProject(); diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index a31469952..e85750e57 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -552,7 +552,9 @@ - +