Skip to content

Commit

Permalink
feat: map LSP4J CompletionItemKinds to Intellij IDEA icons
Browse files Browse the repository at this point in the history
Signed-off-by: Fred Bricon <[email protected]>
  • Loading branch information
fbricon committed Jun 29, 2023
1 parent 15c0a0f commit e988225
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,30 @@
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.util.TextRange;
import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils;
import com.redhat.devtools.intellij.lsp4ij.LanguageServiceAccessor;
import com.redhat.devtools.intellij.lsp4ij.command.internal.CommandExecutor;
import com.redhat.devtools.intellij.lsp4ij.ui.IconMapper;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.util.ArrayList;
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);

Expand Down Expand Up @@ -185,12 +184,14 @@ 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.setIcon(getIcon(item.getKind()));
if (isDeprecated()) {
presentation.setStrikeout(true);
}
Expand Down
105 changes: 105 additions & 0 deletions src/main/java/com/redhat/devtools/intellij/lsp4ij/ui/IconMapper.java
Original file line number Diff line number Diff line change
@@ -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 <a href="https://jetbrains.design/intellij/resources/icons_list/" target="_blank">JetBrains icon list</a> 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);
}
}
7 changes: 7 additions & 0 deletions src/main/resources/images/expui/fileTypes/text.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/main/resources/images/expui/fileTypes/text_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/main/resources/images/nodes/template.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -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 matchng icon for "+value);
}
}
}

0 comments on commit e988225

Please sign in to comment.