Skip to content

Commit 8d3cda1

Browse files
authored
Revamp/947 cleanup sbm support rewrite (#951)
* Remove @component and declare using @bean * Add dependency to rewrite-java-17 * Add dependency to rewrite-migrate-java * Add delombok * Renamed HelperWithoutAGoodName * Enhance README * Moved Maven-related classes to the maven package * Add javadoc * Remove dead code * Remove ExecutionContext parameter * Renamed SbmMavenProject * Moved logic into ParserContext * Add MavenModuleParser * Cleanup pom
1 parent 2b7ffa7 commit 8d3cda1

File tree

57 files changed

+613
-696
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+613
-696
lines changed

components/sbm-core/src/main/java/org/springframework/sbm/build/api/Module.java

+3-8
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@
1515
*/
1616
package org.springframework.sbm.build.api;
1717

18+
import lombok.Getter;
19+
import lombok.RequiredArgsConstructor;
1820
import org.openrewrite.ExecutionContext;
21+
import org.openrewrite.SourceFile;
1922
import org.openrewrite.maven.tree.MavenResolutionResult;
2023
import org.springframework.sbm.build.impl.JavaSourceSetImpl;
2124
import org.springframework.sbm.build.impl.MavenBuildFileUtil;
2225
import org.springframework.sbm.build.impl.OpenRewriteMavenBuildFile;
2326
import org.springframework.sbm.common.util.Verify;
24-
import org.springframework.sbm.engine.recipe.MigrationResultProjectContextMerger;
2527
import org.springframework.sbm.java.api.JavaSource;
2628
import org.springframework.sbm.java.api.JavaSourceLocation;
2729
import org.springframework.sbm.java.refactoring.JavaRefactoringFactory;
@@ -32,9 +34,6 @@
3234
import org.springframework.sbm.project.resource.RewriteMigrationResultMerger;
3335
import org.springframework.sbm.project.resource.RewriteSourceFileHolder;
3436
import org.springframework.sbm.project.resource.finder.ProjectResourceFinder;
35-
import lombok.Getter;
36-
import lombok.RequiredArgsConstructor;
37-
import org.openrewrite.SourceFile;
3837

3938
import java.nio.file.Path;
4039
import java.util.ArrayList;
@@ -67,10 +66,6 @@ public JavaSourceLocation getBaseJavaSourceLocation() {
6766
return getMainJavaSourceSet().getJavaSourceLocation();
6867
}
6968

70-
public JavaSourceLocation getBaseTestJavaSourceLocation() {
71-
return getTestJavaSourceSet().getJavaSourceLocation();
72-
}
73-
7469
public JavaSourceSet getTestJavaSourceSet() {
7570
Path testJavaPath = Path.of("src/test/java");
7671
// FIXME: #7 JavaParser

components/sbm-core/src/main/java/org/springframework/sbm/java/impl/OpenRewriteRecipeJavaSearch.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void commentFindings(List<? extends JavaSource> javaSources, String comme
5151
OpenRewriteJavaSource affectedJavaSource = javaSources.stream()
5252
.filter(js -> js.getClass().isAssignableFrom(OpenRewriteJavaSource.class))
5353
.map(OpenRewriteJavaSource.class::cast)
54-
.filter(js -> result.getBefore().getId().equals(js.getResource().getId()))
54+
.filter(js -> result.getBefore().getId().equals(js.getResource().getSourceFile().getId()))
5555
.findFirst()
5656
.get();
5757

components/sbm-core/src/main/java/org/springframework/sbm/java/impl/ProjectJavaSourcesImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public List<MethodCall> findMethodCalls(String methodPattern) {
109109
FindMethods findMethods = new FindMethods(methodPattern,true);
110110
MethodMatcher methodMatcher = new MethodMatcher(methodPattern);
111111
find(findMethods).stream()
112-
.map(m -> list().stream().filter(js -> js.getResource().getId().equals(m.getId())).findFirst().get())
112+
.map(m -> list().stream().filter(js -> js.getResource().getSourceFile().getId().equals(m.getSourceFile().getId())).findFirst().get())
113113
.map(m -> new MethodCall(m, methodMatcher))
114114
.forEach(matches::add);
115115
return matches;

components/sbm-core/src/main/java/org/springframework/sbm/java/refactoring/JavaGlobalRefactoringImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ protected List<RewriteSourceFileHolder<J.CompilationUnit>> findInternal(List<Rew
9797
.filter(r -> J.CompilationUnit.class.isAssignableFrom(r.getClass()))
9898
.map(J.CompilationUnit.class::cast)
9999
.map(cu -> resourceWrappers.stream()
100-
.filter(fh -> fh.getId().equals(cu.getId()))
100+
.filter(fh -> fh.getSourceFile().getId().equals(cu.getId()))
101101
.map(pr -> {
102102
J.CompilationUnit cuRemovedMarkers = removeMarkers(cu, SearchResult.class, RecipesThatMadeChanges.class);
103103
pr.replaceWith(cuRemovedMarkers);

components/sbm-core/src/main/java/org/springframework/sbm/project/parser/MavenProjectParser.java

+1-16
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,9 @@
1717

1818
import lombok.RequiredArgsConstructor;
1919
import lombok.extern.slf4j.Slf4j;
20-
import org.openrewrite.ExecutionContext;
2120
import org.openrewrite.SourceFile;
22-
import org.openrewrite.java.JavaParser;
23-
import org.openrewrite.maven.utilities.MavenArtifactDownloader;
24-
import org.springframework.context.ApplicationEventPublisher;
2521
import org.springframework.core.io.Resource;
26-
import org.springframework.sbm.build.impl.RewriteMavenParser;
2722
import org.springframework.sbm.parsers.RewriteProjectParser;
28-
import org.springframework.sbm.scopes.ProjectMetadata;
2923
import org.springframework.stereotype.Component;
3024

3125
import java.nio.file.Path;
@@ -44,19 +38,10 @@
4438
@Deprecated(forRemoval = true)
4539
public class MavenProjectParser {
4640

47-
private final ResourceParser resourceParser;
48-
private final RewriteMavenParser mavenParser;
49-
private final MavenArtifactDownloader artifactDownloader;
50-
private final ApplicationEventPublisher eventPublisher;
51-
private final JavaProvenanceMarkerFactory javaProvenanceMarkerFactory;
52-
private final JavaParser javaParser;
53-
private final MavenConfigHandler mavenConfigHandler;
54-
private final ProjectMetadata projectMetadata;
55-
private final ExecutionContext executionContext;
5641
private final RewriteProjectParser parser;
5742

5843
public List<SourceFile> parse(Path projectDirectory, List<Resource> resources) {
59-
return parser.parse(projectDirectory, resources, executionContext).sourceFiles();
44+
return parser.parse(projectDirectory, resources).sourceFiles();
6045
}
6146

6247

components/sbm-core/src/main/java/org/springframework/sbm/project/parser/ProjectContextInitializer.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ public class ProjectContextInitializer {
4343
private final RewriteProjectParser mavenProjectParser;
4444
private final GitSupport gitSupport;
4545
private final RewriteSourceFileWrapper rewriteSourceFileWrapper;
46-
private final ExecutionContext executionContext;
4746
private final ProjectContextHolder projectContextHolder;
4847
private final ProjectResourceSetFactory projectResourceSetFactory;
4948

@@ -52,7 +51,7 @@ public ProjectContext initProjectContext(Path projectDir, List<Resource> resourc
5251
// TODO: remove git initialization, handled by precondition check
5352
initializeGitRepoIfNoneExists(absoluteProjectDir);
5453

55-
List<SourceFile> parsedResources = mavenProjectParser.parse(absoluteProjectDir, resources, executionContext).sourceFiles();
54+
List<SourceFile> parsedResources = mavenProjectParser.parse(absoluteProjectDir, resources).sourceFiles();
5655
List<RewriteSourceFileHolder<? extends SourceFile>> rewriteSourceFileHolders = rewriteSourceFileWrapper.wrapRewriteSourceFiles(absoluteProjectDir, parsedResources);
5756

5857
ProjectResourceSet projectResourceSet = projectResourceSetFactory.createFromSourceFileHolders(rewriteSourceFileHolders);

sbm-support-rewrite-integration-test/src/main/java/com/acme/example/SpringBoot3Upgrade.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public void run(String... args) throws Exception {
7575
List<Resource> resources = scanner.scan(baseDir);
7676

7777
// parse
78-
RewriteProjectParsingResult parsingResult = parser.parse(baseDir, resources, executionContext);
78+
RewriteProjectParsingResult parsingResult = parser.parse(baseDir);
7979
List<SourceFile> sourceFiles = parsingResult.sourceFiles();
8080
ProjectResourceSet projectResourceSet = projectResourceSetFactory.create(baseDir, sourceFiles);
8181

sbm-support-rewrite/README.adoc

+109-33
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,37 @@
11
# sbm-support-rewrite
2-
these components
32

43
The `sbm-support-rewrite` project provides Spring beans classes to parse a given project to an OpenRewrite abstract syntax tree (AST) which can then be used to run OpenRewrite recipes that were discovered on the classpath.
54

6-
- `RewriteProjectParser` - parses a project to OpenRewrite's AST representation
7-
- `RecipeDiscovery` - provides access to discovered recipes
5+
## Components
6+
The following components can be used to parse a project, run recipes and write changes back to the filesystem.
7+
These components are provided as Spring beans and can be injected into other Spring beans that require them.
8+
9+
_Example: Inject RewriteProjectParser into your Spring bean_
10+
[source,java]
11+
....
12+
@Autowired
13+
RewriteProjectParser parser;
14+
....
15+
16+
### ProjectScanner
17+
Scan a given path to a list of resources using filter definitions provided as application properties.
18+
19+
### RewriteProjectParser
20+
Parses a project to OpenRewrite's AST representation.
21+
22+
### RewriteExecutionContext
23+
OpenRewrite's `ExecutionContext` gets initialized during parsing.
24+
This `ExecutionContext` is required for some recipes and inner workings of OpenRewrite.
25+
26+
### RecipeDiscovery
27+
Discover OpenRewrite recipes on classpath
28+
29+
### ProjectResourceSet
30+
Abstraction of OpenRewrite SourceFiles that allows execution of recipes against the SourceFiles while
31+
synchronizing changes with the underlying list of SourceFiles.
32+
33+
### ProjectResourceSetSerializer
34+
Write back the in-memory changed SourceFiles from the ProjectResourceSet to the filesystem.
835

936
## Getting started
1037

@@ -36,15 +63,13 @@ Then the dependency can be retrieved.
3663
</dependency>
3764
.....
3865

39-
### Parse a project
40-
41-
`RewriteProjectParser` is provided as Spring bean and can be injected into components.
66+
### (Optional) Scan a project
67+
`ProjectScanner` scans a given `Path` to a list of ``Resource``s.
68+
It filters out resources and directories matching any of the ignore patterns in
69+
`parser.ignoredPathPatterns`.
4270

43-
[source,java]
44-
.....
45-
@Autowired
46-
private RewriteProjectParser parser;
47-
.....
71+
### Parse a project
72+
`RewriteProjectParser` parses a project to OpenRewrite AST.
4873

4974
The provided `parse(Path)` method can be used to parse a project under a given `Path` to OpenRewrite AST.
5075

@@ -55,12 +80,11 @@ List<SourceFile> ast = parser.parse(baseDir);
5580
.....
5681

5782
### ExecutionContext
58-
59-
OpenRewrite's `ExecutionContext` is populated during parsing and the settings can be important for recipes executed later.
60-
The `ExecutionContext` is provided as scoped Spring bean.
83+
OpenRewrite's `ExecutionContext` is populated during parsing and the settings might be required for recipes executed later.
84+
The `ExecutionContext` is provided as scoped Spring bean and can be injected into other Spring beans.
6185
It has the same scope as the parsing and a new instance is automatically created with every parse.
6286

63-
NOTE: The ExecutionContext should be injected and should not be created programmatically.
87+
NOTE: The ExecutionContext should always be injected and should not be created programmatically.
6488

6589
### Discover and run recipes
6690

@@ -78,6 +102,49 @@ Recipe recipe = discovery.getRecipe("org.openrewrite.java.spring.boot3.UpgradeSp
78102
RecipeRun recipe = recipe.run(new InMemoryLargeSourceSet(ast), ctx));
79103
....
80104

105+
### Use ProjectResourceSet
106+
A successful recipe run will return the modified ``SourceFile``s.
107+
Before another recipe can be applied to the AST the changed ``SourceFile``s need to be merged into the original list of ``SourceFile``s (the AST).
108+
The `ProjectResourceSet` provides this capability.
109+
110+
[source,java]
111+
....
112+
@Component
113+
public class SomeClass {
114+
115+
@Autowired
116+
ProjectResourceSetFactory factory;
117+
118+
@Autowired
119+
RewriteProjectParser parser;
120+
121+
void method() {
122+
Recipe r1 = ...
123+
Recipe r2 = ...
124+
RewriteProjectParsingResult parsingResult = parser.parse(baseDir);
125+
List<SourceFile> sourceFiles = parsingResult.sourceFiles();
126+
ProjectResourceSet projectResourceSet = factory.create(baseDir, sourceFiles);
127+
projectResourceSet.apply(r1); // internally changes get merged back to AST
128+
projectResourceSet.apply(r2); // r2 applied against the AST with changes from r1
129+
}
130+
}
131+
....
132+
133+
### Write changes back to filesystem
134+
The `ProjectResourceSetSerializer` can be used to write all changes (modify, delete, add) in `ProjectResourceSet` to the filesystem.
135+
136+
[source,java]
137+
....
138+
@Autowired
139+
private ProjectResourceSetSerializer serializer;
140+
...
141+
public void method() {
142+
...
143+
serializer.writeChanges(projectResourceSet);
144+
}
145+
....
146+
147+
81148

82149
### Listen to ParserEvents
83150

@@ -177,21 +244,23 @@ Example code showing how to apply OpenRewrite's UpgradeSpringBoot_3_1 recipe
177244

178245
[source, java]
179246
.....
247+
package com.example;
248+
180249
import org.openrewrite.*;
181-
import org.openrewrite.internal.InMemoryLargeSourceSet;
182250
import org.springframework.beans.factory.annotation.Autowired;
183251
import org.springframework.boot.CommandLineRunner;
184252
import org.springframework.boot.SpringApplication;
185253
import org.springframework.boot.autoconfigure.SpringBootApplication;
186-
import org.springframework.core.io.Resource;
187254
import org.springframework.sbm.parsers.ProjectScanner;
188-
import org.springframework.sbm.parsers.RewriteMavenProjectParser;
255+
import org.springframework.sbm.parsers.RewriteProjectParser;
189256
import org.springframework.sbm.parsers.RewriteProjectParsingResult;
257+
import org.springframework.sbm.project.resource.ProjectResourceSet;
258+
import org.springframework.sbm.project.resource.ProjectResourceSetFactory;
259+
import org.springframework.sbm.project.resource.ProjectResourceSetSerializer;
190260
import org.springframework.sbm.recipes.RewriteRecipeDiscovery;
191261
192262
import java.nio.file.Path;
193263
import java.util.List;
194-
import java.util.Set;
195264
196265
@SpringBootApplication
197266
public class BootUpgrade implements CommandLineRunner {
@@ -202,9 +271,13 @@ public class BootUpgrade implements CommandLineRunner {
202271
@Autowired
203272
ProjectScanner scanner;
204273
@Autowired
205-
RewriteMavenProjectParser parser;
274+
RewriteProjectParser parser;
206275
@Autowired
207276
RewriteRecipeDiscovery discovery;
277+
@Autowired
278+
ProjectResourceSetSerializer serializer;
279+
@Autowired
280+
ProjectResourceSetFactory factory;
208281
209282
@Override
210283
public void run(String... args) throws Exception {
@@ -215,21 +288,24 @@ public class BootUpgrade implements CommandLineRunner {
215288
if(!baseDir.toFile().exists() || !baseDir.toFile().isDirectory()) {
216289
throw new IllegalArgumentException("Given path '%s' does not exist or is not a directory.".formatted(path));
217290
}
218-
List<Resource> resources = scanner.scan(baseDir, Set.of("**/.idea/**", "**/.DS_Store", "**/.git/**"));
219-
ExecutionContext ctx = new InMemoryExecutionContext(t -> {throw new RuntimeException(t);});
220-
RewriteProjectParsingResult parsingResult = parser.parse(baseDir/*, resources*/, ctx);
291+
292+
// parse
293+
RewriteProjectParsingResult parsingResult = parser.parse(baseDir);
294+
List<SourceFile> sourceFiles = parsingResult.sourceFiles();
295+
296+
// create ProjectResourceSet
297+
ProjectResourceSet projectResourceSet = factory.create(baseDir, sourceFiles);
298+
299+
// find recipe
221300
String recipeName = "org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1";
222301
List<Recipe> recipes = discovery.discoverRecipes();
223-
recipes.stream()
224-
.filter(r -> recipeName.equals(r.getName()))
225-
.forEach(r -> {
226-
System.out.println("Applying recipe '%s'".formatted(r.getName()));
227-
LargeSourceSet lss = new InMemoryLargeSourceSet(parsingResult.sourceFiles());
228-
RecipeRun recipeRun = r.run(lss, ctx);
229-
recipeRun.getChangeset().getAllResults().stream()
230-
.map(Result::diff)
231-
.forEach(System.out::println);
232-
});
302+
Recipe recipe = findRecipe(recipes, recipeName);
303+
304+
// apply recipe
305+
projectResourceSet.apply(recipe);
306+
307+
// write changes to fs
308+
serializer.writeChanges(projectResourceSet);
233309
}
234310
}
235311
.....

0 commit comments

Comments
 (0)