Completions order for non-java context. Bean completions score.

This commit is contained in:
aboyko
2025-03-14 16:06:42 -04:00
parent e906ad9991
commit ad0c208ea1
11 changed files with 64 additions and 46 deletions

View File

@@ -16,6 +16,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.languageserver.util.LanguageSpecific;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -78,5 +79,19 @@ public class CompositeCompletionEngine implements ICompletionEngine {
return new InternalCompletionList(completions.build(), isIncomplete);
}
};
@Override
public boolean keepCompletionsOrder(IDocument doc) {
Collection<ICompletionEngine> engines = subEngines.get(doc.getLanguageId());
if (engines != null) {
for (ICompletionEngine e : engines) {
if (e.keepCompletionsOrder(doc)) {
return true;
}
}
}
return false;
}
}

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.completion;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
@@ -19,4 +20,6 @@ public interface ICompletionEngine {
InternalCompletionList getCompletions(TextDocument document, int offset) throws Exception;
default boolean keepCompletionsOrder(IDocument doc) { return false; };
}

View File

@@ -225,7 +225,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
boolean isIncomplete = rawCompletionList.isIncomplete();
List<CompletionItem> items = new ArrayList<>(completions.size());
SortKeys sortkeys = new SortKeys();
Optional<SortKeys> sortkeysOpt = engine.keepCompletionsOrder(doc) ? Optional.of(new SortKeys()) : Optional.empty();
int count = 0;
for (ICompletionProposal c : completions) {
@@ -237,7 +237,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
break;
}
try {
items.add(adaptItem(doc, c, sortkeys));
items.add(adaptItem(doc, c, sortkeysOpt));
} catch (Exception e) {
log.error("error computing completion", e);
}
@@ -274,11 +274,11 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
return SimpleTextDocumentService.NO_COMPLETIONS;
}
private CompletionItem adaptItem(TextDocument doc, ICompletionProposal completion, SortKeys sortkeys) throws Exception {
private CompletionItem adaptItem(TextDocument doc, ICompletionProposal completion, Optional<SortKeys> sortkeysOpt) throws Exception {
CompletionItem item = new CompletionItem();
item.setLabel(completion.getLabel());
item.setKind(completion.getKind());
item.setSortText(sortkeys.next());
sortkeysOpt.ifPresent(sortkeys -> item.setSortText(sortkeys.next()));
item.setFilterText(completion.getFilterText());
item.setInsertTextMode(InsertTextMode.AsIs);
item.setLabelDetails(completion.getLabelDetails());

View File

@@ -113,7 +113,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
@Override
public CompletionItemKind getKind() {
return CompletionItemKind.Keyword;
return CompletionItemKind.Value;
}
@Override

View File

@@ -480,4 +480,10 @@ public class YamlCompletionEngine implements ICompletionEngine {
throw new IllegalStateException("Missing case");
}
}
@Override
public boolean keepCompletionsOrder(IDocument doc) {
return true;
}
}

View File

@@ -585,21 +585,6 @@ public class Editor {
public List<CompletionItem> getCompletions() throws Exception {
CompletionList cl = harness.getCompletions(this.doc, this.getCursor());
ArrayList<CompletionItem> items = new ArrayList<>(cl.getItems());
Collections.sort(items, new Comparator<CompletionItem>() {
@Override
public int compare(CompletionItem o1, CompletionItem o2) {
return sortKey(o1).compareTo(sortKey(o2));
}
private String sortKey(CompletionItem item) {
String k = item.getSortText();
if (k == null) {
k = item.getLabel();
}
return k;
}
});
return items;
}

View File

@@ -14,6 +14,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.text.similarity.JaroWinklerSimilarity;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
@@ -36,7 +37,6 @@ import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
import org.springframework.ide.vscode.commons.rewrite.java.InjectBeanCompletionRecipe;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -76,7 +76,7 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
this.rewriteRefactorings = rewriteRefactorings;
this.prefix = computePrefix();
this.edits = computeEdit();
this.score = FuzzyMatcher.matchScore(prefix, beanId);
this.score = /*FuzzyMatcher.matchScore*/computeJaroWinklerScore(prefix, beanId);
}
@Override
@@ -88,6 +88,10 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
public CompletionItemKind getKind() {
return CompletionItemKind.Field;
}
private static double computeJaroWinklerScore(CharSequence pattern, CharSequence data) {
return pattern.isEmpty() ? 1 / (double) Integer.MAX_VALUE : new JaroWinklerSimilarity().apply(pattern, data);
}
private String computePrefix() {
String prefix = "";

View File

@@ -33,7 +33,7 @@ public class DataRepositoryQueryStartCompletionProvider implements DataRepositor
for(QueryMethodSubject queryMethodSubject : QueryMethodSubject.QUERY_METHOD_SUBJECTS){
String toInsert = queryMethodSubject.key() + "By";
if(prefix == null || (toInsert.length() > localPrefix.length() && toInsert.startsWith(localPrefix)) || isOffsetAfterWhitespace(doc, offset)) {
completions.add(FindByCompletionProposal.createProposal(offset, CompletionItemKind.Text, prefix, toInsert, toInsert, true, null));
completions.add(FindByCompletionProposal.createProposal(offset, CompletionItemKind.Method, prefix, toInsert, toInsert, true, null));
}
}
}

View File

@@ -114,7 +114,7 @@ public class DataRepositoryPrefixSensitiveCompletionProvider implements DataRepo
if (toReplace.startsWith(lastWord)) {
DocumentEdits edits = new DocumentEdits(null, false);
edits.replace(offset - lastWord.length(), offset, toReplace);
ICompletionProposal proposal = new FindByCompletionProposal(toReplace, CompletionItemKind.Text, edits, "property " + toReplace, null, null, lastWord, true);
ICompletionProposal proposal = new FindByCompletionProposal(toReplace, CompletionItemKind.Property, edits, "property " + toReplace, null, null, lastWord, true);
completions.add(proposal);
}
}

