Extract rewrite specific bits into commons-rewrite

This commit is contained in:
BoykoAlex
2022-05-16 16:57:54 -04:00
parent 964dcae009
commit 5ad3f0c52a
18 changed files with 152 additions and 129 deletions

View File

@@ -1,348 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.rewrite;
import static org.openrewrite.Tree.randomId;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.marker.JavaProject;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.marker.JavaVersion;
import org.openrewrite.marker.BuildTool;
import org.openrewrite.marker.Marker;
import org.openrewrite.maven.MavenParser;
import org.openrewrite.maven.tree.Dependency;
import org.openrewrite.maven.tree.MavenResolutionResult;
import org.openrewrite.maven.tree.Pom;
import org.openrewrite.maven.tree.ResolvedPom;
import org.openrewrite.properties.PropertiesParser;
import org.openrewrite.xml.XmlParser;
import org.openrewrite.xml.tree.Xml;
import org.openrewrite.xml.tree.Xml.Document;
import org.openrewrite.yaml.YamlParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Parse a Maven project on disk into a list of {@link org.openrewrite.SourceFile} including
* Maven, Java, YAML, properties, and XML AST representations of sources and resources found.
*/
public class MavenProjectParser {
private static final Pattern mavenWrapperVersionPattern = Pattern.compile(".*apache-maven/(.*?)/.*");
private static final Logger logger = LoggerFactory.getLogger(MavenProjectParser.class);
private final MavenParser mavenParser;
private final JavaParser.Builder<?, ?> javaParserBuilder;
private final ExecutionContext ctx;
public MavenProjectParser(MavenParser.Builder mavenParserBuilder,
JavaParser.Builder<?, ?> javaParserBuilder,
ExecutionContext ctx) {
this.mavenParser = mavenParserBuilder.build();
this.javaParserBuilder = javaParserBuilder;
this.ctx = ctx;
}
/**
* Given a root path to a maven project, this parser will parse the maven project (including submodules)
* and return a list of ALL source files for all maven modules under the root path.
* <PRE>
* Notes About Provenance Information:
*
* There are always three markers applied to each source file and there can potentially be up to five provenance
* markers in total:
*
* BuildTool - What build tool was used to compile the source file (This will always be Maven)
* JavaVersion - What Java version/vendor was used when compiling the source file.
* JavaProject - For each maven module/sub-module, the same JavaProject will be associated with ALL source files
* belonging to that module.
*
* Optional:
*
* GitProvenance - If the entire project exists in the context of a git repository, all source files (for all modules) will have the same GitProvenance.
* JavaSourceSet - All Java source files and all resource files that exist in src/main or src/test will have a JavaSourceSet marker assigned to them.
*
* </PRE>
* @param projectDirectory A path to the root folder containing a meven project.
* @return A list of source files that have been parsed from the root folder
*/
public List<SourceFile> parse(Path projectDirectory, List<Path> dependencies) {
List<Xml.Document> mavens = mavenParser.parse(getMavenPoms(projectDirectory, ctx), projectDirectory, ctx);
List<Document> sorted = sort(mavens);
// Filter out pom files inside target folders. (Naive implementation.)
mavens = sorted.stream().filter(m -> !isInsideBuildFolderOfOtherMavenProjects(sorted, m)).collect(Collectors.toList());
JavaParser javaParser = javaParserBuilder.build();
logger.info("The order in which projects are being parsed is:");
for (Xml.Document maven : mavens) {
logger.info(" {}:{}", getModel(maven).getGroupId(), getModel(maven).getArtifactId());
}
List<SourceFile> sourceFiles = new ArrayList<>();
for (Xml.Document maven : mavens) {
List<Marker> projectProvenance = getJavaProvenance(maven, projectDirectory);
sourceFiles.add(addProjectProvenance(maven, projectProvenance));
// List<Path> dependencies = downloadArtifacts(getResolvedPom(maven).getDependencies().get(Scope.Compile));
javaParser.setSourceSet("main");
javaParser.setClasspath(dependencies);
sourceFiles.addAll(ListUtils.map(javaParser.parse(
getJavaSources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, ctx), addProvenance(projectProvenance)));
//Resources in the src/main should also have the main source set attached to them.
parseResources(getResources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, sourceFiles, projectProvenance, javaParser.getSourceSet(ctx));
// List<Path> testDependencies = downloadArtifacts(maven.getModel().getDependencies(Scope.Test));
javaParser.setSourceSet("test");
// javaParser.setClasspath(testDependencies);
sourceFiles.addAll(ListUtils.map(javaParser.parse(
getTestJavaSources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, ctx), addProvenance(projectProvenance)));
//Resources in the src/test should also have the test source set attached to them.
parseResources(getTestResources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, sourceFiles, projectProvenance, javaParser.getSourceSet(ctx));
}
return sourceFiles;
}
private List<Marker> getJavaProvenance(Xml.Document maven, Path projectDirectory) {
ResolvedPom mavenModel = getModel(maven);
String javaRuntimeVersion = System.getProperty("java.runtime.version");
String javaVendor = System.getProperty("java.vm.vendor");
String sourceCompatibility = javaRuntimeVersion;
String targetCompatibility = javaRuntimeVersion;
String propertiesSourceCompatibility = mavenModel.getValue(mavenModel.getValue("maven.compiler.source"));
if (propertiesSourceCompatibility != null) {
sourceCompatibility = propertiesSourceCompatibility;
}
String propertiesTargetCompatibility = mavenModel.getValue(mavenModel.getValue("maven.compiler.target"));
if (propertiesTargetCompatibility != null) {
targetCompatibility = propertiesTargetCompatibility;
}
Path wrapperPropertiesPath = projectDirectory.resolve(".mvn/wrapper/maven-wrapper.properties");
String mavenVersion = "3.6";
if (Files.exists(wrapperPropertiesPath)) {
try {
Properties wrapperProperties = new Properties();
wrapperProperties.load(new FileReader(wrapperPropertiesPath.toFile()));
String distributionUrl = (String) wrapperProperties.get("distributionUrl");
if (distributionUrl != null) {
Matcher wrapperVersionMatcher = mavenWrapperVersionPattern.matcher(distributionUrl);
if (wrapperVersionMatcher.matches()) {
mavenVersion = wrapperVersionMatcher.group(1);
}
}
} catch (IOException e) {
ctx.getOnError().accept(e);
}
}
return Arrays.asList(
new BuildTool(randomId(), BuildTool.Type.Maven, mavenVersion),
new JavaVersion(randomId(), javaRuntimeVersion, javaVendor, sourceCompatibility, targetCompatibility),
new JavaProject(randomId(), mavenModel.getRequested().getName(), new JavaProject.Publication(
mavenModel.getGroupId(),
mavenModel.getArtifactId(),
mavenModel.getVersion()
))
);
}
private void parseResources(List<Path> resources, Path projectDirectory, List<SourceFile> sourceFiles, List<Marker> projectProvenance, JavaSourceSet sourceSet) {
List<Marker> provenance = new ArrayList<>(projectProvenance);
provenance.add(sourceSet);
sourceFiles.addAll(ListUtils.map(new XmlParser().parse(
resources.stream()
.filter(p -> p.getFileName().toString().endsWith(".xml") ||
p.getFileName().toString().endsWith(".wsdl") ||
p.getFileName().toString().endsWith(".xhtml") ||
p.getFileName().toString().endsWith(".xsd") ||
p.getFileName().toString().endsWith(".xsl") ||
p.getFileName().toString().endsWith(".xslt"))
.collect(Collectors.toList()),
projectDirectory,
ctx
), addProvenance(provenance)));
sourceFiles.addAll(ListUtils.map(new YamlParser().parse(
resources.stream()
.filter(p -> p.getFileName().toString().endsWith(".yml") || p.getFileName().toString().endsWith(".yaml"))
.collect(Collectors.toList()),
projectDirectory,
ctx
), addProvenance(provenance)));
sourceFiles.addAll(ListUtils.map(new PropertiesParser().parse(
resources.stream()
.filter(p -> p.getFileName().toString().endsWith(".properties"))
.collect(Collectors.toList()),
projectDirectory,
ctx
), addProvenance(provenance)));
}
private <S extends SourceFile> S addProjectProvenance(S s, List<Marker> projectProvenance) {
for (Marker marker : projectProvenance) {
s = s.withMarkers(s.getMarkers().addIfAbsent(marker));
}
return s;
}
private <S extends SourceFile> UnaryOperator<S> addProvenance(List<Marker> projectProvenance) {
return s -> {
s = addProjectProvenance(s, projectProvenance);
return s;
};
}
// private List<Path> downloadArtifacts(Set<Dependency> dependencies) {
// return dependencies.stream()
// .filter(d -> d.getRepository() != null)
// .map(artifactDownloader::downloadArtifact)
// .filter(Objects::nonNull)
// .collect(Collectors.toList());
// }
public static List<Xml.Document> sort(List<Xml.Document> mavens) {
// the value is the set of maven projects that depend on the key
Map<Xml.Document, Set<Xml.Document>> byDependedOn = new HashMap<>();
for (Xml.Document maven : mavens) {
byDependedOn.computeIfAbsent(maven, m -> new HashSet<>());
for (Dependency dependency : getModel(maven).getRequested().getDependencies()) {
for (Xml.Document test : mavens) {
if (getModel(test).getGroupId().equals(dependency.getGroupId()) &&
getModel(test).getArtifactId().equals(dependency.getArtifactId())) {
byDependedOn.computeIfAbsent(maven, m -> new HashSet<>()).add(test);
}
}
}
}
List<Xml.Document> sorted = new ArrayList<>(mavens.size());
next:
while (!byDependedOn.isEmpty()) {
for (Map.Entry<Xml.Document, Set<Xml.Document>> mavenAndDependencies : byDependedOn.entrySet()) {
if (mavenAndDependencies.getValue().isEmpty()) {
Xml.Document maven = mavenAndDependencies.getKey();
byDependedOn.remove(maven);
sorted.add(maven);
for (Set<Xml.Document> dependencies : byDependedOn.values()) {
dependencies.remove(maven);
}
continue next;
}
}
}
return sorted;
}
private static boolean isInsideBuildFolderOfOtherMavenProjects(List<Xml.Document> all, Xml.Document current) {
return all.stream().filter(m -> {
if (m != current) {
Path pomPath = m.getSourcePath();
return current.getSourcePath().startsWith((pomPath.getParent() == null ? Paths.get("") : pomPath.getParent()) .resolve("target"));
}
return false;
}).findFirst().isPresent();
}
private static List<Path> getSources(Path srcDir, ExecutionContext ctx, String... fileTypes) {
if (!srcDir.toFile().exists()) {
return List.of();
}
BiPredicate<Path, java.nio.file.attribute.BasicFileAttributes> predicate = (p, bfa) ->
bfa.isRegularFile() && Arrays.stream(fileTypes).anyMatch(type -> p.getFileName().toString().endsWith(type));
try {
return Files.find(srcDir, 999, predicate).collect(Collectors.toList());
} catch (IOException e) {
ctx.getOnError().accept(e);
return List.of();
}
}
public static List<Path> getMavenPoms(Path projectDir, ExecutionContext ctx) {
return getSources(projectDir, ctx, "pom.xml").stream()
.filter(p -> p.getFileName().toString().equals("pom.xml") &&
!p.toString().contains("/src/"))
.collect(Collectors.toList());
}
private static ResolvedPom getModel(Xml.Document maven) {
MavenResolutionResult pom = getResolvedPom(maven);
return pom == null ? null : pom.getPom();
}
private static MavenResolutionResult getResolvedPom(Xml.Document maven) {
return maven.getMarkers().findFirst(MavenResolutionResult.class).orElse(null);
}
private static List<Path> getJavaSources(Pom pom, Path projectDir, ExecutionContext ctx) {
if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) {
return List.of();
}
return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "main", "java")),
ctx, ".java");
}
private static List<Path> getTestJavaSources(Pom pom, Path projectDir, ExecutionContext ctx) {
if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) {
return List.of();
}
return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "test", "java")),
ctx, ".java");
}
private static List<Path> getResources(Pom pom, Path projectDir, ExecutionContext ctx) {
if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) {
return List.of();
}
return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "main", "resources")),
ctx, ".properties", ".xml", ".yml", ".yaml");
}
private static List<Path> getTestResources(Pom pom, Path projectDir, ExecutionContext ctx) {
if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) {
return List.of();
}
return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "test", "resources")),
ctx, ".properties", ".xml", ".yml", ".yaml");
}
}

