From 6ff3d03477bbfd2ece2ddfc7c17e3dc2c4f2d165 Mon Sep 17 00:00:00 2001 From: rubenporras <43636626+rubenporras@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:43:29 +0200 Subject: [PATCH] Do not return a consumer if the code mining has no action. (#1026) According to ICodeMining.getAction(), null should be returned if there is no action to be executed when the mining is clicked. When several InlayHintLabelParts are used, we cannot be sure if there is an action or not without knowing the actual MouseEvent. However, if no InlayHint has an action, we can be sure there is none even without knowing the MouseEvent. For these cases, the code returns null now. --- .../inlayhint/InlayHintProvider.java | 4 +- .../inlayhint/LSPLineContentCodeMining.java | 95 ++++++++++--------- 2 files changed, 51 insertions(+), 48 deletions(-) diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/InlayHintProvider.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/InlayHintProvider.java index cb74ab0e4..c1f76175c 100644 --- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/InlayHintProvider.java +++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/InlayHintProvider.java @@ -63,8 +63,8 @@ private CompletableFuture> provideCodeMinings(@NonNu } } - private LSPLineContentCodeMining toCodeMining(IDocument document, LanguageServerWrapper languageServerWrapper, - InlayHint inlayHint) { + private LSPLineContentCodeMining toCodeMining(@NonNull IDocument document, @NonNull LanguageServerWrapper languageServerWrapper, + @NonNull InlayHint inlayHint) { try { return new LSPLineContentCodeMining(inlayHint, document, languageServerWrapper, InlayHintProvider.this); } catch (BadLocationException e) { diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/LSPLineContentCodeMining.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/LSPLineContentCodeMining.java index 140345ccd..b7d2d5e9d 100644 --- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/LSPLineContentCodeMining.java +++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/inlayhint/LSPLineContentCodeMining.java @@ -9,6 +9,7 @@ package org.eclipse.lsp4e.operations.inlayhint; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -48,13 +49,13 @@ public class LSPLineContentCodeMining extends LineContentCodeMining { private InlayHint inlayHint; - private final LanguageServerWrapper wrapper; - private IDocument document; + private final @NonNull LanguageServerWrapper wrapper; + private final @NonNull IDocument document; private Point location; private FontData[] fontData; - public LSPLineContentCodeMining(InlayHint inlayHint, IDocument document, LanguageServerWrapper languageServerWrapper, + public LSPLineContentCodeMining(@NonNull InlayHint inlayHint, @NonNull IDocument document, @NonNull LanguageServerWrapper languageServerWrapper, InlayHintProvider provider) throws BadLocationException { super(toPosition(inlayHint.getPosition(), document), provider); this.inlayHint = inlayHint; @@ -122,15 +123,19 @@ private static org.eclipse.jface.text.Position toPosition(Position position, IDo @Override public final Consumer getAction() { - return me -> { - String title= getLabel(); - if (title != null && !title.isEmpty()) { - findLabelPart(me).map(InlayHintLabelPart::getCommand).ifPresent(command -> { + return inlayHint.getLabel().map(l -> null, r -> labelPartAction(r)); + } + + private Consumer labelPartAction(List labelParts) { + String title = getLabel(); + if (title != null && !title.isEmpty() && labelParts.stream().map(InlayHintLabelPart::getCommand).anyMatch(Objects::nonNull)) { + return me -> { + findLabelPart(me, labelParts).map(InlayHintLabelPart::getCommand).filter(Objects::nonNull).ifPresent(command -> { ExecuteCommandOptions provider = wrapper.getServerCapabilities().getExecuteCommandProvider(); String commandId = command.getCommand(); if (provider != null && provider.getCommands().contains(commandId)) { LanguageServers.forDocument(document).computeAll((w, ls) -> { - if (w == this.wrapper) { + if (w == wrapper) { return ls.getWorkspaceService() .executeCommand(new ExecuteCommandParams(commandId, command.getArguments())); } @@ -140,48 +145,46 @@ public final Consumer getAction() { CommandExecutor.executeCommandClientSide(command, document); } }); - } - }; + }; + } + return null; } - private Optional findLabelPart(MouseEvent me) { - if (inlayHint.getLabel().isRight()) { - List labelParts = inlayHint.getLabel().getRight(); - if (labelParts.size() == 1) { - return Optional.of(labelParts.get(0)); - } - if (location != null && fontData != null) { - Point relativeLocation = new Point(me.x - location.x, me.y - location.y); - Display display = Display.getCurrent(); - Image image = null; - GC gc = null; - Font font = null; - try { - image = new Image(display, 1, 1); - gc = new GC(image); - font = new Font(display, fontData); - gc.setFont(font); - Point origin = new Point(0, 0); - for (InlayHintLabelPart labelPart : labelParts) { - Point size = gc.stringExtent(labelPart.getValue()); - Rectangle bounds = new Rectangle(origin.x, origin.y, size.x, size.y); - if (bounds.contains(relativeLocation)) { - return Optional.of(labelPart); - } else { - origin.x += size.x; - } - } - } finally { - if (font != null && !font.isDisposed()) { - font.dispose(); - } - if (gc != null && !gc.isDisposed()) { - gc.dispose(); - } - if (image != null && !image.isDisposed()) { - image.dispose(); + private Optional findLabelPart(MouseEvent me, List labelParts) { + if (labelParts.size() == 1) { + return Optional.of(labelParts.get(0)); + } + if (location != null && fontData != null) { + Point relativeLocation = new Point(me.x - location.x, me.y - location.y); + Display display = Display.getCurrent(); + Image image = null; + GC gc = null; + Font font = null; + try { + image = new Image(display, 1, 1); + gc = new GC(image); + font = new Font(display, fontData); + gc.setFont(font); + Point origin = new Point(0, 0); + for (InlayHintLabelPart labelPart : labelParts) { + Point size = gc.stringExtent(labelPart.getValue()); + Rectangle bounds = new Rectangle(origin.x, origin.y, size.x, size.y); + if (bounds.contains(relativeLocation)) { + return Optional.of(labelPart); + } else { + origin.x += size.x; } } + } finally { + if (font != null && !font.isDisposed()) { + font.dispose(); + } + if (gc != null && !gc.isDisposed()) { + gc.dispose(); + } + if (image != null && !image.isDisposed()) { + image.dispose(); + } } } return Optional.empty();