Rewrite upgrade

This commit is contained in:
aboyko
2022-09-12 15:34:20 -04:00
parent 1a708a44e8
commit 6416432fee
8 changed files with 49 additions and 174 deletions

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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());
}

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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());

View File

@@ -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;