Add recipe launcher

* Bum Spring Boot to 3.2.1
* Remove comment
* Add recipe launcher component
This commit is contained in:
Fabian Krüger
2024-01-24 17:51:27 +00:00
committed by GitHub
parent d1a918a0a5
commit a2406bd719
4 changed files with 168 additions and 17 deletions

View File

@@ -30,7 +30,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- prod dependencies -->
<spring-boot.version>3.1.3</spring-boot.version>
<spring-boot.version>3.2.1</spring-boot.version>
<rewrite.version>8.13.4</rewrite.version>
<rewrite-kotlin.version>1.8.4</rewrite-kotlin.version>
<rewrite-polyglot.version>1.8.11</rewrite-polyglot.version>

View File

@@ -38,22 +38,6 @@
</dependencyManagement>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.rewrite</groupId>-->
<!-- <artifactId>spring-rewrite-commons-launcher</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.openrewrite.recipe</groupId>-->
<!-- <artifactId>rewrite-spring</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.openrewrite.recipe</groupId>-->
<!-- <artifactId>rewrite-migrate-java</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.rewrite</groupId>
<artifactId>spring-rewrite-commons-starter-boot-upgrade</artifactId>

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2021 - 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.rewrite.boot.autoconfigure;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.rewrite.execution.RewriteRecipeLauncher;
import org.springframework.rewrite.parsers.RewriteProjectParser;
import org.springframework.rewrite.project.resource.ProjectResourceSetFactory;
import org.springframework.rewrite.project.resource.ProjectResourceSetSerializer;
import org.springframework.rewrite.recipes.RewriteRecipeDiscovery;
/**
* @author Fabian Krüger
*/
@AutoConfiguration(after = { ProjectResourceSetConfiguration.class, RecipeDiscoveryConfiguration.class })
@Import({ ProjectResourceSetConfiguration.class, RecipeDiscoveryConfiguration.class })
public class RewriteLauncherConfiguration {
@Bean
RewriteRecipeLauncher rewriteRecipeLaucnher(RewriteProjectParser parser, RewriteRecipeDiscovery dicovery,
ProjectResourceSetFactory resourceSetFactory, ProjectResourceSetSerializer deserializer) {
return new RewriteRecipeLauncher(parser, dicovery, resourceSetFactory, deserializer);
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2021 - 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.rewrite.execution;
import org.jetbrains.annotations.NotNull;
import org.openrewrite.Recipe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.rewrite.parsers.RewriteProjectParser;
import org.springframework.rewrite.parsers.RewriteProjectParsingResult;
import org.springframework.rewrite.project.resource.ProjectResourceSet;
import org.springframework.rewrite.project.resource.ProjectResourceSetFactory;
import org.springframework.rewrite.project.resource.ProjectResourceSetSerializer;
import org.springframework.rewrite.recipes.RewriteRecipeDiscovery;
import org.springframework.util.StopWatch;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
* @author Fabian Krüger
*/
public class RewriteRecipeLauncher {
private static final Logger logger = LoggerFactory.getLogger(RewriteRecipeLauncher.class);
private final RewriteProjectParser parser;
private final RewriteRecipeDiscovery discovery;
private final ProjectResourceSetFactory resourceSetFactory;
private final ProjectResourceSetSerializer serializer;
public interface RewriteRecipeRunnerProgressListener {
void progress(String progressMessage);
}
public RewriteRecipeLauncher(RewriteProjectParser parser, RewriteRecipeDiscovery discovery,
ProjectResourceSetFactory resourceSetFactory, ProjectResourceSetSerializer serializer) {
this.parser = parser;
this.discovery = discovery;
this.resourceSetFactory = resourceSetFactory;
this.serializer = serializer;
}
public void run(String recipeName, String path) {
run(recipeName, path, __ -> {
});
}
public void run(String recipeName, String path, RewriteRecipeRunnerProgressListener listener) {
Path baseDir = getBaseDir(path);
RewriteProjectParsingResult parsingResult = parseProject(baseDir, listener);
Optional<Recipe> recipe = discoverRecipe(recipeName);
if (recipe.isPresent()) {
applyRecipe(recipeName, baseDir, parsingResult, recipe, listener);
}
else {
logger.error("Could not find recipe " + recipeName + ".");
}
}
@NotNull
private RewriteProjectParsingResult parseProject(Path baseDir, RewriteRecipeRunnerProgressListener listener) {
listener.progress("Start parsing dir '%s'".formatted(baseDir));
StopWatch stopWatch = new StopWatch("parse");
stopWatch.start();
RewriteProjectParsingResult parsingResult = parser.parse(baseDir);
stopWatch.stop();
double parseTime = stopWatch.getTotalTime(TimeUnit.SECONDS);
listener.progress("Parsed %d resources in %f sec.".formatted(parsingResult.sourceFiles().size(), parseTime));
return parsingResult;
}
private void applyRecipe(String recipeName, Path baseDir, RewriteProjectParsingResult parsingResult,
Optional<Recipe> recipe, RewriteRecipeRunnerProgressListener listener) {
StopWatch stopWatch = new StopWatch("parse");
stopWatch.start();
// Use ProjectResourceSet abstraction
ProjectResourceSet projectResourceSet = resourceSetFactory.create(baseDir, parsingResult.sourceFiles());
// To apply recipes
listener.progress("Applying recipe %s, this may take a few minutes.".formatted(recipeName));
projectResourceSet.apply(recipe.get());
stopWatch.stop();
double recipeRunTime = stopWatch.getTotalTime(TimeUnit.MINUTES);
listener.progress("Applied recipe %s in %f min.".formatted(recipeName, recipeRunTime));
// Synchronize changes with filesystem
listener.progress("Write changes from %s.".formatted(recipeName));
serializer.writeChanges(projectResourceSet);
}
@NotNull
private Optional<Recipe> discoverRecipe(String recipeName) {
// discover recipe
List<Recipe> recipes = discovery.discoverRecipes();
Optional<Recipe> recipe = recipes.stream().filter(r -> recipeName.equals(r.getName())).findFirst();
return recipe;
}
@NotNull
private static Path getBaseDir(String path) {
Path baseDir = Path.of(".").toAbsolutePath().normalize();
if (path != null) {
baseDir = Path.of(path).toAbsolutePath().normalize();
}
return baseDir;
}
}