Rewrite upgrade
This commit is contained in:
@@ -56,7 +56,7 @@ public class LanguageServerProperties {
|
||||
* Reconcile sources regardless whether source is opened in an editor or not.
|
||||
* If on only opened documents will be reconciled
|
||||
*/
|
||||
private boolean reconcileOnlyOpenedDocs = true;
|
||||
private boolean reconcileOnlyOpenedDocs = false;
|
||||
|
||||
public boolean isStandalone() {
|
||||
return standalone;
|
||||
|
||||
@@ -455,8 +455,11 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE
|
||||
int start = doc.toOffset(params.getRange().getStart());
|
||||
int end = doc.toOffset(params.getRange().getEnd());
|
||||
listBuilder.addAll(codeActionHandler.handle(cancelToken, capabilities, context, doc, new Region(start, end - start)));
|
||||
} catch (BadLocationException e) {
|
||||
// ignore bad location. Might come from stale doc version
|
||||
log.debug("Stale range", e);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to compute quick refactorings", e);
|
||||
log.error("Failed to compute quick refactorings", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,32 +10,11 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.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.search.UsesType;
|
||||
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.openrewrite.java.spring.AutowiredFieldIntoConstructorParameterVisitor;
|
||||
|
||||
public class ConvertAutowiredFieldIntoConstructorParameter extends Recipe {
|
||||
|
||||
@@ -61,146 +40,7 @@ public class ConvertAutowiredFieldIntoConstructorParameter extends Recipe {
|
||||
|
||||
@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).getSimpleName())) {
|
||||
|
||||
mv = (VariableDeclarations) new RemoveAnnotationVisitor(new AnnotationMatcher("@" + AUTOWIRED)).visit(multiVariable, p);
|
||||
doAfterVisit(new AddContructorParameterVisitor(classFqName, fieldName, multiVariable.getTypeExpression()));
|
||||
}
|
||||
return mv;
|
||||
}
|
||||
|
||||
};
|
||||
return new AutowiredFieldIntoConstructorParameterVisitor(classFqName, fieldName);
|
||||
}
|
||||
|
||||
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 -> 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.InMemoryExecutionContext;
|
||||
import org.openrewrite.Parser;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.RecipeRun;
|
||||
import org.openrewrite.Result;
|
||||
import org.openrewrite.Tree;
|
||||
import org.openrewrite.TreeVisitor;
|
||||
@@ -226,7 +227,8 @@ public class ORAstUtils {
|
||||
synchronized(parser) {
|
||||
cus = parser.parse(sourceFiles, null, ctx);
|
||||
}
|
||||
List<Result> results = new UpdateSourcePositions()/*.doNext(new MarkParentRecipe())*/.run(cus);
|
||||
RecipeRun reciperun = new UpdateSourcePositions()/*.doNext(new MarkParentRecipe())*/.run(cus);
|
||||
List<Result> results = reciperun.getResults();
|
||||
return results.stream().map(r -> r.getAfter() == null ? r.getBefore() : r.getAfter()).map(CompilationUnit.class::cast).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -237,7 +239,8 @@ public class ORAstUtils {
|
||||
synchronized (parser) {
|
||||
cus = parser.parseInputs(inputs, null, ctx);
|
||||
}
|
||||
List<Result> results = new UpdateSourcePositions()/*.doNext(new MarkParentRecipe())*/.run(cus);
|
||||
RecipeRun reciperun = new UpdateSourcePositions()/*.doNext(new MarkParentRecipe())*/.run(cus);
|
||||
List<Result> results = reciperun.getResults();
|
||||
return results.stream().map(r -> r.getAfter() == null ? r.getBefore() : r.getAfter()).map(CompilationUnit.class::cast).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@@ -109,10 +109,10 @@
|
||||
<commons-codec-version>1.13</commons-codec-version>
|
||||
|
||||
<!-- Rewrite specific properties -->
|
||||
<rewrite-version>7.26.1</rewrite-version>
|
||||
<rewrite-spring-version>4.23.0</rewrite-spring-version>
|
||||
<rewrite-java-migration.version>1.8.0</rewrite-java-migration.version>
|
||||
<rewrite-jackson.version>2.13.2</rewrite-jackson.version>
|
||||
<rewrite-version>7.30.0</rewrite-version>
|
||||
<rewrite-spring-version>4.27.0</rewrite-spring-version>
|
||||
<rewrite-java-migration.version>1.11.0</rewrite-java-migration.version>
|
||||
<rewrite-jackson.version>2.13.3</rewrite-jackson.version>
|
||||
|
||||
<signing.skip>true</signing.skip>
|
||||
<signing.alias>vmware</signing.alias>
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.InMemoryExecutionContext;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.RecipeRun;
|
||||
import org.openrewrite.Result;
|
||||
import org.openrewrite.SourceFile;
|
||||
import org.openrewrite.TreeVisitor;
|
||||
@@ -399,7 +400,8 @@ public class RewriteRecipeRepository {
|
||||
new InMemoryExecutionContext());
|
||||
List<SourceFile> sources = projectParser.parse(absoluteProjectDir, getClasspathEntries(project));
|
||||
server.getProgressService().progressEvent(r.getName(), "Computing changes...");
|
||||
List<Result> results = r.run(sources, new InMemoryExecutionContext(e -> log.error("", e)));
|
||||
RecipeRun reciperun = r.run(sources, new InMemoryExecutionContext(e -> log.error("", e)));
|
||||
List<Result> results = reciperun.getResults();
|
||||
return ORDocUtils.createWorkspaceEdit(absoluteProjectDir, server.getTextDocumentService(), results);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.RecipeRun;
|
||||
import org.openrewrite.Result;
|
||||
import org.openrewrite.config.DeclarativeRecipe;
|
||||
import org.openrewrite.internal.RecipeIntrospectionUtils;
|
||||
@@ -114,7 +115,8 @@ public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler
|
||||
}
|
||||
|
||||
private WorkspaceEdit applyRecipe(Recipe r, IJavaProject project, List<J.CompilationUnit> cus) {
|
||||
List<Result> results = r.run(cus);
|
||||
RecipeRun reciperun = r.run(cus);
|
||||
List<Result> results = reciperun.getResults();
|
||||
List<Either<TextDocumentEdit, ResourceOperation>> edits = results.stream().filter(res -> res.getAfter() != null).map(res -> {
|
||||
URI docUri = res.getAfter().getSourcePath().isAbsolute() ? res.getAfter().getSourcePath().toUri() : project.getLocationUri().resolve(res.getAfter().getSourcePath().toString());
|
||||
TextDocument doc = documents.getLatestSnapshot(docUri.toString());
|
||||
|
||||
@@ -12,15 +12,20 @@ package org.springframework.ide.vscode.boot.java.rewrite.codeaction;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.springBootVersionGreaterOrEqual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.openrewrite.Cursor;
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.Tree;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.spring.AutowiredFieldIntoConstructorParameterVisitor;
|
||||
import org.openrewrite.java.tree.J.Block;
|
||||
import org.openrewrite.java.tree.J.ClassDeclaration;
|
||||
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.TypeUtils;
|
||||
@@ -30,6 +35,7 @@ import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDes
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.AnnotationHierarchies;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
|
||||
|
||||
public class AutowiredFieldIntoConstructorParameterCodeAction implements RecipeCodeActionDescriptor {
|
||||
|
||||
@@ -67,10 +73,29 @@ public class AutowiredFieldIntoConstructorParameterCodeAction implements RecipeC
|
||||
ClassDeclaration classDeclaration = (ClassDeclaration) blockCursor.getParent().getValue();
|
||||
FullyQualified fqType = TypeUtils.asFullyQualified(classDeclaration.getType());
|
||||
if (fqType != null && isApplicableType(fqType)) {
|
||||
m = m.withMarkers(m.getMarkers().add(new FixAssistMarker(Tree.randomId())
|
||||
List<MethodDeclaration> constructors = ORAstUtils.getMethods(classDeclaration).stream().filter(c -> c.isConstructor()).limit(2).collect(Collectors.toList());
|
||||
String fieldName = multiVariable.getVariables().get(0).getSimpleName();
|
||||
FixAssistMarker marker = new FixAssistMarker(Tree.randomId())
|
||||
.withRecipeId(getRecipeId())
|
||||
.withScope(classDeclaration.getMarkers().findFirst(Range.class).get())
|
||||
.withParameters(Map.of("classFqName", fqType.getFullyQualifiedName(), "fieldName", multiVariable.getVariables().get(0).getSimpleName()))));
|
||||
.withParameters(Map.of("classFqName", fqType.getFullyQualifiedName(), "fieldName", fieldName));
|
||||
if (constructors.size() == 0) {
|
||||
m = m.withMarkers(m.getMarkers().add(marker));
|
||||
} else if (constructors.size() == 1 && !AutowiredFieldIntoConstructorParameterVisitor.isConstructorInitializingField(constructors.get(0), fieldName)) {
|
||||
m = m.withMarkers(m.getMarkers().add(marker));
|
||||
} else {
|
||||
List<MethodDeclaration> autowiredConstructors = constructors.stream().filter(constr -> constr.getLeadingAnnotations().stream()
|
||||
.map(a -> TypeUtils.asFullyQualified(a.getType()))
|
||||
.filter(Objects::nonNull)
|
||||
.map(FullyQualified::getFullyQualifiedName)
|
||||
.anyMatch(AUTOWIRED::equals)
|
||||
)
|
||||
.limit(2)
|
||||
.collect(Collectors.toList());
|
||||
if (autowiredConstructors.size() == 1 && !AutowiredFieldIntoConstructorParameterVisitor.isConstructorInitializingField(autowiredConstructors.get(0), fieldName)) {
|
||||
m = m.withMarkers(m.getMarkers().add(marker));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m;
|
||||
|
||||
Reference in New Issue
Block a user