Bean completion case of constructor with parameter
This commit is contained in:
@@ -139,13 +139,16 @@ public class ConstructorInjectionRecipe extends Recipe {
|
||||
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());
|
||||
@@ -236,31 +239,42 @@ public class ConstructorInjectionRecipe extends Recipe {
|
||||
@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
|
||||
|
||||
@@ -136,6 +136,49 @@ public class ConstructorInjectionRecipeTest implements RewriteTest {
|
||||
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() {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
@@ -94,8 +95,9 @@ public class BeanCompletionProviderTest {
|
||||
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
|
||||
@@ -155,7 +157,7 @@ ownerService<*>
|
||||
|
||||
@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;
|
||||
|
||||
@@ -180,7 +182,7 @@ ownerService<*>
|
||||
|
||||
@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;
|
||||
|
||||
@@ -297,7 +299,7 @@ public class TestBeanCompletionSecondClass {
|
||||
}
|
||||
""";
|
||||
|
||||
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;
|
||||
|
||||
@@ -526,6 +528,48 @@ public class TestBeanCompletionClass {
|
||||
""");
|
||||
}
|
||||
|
||||
@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 = """
|
||||
@@ -659,7 +703,7 @@ public class 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;
|
||||
|
||||
@@ -965,7 +1009,7 @@ public class 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;
|
||||
|
||||
@@ -1002,7 +1046,7 @@ public class 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;
|
||||
|
||||
@@ -1039,7 +1083,7 @@ public class 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;
|
||||
|
||||
@@ -1076,7 +1120,7 @@ public class 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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user