Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix missing completion items for fully qualified name completion #2736

Merged
merged 3 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,34 +164,7 @@ public void updateReplacement(CompletionProposal proposal, CompletionItem item,

setInsertReplaceRange(proposal, insertReplaceEdit);

if (preferences.isCompletionLazyResolveTextEditEnabled() && !isResolvingRequest) {
if (completionBuffer.isEmpty()) {
completionBuffer.append(getDefaultTextEditText(item));
}
} else {
switch (proposal.getKind()) {
case CompletionProposal.METHOD_DECLARATION:
appendMethodOverrideReplacement(completionBuffer, proposal);
break;
case CompletionProposal.POTENTIAL_METHOD_DECLARATION:
if (proposal instanceof GetterSetterCompletionProposal getterSetterProposal) {
appendMethodPotentialReplacement(completionBuffer, getterSetterProposal);
} else {
appendReplacementString(completionBuffer, proposal);
}
break;
case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION:
case CompletionProposal.ANONYMOUS_CLASS_DECLARATION:
appendAnonymousClass(completionBuffer, proposal, insertReplaceEdit);
break;
case CompletionProposal.LAMBDA_EXPRESSION:
appendLambdaExpressionReplacement(completionBuffer, proposal);
break;
default:
appendReplacementString(completionBuffer, proposal);
break;
}
}
String text = getTextEditText(proposal, item, completionBuffer, insertReplaceEdit);

//select insertTextFormat.
if (client.isCompletionSnippetsSupported()) {
Expand All @@ -203,7 +176,7 @@ public void updateReplacement(CompletionProposal proposal, CompletionItem item,
&& JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().getCompletionItemInsertTextModeDefault() != InsertTextMode.AdjustIndentation)) {
item.setInsertTextMode(InsertTextMode.AdjustIndentation);
}
String text = completionBuffer.toString();

if (insertReplaceEdit.getReplace() == null || insertReplaceEdit.getInsert() == null) {
// fallback
item.setInsertText(text);
Expand All @@ -228,6 +201,57 @@ public void updateReplacement(CompletionProposal proposal, CompletionItem item,
}
}

/**
* Get the content of the text edit.
*/
private String getTextEditText(CompletionProposal proposal, CompletionItem item, StringBuilder completionBuffer, InsertReplaceEdit insertReplaceEdit) {
if (preferences.isCompletionLazyResolveTextEditEnabled() && !isResolvingRequest) {
if (!completionBuffer.isEmpty()) {
return completionBuffer.toString();
}

String defaultText = getDefaultTextEditText(item);
int start = proposal.getReplaceStart();
int end = proposal.getReplaceEnd();
String toReplace;
try {
toReplace = compilationUnit.getBuffer().getText(start, end - start);
// in lazy resolve mode, early return when the text edit content starts
// with the replaced content. Otherwise, the filter text will mismatch the
// replaced content, causing the item disappear at client.
if (defaultText.startsWith(toReplace)) {
return defaultText;
}
} catch (IndexOutOfBoundsException | JavaModelException e) {
JavaLanguageServerPlugin.logException(e);
}
}

switch (proposal.getKind()) {
case CompletionProposal.METHOD_DECLARATION:
appendMethodOverrideReplacement(completionBuffer, proposal);
break;
case CompletionProposal.POTENTIAL_METHOD_DECLARATION:
if (proposal instanceof GetterSetterCompletionProposal getterSetterProposal) {
appendMethodPotentialReplacement(completionBuffer, getterSetterProposal);
} else {
appendReplacementString(completionBuffer, proposal);
}
break;
case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION:
case CompletionProposal.ANONYMOUS_CLASS_DECLARATION:
appendAnonymousClass(completionBuffer, proposal, insertReplaceEdit);
break;
case CompletionProposal.LAMBDA_EXPRESSION:
appendLambdaExpressionReplacement(completionBuffer, proposal);
break;
default:
appendReplacementString(completionBuffer, proposal);
break;
}
return completionBuffer.toString();
}

/**
* Return a default text edit text (more like a placeholder). And let it
* be corrected in completionItem/resolve request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ public CompletionItem toCompletionItem(CompletionProposal proposal, int index) {
if ($.getTextEdit() != null) {
String newText = $.getTextEdit().isLeft() ? $.getTextEdit().getLeft().getNewText() : $.getTextEdit().getRight().getNewText();
Range range = $.getTextEdit().isLeft() ? $.getTextEdit().getLeft().getRange() : ($.getTextEdit().getRight().getInsert() != null ? $.getTextEdit().getRight().getInsert() : $.getTextEdit().getRight().getReplace());
if (proposal.getKind() == CompletionProposal.TYPE_REF && range != null && newText != null) {
if (range != null && newText != null) {
$.setFilterText(newText);
}
// See https://github.com/eclipse/eclipse.jdt.ls/issues/2387
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.InsertTextFormat;
import org.eclipse.lsp4j.InsertTextMode;
import org.eclipse.lsp4j.Range;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -78,6 +79,51 @@ public void tearDown() throws Exception {
javaClient.disconnect();
}

@Test
public void testFullyQualifiedTypeCompletion1() throws JavaModelException {
ICompilationUnit unit = getWorkingCopy(
"src/org/sample/Test.java",
"""
package org.sample;
public class Test {
java.util.List
}
"""
);

CompletionList list = requestCompletions(unit, "java.util.List");
assertNotNull(list);
CompletionItem item = list.getItems().get(0);
String filterText = item.getFilterText();
Range range = item.getTextEdit().getLeft().getRange();
int start = JsonRpcHelpers.toOffset(unit.getBuffer(), range.getStart().getLine(), range.getStart().getCharacter());
int end = JsonRpcHelpers.toOffset(unit.getBuffer(), range.getEnd().getLine(), range.getEnd().getCharacter());
String replacedContent = unit.getBuffer().getText(start, end - start);
assertTrue(filterText.startsWith(replacedContent));
}

@Test
public void testFullyQualifiedTypeCompletion2() throws JavaModelException {
ICompilationUnit unit = getWorkingCopy(
"src/org/sample/Test.java",
"""
package org.sample;
import java.util.List
public class Test {}
"""
);

CompletionList list = requestCompletions(unit, "import java.util.List");
assertNotNull(list);
CompletionItem item = list.getItems().get(0);
String filterText = item.getFilterText();
Range range = item.getTextEdit().getLeft().getRange();
int start = JsonRpcHelpers.toOffset(unit.getBuffer(), range.getStart().getLine(), range.getStart().getCharacter());
int end = JsonRpcHelpers.toOffset(unit.getBuffer(), range.getEnd().getLine(), range.getEnd().getCharacter());
String replacedContent = unit.getBuffer().getText(start, end - start);
assertTrue(filterText.startsWith(replacedContent));
}

@Test
public void testSnippet_sysout() throws JavaModelException {
when(preferenceManager.getClientPreferences().getCompletionItemInsertTextModeDefault()).thenReturn(InsertTextMode.AdjustIndentation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3480,7 +3480,7 @@ public void testCompletion_QualifiedName2() throws Exception {
//@formatter:on
CompletionList list = requestCompletions(unit, "ArrayL");
assertFalse(list.getItems().isEmpty());
assertEquals("java.util.ArrayList()", list.getItems().get(0).getFilterText());
assertTrue(list.getItems().get(0).getFilterText().startsWith("java.util.ArrayList"));
}

@Test
Expand Down