Skip to content

Commit b0d42d1

Browse files
committed
Bean completion case of the same name field
1 parent d595f03 commit b0d42d1

File tree

3 files changed

+102
-18
lines changed

3 files changed

+102
-18
lines changed

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeanCompletionProposal.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
5454
private IDocument doc;
5555
private String beanId;
5656
private String beanType;
57+
private String fieldName;
5758
private String className;
5859
private RewriteRefactorings rewriteRefactorings;
5960
private double score;
@@ -64,12 +65,13 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
6465
private DocumentEdits edits;
6566

6667
public BeanCompletionProposal(ASTNode node, int offset, IDocument doc, String beanId, String beanType,
67-
String className, RewriteRefactorings rewriteRefactorings) {
68+
String fieldName, String className, RewriteRefactorings rewriteRefactorings) {
6869
this.node = node;
6970
this.offset = offset;
7071
this.doc = doc;
7172
this.beanId = beanId;
7273
this.beanType = beanType;
74+
this.fieldName = fieldName;
7375
this.className = className;
7476
this.rewriteRefactorings = rewriteRefactorings;
7577
this.prefix = computePrefix();
@@ -130,19 +132,19 @@ private DocumentEdits computeEdit() {
130132
DocumentEdits edits = new DocumentEdits(doc, false);
131133
if (isInsideConstructor(node)) {
132134
if (node instanceof Block) {
133-
edits.insert(offset, "this.%s = %s;".formatted(beanId, beanId));
135+
edits.insert(offset, "this.%s = %s;".formatted(fieldName, fieldName));
134136
} else {
135137
if (node.getParent() instanceof Assignment || node.getParent() instanceof FieldAccess) {
136-
edits.replace(offset - prefix.length(), offset, "%s = %s;".formatted(beanId, beanId));
138+
edits.replace(offset - prefix.length(), offset, "%s = %s;".formatted(fieldName, fieldName));
137139
} else {
138-
edits.replace(offset - prefix.length(), offset, "this.%s = %s;".formatted(beanId, beanId));
140+
edits.replace(offset - prefix.length(), offset, "this.%s = %s;".formatted(fieldName, fieldName));
139141
}
140142
}
141143
} else {
142144
if (node instanceof Block) {
143-
edits.insert(offset, beanId);
145+
edits.insert(offset, fieldName);
144146
} else {
145-
edits.replace(offset - prefix.length(), offset, beanId);
147+
edits.replace(offset - prefix.length(), offset, fieldName);
146148
}
147149
}
148150
return edits;
@@ -176,7 +178,7 @@ public Renderable getDocumentation() {
176178
public Optional<Command> getCommand() {
177179
FixDescriptor f = new FixDescriptor(InjectBeanCompletionRecipe.class.getName(), List.of(this.doc.getUri()),
178180
"Inject bean completions")
179-
.withParameters(Map.of("fullyQualifiedName", beanType, "fieldName", beanId, "classFqName", className))
181+
.withParameters(Map.of("fullyQualifiedName", beanType, "fieldName", fieldName, "classFqName", className))
180182
.withRecipeScope(RecipeScope.NODE);
181183
return Optional.of(rewriteRefactorings.createFixCommand("Inject bean '%s'".formatted(beanId), f));
182184
}

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeanCompletionProvider.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,18 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.java.beans;
1212

13-
import java.util.Arrays;
1413
import java.util.Collection;
15-
import java.util.Objects;
14+
import java.util.HashSet;
1615
import java.util.Optional;
1716
import java.util.Set;
18-
import java.util.stream.Collectors;
1917

2018
import org.eclipse.jdt.core.dom.ASTNode;
2119
import org.eclipse.jdt.core.dom.Annotation;
2220
import org.eclipse.jdt.core.dom.Block;
2321
import org.eclipse.jdt.core.dom.CompilationUnit;
2422
import org.eclipse.jdt.core.dom.FieldAccess;
2523
import org.eclipse.jdt.core.dom.ITypeBinding;
24+
import org.eclipse.jdt.core.dom.IVariableBinding;
2625
import org.eclipse.jdt.core.dom.QualifiedName;
2726
import org.eclipse.jdt.core.dom.SimpleName;
2827
import org.eclipse.jdt.core.dom.ThisExpression;
@@ -99,23 +98,28 @@ public void provideCompletions(ASTNode node, int offset, TextDocument doc,
9998
String className = getFullyQualifiedName(topLevelClass);
10099
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
101100
ITypeBinding topLevelBeanType = topLevelClass.resolveBinding();
102-
Set<String> declaredFiledsTypes = Arrays.stream(topLevelBeanType.getDeclaredFields())
103-
.map(vd -> vd.getType())
104-
.filter(Objects::nonNull)
105-
.map(t -> t.getQualifiedName())
106-
.collect(Collectors.toSet());
101+
Set<String> fieldTypes = new HashSet<>();
102+
Set<String> fieldNames = new HashSet<>();
103+
for (IVariableBinding vd : topLevelBeanType.getDeclaredFields()) {
104+
fieldNames.add(vd.getName());
105+
fieldTypes.add(vd.getType().getQualifiedName());
106+
}
107107
for (Bean bean : beans) {
108108
// If current class is a bean - ignore it
109109
if (className.equals(bean.getType())) {
110110
continue;
111111
}
112112
// Filter out beans already injected into this class
113-
if (declaredFiledsTypes.contains(bean.getType())) {
113+
if (fieldTypes.contains(bean.getType())) {
114114
continue;
115115
}
116-
116+
117+
String fieldName = bean.getName();
118+
for (int i = 0; i < Integer.MAX_VALUE && fieldNames.contains(fieldName); i++, fieldName = "%s_%d".formatted(bean.getName(), i)) {
119+
// nothing
120+
}
117121
BeanCompletionProposal proposal = new BeanCompletionProposal(node, offset, doc, bean.getName(),
118-
bean.getType(), className, rewriteRefactorings);
122+
bean.getType(), fieldName, className, rewriteRefactorings);
119123

120124
if (proposal.getScore() > 0) {
121125
completions.add(proposal);

headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/BeanCompletionProviderTest.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,84 @@ public void test() {
677677
""");
678678
}
679679

680+
@Test
681+
public void sameNameFieldExists_Constructor() throws Exception {
682+
String content = """
683+
package org.sample.test;
684+
685+
import org.springframework.web.bind.annotation.RestController;
686+
687+
@RestController
688+
public class TestBeanCompletionClass {
689+
String ownerRepository;
690+
public TestBeanCompletionClass(String ownerRepository) {
691+
this.ownerRepository = ownerRepository;
692+
ow<*>
693+
}
694+
}
695+
""";
696+
697+
698+
assertCompletions(content, new String[] {"ownerRepository", "ownerService"}, 0,
699+
"""
700+
package org.sample.test;
701+
702+
import org.springframework.samples.petclinic.owner.OwnerRepository;
703+
import org.springframework.web.bind.annotation.RestController;
704+
705+
@RestController
706+
public class TestBeanCompletionClass {
707+
708+
private final OwnerRepository ownerRepository_1;
709+
String ownerRepository;
710+
public TestBeanCompletionClass(String ownerRepository, OwnerRepository ownerRepository_1) {
711+
this.ownerRepository = ownerRepository;
712+
this.ownerRepository_1 = ownerRepository_1;<*>
713+
}
714+
}
715+
""");
716+
}
717+
718+
@Test
719+
public void sameNameFieldExists_Method() throws Exception {
720+
String content = """
721+
package org.sample.test;
722+
723+
import org.springframework.web.bind.annotation.RestController;
724+
725+
@RestController
726+
public class TestBeanCompletionClass {
727+
String ownerRepository;
728+
public void test() {
729+
ow<*>
730+
}
731+
}
732+
""";
733+
734+
735+
assertCompletions(content, new String[] {"ownerRepository", "ownerService"}, 0,
736+
"""
737+
package org.sample.test;
738+
739+
import org.springframework.samples.petclinic.owner.OwnerRepository;
740+
import org.springframework.web.bind.annotation.RestController;
741+
742+
@RestController
743+
public class TestBeanCompletionClass {
744+
745+
private final OwnerRepository ownerRepository_1;
746+
String ownerRepository;
747+
748+
TestBeanCompletionClass(OwnerRepository ownerRepository_1) {
749+
this.ownerRepository_1 = ownerRepository_1;
750+
}
751+
public void test() {
752+
ownerRepository_1<*>
753+
}
754+
}
755+
""");
756+
}
757+
680758
@Test
681759
public void beforeStatementStartingWithThisAndPrefix() throws Exception {
682760
String content = """

0 commit comments

Comments
 (0)