Skip to content

Commit

Permalink
Introduce completion item collapse for method overloads
Browse files Browse the repository at this point in the history
Signed-off-by: Hope Hadfield <[email protected]>
  • Loading branch information
hopehadfield committed Feb 9, 2024
1 parent 975e1c3 commit 50841f1
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -57,6 +56,7 @@
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemDefaults;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.CompletionItemLabelDetails;
import org.eclipse.lsp4j.CompletionItemTag;
import org.eclipse.lsp4j.InsertReplaceRange;
import org.eclipse.lsp4j.InsertTextMode;
Expand All @@ -69,7 +69,7 @@ public final class CompletionProposalRequestor extends CompletionRequestor {

private List<CompletionProposal> proposals = new ArrayList<>();
// Cache to store all the types that has been collapsed, due to off mode of argument guessing.
private Set<String> collapsedTypes = new HashSet<>();
private Map<String, Integer> collapsedTypes = new HashMap<>();
private final ICompilationUnit unit;
private final String uri; // URI of this.unit, used in future "resolve" requests
private CompletionProposalDescriptionProvider descriptionProvider;
Expand Down Expand Up @@ -430,6 +430,19 @@ public CompletionItem toCompletionItem(CompletionProposal proposal, int index) {
} else if (labelDetailsEnabled && $.getKind() == CompletionItemKind.Constructor && $.getLabelDetails() != null && $.getLabelDetails().getDetail() != null) {
filterText = newText.concat($.getLabelDetails().getDetail());
}
if (proposal.getKind() == CompletionProposal.METHOD_REF
&& collapsedTypes.containsKey(String.valueOf(proposal.getName())) && collapsedTypes.get(String.valueOf(proposal.getName())) > 1) {
if (labelDetailsEnabled) {
CompletionItemLabelDetails newLabelDetails = new CompletionItemLabelDetails();
newLabelDetails.setDetail("(...)");
newLabelDetails.setDescription(collapsedTypes.get(String.valueOf(proposal.getName())).toString() + " overloads");
$.setLabelDetails(newLabelDetails);
$.setDetail(null);
} else {
$.setLabel(String.valueOf(proposal.getName()) + "(...)");
$.setDetail(collapsedTypes.get(String.valueOf(proposal.getName())).toString() + " overloads");
}
}
if (range != null && !filterText.isEmpty()) {
$.setFilterText(filterText);
} else if (range != null && newText != null) {
Expand Down Expand Up @@ -739,15 +752,20 @@ private boolean matchCase(CompletionProposal proposal) {
* Check if the current completion proposal needs to be collapsed.
*/
private boolean needToCollapse(CompletionProposal proposal) {
if (preferenceManager.getPreferences().getGuessMethodArgumentsMode() != CompletionGuessMethodArgumentsMode.OFF) {
if (preferenceManager.getPreferences().isCollapseCompletionItemsEnabled() == false || preferenceManager.getPreferences().getGuessMethodArgumentsMode() != CompletionGuessMethodArgumentsMode.OFF) {
return false;
}


CompletionProposal requiredProposal = CompletionProposalUtils.getRequiredTypeProposal(proposal);
if (proposal.getKind() == CompletionProposal.METHOD_REF) {
return collapsedTypes.merge(String.valueOf(proposal.getName()), 1, Integer::sum) > 1;
}

if (requiredProposal == null) {
return false;
}

return !collapsedTypes.add(String.valueOf(requiredProposal.getSignature()));
return collapsedTypes.merge(String.valueOf(requiredProposal.getSignature()), 1, Integer::sum) > 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,8 @@ public class Preferences {
*/
public static final String JAVA_COMPLETION_GUESS_METHOD_ARGUMENTS_KEY = "java.completion.guessMethodArguments";

public static final String JAVA_COMPLETION_COLLAPSE_KEY = "java.completion.collapseCompletionItems";

/**
* A named preference that defines how member elements are ordered by code
* actions.
Expand Down Expand Up @@ -621,6 +623,7 @@ public class Preferences {
private boolean foldingRangeEnabled;
private boolean selectionRangeEnabled;
private CompletionGuessMethodArgumentsMode guessMethodArguments;
private boolean collapseCompletionItems;

private boolean javaFormatComments;
private boolean hashCodeEqualsTemplateUseJava7Objects;
Expand Down Expand Up @@ -877,6 +880,7 @@ public Preferences() {
foldingRangeEnabled = true;
selectionRangeEnabled = true;
guessMethodArguments = CompletionGuessMethodArgumentsMode.INSERT_PARAMETER_NAMES;
collapseCompletionItems = false;
javaFormatComments = true;
hashCodeEqualsTemplateUseJava7Objects = false;
hashCodeEqualsTemplateUseInstanceof = false;
Expand Down Expand Up @@ -1080,6 +1084,9 @@ public static Preferences createFrom(Map<String, Object> configuration) {
CompletionGuessMethodArgumentsMode.INSERT_PARAMETER_NAMES));
}

boolean collapseCompletionItemsEnabled = getBoolean(configuration, JAVA_COMPLETION_COLLAPSE_KEY, false);
prefs.setCollapseCompletionItemsEnabled(collapseCompletionItemsEnabled);

boolean hashCodeEqualsTemplateUseJava7Objects = getBoolean(configuration, JAVA_CODEGENERATION_HASHCODEEQUALS_USEJAVA7OBJECTS, false);
prefs.setHashCodeEqualsTemplateUseJava7Objects(hashCodeEqualsTemplateUseJava7Objects);
boolean hashCodeEqualsTemplateUseInstanceof = getBoolean(configuration, JAVA_CODEGENERATION_HASHCODEEQUALS_USEINSTANCEOF, false);
Expand Down Expand Up @@ -1544,6 +1551,11 @@ public Preferences setGuessMethodArgumentsMode(CompletionGuessMethodArgumentsMod
return this;
}

public Preferences setCollapseCompletionItemsEnabled(boolean enabled) {
this.collapseCompletionItems = enabled;
return this;
}

public Preferences setJavaFormatEnabled(boolean enabled) {
this.javaFormatEnabled = enabled;
return this;
Expand Down Expand Up @@ -1864,6 +1876,10 @@ public CompletionGuessMethodArgumentsMode getGuessMethodArgumentsMode() {
return guessMethodArguments;
}

public boolean isCollapseCompletionItemsEnabled() {
return collapseCompletionItems;
}

public boolean isHashCodeEqualsTemplateUseJava7Objects() {
return hashCodeEqualsTemplateUseJava7Objects;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4087,6 +4087,55 @@ public void testCompletion_order() throws Exception {
assertTrue(list.getItems().get(2).getFilterText().startsWith("test(String x, int y, boolean z)"));
}

@Test
public void testCompletion_collapse() throws Exception {
when(preferenceManager.getClientPreferences().isCompletionItemLabelDetailsSupport()).thenReturn(true);
preferenceManager.getPreferences().setCollapseCompletionItemsEnabled(true);
preferenceManager.getPreferences().setGuessMethodArgumentsMode(CompletionGuessMethodArgumentsMode.OFF);
ICompilationUnit unit = getWorkingCopy("src/org/sample/Test.java", String.join("\n",
//@formatter:off
"package org.sample",
"public class Test {",
" public void test(String x){}",
" public void test(String x, int y){}",
" public void test(String x, int y, boolean z){}",
" public static void main(String[] args) {",
" Test obj = new Test();",
" obj.test",
" }",
"}"));
//@formatter:on
CompletionList list = requestCompletions(unit, "obj.test");
assertFalse(list.getItems().isEmpty());
assertTrue(list.getItems().get(0).getLabelDetails().getDetail().startsWith("(...)"));
assertTrue(list.getItems().get(0).getLabelDetails().getDescription().startsWith("3 overloads"));
}

@Test
public void testCompletion_collapse_extends() throws Exception {
when(preferenceManager.getClientPreferences().isCompletionItemLabelDetailsSupport()).thenReturn(true);
preferenceManager.getPreferences().setCollapseCompletionItemsEnabled(true);
preferenceManager.getPreferences().setGuessMethodArgumentsMode(CompletionGuessMethodArgumentsMode.OFF);
ICompilationUnit unit = getWorkingCopy("src/org/sample/Test.java", String.join("\n",
//@formatter:off
"package org.sample",
"class Test extends TestSuper {",
" public void test(String x){}",
" public static void main(String[] args) {",
" Test obj = new Test();",
" obj.test",
" }",
"}",
"public class TestSuper {",
" public void test(String x, int y){}",
"}"));
//@formatter:on
CompletionList list = requestCompletions(unit, "obj.test");
assertFalse(list.getItems().isEmpty());
assertTrue(list.getItems().get(0).getLabelDetails().getDetail().startsWith("(...)"));
assertTrue(list.getItems().get(0).getLabelDetails().getDescription().startsWith("2 overloads"));
}

private CompletionList requestCompletions(ICompilationUnit unit, String completeBehind) throws JavaModelException {
return requestCompletions(unit, completeBehind, 0);
}
Expand Down

0 comments on commit 50841f1

Please sign in to comment.