Bean completion account for FieldAccess invocation node

This commit is contained in:
aboyko
2025-02-27 10:34:26 -05:00
parent 51b3a06a48
commit 1630eb1f16
2 changed files with 139 additions and 9 deletions

View File

@@ -64,7 +64,7 @@ public class BeanCompletionProvider implements CompletionProvider {
@Override
public void provideCompletions(ASTNode node, int offset, TextDocument doc,
Collection<ICompletionProposal> completions) {
if (node instanceof SimpleName || node instanceof Block) {
if (node instanceof SimpleName || node instanceof Block || node instanceof FieldAccess) {
try {
// Don't look at anything inside Annotation or VariableDelcaration node
for (ASTNode n = node; n != null; n = n.getParent()) {
@@ -85,14 +85,25 @@ public class BeanCompletionProvider implements CompletionProvider {
return;
}
// Empty SimpleName usually comes from unresolved FieldAccess, i.e. `this.owner` where `owner` field is not defined
if (node instanceof SimpleName se && se.getLength() == 0
&& node.getParent() instanceof Assignment assign
&& assign.getLeftHandSide() instanceof FieldAccess fa
&& fa.getExpression() instanceof ThisExpression) {
node = fa.getName();
}
String prefix = "";
// Empty SimpleName usually comes from unresolved FieldAccess, i.e. `this.owner` where `owner` field is not defined
if (node instanceof SimpleName sn) {
if (sn.getLength() == 0
&& sn.getParent() instanceof Assignment assign
&& assign.getLeftHandSide() instanceof FieldAccess fa
&& fa.getExpression() instanceof ThisExpression) {
prefix = fa.getName().toString();
} else {
prefix = sn.toString();
}
} else if (node instanceof FieldAccess fa && fa.getExpression() instanceof ThisExpression) {
int start = fa.getExpression().getStartPosition() + fa.getExpression().getLength();
while (start < doc.getLength() && doc.getChar(start) != '.') {
start++;
}
prefix = doc.get(start + 1, offset - start - 1);
}
if (AnnotationHierarchies.get(node).isAnnotatedWith(topLevelClass.resolveBinding(), Annotations.COMPONENT)) {
String className = getFullyQualifiedName(topLevelClass);
@@ -103,7 +114,6 @@ public class BeanCompletionProvider implements CompletionProvider {
.filter(Objects::nonNull)
.map(t -> t.getQualifiedName())
.collect(Collectors.toSet());
final String prefix = node instanceof Block ? "" : node.toString();
for (Bean bean : beans) {
// If current class is a bean - ignore it
if (className.equals(bean.getType())) {

View File

@@ -558,6 +558,126 @@ public class TestBeanCompletionClass {
""");
}
@Test
public void beforeStatement() throws Exception {
String content = """
package org.sample.test;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestBeanCompletionClass {
public void test() {
owner<*>
System.out.println();
}
}
""";
assertCompletions(content, new String[] {"ownerRepository", "ownerService"}, 0,
"""
package org.sample.test;
import org.springframework.samples.petclinic.owner.OwnerRepository;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestBeanCompletionClass {
private final OwnerRepository ownerRepository;
TestBeanCompletionClass(OwnerRepository ownerRepository) {
this.ownerRepository = ownerRepository;
}
public void test() {
ownerRepository<*>
System.out.println();
}
}
""");
}
@Test
public void beforeStatementStartingWithThis() throws Exception {
String content = """
package org.sample.test;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestBeanCompletionClass {
public void test() {
this.<*>
System.out.println();
}
}
""";
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
"""
package org.sample.test;
import org.springframework.samples.petclinic.owner.OwnerRepository;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestBeanCompletionClass {
private final OwnerRepository ownerRepository;
TestBeanCompletionClass(OwnerRepository ownerRepository) {
this.ownerRepository = ownerRepository;
}
public void test() {
this.ownerRepository<*>
System.out.println();
}
}
""");
}
@Test
public void beforeStatementStartingWithThisAndPrefix() throws Exception {
String content = """
package org.sample.test;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestBeanCompletionClass {
public void test() {
this.ow<*>
System.out.println();
}
}
""";
assertCompletions(content, new String[] {"ownerRepository", "ownerService"}, 0,
"""
package org.sample.test;
import org.springframework.samples.petclinic.owner.OwnerRepository;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestBeanCompletionClass {
private final OwnerRepository ownerRepository;
TestBeanCompletionClass(OwnerRepository ownerRepository) {
this.ownerRepository = ownerRepository;
}
public void test() {
this.ownerRepository<*>
System.out.println();
}
}
""");
}
private void assertCompletions(String completionLine, String[] expectedCompletions, int chosenCompletion, String expectedResult) throws Exception {
assertCompletions(completionLine, expectedCompletions.length, expectedCompletions, chosenCompletion, expectedResult);
}