View File

@@ -1,341 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.rewrite;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.openrewrite.ExecutionContext;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.Parser;
import org.openrewrite.Recipe;
import org.openrewrite.Tree;
import org.openrewrite.TreeVisitor;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ORAstUtils {
private static final Logger log = LoggerFactory.getLogger(ORAstUtils.class);
// private static class ParentMarker implements Marker {
//
// private UUID uuid;
// private J parent;
//
// public ParentMarker(J parent) {
// this.uuid = Tree.randomId();
// this.parent = parent;
// }
//
// @Override
// public UUID getId() {
// return uuid;
// }
//
// public J getParent() {
// return parent;
// }
//
// public J getGrandParent() {
// if (parent != null) {
// return parent.getMarkers().findFirst(ParentMarker.class).map(m -> m.getParent()).orElse(null);
// }
// return null;
// }
//
// public <T> T getFirstAnsector(Class<T> clazz) {
// if (clazz.isInstance(parent)) {
// return clazz.cast(parent);
// } else if (parent != null) {
// return parent.getMarkers().findFirst(ParentMarker.class).map(m -> m.getFirstAnsector(clazz)).orElse(null);
// }
// return null;
// }
//
// @Override
// public <T extends Tree> T withId(UUID id) {
// this.uuid = id;
// return (T) this;
// }
// }
//
// private static class AncestersMarker implements Marker {
//
// private UUID uuid;
// private List<J> ancesters = List.of();
//
// public AncestersMarker(List<J> ancesters) {
// this.uuid = Tree.randomId();
// this.ancesters = ancesters;
// }
//
// @Override
// public UUID getId() {
// return uuid;
// }
//
// @SuppressWarnings("unchecked")
// public <T> T getFirstAnsector(Class<T> clazz) {
// if (ancesters != null) {
// for (J node : ancesters) {
// if (clazz.isInstance(node)) {
// return (T) node;
// }
// }
// }
// return null;
// }
//
// public J getParent() {
// if (ancesters != null && !ancesters.isEmpty()) {
// return ancesters.get(0);
// }
// return null;
// }
//
// public J getGrandParent() {
// if (ancesters != null && ancesters.size() > 1) {
// return ancesters.get(1);
// }
// return null;
// }
// }
//
// private static class MarkParentRecipe extends Recipe {
//
// @Override
// public String getDisplayName() {
// return "Create parent AST node references via markers";
// }
//
// @Override
// protected TreeVisitor<?, ExecutionContext> getVisitor() {
// return new JavaIsoVisitor<>() {
//
// private Cursor parentCursor(Class<?> clazz) {
// for (Cursor c = getCursor(); c != null
// && !(c.getValue() instanceof SourceFile); c = c.getParent()) {
// Object o = c.getValue();
// if (clazz.isInstance(o)) {
// return c;
// }
// }
// return null;
// }
//
// @Override
// public J visit(Tree tree, ExecutionContext p) {
// if (tree instanceof J) {
// J j = (J) tree;
// J newJ = super.visit(j, p).withMarkers(j.getMarkers().addIfAbsent(new ParentMarker(null)));
//
// List<J> children = p.pollMessage(j.getId().toString(), Collections.emptyList());
// for (J child : children) {
// child.getMarkers().findFirst(ParentMarker.class).map(m -> m.parent = newJ);
// }
//
// // Prepare myself for the parent;
//
// Cursor parentCursor = parentCursor(J.class);
// if (parentCursor != null) {
// J parent = parentCursor.getValue();
// String parentId = parent.getId().toString();
// List<J> siblings = p.pollMessage(parentId, new ArrayList<J>());
// siblings.add(newJ);
// p.putMessage(parentId, siblings);
// }
// return newJ;
// }
// return (J) tree;
// }
// };
// }
//
// }
//
// public static J findAstNodeAt(CompilationUnit cu, int offset) {
// AtomicReference<J> f = new AtomicReference<>();
// new JavaIsoVisitor<AtomicReference<J>>() {
// public J visit(Tree tree, AtomicReference<J> found) {
// if (tree == null) {
// return null;
// }
// if (found.get() == null && tree instanceof J) {
// J node = (J) tree;
// Range range = node.getMarkers().findFirst(Range.class).orElse(null);
// if (range != null
// && range.getStart().getOffset() <= offset
// && offset <= range.getEnd().getOffset()) {
// super.visit(tree, found);
// if (found.get() == null) {
// found.set(node);
// return node;
// }
// } else {
// return (J) tree;
// }
// }
// return (J) tree;
// };
// }.visitNonNull(cu, f);
// return f.get();
// }
//
// @SuppressWarnings("unchecked")
// public static <T> T findNode(J node, Class<T> clazz) {
// if (clazz.isInstance(node)) {
// return (T) node;
// }
// return node.getMarkers().findFirst(ParentMarker.class).map(m -> m.getFirstAnsector(clazz)).orElse(null);
// }
//
// public static J getParent(J node) {
// return node.getMarkers().findFirst(ParentMarker.class).map(m -> m.getParent()).orElse(null);
// }
public static List<CompilationUnit> parse(JavaParser parser, Iterable<Path> sourceFiles) {
InMemoryExecutionContext ctx = new InMemoryExecutionContext(e -> log.error("", e));
ctx.putMessage(JavaParser.SKIP_SOURCE_SET_TYPE_GENERATION, true);
List<CompilationUnit> cus = parser.parse(sourceFiles, null, ctx);
return cus;
// List<Result> results = new UpdateSourcePositions().doNext(new MarkParentRecipe()).run(cus);
// return results.stream().map(r -> r.getAfter() == null ? r.getBefore() : r.getAfter()).map(CompilationUnit.class::cast).collect(Collectors.toList());
}
public static List<CompilationUnit> parseInputs(JavaParser parser, Iterable<Parser.Input> inputs) {
InMemoryExecutionContext ctx = new InMemoryExecutionContext(e -> log.error("", e));
ctx.putMessage(JavaParser.SKIP_SOURCE_SET_TYPE_GENERATION, true);
List<CompilationUnit> cus = parser.parseInputs(inputs, null, ctx);
return cus;
// List<Result> results = new UpdateSourcePositions().doNext(new MarkParentRecipe()).run(cus);
// return results.stream().map(r -> r.getAfter() == null ? r.getBefore() : r.getAfter()).map(CompilationUnit.class::cast).collect(Collectors.toList());
}
public static J.EnumValueSet getEnumValues(J.ClassDeclaration classDecl) {
return classDecl.getBody().getStatements().stream()
.filter(J.EnumValueSet.class::isInstance)
.map(J.EnumValueSet.class::cast)
.findAny()
.orElse(null);
}
public static List<J.VariableDeclarations> getFields(J.ClassDeclaration classDecl) {
return classDecl.getBody().getStatements().stream()
.filter(J.VariableDeclarations.class::isInstance)
.map(J.VariableDeclarations.class::cast)
.collect(Collectors.toList());
}
public static List<J.MethodDeclaration> getMethods(J.ClassDeclaration classDecl) {
return classDecl.getBody().getStatements().stream()
.filter(J.MethodDeclaration.class::isInstance)
.map(J.MethodDeclaration.class::cast)
.collect(Collectors.toList());
}
public static String getSimpleName(String fqName) {
int idx = fqName.lastIndexOf('.');
if (idx < fqName.length() - 1) {
return fqName.substring(idx + 1);
}
return fqName;
}
@SuppressWarnings("unchecked")
private static TreeVisitor<?, ExecutionContext> getVisitor(Recipe r) {
try {
Method m = Recipe.class.getDeclaredMethod("getVisitor");
m.setAccessible(true);
return (TreeVisitor<?, ExecutionContext>) m.invoke(r);
} catch (Exception e) {
return null;
}
}
@SuppressWarnings("unchecked")
private static List<TreeVisitor<J, ExecutionContext>> getAfterVisitors(TreeVisitor<J, ExecutionContext> visitor) {
try {
Method m = TreeVisitor.class.getDeclaredMethod("getAfterVisit");
m.setAccessible(true);
return (List<TreeVisitor<J, ExecutionContext>>) m.invoke(visitor);
} catch (Exception e) {
return Collections.emptyList();
}
}
private static void makeVisitorNonTopLevel(JavaVisitor<ExecutionContext> visitor) {
try {
Field f = TreeVisitor.class.getDeclaredField("afterVisit");
f.setAccessible(true);
f.set(visitor, new ArrayList<>());
} catch (Exception e) {
// ignore
}
}
public static Recipe nodeRecipe(JavaVisitor<ExecutionContext> v, Predicate<J> condition) {
return new NodeRecipe((JavaVisitor<ExecutionContext>) v, condition);
}
@SuppressWarnings("unchecked")
public static Recipe nodeRecipe(Recipe r, Predicate<J> condition) {
return new NodeRecipe((JavaVisitor<ExecutionContext>) getVisitor(r), condition);
}
private static class NodeRecipe extends Recipe {
private JavaVisitor<ExecutionContext> visitor;
private Predicate<J> condition;
public NodeRecipe(JavaVisitor<ExecutionContext> visitor, Predicate<J> condition) {
this.visitor = visitor;
this.condition = condition;
}
@Override
public String getDisplayName() {
return "";
}
@Override
protected TreeVisitor<?, ExecutionContext> getVisitor() {
return new JavaVisitor<>() {
@Override
public J visit(Tree tree, ExecutionContext ctx) {
J t = super.visit(tree, ctx);
if (condition.test(t)) {
makeVisitorNonTopLevel(visitor);
t = visitor.visit(t, ctx, getCursor());
for (TreeVisitor<J, ExecutionContext> v : getAfterVisitors(visitor)) {
doAfterVisit(v);
}
}
return t;
}
};
}
}
}

