Bean completion case of the same name field
This commit is contained in:
@@ -54,6 +54,7 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
|
||||
private IDocument doc;
|
||||
private String beanId;
|
||||
private String beanType;
|
||||
private String fieldName;
|
||||
private String className;
|
||||
private RewriteRefactorings rewriteRefactorings;
|
||||
private double score;
|
||||
@@ -64,12 +65,13 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
|
||||
private DocumentEdits edits;
|
||||
|
||||
public BeanCompletionProposal(ASTNode node, int offset, IDocument doc, String beanId, String beanType,
|
||||
String className, RewriteRefactorings rewriteRefactorings) {
|
||||
String fieldName, String className, RewriteRefactorings rewriteRefactorings) {
|
||||
this.node = node;
|
||||
this.offset = offset;
|
||||
this.doc = doc;
|
||||
this.beanId = beanId;
|
||||
this.beanType = beanType;
|
||||
this.fieldName = fieldName;
|
||||
this.className = className;
|
||||
this.rewriteRefactorings = rewriteRefactorings;
|
||||
this.prefix = computePrefix();
|
||||
@@ -130,19 +132,19 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
|
||||
DocumentEdits edits = new DocumentEdits(doc, false);
|
||||
if (isInsideConstructor(node)) {
|
||||
if (node instanceof Block) {
|
||||
edits.insert(offset, "this.%s = %s;".formatted(beanId, beanId));
|
||||
edits.insert(offset, "this.%s = %s;".formatted(fieldName, fieldName));
|
||||
} else {
|
||||
if (node.getParent() instanceof Assignment || node.getParent() instanceof FieldAccess) {
|
||||
edits.replace(offset - prefix.length(), offset, "%s = %s;".formatted(beanId, beanId));
|
||||
edits.replace(offset - prefix.length(), offset, "%s = %s;".formatted(fieldName, fieldName));
|
||||
} else {
|
||||
edits.replace(offset - prefix.length(), offset, "this.%s = %s;".formatted(beanId, beanId));
|
||||
edits.replace(offset - prefix.length(), offset, "this.%s = %s;".formatted(fieldName, fieldName));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (node instanceof Block) {
|
||||
edits.insert(offset, beanId);
|
||||
edits.insert(offset, fieldName);
|
||||
} else {
|
||||
edits.replace(offset - prefix.length(), offset, beanId);
|
||||
edits.replace(offset - prefix.length(), offset, fieldName);
|
||||
}
|
||||
}
|
||||
return edits;
|
||||
@@ -176,7 +178,7 @@ public class BeanCompletionProposal implements ICompletionProposalWithScore {
|
||||
public Optional<Command> getCommand() {
|
||||
FixDescriptor f = new FixDescriptor(InjectBeanCompletionRecipe.class.getName(), List.of(this.doc.getUri()),
|
||||
"Inject bean completions")
|
||||
.withParameters(Map.of("fullyQualifiedName", beanType, "fieldName", beanId, "classFqName", className))
|
||||
.withParameters(Map.of("fullyQualifiedName", beanType, "fieldName", fieldName, "classFqName", className))
|
||||
.withRecipeScope(RecipeScope.NODE);
|
||||
return Optional.of(rewriteRefactorings.createFixCommand("Inject bean '%s'".formatted(beanId), f));
|
||||
}
|
||||
|
||||
@@ -10,12 +10,10 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.beans;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
@@ -23,6 +21,7 @@ import org.eclipse.jdt.core.dom.Block;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.FieldAccess;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.IVariableBinding;
|
||||
import org.eclipse.jdt.core.dom.QualifiedName;
|
||||
import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.ThisExpression;
|
||||
@@ -99,23 +98,28 @@ public class BeanCompletionProvider implements CompletionProvider {
|
||||
String className = getFullyQualifiedName(topLevelClass);
|
||||
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
|
||||
ITypeBinding topLevelBeanType = topLevelClass.resolveBinding();
|
||||
Set<String> declaredFiledsTypes = Arrays.stream(topLevelBeanType.getDeclaredFields())
|
||||
.map(vd -> vd.getType())
|
||||
.filter(Objects::nonNull)
|
||||
.map(t -> t.getQualifiedName())
|
||||
.collect(Collectors.toSet());
|
||||
Set<String> fieldTypes = new HashSet<>();
|
||||
Set<String> fieldNames = new HashSet<>();
|
||||
for (IVariableBinding vd : topLevelBeanType.getDeclaredFields()) {
|
||||
fieldNames.add(vd.getName());
|
||||
fieldTypes.add(vd.getType().getQualifiedName());
|
||||
}
|
||||
for (Bean bean : beans) {
|
||||
// If current class is a bean - ignore it
|
||||
if (className.equals(bean.getType())) {
|
||||
continue;
|
||||
}
|
||||
// Filter out beans already injected into this class
|
||||
if (declaredFiledsTypes.contains(bean.getType())) {
|
||||
if (fieldTypes.contains(bean.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
String fieldName = bean.getName();
|
||||
for (int i = 0; i < Integer.MAX_VALUE && fieldNames.contains(fieldName); i++, fieldName = "%s_%d".formatted(bean.getName(), i)) {
|
||||
// nothing
|
||||
}
|
||||
BeanCompletionProposal proposal = new BeanCompletionProposal(node, offset, doc, bean.getName(),
|
||||
bean.getType(), className, rewriteRefactorings);
|
||||
bean.getType(), fieldName, className, rewriteRefactorings);
|
||||
|
||||
if (proposal.getScore() > 0) {
|
||||
completions.add(proposal);
|
||||
|
||||
@@ -677,6 +677,84 @@ public class TestBeanCompletionClass {
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sameNameFieldExists_Constructor() throws Exception {
|
||||
String content = """
|
||||
package org.sample.test;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class TestBeanCompletionClass {
|
||||
String ownerRepository;
|
||||
public TestBeanCompletionClass(String ownerRepository) {
|
||||
this.ownerRepository = ownerRepository;
|
||||
ow<*>
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
|
||||
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_1;
|
||||
String ownerRepository;
|
||||
public TestBeanCompletionClass(String ownerRepository, OwnerRepository ownerRepository_1) {
|
||||
this.ownerRepository = ownerRepository;
|
||||
this.ownerRepository_1 = ownerRepository_1;<*>
|
||||
}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sameNameFieldExists_Method() throws Exception {
|
||||
String content = """
|
||||
package org.sample.test;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class TestBeanCompletionClass {
|
||||
String ownerRepository;
|
||||
public void test() {
|
||||
ow<*>
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
|
||||
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_1;
|
||||
String ownerRepository;
|
||||
|
||||
TestBeanCompletionClass(OwnerRepository ownerRepository_1) {
|
||||
this.ownerRepository_1 = ownerRepository_1;
|
||||
}
|
||||
public void test() {
|
||||
ownerRepository_1<*>
|
||||
}
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beforeStatementStartingWithThisAndPrefix() throws Exception {
|
||||
String content = """
|
||||
|
||||
Reference in New Issue
Block a user