From b59d4a74276bb32037e0d0b74fde4d56e3e7a9dd Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Thu, 29 Jun 2023 12:13:08 +0200 Subject: [PATCH] feat: map LSP4J CompletionItemKinds to Intellij IDEA icons Signed-off-by: Fred Bricon --- .../LSIncompleteCompletionProposal.java | 15 ++- .../intellij/lsp4ij/ui/IconMapper.java | 105 ++++++++++++++++++ .../resources/images/expui/fileTypes/text.svg | 7 ++ .../images/expui/fileTypes/text_dark.svg | 7 ++ src/main/resources/images/nodes/template.svg | 6 + .../intellij/lsp4ij/ui/IconMapperTest.java | 32 ++++++ 6 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapper.java create mode 100644 src/main/resources/images/expui/fileTypes/text.svg create mode 100644 src/main/resources/images/expui/fileTypes/text_dark.svg create mode 100644 src/main/resources/images/nodes/template.svg create mode 100644 src/test/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapperTest.java diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSIncompleteCompletionProposal.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSIncompleteCompletionProposal.java index 2fe058d7d..28df8a2c5 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSIncompleteCompletionProposal.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/completion/LSIncompleteCompletionProposal.java @@ -23,13 +23,7 @@ import com.redhat.devtools.intellij.lsp4ij.LanguageServiceAccessor; import com.redhat.devtools.intellij.lsp4ij.command.internal.CommandExecutor; import org.apache.commons.lang.StringUtils; -import org.eclipse.lsp4j.Command; -import org.eclipse.lsp4j.CompletionItem; -import org.eclipse.lsp4j.InsertReplaceEdit; -import org.eclipse.lsp4j.InsertTextFormat; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.TextEdit; +import org.eclipse.lsp4j.*; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.services.LanguageServer; import org.jetbrains.annotations.NotNull; @@ -40,6 +34,8 @@ import java.util.Collections; import java.util.List; +import static com.redhat.devtools.intellij.lsp4ij.ui.IconMapper.getIcon; + public class LSIncompleteCompletionProposal extends LookupElement { private static final Logger LOGGER = LoggerFactory.getLogger(LSIncompleteCompletionProposal.class); @@ -185,12 +181,15 @@ public String getLookupString() { } private boolean isDeprecated() { - return item.getDeprecated() != null && item.getDeprecated().booleanValue(); + return (item.getTags() != null && item.getTags().contains(CompletionItemTag.Deprecated)) + || (item.getDeprecated() != null && item.getDeprecated().booleanValue()); } @Override public void renderElement(LookupElementPresentation presentation) { presentation.setItemText(item.getLabel()); + presentation.setTypeText(item.getDetail()); + presentation.setIcon(getIcon(item.getKind())); if (isDeprecated()) { presentation.setStrikeout(true); } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapper.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapper.java new file mode 100644 index 000000000..32a1045eb --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapper.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * 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.lsp4ij.ui; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.util.IconLoader; +import org.eclipse.lsp4j.CompletionItemKind; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.Icon; + +/** + * Maps LSP4J kinds to Intellij Icons. See the JetBrains icon list for reference. + */ +public class IconMapper { + + // Copied from IntelliJ icons. To be removed once the minimal supported version of IDEA is > 213 + // See https://github.com/JetBrains/intellij-community/blob/50157fc8eec4af77f67bd468ada4dff39daa1b88/platform/util/ui/src/com/intellij/icons/AllIcons.java#L415 + // Original https://github.com/JetBrains/intellij-community/blob/50157fc8eec4af77f67bd468ada4dff39daa1b88/platform/icons/src/nodes/template.svg + public static final @NotNull Icon Template = load("images/nodes/template.svg"); + + // Copied from IntelliJ icons. To be removed once the minimal supported version of IDEA is > 232 + // See https://github.com/JetBrains/intellij-community/blob/50157fc8eec4af77f67bd468ada4dff39daa1b88/platform/util/ui/src/com/intellij/icons/ExpUiIcons.java#L226 + // Original light https://github.com/JetBrains/intellij-community/blob/50157fc8eec4af77f67bd468ada4dff39daa1b88/platform/icons/src/expui/fileTypes/text.svg + // Original dark https://github.com/JetBrains/intellij-community/blob/50157fc8eec4af77f67bd468ada4dff39daa1b88/platform/icons/src/expui/fileTypes/text_dark.svg + public static final @NotNull Icon Text = load("images/expui/fileTypes/text.svg"); + + + private IconMapper(){ + } + + + /** + * Maps LSP4J {@link CompletionItemKind} to Intellij Icons + */ + public static @Nullable Icon getIcon(@Nullable CompletionItemKind kind) { + if (kind == null) { + return null; + } + + switch (kind) { + case Snippet: + return Template; + case Text: + return Text; + case Constructor: + return AllIcons.Nodes.ClassInitializer; + case Method: + return AllIcons.Nodes.Method; + case Function: + return AllIcons.Nodes.Function; + case EnumMember://No matching icon, IDEA show enum members as fields + case Field: + return AllIcons.Nodes.Field; + case Value: //No matching icon + case Variable: + return AllIcons.Nodes.Variable; + case Class: + return AllIcons.Nodes.Class; + case Interface: + return AllIcons.Nodes.Interface; + case Module: + return AllIcons.Nodes.Module; + case Property: + return AllIcons.Nodes.Property; + case Unit: + return AllIcons.Nodes.Test; + case Enum: + return AllIcons.Nodes.Enum; + case File: + return AllIcons.FileTypes.Any_type; + case Folder: + return AllIcons.Nodes.Folder; + case Constant: + return AllIcons.Nodes.Constant; + case TypeParameter: + return AllIcons.Nodes.Parameter; + //No matching icons, no fallback + case Keyword: + case Struct: + case Event: + case Operator: + case Reference: + case Color: + default: + return AllIcons.Nodes.EmptyNode; + } + } + + private static @NotNull Icon load(String iconPath) { + return IconLoader.getIcon(iconPath, IconMapper.class); + } +} diff --git a/src/main/resources/images/expui/fileTypes/text.svg b/src/main/resources/images/expui/fileTypes/text.svg new file mode 100644 index 000000000..110139cf6 --- /dev/null +++ b/src/main/resources/images/expui/fileTypes/text.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/main/resources/images/expui/fileTypes/text_dark.svg b/src/main/resources/images/expui/fileTypes/text_dark.svg new file mode 100644 index 000000000..86468276b --- /dev/null +++ b/src/main/resources/images/expui/fileTypes/text_dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/main/resources/images/nodes/template.svg b/src/main/resources/images/nodes/template.svg new file mode 100644 index 000000000..6ccbcf156 --- /dev/null +++ b/src/main/resources/images/nodes/template.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapperTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapperTest.java new file mode 100644 index 000000000..d962f854d --- /dev/null +++ b/src/test/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapperTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.lsp4ij.ui; + +import org.eclipse.lsp4j.CompletionItemKind; +import org.junit.Test; + +import static com.redhat.devtools.intellij.lsp4ij.ui.IconMapper.getIcon; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class IconMapperTest { + + @Test + public void getIconTest() { + assertNull(getIcon(null)); + for (CompletionItemKind value : CompletionItemKind.values()) { + assertNotNull(getIcon(value), "Missing matching icon for "+value); + } + } +}