View File

@@ -45,6 +45,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFin
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.cache.Cache;

View File

@@ -1,191 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.rewrite;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.lsp4j.CreateFile;
import org.eclipse.lsp4j.DeleteFile;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.openrewrite.Result;
import org.openrewrite.shaded.jgit.diff.Edit;
import org.openrewrite.shaded.jgit.diff.EditList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.utils.JGitUtils;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.IRegion;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class ORDocUtils {
private static final Logger log = LoggerFactory.getLogger(ORDocUtils.class);
public static Optional<DocumentEdits> computeEdits(IDocument doc, Result result) {
TextDocument newDoc = new TextDocument(null, LanguageId.PLAINTEXT, 0, result.getAfter().printAll());
EditList diff = JGitUtils.getDiff(result.getBefore().printAll(), newDoc.get());
if (!diff.isEmpty()) {
DocumentEdits edits = new DocumentEdits(doc, false);
for (Edit e : diff) {
try {
switch(e.getType()) {
case DELETE:
edits.delete(doc.getLineOffset(e.getBeginA()), getStartOfLine(doc, e.getEndA()));
break;
case INSERT:
edits.insert(doc.getLineOffset(e.getBeginA()), newDoc.textBetween(newDoc.getLineOffset(e.getBeginB()), getStartOfLine(newDoc, e.getEndB())));
break;
case REPLACE:
edits.replace(doc.getLineOfOffset(e.getBeginA()), getStartOfLine(doc, e.getEndA()), newDoc.textBetween(newDoc.getLineOffset(e.getBeginB()), getStartOfLine(newDoc, e.getEndB())));
break;
case EMPTY:
break;
}
} catch (BadLocationException ex) {
log.error("Diff conversion failed", ex);
}
}
return Optional.of(edits);
}
return Optional.empty();
}
public static Optional<TextDocumentEdit> computeTextDocEdit(TextDocument doc, Result result) {
TextDocument newDoc = new TextDocument(null, LanguageId.PLAINTEXT, 0, result.getAfter().printAll());
EditList diff = JGitUtils.getDiff(result.getBefore().printAll(), newDoc.get());
if (!diff.isEmpty()) {
TextDocumentEdit edit = new TextDocumentEdit();
edit.setTextDocument(new VersionedTextDocumentIdentifier(doc.getUri(), doc.getVersion()));
List<TextEdit> textEdits = new ArrayList<>();
edit.setEdits(textEdits);
for (Edit e : diff) {
try {
switch(e.getType()) {
case DELETE:
TextEdit textEdit = new TextEdit();
int start = doc.getLineOffset(e.getBeginA());
int end = getStartOfLine(doc, e.getEndA());
textEdit.setRange(new Range(doc.toPosition(start), doc.toPosition(end)));
textEdit.setNewText("");
textEdits.add(textEdit);
break;
case INSERT:
textEdit = new TextEdit();
Position position = doc.toPosition(doc.getLineOffset(e.getBeginA()));
textEdit.setRange(new Range(position, position));
textEdit.setNewText(newDoc.textBetween(newDoc.getLineOffset(e.getBeginB()), getStartOfLine(newDoc, e.getEndB())));
textEdits.add(textEdit);
break;
case REPLACE:
textEdit = new TextEdit();
start = doc.getLineOffset(e.getBeginA());
end = getStartOfLine(doc, e.getEndA());
textEdit.setRange(new Range(doc.toPosition(start), doc.toPosition(end)));
textEdit.setNewText(newDoc.textBetween(newDoc.getLineOffset(e.getBeginB()), getStartOfLine(newDoc, e.getEndB())));
textEdits.add(textEdit);
break;
case EMPTY:
break;
}
} catch (BadLocationException ex) {
log.error("Diff conversion failed", ex);
}
}
return Optional.of(edit);
}
return Optional.empty();
}
public static Optional<TextDocumentEdit> computeSimpleTextDocEdit(TextDocument doc, Result result) {
TextDocument newDoc = new TextDocument(null, LanguageId.PLAINTEXT, 0, result.getAfter().printAll());
EditList diff = JGitUtils.getDiff(result.getBefore().printAll(), newDoc.get());
if (!diff.isEmpty()) {
TextDocumentEdit edit = new TextDocumentEdit();
edit.setTextDocument(new VersionedTextDocumentIdentifier(doc.getUri(), doc.getVersion()));
TextEdit te = new TextEdit();
te.setNewText(result.getAfter().printAll());
try {
te.setRange(new Range(new Position(0,0), doc.toPosition(doc.getLength())));
} catch (BadLocationException e) {
// ignore
}
edit.setEdits(List.of(te));
return Optional.of(edit);
}
return Optional.empty();
}
private static int getStartOfLine(IDocument doc, int lineNumber) {
IRegion lineInformation = doc.getLineInformation(lineNumber);
if (lineInformation != null) {
return lineInformation.getOffset();
}
if (lineNumber > 0) {
IRegion currentLine = doc.getLineInformation(lineNumber - 1);
return currentLine.getOffset() + currentLine.getLength();
}
return 0;
}
public static Optional<WorkspaceEdit> createWorkspaceEdit(Path absoluteProjectDir, SimpleTextDocumentService documents, List<Result> results) {
if (results.isEmpty()) {
return Optional.empty();
}
WorkspaceEdit we = new WorkspaceEdit();
we.setDocumentChanges(new ArrayList<>());
for (Result result : results) {
if (result.getBefore() == null) {
String docUri = absoluteProjectDir.resolve(result.getAfter().getSourcePath()).toUri().toString();
CreateFile ro = new CreateFile();
ro.setUri(docUri);
we.getDocumentChanges().add(Either.forRight(ro));
TextDocumentEdit te = new TextDocumentEdit();
te.setTextDocument(new VersionedTextDocumentIdentifier(docUri, 0));
Position cursor = new Position(0,0);
te.setEdits(List.of(new TextEdit(new Range(cursor, cursor), result.getAfter().printAll())));
we.getDocumentChanges().add(Either.forLeft(te));
} else if (result.getAfter() == null) {
String docUri = absoluteProjectDir.resolve(result.getBefore().getSourcePath()).toUri().toString();
we.getDocumentChanges().add(Either.forRight(new DeleteFile(docUri)));
} else {
String docUri = absoluteProjectDir.resolve(result.getBefore().getSourcePath()).toUri().toString();
TextDocument doc = documents.getLatestSnapshot(docUri);
if (doc == null) {
doc = new TextDocument(docUri, null, 0, result.getBefore().printAll());
ORDocUtils.computeTextDocEdit(doc, result).ifPresent(te -> we.getDocumentChanges().add(Either.forLeft(te)));
} else {
ORDocUtils.computeTextDocEdit(doc, result).ifPresent(te -> we.getDocumentChanges().add(Either.forLeft(te)));
}
}
}
return Optional.of(we);
}
}

