Skip to content

Commit

Permalink
Fixes #2592: Filter code completion proposals from language server (#…
Browse files Browse the repository at this point in the history
…2658)

* Fixes #2592: Filter code completion proposals from language server

Implements filtering based on the existing FuzzyMatches used for the
GoToSymbolAction.

Signed-off-by: Kaloyan Raev <kaloyan.r@zend.com>

* Add empty line at end of file.
  • Loading branch information
kaloyan-raev authored and Vitalii Parfonov committed Oct 6, 2016
1 parent 13a1a52 commit 902912b
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,13 @@ public interface Theme {
*/
String completionPopupItemSubtitleTextColor();

/**
* Item highlight text color for completion popup.
*
* @return color
*/
String completionPopupItemHighlightTextColor();

/**
* Background color of the window widget.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
@eval completionPopupSelectedItemBackgroundColor org.eclipse.che.ide.api.theme.Style.theme.completionPopupSelectedItemBackgroundColor();
@eval completionPopupItemTextColor org.eclipse.che.ide.api.theme.Style.theme.completionPopupItemTextColor();
@eval completionPopupItemSubtitleTextColor org.eclipse.che.ide.api.theme.Style.theme.completionPopupItemSubtitleTextColor();
@eval completionPopupItemHighlightTextColor org.eclipse.che.ide.api.theme.Style.theme.completionPopupItemHighlightTextColor();

@eval editorInfoBorderColor org.eclipse.che.ide.api.theme.Style.getEditorInfoBorderColor();
@eval editorInfoBorderShadowColor org.eclipse.che.ide.api.theme.Style.getEditorInfoBorderShadowColor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,11 @@ public String completionPopupItemSubtitleTextColor() {
return "#727272";
}

@Override
public String completionPopupItemHighlightTextColor() {
return "#4EABFF";
}

@Override
public String getWindowContentBackground() {
return "#292C2F";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,11 @@ public String completionPopupItemSubtitleTextColor() {
return "#909090";
}

@Override
public String completionPopupItemHighlightTextColor() {
return "#1A68AF";
}

@Override
public String getWindowContentBackground() {
return "#ECECEC";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,3 @@

color: completionPopupItemTextColor;
}

.label span {
color: completionPopupItemSubtitleTextColor !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public interface LanguageServerResources extends ClientBundle {

LanguageServerResources INSTANCE = GWT.create(LanguageServerResources.class);

@Source("languageserver.css")
@Source({"languageserver.css", "org/eclipse/che/ide/api/ui/style.css"})
LSCss css();

@Source({"QuickOpenList.css", "org/eclipse/che/ide/ui/constants.css", "org/eclipse/che/ide/api/ui/style.css"})
Expand Down Expand Up @@ -103,6 +103,9 @@ interface LSCss extends CssResource {

@ClassName("codeassistant-detail")
String codeassistantDetail();

@ClassName("codeassistant-highlight")
String codeassistantHighlight();
}

interface QuickOpenListCss extends SimpleList.Css{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

import java.util.List;

import org.eclipse.che.api.languageserver.shared.lsapi.CompletionItemDTO;
import org.eclipse.che.api.languageserver.shared.lsapi.RangeDTO;
import org.eclipse.che.api.languageserver.shared.lsapi.TextDocumentIdentifierDTO;
Expand All @@ -31,31 +33,35 @@
import org.eclipse.che.ide.api.icon.Icon;
import org.eclipse.che.ide.util.loging.Log;
import org.eclipse.che.plugin.languageserver.ide.LanguageServerResources;
import org.eclipse.che.plugin.languageserver.ide.filters.Match;
import org.eclipse.che.plugin.languageserver.ide.service.TextDocumentServiceClient;

/**
* @author Anatolii Bazko
*/
public class CompletionItemBasedCompletionProposal implements CompletionProposal {

private final CompletionItemDTO completionItem;
private final TextDocumentServiceClient documentServiceClient;
private final TextDocumentIdentifierDTO documentId;
private final LanguageServerResources resources;
private final Icon icon;
private final ServerCapabilities serverCapabilities;
private CompletionItemDTO completionItem;
private final List<Match> highlights;

CompletionItemBasedCompletionProposal(CompletionItemDTO completionItem,
TextDocumentServiceClient documentServiceClient,
TextDocumentIdentifierDTO documentId,
LanguageServerResources resources, Icon icon,
ServerCapabilities serverCapabilities) {
ServerCapabilities serverCapabilities,
List<Match> highlights) {
this.completionItem = completionItem;
this.documentServiceClient = documentServiceClient;
this.documentId = documentId;
this.resources = resources;
this.icon = icon;
this.serverCapabilities = serverCapabilities;
this.highlights = highlights;
}

@Override
Expand All @@ -72,14 +78,48 @@ public Widget getAdditionalProposalInfo() {

@Override
public String getDisplayString() {
SafeHtmlBuilder builder = new SafeHtmlBuilder();

String label = completionItem.getLabel();
int pos = 0;
for (Match highlight : highlights) {
if (highlight.getStart() == highlight.getEnd()) {
continue;
}

if (pos < highlight.getStart()) {
appendPlain(builder, label.substring(pos, highlight.getStart()));
}

appendHighlighted(builder, label.substring(highlight.getStart(), highlight.getEnd()));
pos = highlight.getEnd();
}

if (pos < label.length()) {
appendPlain(builder, label.substring(pos));
}

if (completionItem.getDetail() != null) {
SafeHtmlBuilder builder = new SafeHtmlBuilder();
builder.appendEscaped(completionItem.getLabel());
builder.appendHtmlConstant(" <span class=\"" + resources.css().codeassistantDetail() + "\">");
builder.appendEscaped(completionItem.getDetail());
builder.appendHtmlConstant("</span>");
appendDetail(builder, completionItem.getDetail());
}
return completionItem.getLabel();

return builder.toSafeHtml().asString();
}

private void appendPlain(SafeHtmlBuilder builder, String text) {
builder.appendEscaped(text);
}

private void appendHighlighted(SafeHtmlBuilder builder, String text) {
builder.appendHtmlConstant("<span class=\"" + resources.css().codeassistantHighlight() + "\">");
builder.appendEscaped(text);
builder.appendHtmlConstant("</span>");
}

private void appendDetail(SafeHtmlBuilder builder, String text) {
builder.appendHtmlConstant(" <span class=\"" + resources.css().codeassistantDetail() + "\">");
builder.appendEscaped(text);
builder.appendHtmlConstant("</span>");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
import org.eclipse.che.ide.api.editor.codeassist.CompletionProposal;
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
import org.eclipse.che.plugin.languageserver.ide.LanguageServerResources;
import org.eclipse.che.plugin.languageserver.ide.filters.FuzzyMatches;
import org.eclipse.che.plugin.languageserver.ide.filters.Match;
import org.eclipse.che.plugin.languageserver.ide.service.TextDocumentServiceClient;
import org.eclipse.che.plugin.languageserver.ide.util.DtoBuildHelper;

import java.util.ArrayList;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
Expand All @@ -41,40 +44,49 @@ public class LanguageServerCodeAssistProcessor implements CodeAssistProcessor {
private final DtoBuildHelper dtoBuildHelper;
private final LanguageServerResources resources;
private final CompletionImageProvider imageProvider;
private final ServerCapabilities serverCapabilities;
private TextDocumentServiceClient documentServiceClient;
private String lastErrorMessage;
private final ServerCapabilities serverCapabilities;
private final TextDocumentServiceClient documentServiceClient;
private final FuzzyMatches fuzzyMatches;
private String lastErrorMessage;

@Inject
public LanguageServerCodeAssistProcessor(TextDocumentServiceClient documentServiceClient,
DtoBuildHelper dtoBuildHelper,
LanguageServerResources resources,
CompletionImageProvider imageProvider,
@Assisted ServerCapabilities serverCapabilities) {
@Assisted ServerCapabilities serverCapabilities,
FuzzyMatches fuzzyMatches) {
this.documentServiceClient = documentServiceClient;
this.dtoBuildHelper = dtoBuildHelper;
this.resources = resources;
this.imageProvider = imageProvider;
this.serverCapabilities = serverCapabilities;
this.fuzzyMatches = fuzzyMatches;
}

@Override
public void computeCompletionProposals(TextEditor editor, int offset, final CodeAssistCallback callback) {
TextDocumentPositionParamsDTO documentPosition = dtoBuildHelper.createTDPP(editor.getDocument(), offset);
final TextDocumentIdentifierDTO documentId = documentPosition.getTextDocument();
String currentLine = editor.getDocument().getLineContent(documentPosition.getPosition().getLine());
final String currentIdentifier = getCurrentIdentifier(currentLine, documentPosition.getPosition().getCharacter());
this.lastErrorMessage = null;
documentServiceClient.completion(documentPosition).then(new Operation<List<CompletionItemDTO>>() {

@Override
public void apply(List<CompletionItemDTO> items) throws OperationException {
List<CompletionProposal> proposals = newArrayList();
for (CompletionItemDTO item : items) {
proposals.add(new CompletionItemBasedCompletionProposal(item,
documentServiceClient,
documentId,
resources,
imageProvider.getIcon(item.getKind()),
serverCapabilities));
List<Match> highlights = filter(currentIdentifier, item);
if (highlights != null ) {
proposals.add(new CompletionItemBasedCompletionProposal(item,
documentServiceClient,
documentId,
resources,
imageProvider.getIcon(item.getKind()),
serverCapabilities,
highlights));
}
}
callback.proposalComputed(proposals);
}
Expand All @@ -91,4 +103,42 @@ public String getErrorMessage() {
return lastErrorMessage;
}

private String getCurrentIdentifier(String text, int offset) {
int i = offset - 1;
while (i >= 0 && isIdentifierChar(text.charAt(i))) {
i--;
}
return text.substring(i + 1, offset);
}

private boolean isIdentifierChar(char c) {
return c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z' ||
c >= '0' && c <= '9' ||
c >= '\u007f' && c <= '\u00ff' ||
c == '$' ||
c == '_' ||
c == '-';
}

private List<Match> filter(String word, CompletionItemDTO item) {
return filter(word, item.getLabel(), item.getFilterText());
}

private List<Match> filter(String word, String label, String filterText) {
if (filterText == null || filterText.isEmpty()) {
filterText = label;
}

// check if the word matches the filterText
if (fuzzyMatches.fuzzyMatch(word, filterText) != null) {
// return the highlights based on the label
List<Match> highlights = fuzzyMatches.fuzzyMatch(word, label);
// return empty list of highlights if nothing matches the label
return (highlights == null) ? new ArrayList<Match>() : highlights;
}

return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,9 @@
}

.codeassistant-detail {
color: #326EED;
}
color: completionPopupItemSubtitleTextColor;
}

.codeassistant-highlight {
color: completionPopupItemHighlightTextColor;
}

0 comments on commit 902912b

Please sign in to comment.