GH-1386: labels for bean type proposals show simple class name and fully qualified name in details

This commit is contained in:
Martin Lippert
2024-10-25 12:35:49 +02:00
parent 4aeaf05a4f
commit f81f359cca
5 changed files with 76 additions and 9 deletions

View File

@@ -136,14 +136,14 @@ public class AnnotationAttributeCompletionProcessor implements CompletionProvide
List<AnnotationAttributeProposal> proposals = completionProvider.getCompletionCandidates(project, node);
List<AnnotationAttributeProposal> filteredProposals = proposals.stream()
.filter(proposal -> proposal.getLabel().toLowerCase().contains(filterPrefix.toLowerCase()))
.filter(proposal -> !alreadyMentionedValues.contains(proposal.getLabel()))
.filter(proposal -> proposal.getFilterText().toLowerCase().contains(filterPrefix.toLowerCase()))
.filter(proposal -> !alreadyMentionedValues.contains(proposal.getFilterText()))
.collect(Collectors.toList());
double score = filteredProposals.size();
for (AnnotationAttributeProposal candidate : filteredProposals) {
DocumentEdits edits = new DocumentEdits(doc, false);
edits.replace(startOffset, endOffset, createReplacementText.apply(candidate.getLabel()));
edits.replace(startOffset, endOffset, createReplacementText.apply(candidate.getFilterText()));
AnnotationAttributeCompletionProposal proposal = new AnnotationAttributeCompletionProposal(edits,
candidate, null, score--);

View File

@@ -33,14 +33,15 @@ public class AnnotationAttributeCompletionProposal extends ScoreableProposal {
this.score = score;
}
// public AnnotationAttributeCompletionProposal(DocumentEdits edits, String label, String detail, Renderable documentation, double score) {
// this(edits, new AnnotationAttributeProposal(label, detail), documentation, score);
// }
@Override
public String getLabel() {
return this.coreProposal.getLabel();
}
@Override
public String getFilterText() {
return this.coreProposal.getFilterText();
}
@Override
public CompletionItemKind getKind() {

View File

@@ -10,6 +10,8 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.annotations;
import java.util.Objects;
/**
* @author Martin Lippert
*/
@@ -47,4 +49,22 @@ public class AnnotationAttributeProposal {
return filterText;
}
@Override
public int hashCode() {
return Objects.hash(detail, filterText, label);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AnnotationAttributeProposal other = (AnnotationAttributeProposal) obj;
return Objects.equals(detail, other.detail) && Objects.equals(filterText, other.filterText)
&& Objects.equals(label, other.label);
}
}

View File

@@ -36,9 +36,15 @@ public class BeanTypesCompletionProcessor implements AnnotationAttributeCompleti
public List<AnnotationAttributeProposal> getCompletionCandidates(IJavaProject project, ASTNode node) {
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
return Arrays.stream(beans)
.map(Bean::getType)
.map(bean -> new AnnotationAttributeProposal(getClass(bean.getType()), bean.getType(), bean.getType()))
.distinct()
.map(beanType -> new AnnotationAttributeProposal(beanType))
.collect(Collectors.toList());
}
private String getClass(String type) {
if (type != null && type.lastIndexOf('.') >= 0) {
return type.substring(type.lastIndexOf('.') + 1);
}
return type;
}
}

View File

@@ -102,6 +102,11 @@ public class ConditionalOnBeanCompletionTest {
assertCompletions("@ConditionalOnBean(type=ty<*>)", 2, "@ConditionalOnBean(type=\"org.example.type1\"<*>)");
}
@Test
public void testConditionalOnBeanCompletionWithoutQuotesWithComplexPrefixForTypeAttribute() throws Exception {
assertCompletions("@ConditionalOnBean(type=org.exam<*>)", 2, "@ConditionalOnBean(type=\"org.example.type1\"<*>)");
}
@Test
public void testConditionalOnBeanCompletionWithoutQuotesWithPrefixWithoutMatches() throws Exception {
assertCompletions("@ConditionalOnBean(\"XXX<*>\")", 0, null);
@@ -169,6 +174,20 @@ public class ConditionalOnBeanCompletionTest {
assertCompletions("@ConditionalOnBean(name={\"bean1\",<*>\"bean2\"})", 1, "@ConditionalOnBean(name={\"bean1\",\"bean3\",<*>\"bean2\"})");
}
@Test
public void testConditionalOnBeanTypeCompletions() throws Exception {
List<CompletionItem> completions = getCompletions("@ConditionalOnBean(type=<*>)");
assertEquals(2, completions.size());
CompletionItem completionItem = completions.get(0);
completionItem = harness.resolveCompletionItem(completionItem);
assertEquals("type1", completionItem.getLabel());
assertEquals("org.example.type1", completionItem.getDetail());
assertEquals("org.example.type1", completionItem.getFilterText());
}
private void assertCompletions(String completionLine, int noOfExpectedCompletions, String expectedCompletedLine) throws Exception {
String editorContent = """
@@ -215,4 +234,25 @@ public class ConditionalOnBeanCompletionTest {
}
}
private List<CompletionItem> getCompletions(String completionLine) throws Exception {
String editorContent = """
package org.test;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestConditionalOnBeanCompletion {
""" +
completionLine + "\n" +
"""
@Bean
public void method() {
}
""";
Editor editor = harness.newEditor(LanguageId.JAVA, editorContent, tempJavaDocUri);
return editor.getCompletions();
}
}