View File

@@ -48,6 +48,8 @@ import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.rewrite.ORDocUtils;
import org.springframework.ide.vscode.commons.rewrite.maven.MavenProjectParser;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;

View File

@@ -34,12 +34,12 @@ import org.openrewrite.Result;
import org.openrewrite.java.tree.J;
import org.springframework.ide.vscode.boot.java.handlers.JavaCodeAction;
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
import org.springframework.ide.vscode.boot.java.rewrite.ORDocUtils;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.LspClient;
import org.springframework.ide.vscode.commons.languageserver.util.LspClient.Client;
import org.springframework.ide.vscode.commons.rewrite.ORDocUtils;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.text.IRegion;
import org.springframework.ide.vscode.commons.util.text.LanguageId;

View File

@@ -32,10 +32,10 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
import org.springframework.ide.vscode.boot.rewrite.java.ConvertAutowiredParameterIntoConstructorParameter;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.rewrite.java.ConvertAutowiredParameterIntoConstructorParameter;
import org.springframework.ide.vscode.commons.util.text.IRegion;
import org.springframework.ide.vscode.commons.util.text.TextDocument;

View File

@@ -29,12 +29,12 @@ import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.spring.NoRequestMappingAnnotation;
import org.springframework.ide.vscode.boot.java.rewrite.ORAstUtils;
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
import org.springframework.ide.vscode.commons.util.text.IRegion;
import org.springframework.ide.vscode.commons.util.text.TextDocument;

