Skip to content

Commit

Permalink
Bean completion case of constructor with parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
BoykoAlex committed Mar 3, 2025
1 parent 7f36d34 commit edd78c0
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,16 @@ public J visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ct
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable,
ExecutionContext ctx) {

Cursor blockCursor = getCursor().dropParentUntil(it -> it instanceof J.Block || it == Cursor.ROOT_VALUE);
Cursor blockCursor = getCursor().getParentTreeCursor();
if (!(blockCursor.getValue() instanceof J.Block)) {
return multiVariable;
}
Cursor typeDeclCursor = blockCursor.getParentTreeCursor();
if (!(typeDeclCursor.getValue() instanceof J.ClassDeclaration)) {
return multiVariable;
}
VariableDeclarations mv = multiVariable;
if (blockCursor.getParent() != null && blockCursor.getParent().getValue() instanceof ClassDeclaration
&& multiVariable.getVariables().size() == 1
if (multiVariable.getVariables().size() == 1
&& fieldName.equals(multiVariable.getVariables().get(0).getName().getSimpleName())) {
if (mv.getModifiers().stream().noneMatch(m -> m.getType() == J.Modifier.Type.Final)) {
Space prefix = Space.firstPrefix(mv.getVariables());
Expand Down Expand Up @@ -236,31 +239,42 @@ public AddConstructorParameterAndAssignment(MethodDeclaration constructor, Strin
@Override
public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, ExecutionContext p) {
J.MethodDeclaration md = super.visitMethodDeclaration(method, p);
if (md == this.constructor && md.getBody() != null) {
if (md.getId().equals(constructor.getId()) && md.getBody() != null) {

List<Statement> newParams = new ArrayList<>(md.getParameters().stream().filter(s -> !(s instanceof J.Empty)).toList());
J.VariableDeclarations vd = new J.VariableDeclarations(
Tree.randomId(),
newParams.isEmpty() ? Space.EMPTY : Space.SINGLE_SPACE,
Markers.EMPTY,
Collections.emptyList(),
Collections.emptyList(),
TypeTree.build(methodType),
null,
Collections.emptyList(),
List.of(JRightPadded.build(new J.VariableDeclarations.NamedVariable(
Tree.randomId(),
Space.SINGLE_SPACE,
Markers.EMPTY,
createFieldNameIdentifier(),
Collections.emptyList(),
null,
null
)))
);
newParams.add(vd);
md = md.withParameters(newParams);
updateCursor(md);
boolean parameterExists = md.getParameters().stream().filter(J.VariableDeclarations.class::isInstance).map(J.VariableDeclarations.class::cast).filter(vd -> {
if (vd.getVariables().stream().anyMatch(vn -> fieldName.equals(vn.getSimpleName()))) {
FullyQualified fqType = vd.getTypeAsFullyQualified();
if (fqType != null && methodType.equals(fqType.getClassName())) {
return true;
}
}
return false;
}).findFirst().isPresent();
if (!parameterExists) {
List<Statement> newParams = new ArrayList<>(md.getParameters().stream().filter(s -> !(s instanceof J.Empty)).toList());
J.VariableDeclarations vd = new J.VariableDeclarations(
Tree.randomId(),
newParams.isEmpty() ? Space.EMPTY : Space.SINGLE_SPACE,
Markers.EMPTY,
Collections.emptyList(),
Collections.emptyList(),
TypeTree.build(methodType),
null,
Collections.emptyList(),
List.of(JRightPadded.build(new J.VariableDeclarations.NamedVariable(
Tree.randomId(),
Space.SINGLE_SPACE,
Markers.EMPTY,
createFieldNameIdentifier(),
Collections.emptyList(),
null,
null
)))
);
newParams.add(vd);
md = md.withParameters(newParams);
updateCursor(md);
}

if (!isConstructorInitializingField(md, fieldName)) {
// noinspection ConstantConditions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,49 @@ public interface OwnerRepository{}
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}

@Test
void injectFieldIntoExistingSingleConstructorWithExisitngParameter() {

String beforeSourceStr = """
package com.example.demo;
import com.example.test.OwnerRepository;
public class A {
private final OwnerRepository ownerRepository;
A(OwnerRepository ownerRepository) {
}
}
""";

String expectedSourceStr = """
package com.example.demo;
import com.example.test.OwnerRepository;
public class A {
private final OwnerRepository ownerRepository;
A(OwnerRepository ownerRepository) {
this.ownerRepository = ownerRepository;
}
}
""";

String dependsOn = """
package com.example.test;
public interface OwnerRepository{}
""";

Recipe recipe = new ConstructorInjectionRecipe("com.example.test.OwnerRepository", "ownerRepository", "com.example.demo.A");
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}

@Test
void injectFieldIntoAutowiredConstructor() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class BeanCompletionProviderTest {
private Bean bean4;
private Bean bean5;
private Bean bean6;
private Bean bean7;

@BeforeEach
public void setup() throws Exception {
Expand All @@ -94,8 +95,9 @@ public void setup() throws Exception {
bean4 = new Bean("visitService", "org.springframework.samples.petclinic.owner.VisitService", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");
bean5 = new Bean("petService", "org.springframework.samples.petclinic.pet.Inner.PetService", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");
bean6 = new Bean("testBeanCompletionClass", "org.sample.test.TestBeanCompletionClass", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");
bean7 = new Bean("testIntBean", "java.lang.Integer", new Location(tempJavaDocUri, new Range(new Position(1,1), new Position(1, 20))), null, null, null, false, "symbolLabel");

springIndex.updateBeans(project.getElementName(), new Bean[] {bean1, bean2, bean3, bean4, bean5, bean6});
springIndex.updateBeans(project.getElementName(), new Bean[] {bean1, bean2, bean3, bean4, bean5, bean6, bean7});
}

@AfterEach
Expand Down Expand Up @@ -155,7 +157,7 @@ public void test() {

@Test
public void noPrefix_secondCompletion() throws Exception {
assertCompletions(getCompletion("<*>"), new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 1,
assertCompletions(getCompletion("<*>"), new String[] {"ownerRepository", "ownerService", "petService", "testIntBean", "visitRepository", "visitService"}, 1,
"""
package org.sample.test;
Expand All @@ -180,7 +182,7 @@ public void test() {

@Test
public void testBeanCompletion_injectInnerClass() throws Exception {
assertCompletions(getCompletion("<*>"), new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 2,
assertCompletions(getCompletion("<*>"), new String[] {"ownerRepository", "ownerService", "petService", "testIntBean", "visitRepository", "visitService"}, 2,
"""
package org.sample.test;
Expand Down Expand Up @@ -297,7 +299,7 @@ public void test() {
}
""";

assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testBeanCompletionClass", "visitRepository", "visitService"}, 1,
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testBeanCompletionClass", "testIntBean", "visitRepository", "visitService"}, 1,
"""
package org.sample.test;
Expand Down Expand Up @@ -526,6 +528,48 @@ public void test() {
""");
}

@Test
public void beanCompletionWithConstructorParameterPresent() throws Exception {
String content = """
package org.sample.test;
import org.springframework.stereotype.Controller;
@Controller
public class TestBeanCompletionClass {
TestBeanCompletionClass(Integer testIntBean) {
}
public void test() {
this.testI<*>
}
}
""";


assertCompletions(content, new String[] {"testIntBean"}, 0,
"""
package org.sample.test;
import org.springframework.stereotype.Controller;
@Controller
public class TestBeanCompletionClass {
private final Integer testIntBean;
TestBeanCompletionClass(Integer testIntBean) {
this.testIntBean = testIntBean;
}
public void test() {
this.testIntBean<*>
}
}
""");
}

@Test
public void noCompletionsInMethod_1() throws Exception {
String content = """
Expand Down Expand Up @@ -659,7 +703,7 @@ public void test() {
""";


assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testIntBean", "visitRepository", "visitService"}, 0,
"""
package org.sample.test;
Expand Down Expand Up @@ -965,7 +1009,7 @@ public TestBeanCompletionClass() {
""";


assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testIntBean", "visitRepository", "visitService"}, 0,
"""
package org.sample.test;
Expand Down Expand Up @@ -1002,7 +1046,7 @@ public TestBeanCompletionClass() {
""";


assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testIntBean", "visitRepository", "visitService"}, 0,
"""
package org.sample.test;
Expand Down Expand Up @@ -1039,7 +1083,7 @@ public TestBeanCompletionClass() {
""";


assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testIntBean", "visitRepository", "visitService"}, 0,
"""
package org.sample.test;
Expand Down Expand Up @@ -1076,7 +1120,7 @@ public TestBeanCompletionClass() {
""";


assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "visitRepository", "visitService"}, 0,
assertCompletions(content, new String[] {"ownerRepository", "ownerService", "petService", "testIntBean", "visitRepository", "visitService"}, 0,
"""
package org.sample.test;
Expand Down

0 comments on commit edd78c0

Please sign in to comment.