Skip to content

Commit

Permalink
Bean completion account for FieldAccess invocation node
Browse files Browse the repository at this point in the history
  • Loading branch information
BoykoAlex committed Feb 27, 2025
1 parent 51b3a06 commit 1630eb1
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public BeanCompletionProvider(JavaProjectFinder javaProjectFinder, SpringMetamod
@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()) {
Expand All @@ -85,15 +85,26 @@ public void provideCompletions(ASTNode node, int offset, TextDocument doc,
return;
}

String prefix = "";

// 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();
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);
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
Expand All @@ -103,7 +114,6 @@ public void provideCompletions(ASTNode node, int offset, TextDocument doc,
.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())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,126 @@ public void test() {
""");
}

@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);
}
Expand Down

0 comments on commit 1630eb1

Please sign in to comment.