Fix bean injection when bean name is different from type simple name

This commit is contained in:
aboyko
2025-02-26 14:07:34 -05:00
parent 6caac676ee
commit 6a9c390217
5 changed files with 80 additions and 21 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 Broadcom, Inc.
* Copyright (c) 2017, 2025 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@ import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.Tree;
@@ -51,11 +52,20 @@ public class AddFieldRecipe extends Recipe {
@NonNull
String classFqName;
String fieldName;
transient JavaType.FullyQualified fullyQualifiedType;
@JsonCreator
public AddFieldRecipe(@NonNull @JsonProperty("fullyQualifiedClassName") String fullyQualifiedName, @NonNull @JsonProperty("classFqName") String classFqName) {
public AddFieldRecipe(
@NonNull @JsonProperty("fullyQualifiedClassName") String fullyQualifiedName,
@NonNull @JsonProperty("classFqName") String classFqName,
@Nullable @JsonProperty("fieldName") String fieldName) {
this.fullyQualifiedName = fullyQualifiedName;
fullyQualifiedType = JavaType.ShallowClass.build(fullyQualifiedName);
this.classFqName = classFqName;
this.fieldName = fieldName == null ? getFieldName(fullyQualifiedType) : fieldName;
}
@Override
@@ -63,9 +73,7 @@ public class AddFieldRecipe extends Recipe {
return new JavaIsoVisitor<ExecutionContext>() {
JavaType.FullyQualified fullyQualifiedType = JavaType.ShallowClass.build(fullyQualifiedName);
String fieldType = getFieldType(fullyQualifiedType);
String fieldName = getFieldName(fullyQualifiedType);
@Override
public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ctx) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 Broadcom, Inc.
* Copyright (c) 2017, 2025 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -289,9 +289,17 @@ public class ConstructorInjectionRecipe extends Recipe {
ShallowClass type = JavaType.ShallowClass.build(methodType);
J.FieldAccess fa = new J.FieldAccess(Tree.randomId(), Space.EMPTY, Markers.EMPTY, new J.Identifier(Tree.randomId(), Space.EMPTY, Markers.EMPTY, Collections.emptyList(), "this", md.getMethodType().getDeclaringType(), null), JLeftPadded.build(createFieldNameIdentifier()), type);
Assignment assign = new J.Assignment(Tree.randomId(), Space.build("\n", Collections.emptyList()), Markers.EMPTY, fa, JLeftPadded.build(createFieldNameIdentifier()), type);
assign = autoFormat(assign, p, getCursor());
List<Statement> newStatements = new ArrayList<>(md.getBody().getStatements());
newStatements.add(assign);
md = md.withBody(autoFormat(md.getBody().withStatements(newStatements), p, getCursor()));
boolean empty = newStatements.isEmpty();
if (empty) {
newStatements.add(assign);
md = md.withBody(autoFormat(md.getBody().withStatements(newStatements), p, getCursor()));
} else {
// Prefix is off otherwise even after autoFormat
newStatements.add(assign.withPrefix(newStatements.get(newStatements.size() - 1).getPrefix()));
md = md.withBody(md.getBody().withStatements(newStatements));
}
}
return md;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 Broadcom, Inc.
* Copyright (c) 2017, 2025 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -47,7 +47,7 @@ public class InjectBeanCompletionRecipe extends Recipe {
@Override
public List<Recipe> getRecipeList() {
List<Recipe> list = new ArrayList<>();
list.add(new AddFieldRecipe(fullyQualifiedName, classFqName));
list.add(new AddFieldRecipe(fullyQualifiedName, classFqName, fieldName));
list.add(new ConstructorInjectionRecipe(fullyQualifiedName, fieldName, classFqName));
return list;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 Broadcom, Inc.
* Copyright (c) 2017, 2025 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -28,7 +28,7 @@ public class AddFieldRecipeTest implements RewriteTest {
@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new AddFieldRecipe("com.example.test.OwnerRepository", "com.example.demo.FooBar"))
spec.recipe(new AddFieldRecipe("com.example.test.OwnerRepository", "com.example.demo.FooBar", null))
.parser(JavaParser.fromJavaVersion()
.logCompilationWarningsAndErrors(true));
}
@@ -86,7 +86,7 @@ public class AddFieldRecipeTest implements RewriteTest {
public interface OwnerRepository{}
""";
Recipe recipe = new AddFieldRecipe("com.example.demo.OwnerRepository", "com.example.demo.FooBar");
Recipe recipe = new AddFieldRecipe("com.example.demo.OwnerRepository", "com.example.demo.FooBar", null);
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}
@@ -128,7 +128,7 @@ public class AddFieldRecipeTest implements RewriteTest {
public interface OwnerRepository{}
""";
Recipe recipe = new AddFieldRecipe("com.example.test.OwnerRepository", "com.example.demo.FooBar");
Recipe recipe = new AddFieldRecipe("com.example.test.OwnerRepository", "com.example.demo.FooBar", null);
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}
@@ -170,7 +170,7 @@ public class AddFieldRecipeTest implements RewriteTest {
public interface OwnerRepository{}
""";
Recipe recipe = new AddFieldRecipe("com.example.test.Inner.OwnerRepository", "com.example.demo.FooBar");
Recipe recipe = new AddFieldRecipe("com.example.test.Inner.OwnerRepository", "com.example.demo.FooBar", null);
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}
@@ -214,7 +214,7 @@ class FooBar {
public interface OwnerRepository{}
""";
Recipe recipe = new AddFieldRecipe("com.example.test.OwnerRepository", "com.example.demo.FooBar$Inner");
Recipe recipe = new AddFieldRecipe("com.example.test.OwnerRepository", "com.example.demo.FooBar$Inner", null);
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}
@@ -266,7 +266,7 @@ class FooBar {
public interface OwnerRepository{}
""";
Recipe recipe = new AddFieldRecipe("com.example.test.Inner.OwnerRepository", "com.example.demo.FooBar");
Recipe recipe = new AddFieldRecipe("com.example.test.Inner.OwnerRepository", "com.example.demo.FooBar", null);
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}
@@ -313,7 +313,7 @@ import org.springframework.stereotype.Component;
@Component
class FooBarNew {
private final Inner.OwnerRepository ownerRepository;
private final Inner.OwnerRepository ownerRepo;
public void test1() {}
@@ -325,7 +325,7 @@ import org.springframework.stereotype.Component;
public interface OwnerRepository{}
""";
Recipe recipe = new AddFieldRecipe("com.example.test.Inner.OwnerRepository", "com.example.demo.FooBarNew");
Recipe recipe = new AddFieldRecipe("com.example.test.Inner.OwnerRepository", "com.example.demo.FooBarNew", "ownerRepo");
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 Broadcom, Inc.
* Copyright (c) 2017, 2025 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,6 +21,7 @@ import org.openrewrite.RecipeRun;
import org.openrewrite.SourceFile;
import org.openrewrite.internal.InMemoryLargeSourceSet;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.JavaParser.Builder;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;
@@ -32,8 +33,12 @@ public class ConstructorInjectionRecipeTest implements RewriteTest {
.parser(JavaParser.fromJavaVersion().classpath("spring-beans"));
}
public static void runRecipeAndAssert(Recipe recipe, String beforeSourceStr, String expectedSourceStr, String dependsOn) {
JavaParser javaParser = JavaParser.fromJavaVersion().dependsOn(dependsOn).build();
public static void runRecipeAndAssert(Recipe recipe, String beforeSourceStr, String expectedSourceStr, String... dependsOn) {
Builder<? extends JavaParser, ?> builder = JavaParser.fromJavaVersion();
if (dependsOn.length > 0) {
builder.dependsOn(dependsOn);
}
JavaParser javaParser = builder.build();
List<SourceFile> list = javaParser.parse(beforeSourceStr).toList();
SourceFile beforeSource = list.get(0);
@@ -486,4 +491,42 @@ public class Inner {
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr, dependsOn);
}
@Test
void injectObjectFieldIntoNewConstructor() {
String beforeSourceStr = """
package com.example.demo;
public class A {
private final String s;
private final Object obj;
A(String s) {
this.s = s;
}
}
""";
String expectedSourceStr = """
package com.example.demo;
public class A {
private final String s;
private final Object obj;
A(String s, Object obj) {
this.s = s;
this.obj = obj;
}
}
""";
Recipe recipe = new ConstructorInjectionRecipe("java.lang.Object", "obj", "com.example.demo.A");
runRecipeAndAssert(recipe, beforeSourceStr, expectedSourceStr);
}
}