View File

@@ -23,12 +23,12 @@ import org.openrewrite.Recipe;
import org.openrewrite.Result;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.tree.J;
import org.springframework.ide.vscode.boot.java.rewrite.ORAstUtils;
import org.springframework.ide.vscode.boot.java.rewrite.ORCompilationUnitCache;
import org.springframework.ide.vscode.boot.java.rewrite.ORDocUtils;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit;
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixHandler;
import org.springframework.ide.vscode.commons.rewrite.ORDocUtils;
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.gson.Gson;

View File

@@ -1,20 +0,0 @@
package org.springframework.ide.vscode.boot.java.utils;
import java.nio.charset.StandardCharsets;
import org.openrewrite.shaded.jgit.diff.EditList;
import org.openrewrite.shaded.jgit.diff.HistogramDiff;
import org.openrewrite.shaded.jgit.diff.RawText;
import org.openrewrite.shaded.jgit.diff.RawTextComparator;
public class JGitUtils {
public static EditList getDiff(String txt1, String txt2) {
RawText rt1 = new RawText(txt1.getBytes(StandardCharsets.UTF_8));
RawText rt2 = new RawText(txt2.getBytes(StandardCharsets.UTF_8));
EditList diffList = new EditList();
diffList.addAll(new HistogramDiff().diff(RawTextComparator.DEFAULT, rt1, rt2));
return diffList;
}
}

