Skip to content

Commit 99b47b4

Browse files
committed
Allows to integrate Rewrite YAML snippets and recipes by name into SBM recipes
- Split generic RecipeLoader into SbmRecipeLoader and RewriteRecipeLoader
1 parent 80cacbc commit 99b47b4

23 files changed

+861
-101
lines changed

applications/spring-shell/src/test/java/org/springframework/sbm/shell/RecipesAreFound.java

Lines changed: 0 additions & 48 deletions
This file was deleted.

changelog.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
## [0.11.2](https://github.com/spring-projects-experimental/spring-boot-migrator/releases/tag/0.11.2) - 2022-05-27
1+
## [0.12.0](https://github.com/spring-projects-experimental/spring-boot-migrator/releases/tag/0.12.0) -
22

33
### Adds
4-
-
4+
- Reworked OpenRewrite recipe integration. (#181)
5+
- OpenRewriteDeclarativeRecipeAdapter allows to declare SBM action which applies a declarative OR recipe
6+
- OpenRewriteNamedRecipeAdapter allows to declare SBM action which applies an OR recipe by name
7+
- Bumps OpenRewrite to version 7.22.0 (#174)
58

69
### Fixes
710
- Fix Conditions for Spring Boot 2.4 to 2.5 Upgrade recipes (#133). Thanks @Turbots

components/recipe-test-support/src/main/java/org/springframework/sbm/test/RecipeTestSupport.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ private RecipeTestSupport() {
5858
ValidatorConfiguration.class,
5959
YamlObjectMapperConfiguration.class,
6060
ResourceHelperDummy.class,
61-
RecipeLoader.class,
61+
RewriteRecipeLoader.class,
62+
SbmRecipeLoader.class,
6263
BasePackageCalculator.class,
6364
ActionDeserializerRegistry.class
6465
};

components/sbm-core/src/main/java/org/springframework/sbm/common/filter/AbsolutePathResourceFinder.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,29 @@
1717
package org.springframework.sbm.common.filter;
1818

1919
import lombok.RequiredArgsConstructor;
20+
import org.openrewrite.SourceFile;
2021
import org.springframework.sbm.project.resource.ProjectResource;
2122
import org.springframework.sbm.project.resource.ProjectResourceSet;
23+
import org.springframework.sbm.project.resource.RewriteSourceFileHolder;
2224
import org.springframework.sbm.project.resource.filter.ProjectResourceFinder;
2325

2426
import java.nio.file.Path;
2527
import java.util.Optional;
2628

2729
@RequiredArgsConstructor
28-
public class AbsolutePathResourceFinder implements ProjectResourceFinder<Optional<ProjectResource>> {
30+
public class AbsolutePathResourceFinder implements ProjectResourceFinder<Optional<RewriteSourceFileHolder<? extends SourceFile>>> {
2931

3032
private final Path absoluteResourcePath;
3133

3234
@Override
33-
public Optional<ProjectResource> apply(ProjectResourceSet projectResourceSet) {
35+
public Optional<RewriteSourceFileHolder<? extends SourceFile>> apply(ProjectResourceSet projectResourceSet) {
3436
if (absoluteResourcePath == null || ! absoluteResourcePath.isAbsolute()) {
3537
throw new IllegalArgumentException("Given path '"+absoluteResourcePath+"' is not absolute");
3638
}
3739
Path searchForPath = absoluteResourcePath.normalize();
3840
return projectResourceSet
3941
.stream()
4042
.filter(r -> searchForPath.equals(r.getAbsolutePath()))
41-
.map(ProjectResource.class::cast)
4243
.findFirst();
4344

4445
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.common.filter;
18+
19+
import org.openrewrite.SourceFile;
20+
import org.springframework.sbm.project.resource.ProjectResource;
21+
import org.springframework.sbm.project.resource.ProjectResourceSet;
22+
import org.springframework.sbm.project.resource.RewriteSourceFileHolder;
23+
import org.springframework.sbm.project.resource.filter.ProjectResourceFinder;
24+
25+
import java.nio.file.Path;
26+
import java.util.*;
27+
import java.util.stream.Collectors;
28+
29+
public class AbsolutePathResourcesFinder implements ProjectResourceFinder<List<RewriteSourceFileHolder<? extends SourceFile>>> {
30+
31+
private final Set<Path> absoluteResourcePaths;
32+
public AbsolutePathResourcesFinder(List<Path> absoluteResourcePaths) {
33+
this(new HashSet<>(absoluteResourcePaths));
34+
}
35+
public AbsolutePathResourcesFinder(Path... absoluteResourcePath) {
36+
this(Arrays.asList(absoluteResourcePath));
37+
}
38+
public AbsolutePathResourcesFinder(Path absoluteResourcePath) {
39+
this(Set.of(absoluteResourcePath));
40+
}
41+
public AbsolutePathResourcesFinder(Set<Path> absoluteResourcePaths) {
42+
String invalidPaths = absoluteResourcePaths.stream()
43+
.filter(absoluteResourcePath -> absoluteResourcePath == null || !absoluteResourcePath.isAbsolute())
44+
.map(p -> {
45+
if(p == null) {
46+
return "null";
47+
} else {
48+
return p.toString();
49+
}
50+
})
51+
.collect(Collectors.joining("', '"));
52+
53+
if(invalidPaths != null) {
54+
throw new IllegalArgumentException("Given paths '"+ invalidPaths +"' were not absolute");
55+
}
56+
57+
this.absoluteResourcePaths = absoluteResourcePaths.stream().map(Path::normalize).collect(Collectors.toSet());
58+
}
59+
60+
@Override
61+
public List<RewriteSourceFileHolder<? extends SourceFile>> apply(ProjectResourceSet projectResourceSet) {
62+
return projectResourceSet
63+
.stream()
64+
.filter(r -> absoluteResourcePaths.contains(r.getAbsolutePath()))
65+
.collect(Collectors.toList());
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.engine.recipe;
18+
19+
import com.fasterxml.jackson.annotation.JsonIgnore;
20+
import lombok.*;
21+
import org.openrewrite.Recipe;
22+
import org.openrewrite.Result;
23+
import org.openrewrite.SourceFile;
24+
import org.openrewrite.config.YamlResourceLoader;
25+
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.sbm.engine.context.ProjectContext;
27+
28+
import java.io.ByteArrayInputStream;
29+
import java.io.IOException;
30+
import java.net.URI;
31+
import java.nio.charset.StandardCharsets;
32+
import java.util.Collection;
33+
import java.util.List;
34+
import java.util.Properties;
35+
36+
@Builder
37+
@NoArgsConstructor
38+
@AllArgsConstructor
39+
public class OpenRewriteDeclarativeRecipeAdapter extends AbstractAction {
40+
@Setter
41+
@Getter
42+
private String openRewriteRecipe;
43+
44+
@JsonIgnore
45+
@Autowired
46+
private RewriteMigrationResultMerger resultMerger;
47+
48+
@Override
49+
public boolean isApplicable(ProjectContext context) {
50+
return super.isApplicable(context);
51+
}
52+
53+
@Override
54+
public void apply(ProjectContext context) {
55+
ByteArrayInputStream yamlInput = new ByteArrayInputStream(openRewriteRecipe.getBytes(StandardCharsets.UTF_8));
56+
URI source = URI.create("embedded-recipe");
57+
YamlResourceLoader yamlResourceLoader = new YamlResourceLoader(yamlInput, source, new Properties());
58+
Collection<Recipe> rewriteYamlRecipe = yamlResourceLoader.listRecipes();
59+
if(rewriteYamlRecipe.size() != 1) {
60+
throw new RuntimeException(String.format("Ambiguous number of recipes found. Expected exactly one, found %s", rewriteYamlRecipe.size()));
61+
}
62+
Recipe recipe = rewriteYamlRecipe.iterator().next();
63+
List<? extends SourceFile> rewriteSourceFiles = context.search(new OpenRewriteSourceFilesFinder());
64+
List<Result> results = recipe.run(rewriteSourceFiles);
65+
resultMerger.mergeResults(context, results);
66+
}
67+
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.engine.recipe;
18+
19+
import com.fasterxml.jackson.annotation.JsonIgnore;
20+
import lombok.AllArgsConstructor;
21+
import lombok.Builder;
22+
import lombok.NoArgsConstructor;
23+
import lombok.Setter;
24+
import org.openrewrite.Recipe;
25+
import org.openrewrite.Result;
26+
import org.openrewrite.SourceFile;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.sbm.engine.context.ProjectContext;
29+
30+
import java.util.List;
31+
32+
@Builder
33+
@NoArgsConstructor
34+
@AllArgsConstructor
35+
public class OpenRewriteNamedRecipeAdapter extends AbstractAction {
36+
37+
@Setter
38+
private String openRewriteRecipeName;
39+
40+
@Autowired
41+
@JsonIgnore
42+
private RewriteRecipeLoader rewriteRecipeLoader;
43+
44+
@JsonIgnore
45+
@Autowired
46+
private RewriteMigrationResultMerger resultMerger;
47+
48+
@Override
49+
public void apply(ProjectContext context) {
50+
Recipe recipe = rewriteRecipeLoader.loadRewriteRecipe(openRewriteRecipeName);
51+
List<? extends SourceFile> rewriteSourceFiles = context.search(new OpenRewriteSourceFilesFinder());
52+
List<Result> results = recipe.run(rewriteSourceFiles);
53+
resultMerger.mergeResults(context, results);
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.engine.recipe;
18+
19+
import com.fasterxml.jackson.annotation.JsonIgnore;
20+
import lombok.extern.slf4j.Slf4j;
21+
import org.openrewrite.*;
22+
import org.openrewrite.Recipe;
23+
import org.springframework.beans.factory.annotation.Autowired;
24+
import org.springframework.sbm.common.filter.AbsolutePathResourceFinder;
25+
import org.springframework.sbm.engine.context.ProjectContext;
26+
import org.springframework.sbm.project.RewriteSourceFileWrapper;
27+
import org.springframework.sbm.project.resource.RewriteSourceFileHolder;
28+
29+
import java.nio.file.Path;
30+
import java.util.*;
31+
32+
@Slf4j
33+
//@RequiredArgsConstructor
34+
public class OpenRewriteRecipeAdapterAction extends AbstractAction {
35+
36+
private final Recipe recipe;
37+
38+
@JsonIgnore
39+
@Autowired
40+
private RewriteMigrationResultMerger resultMerger;
41+
42+
// private final ModifiableProjectResourceFactory modifiableProjectResourceFactory = new ModifiableProjectResourceFactory();
43+
44+
45+
@Override
46+
public boolean isApplicable(ProjectContext context) {
47+
return true;
48+
// FIXME: use getApplicableTest and getSingleSourceApplicableTest to calculate
49+
/*
50+
Method getApplicableTest = ReflectionUtils.findMethod(Recipe.class, "getApplicableTest");
51+
ReflectionUtils.makeAccessible(getApplicableTest);
52+
try {
53+
TreeVisitor<?, ExecutionContext> visitor = (TreeVisitor<?, ExecutionContext>) getApplicableTest.invoke(recipe);
54+
if(visitor == null) {
55+
return true;
56+
} else {
57+
List<SourceFile> search = context.search(new OpenRewriteSourceFileFinder());
58+
return visitor.visit(search, new InMemoryExecutionContext());
59+
}
60+
} catch (IllegalAccessException e) {
61+
throw new RuntimeException(e);
62+
} catch (InvocationTargetException e) {
63+
throw new RuntimeException(e);
64+
}
65+
*/
66+
}
67+
68+
public OpenRewriteRecipeAdapterAction(Recipe recipe) {
69+
this.recipe = recipe;
70+
}
71+
72+
@Override
73+
public String getDescription() {
74+
return recipe.getDescription().isEmpty() ? recipe.getDisplayName() : recipe.getDescription();
75+
}
76+
77+
@Override
78+
public void apply(ProjectContext context) {
79+
List<? extends SourceFile> rewriteSourceFiles = context.search(new OpenRewriteSourceFilesFinder());
80+
List<Result> results = recipe.run(rewriteSourceFiles);
81+
resultMerger.mergeResults(context, results);
82+
}
83+
84+
85+
}

0 commit comments

Comments
 (0)