View File

@@ -24,6 +24,7 @@ import org.springframework.ide.vscode.commons.languageserver.completion.Internal
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.LanguageSpecific;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -79,4 +80,9 @@ public class SpringPropertiesCompletionEngine implements ICompletionEngine, Lang
return ImmutableList.of(LanguageId.BOOT_PROPERTIES);
}
@Override
public boolean keepCompletionsOrder(IDocument doc) {
return true;
}
}

View File

@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.boot.java.beans.test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.List;
@@ -107,7 +108,7 @@ public class BeanCompletionProviderTest {
@Test
public void testBeanCompletion_firstCompletion() throws Exception {
assertCompletions(getCompletion("owner<*>"), new String[] {"ownerRepository", "ownerService"}, 0,
assertCompletions(getCompletion("ownerRe<*>"), new String[] {"ownerRepository", "ownerService"}, 0,
"""
package org.sample.test;
@@ -132,7 +133,7 @@ ownerRepository<*>
@Test
public void testBeanCompletion_secondCompletion() throws Exception {
assertCompletions(getCompletion("owner<*>"), new String[] {"ownerRepository", "ownerService"}, 1,
assertCompletions(getCompletion("ownerRe<*>"), new String[] {"ownerRepository", "ownerService"}, 1,
"""
package org.sample.test;
@@ -229,7 +230,7 @@ petService<*>
public class TestBeanCompletionSecondClass {
public void test() {
owner<*>
ownerRe<*>
}
}
""";
@@ -379,7 +380,7 @@ public class TestBeanCompletionClass {
public class Inner {
public void test() {
owner<*>
ownerRe<*>
}
}
}
@@ -446,7 +447,7 @@ public class TestBeanCompletionClass {
}
public void test() {
owner<*>
ownerRe<*>
}
}
@@ -500,7 +501,7 @@ public class TestBeanCompletionClass {
@Controller
public class TestBeanCompletionClass {
public void test() {
this.owner<*>
this.ownerRe<*>
}
}
""";
@@ -618,7 +619,7 @@ public class TestBeanCompletionClass {
@RestController
public class TestBeanCompletionClass {
public void test() {
owner<*>
ownerRe<*>
}
}
""";
@@ -656,7 +657,7 @@ public class TestBeanCompletionClass {
@RestController
public class TestBeanCompletionClass {
public void test() {
owner<*>
ownerRe<*>
System.out.println();
}
}
@@ -738,7 +739,7 @@ public class TestBeanCompletionClass {
String ownerRepository;
public TestBeanCompletionClass(String ownerRepository) {
this.ownerRepository = ownerRepository;
ow<*>
ownerRe<*>
}
}
""";
@@ -775,7 +776,7 @@ public class TestBeanCompletionClass {
public class TestBeanCompletionClass {
String ownerRepository;
public void test() {
ow<*>
ownerRe<*>
}
}
""";
@@ -814,7 +815,7 @@ public class TestBeanCompletionClass {
@RestController
public class TestBeanCompletionClass {
public void test() {
this.ow<*>
this.ownerRe<*>
System.out.println();
}
}
@@ -855,7 +856,7 @@ public class TestBeanCompletionClass {
public class TestBeanCompletionClass {
public TestBeanCompletionClass() {
super();
this.ow<*>
this.ownerRe<*>
}
}
""";
@@ -891,7 +892,7 @@ public class TestBeanCompletionClass {
public class TestBeanCompletionClass {
public TestBeanCompletionClass() {
super();
this.ow<*>
this.ownerRe<*>
System.out.println();
}
}
@@ -929,7 +930,7 @@ public class TestBeanCompletionClass {
public class TestBeanCompletionClass {
public TestBeanCompletionClass() {
super();
ow<*>
ownerRe<*>
}
}
""";
@@ -965,7 +966,7 @@ public class TestBeanCompletionClass {
public class TestBeanCompletionClass {
public TestBeanCompletionClass() {
super();
ow<*>
ownerRe<*>
System.out.println();
}
}
@@ -1177,24 +1178,22 @@ public class TestBeanCompletionClass {
}
private void assertCompletions(String completionLine, String[] expectedCompletions, int chosenCompletion, String expectedResult) throws Exception {
assertCompletions(completionLine, expectedCompletions.length, expectedCompletions, chosenCompletion, expectedResult);
}
private void assertCompletions(String editorContent, int noOfExcpectedCompletions, String[] expectedCompletions, int chosenCompletion, String expectedResult) throws Exception {
Editor editor = harness.newEditor(LanguageId.JAVA, editorContent, tempJavaDocUri);
Editor editor = harness.newEditor(LanguageId.JAVA, completionLine, tempJavaDocUri);
List<CompletionItem> completions = editor.getCompletions();
assertEquals(noOfExcpectedCompletions, completions.size());
// assertEquals(noOfExcpectedCompletions, completions.size());
assertTrue(expectedCompletions.length <= completions.size());
if (expectedCompletions != null) {
String[] completionItems = completions.stream()
.map(item -> item.getLabel())
.limit(expectedCompletions.length)
.toArray(size -> new String[size]);
assertArrayEquals(expectedCompletions, completionItems);
}
if (noOfExcpectedCompletions > 0) {
if (expectedCompletions.length > 0) {
editor.apply(completions.get(chosenCompletion));
assertEquals(expectedResult, editor.getText());
}