View File

@@ -1,201 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.rewrite.java;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.openrewrite.Cursor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.java.AnnotationMatcher;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.RemoveAnnotationVisitor;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.Block;
import org.openrewrite.java.tree.J.ClassDeclaration;
import org.openrewrite.java.tree.J.Empty;
import org.openrewrite.java.tree.J.MethodDeclaration;
import org.openrewrite.java.tree.J.VariableDeclarations;
import org.openrewrite.java.tree.JavaType.FullyQualified;
import org.openrewrite.java.tree.Statement;
import org.openrewrite.java.tree.TypeTree;
import org.openrewrite.java.tree.TypeUtils;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.rewrite.ORAstUtils;
public class ConvertAutowiredParameterIntoConstructorParameter extends Recipe {
private String classFqName;
private String fieldName;
public ConvertAutowiredParameterIntoConstructorParameter(String classFqName, String fieldName) {
super();
this.classFqName = classFqName;
this.fieldName = fieldName;
}
@Override
public String getDisplayName() {
return "Convert autowired field into constructor parameter";
}
@Override
protected TreeVisitor<?, ExecutionContext> getVisitor() {
return new JavaVisitor<ExecutionContext>() {
@Override
public J visitClassDeclaration(ClassDeclaration classDecl, ExecutionContext p) {
if (classFqName.equals(classDecl.getType().getFullyQualifiedName())) {
return super.visitClassDeclaration(classDecl, p);
}
return classDecl;
}
@Override
public J visitVariableDeclarations(VariableDeclarations multiVariable, ExecutionContext p) {
Cursor blockCursor = getCursor().dropParentUntil(Block.class::isInstance);
VariableDeclarations mv = multiVariable;
if (blockCursor != null && blockCursor.getParent().getValue() instanceof ClassDeclaration
&& multiVariable.getVariables().size() == 1
&& fieldName.equals(multiVariable.getVariables().get(0).getName().printTrimmed())) {
mv = (VariableDeclarations) new RemoveAnnotationVisitor(new AnnotationMatcher("@" + Annotations.AUTOWIRED)).visit(multiVariable, p);
doAfterVisit(new AddContructorParameterVisitor(classFqName, fieldName, multiVariable.getTypeExpression()));
}
return mv;
}
};
}
private static class AddContructorParameterVisitor extends JavaVisitor<ExecutionContext> {
private String classFqName;
private String fieldName;
private TypeTree type;
public AddContructorParameterVisitor(String classFqName, String fieldName, TypeTree type) {
super();
this.classFqName = classFqName;
this.fieldName = fieldName;
this.type = type;
}
@Override
public J visitClassDeclaration(ClassDeclaration classDecl, ExecutionContext p) {
ClassDeclaration c = classDecl;
if (classFqName.equals(c.getType().getFullyQualifiedName())) {
List<MethodDeclaration> constructors = ORAstUtils.getMethods(c).stream().filter(m -> m.isConstructor()).collect(Collectors.toList());
if (constructors.isEmpty()) {
doAfterVisit(new AddConstructorVisitor(c.getSimpleName(), fieldName, type));
} else {
Optional<MethodDeclaration> autowiredConstructor = constructors.stream().filter(constr -> constr.getLeadingAnnotations().stream()
.map(a -> TypeUtils.asFullyQualified(a.getType()))
.filter(Objects::nonNull)
.map(fq -> fq.getFullyQualifiedName())
.filter(fqn -> Annotations.AUTOWIRED.equals(fqn))
.findFirst()
.isPresent()
)
.findFirst();
if (autowiredConstructor.isPresent()) {
// Autowired constructor found - add argument to it
doAfterVisit(new AddMethodParameter(autowiredConstructor.get(), fieldName, type));
} else {
if (constructors.size() == 1) {
doAfterVisit(new AddMethodParameter(constructors.get(0), fieldName, type));
}
}
}
}
return c;
}
}
private static class AddConstructorVisitor extends JavaVisitor<ExecutionContext> {
private String className;
private String fieldName;
private TypeTree type;
public AddConstructorVisitor(String className, String fieldName, TypeTree type) {
this.className = className;
this.fieldName = fieldName;
this.type = type;
}
@Override
public J visitBlock(Block block, ExecutionContext p) {
if (getCursor().getParent() != null) {
Object n = getCursor().getParent().getValue();
if (n instanceof ClassDeclaration) {
ClassDeclaration classDecl = (ClassDeclaration) n;
if (classDecl.getKind() == ClassDeclaration.Kind.Type.Class && className.equals(classDecl.getSimpleName())) {
JavaTemplate.Builder template = JavaTemplate.builder(() -> getCursor(), ""
+ classDecl.getSimpleName() + "(" + type.printTrimmed() + " " + fieldName + ") {\n"
+ "this." + fieldName + " = " + fieldName + ";\n"
+ "}\n"
);
FullyQualified fq = TypeUtils.asFullyQualified(type.getType());
if (fq != null) {
template.imports(fq.getFullyQualifiedName());
maybeAddImport(fq);
}
Optional<Statement> firstMethod = block.getStatements().stream().filter(MethodDeclaration.class::isInstance).findFirst();
if (firstMethod.isPresent()) {
return block.withTemplate(template.build(), firstMethod.get().getCoordinates().before());
} else {
return block.withTemplate(template.build(), block.getCoordinates().lastStatement());
}
}
}
}
return block;
}
}
private static class AddMethodParameter extends JavaIsoVisitor<ExecutionContext> {
private MethodDeclaration method;
private String fieldName;
private TypeTree type;
public AddMethodParameter(MethodDeclaration method, String fieldName, TypeTree type) {
this.method = method;
this.fieldName = fieldName;
this.type = type;
}
@Override
public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, ExecutionContext p) {
if (method == this.method) {
String paramsStr = Stream.concat(method.getParameters().stream().filter(s -> !Empty.class.isInstance(s)).map(s -> s.printTrimmed()), Stream.of(type.printTrimmed() + " " + fieldName)).collect(Collectors.joining(", "));
JavaTemplate.Builder paramsTemplate = JavaTemplate.builder(() -> getCursor(), paramsStr);
JavaTemplate.Builder statementTemplate = JavaTemplate.builder(() -> getCursor(), "this." + fieldName + " = " + fieldName + ";\n");
return method
.withTemplate(paramsTemplate.build(), method.getCoordinates().replaceParameters())
.withTemplate(statementTemplate.build(), method.getBody().getCoordinates().lastStatement());
}
return method;
}
}
}

View File

@@ -1,131 +0,0 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.rewrite.maven;
import java.util.Objects;
import java.util.Optional;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Option;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.maven.MavenVisitor;
import org.openrewrite.xml.AddToTagVisitor;
import org.openrewrite.xml.ChangeTagValueVisitor;
import org.openrewrite.xml.RemoveContentVisitor;
import org.openrewrite.xml.tree.Xml;
public class ChangeDependencyClassifier extends Recipe {
@Option(displayName = "Group",
description = "The first part of a dependency coordinate 'com.google.guava:guava:VERSION'.",
example = "com.google.guava")
String groupId;
@Option(displayName = "Artifact",
description = "The second part of a dependency coordinate 'com.google.guava:guava:VERSION'.",
example = "guava")
String artifactId;
/**
* If null, strips the scope from an existing dependency.
*/
@Option(displayName = "New classifier",
description = "Classifier to apply to specified Maven dependency. " +
"May be omitted, which indicates that no classifier should be added and any existing scope be removed from the dependency.",
example = "jar",
required = false)
@Nullable
String newClassifier;
@Override
public String getDisplayName() {
return "Change Maven dependency classifier";
}
@Override
public String getDescription() {
return "Add or alter the classifier of the specified dependency.";
}
@Override
protected TreeVisitor<?, ExecutionContext> getVisitor() {
return new MavenVisitor<ExecutionContext>() {
@Override
public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
if (isDependencyTag()) {
if (groupId.equals(tag.getChildValue("groupId").orElse(getResolutionResult().getPom().getGroupId())) &&
artifactId.equals(tag.getChildValue("artifactId").orElse(null))) {
Optional<Xml.Tag> scope = tag.getChild("classifier");
if (scope.isPresent()) {
if (newClassifier == null) {
doAfterVisit(new RemoveContentVisitor<>(scope.get(), false));
} else if (!newClassifier.equals(scope.get().getValue().orElse(null))) {
doAfterVisit(new ChangeTagValueVisitor<>(scope.get(), newClassifier));
}
} else if (newClassifier != null) {
doAfterVisit(new AddToTagVisitor<>(tag, Xml.Tag.build("<classifier>" + newClassifier + "</classifier>")));
}
}
}
return super.visitTag(tag, ctx);
}
};
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getArtifactId() {
return artifactId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
public String getNewClassifier() {
return newClassifier;
}
public void setNewClassifier(String newClassifier) {
this.newClassifier = newClassifier;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hash(artifactId, groupId, newClassifier);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
ChangeDependencyClassifier other = (ChangeDependencyClassifier) obj;
return Objects.equals(artifactId, other.artifactId) && Objects.equals(groupId, other.groupId)
&& Objects.equals(newClassifier, other.newClassifier);
}
}

View File

@@ -1,25 +0,0 @@
---
########################################################################################################################
# SpringBoot 3_0
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0
displayName: Upgrade to Spring Boot 3.0 from 2.x
description: 'Upgrade to Spring Boot 3.0 from prior 2.x version.'
recipeList:
# Upgrade 3.0.x from 2.x
- org.openrewrite.maven.UpgradeDependencyVersion:
groupId: org.springframework.boot
artifactId: "*"
newVersion: 3.0.0-SNAPSHOT
trustParent: true
- org.openrewrite.maven.UpgradeParentVersion:
groupId: org.springframework.boot
artifactId: spring-boot-starter-parent
newVersion: 3.0.0-SNAPSHOT
- org.openrewrite.maven.ChangePropertyValue:
key: 'java.version'
newValue: 17
addIfMissing: true
- org.openrewrite.java.spring.data.UpgradeSpringData_3_0

View File

@@ -1,24 +0,0 @@
########################################################################################################################
# Spring Data 3.0
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.spring.data.UpgradeSpringData_3_0
displayName: Upgrade to Spring Data 3.0
description: 'Upgrade to Spring Data to 3.0 from any prior version.'
recipeList:
- org.springframework.ide.vscode.boot.rewrite.maven.ChangeDependencyClassifier:
groupId: org.ehcache
artifactId: ehcache
newClassifier: jakarta
- org.openrewrite.java.ChangePackage:
oldPackageName: javax.persistence
newPackageName: jakarta.persistence
recursive: true
- org.openrewrite.java.ChangePackage:
oldPackageName: javax.validation
newPackageName: jakarta.validation
recursive: true
- org.openrewrite.java.ChangePackage:
oldPackageName: javax.xml.bind
newPackageName: jakarta.xml.bind
recursive: true