Prompt for changes preview when applying OR recipes
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022, 2023 VMware, Inc.
|
||||
* Copyright (c) 2022, 2024 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
|
||||
@@ -101,7 +101,8 @@ public class RewriteRefactoringsHandler extends AbstractHandler {
|
||||
cmdParams.setCommand(REWRITE_REFACTORINGS_EXEC);
|
||||
cmdParams.setArguments(List.of(
|
||||
uri,
|
||||
SERIALIZATION_GSON.toJsonTree(recipeSelection)
|
||||
SERIALIZATION_GSON.toJsonTree(recipeSelection),
|
||||
true // ask for preview
|
||||
));
|
||||
|
||||
ls.getWorkspaceService().executeCommand(cmdParams).get();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2023 VMware, Inc.
|
||||
* Copyright (c) 2023, 2024 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
|
||||
@@ -12,12 +12,9 @@ package org.springframework.ide.vscode.commons.rewrite;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.lsp4j.AnnotatedTextEdit;
|
||||
import org.eclipse.lsp4j.ChangeAnnotation;
|
||||
import org.eclipse.lsp4j.CreateFile;
|
||||
import org.eclipse.lsp4j.DeleteFile;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
@@ -157,14 +154,12 @@ public class ORDocUtils {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Optional<WorkspaceEdit> createWorkspaceEdit(SimpleTextDocumentService documents, List<Result> results, ChangeAnnotation changeAnnotation) {
|
||||
public static Optional<WorkspaceEdit> createWorkspaceEdit(SimpleTextDocumentService documents, List<Result> results, String changeAnnotationId) {
|
||||
if (results.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
WorkspaceEdit we = new WorkspaceEdit();
|
||||
we.setDocumentChanges(new ArrayList<>());
|
||||
final String changeAnnotationId = UUID.randomUUID().toString();
|
||||
we.setChangeAnnotations(Map.of(changeAnnotationId, changeAnnotation));
|
||||
for (Result result : results) {
|
||||
if (result.getBefore() == null) {
|
||||
String docUri = result.getAfter().getSourcePath().toUri().toASCIIString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022, 2023 VMware, Inc.
|
||||
* Copyright (c) 2022, 2024 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
|
||||
@@ -36,8 +36,12 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
|
||||
import org.eclipse.lsp4j.ChangeAnnotation;
|
||||
import org.eclipse.lsp4j.MessageActionItem;
|
||||
import org.eclipse.lsp4j.MessageType;
|
||||
import org.eclipse.lsp4j.ShowMessageRequestParams;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.WorkspaceEditChangeAnnotationSupportCapabilities;
|
||||
import org.openrewrite.InMemoryExecutionContext;
|
||||
import org.openrewrite.ParseExceptionResult;
|
||||
import org.openrewrite.Parser;
|
||||
@@ -102,7 +106,6 @@ public class RewriteRecipeRepository {
|
||||
private static final String CMD_REWRITE_EXECUTE = "sts/rewrite/execute";
|
||||
private static final String CMD_REWRITE_LIST = "sts/rewrite/list";
|
||||
private static final String CMD_REWRITE_SUBLIST = "sts/rewrite/sublist";
|
||||
private static final String CMD_REWRITE_RECIPE_EXECUTE = "sts/rewrite/recipe/execute";
|
||||
private static final Logger log = LoggerFactory.getLogger(RewriteRecipeRepository.class);
|
||||
|
||||
private static final Set<String> UNINITIALIZED_SET = Collections.emptySet();
|
||||
@@ -356,7 +359,7 @@ public class RewriteRecipeRepository {
|
||||
return recipes().thenCompose(recipesMap -> {
|
||||
String uri = ((JsonElement) params.getArguments().get(0)).getAsString();
|
||||
JsonElement recipesJson = ((JsonElement) params.getArguments().get(1));
|
||||
boolean needsConfirmation = params.getArguments().size() > 2 ? ((JsonElement) params.getArguments().get(2)).getAsBoolean() : false;
|
||||
boolean askForPreview = params.getArguments().size() > 2 ? ((JsonElement) params.getArguments().get(2)).getAsBoolean() : false;
|
||||
|
||||
RecipeSelectionDescriptor[] descriptors = serializationGson.fromJson(recipesJson, RecipeSelectionDescriptor[].class);
|
||||
List<Recipe> recipes = Arrays.stream(descriptors).map(d -> createRecipeFromSelection(recipesMap.get(d.id()), d.subselection())).collect(Collectors.toList());
|
||||
@@ -366,7 +369,7 @@ public class RewriteRecipeRepository {
|
||||
|| params.getWorkDoneToken().getLeft() == null
|
||||
? (r.getName() == null ? UUID.randomUUID().toString() : r.getName())
|
||||
: params.getWorkDoneToken().getLeft();
|
||||
return apply(r, uri, progressToken, needsConfirmation);
|
||||
return apply(r, uri, progressToken, askForPreview);
|
||||
} else {
|
||||
String name = recipes.size() + " recipes";
|
||||
DeclarativeRecipe aggregateRecipe = new DeclarativeRecipe(
|
||||
@@ -385,7 +388,7 @@ public class RewriteRecipeRepository {
|
||||
? (aggregateRecipe.getName() == null ? UUID.randomUUID().toString()
|
||||
: aggregateRecipe.getName())
|
||||
: params.getWorkDoneToken().getLeft();
|
||||
return apply(aggregateRecipe, uri, progressToken, needsConfirmation);
|
||||
return apply(aggregateRecipe, uri, progressToken, askForPreview);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -395,72 +398,98 @@ public class RewriteRecipeRepository {
|
||||
return CompletableFuture.completedFuture("executed");
|
||||
});
|
||||
|
||||
server.onCommand(CMD_REWRITE_RECIPE_EXECUTE, params -> {
|
||||
String recipeId = ((JsonElement) params.getArguments().get(0)).getAsString();
|
||||
boolean needsConfirmation = params.getArguments().size() > 1 ? ((JsonElement) params.getArguments().get(1)).getAsBoolean() : false;
|
||||
return getRecipe(recipeId).thenCompose(optRecipe -> {
|
||||
Recipe r = optRecipe.orElseThrow(() -> new IllegalArgumentException("No such recipe exists with name " + recipeId));
|
||||
final String progressToken = params.getWorkDoneToken() == null || params.getWorkDoneToken().getLeft() == null ? r.getName() : params.getWorkDoneToken().getLeft();
|
||||
String uri = ((JsonElement) params.getArguments().get(1)).getAsString();
|
||||
return apply(r, uri, progressToken, needsConfirmation);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
CompletableFuture<Object> apply(Recipe r, String uri, String progressToken, boolean needsConfirmation) {
|
||||
CompletableFuture<Object> apply(Recipe r, String uri, String progressToken, boolean askForPreview) {
|
||||
final IndefiniteProgressTask progressTask = server.getProgressService().createIndefiniteProgressTask(progressToken, r.getDisplayName(), "Initiated...");
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
return projectFinder.find(new TextDocumentIdentifier(uri));
|
||||
}).thenCompose(p -> {
|
||||
if (p.isPresent()) {
|
||||
try {
|
||||
Optional<WorkspaceEdit> edit = computeWorkspaceEdit(r, p.get(), progressTask, needsConfirmation);
|
||||
return CompletableFuture.completedFuture(edit).thenCompose(we -> {
|
||||
if (we.isPresent()) {
|
||||
progressTask.progressEvent("Applying document changes...");
|
||||
return server.getClient().applyEdit(new ApplyWorkspaceEditParams(we.get(), r.getDisplayName())).thenCompose(res -> {
|
||||
if (res.isApplied()) {
|
||||
progressTask.done();
|
||||
return CompletableFuture.completedFuture("success");
|
||||
} else {
|
||||
progressTask.done();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
progressTask.done();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
progressTask.done();
|
||||
throw t;
|
||||
}
|
||||
IJavaProject project = p.get();
|
||||
Path absoluteProjectDir = Paths.get(project.getLocationUri());
|
||||
progressTask.progressEvent("Parsing files...");
|
||||
ProjectParser projectParser = createRewriteProjectParser(project,
|
||||
pr -> {
|
||||
TextDocument doc = server.getTextDocumentService().getLatestSnapshot(pr.toUri().toASCIIString());
|
||||
if (doc != null) {
|
||||
return new Parser.Input(pr, () -> new ByteArrayInputStream(doc.get().getBytes()));
|
||||
}
|
||||
return null;
|
||||
});
|
||||
List<SourceFile> sources = projectParser.parse(absoluteProjectDir, new InMemoryExecutionContext(e -> log.error("Project Parsing error:", e)));
|
||||
|
||||
return computeWorkspaceEditAwareOfPreview(r, sources, progressTask, askForPreview)
|
||||
.thenCompose(we -> applyEdit(we, progressTask, r.getDisplayName()));
|
||||
} else {
|
||||
return CompletableFuture.failedFuture(new IllegalArgumentException("Cannot find Spring Boot project for uri: " + uri));
|
||||
}
|
||||
}).whenComplete((o,t) -> progressTask.done());
|
||||
}
|
||||
|
||||
CompletableFuture<Optional<WorkspaceEdit>> computeWorkspaceEditAwareOfPreview(Recipe r, List<SourceFile> sources, IndefiniteProgressTask progressTask, boolean askForPreview) {
|
||||
String changeAnnotationId = UUID.randomUUID().toString();
|
||||
Optional<WorkspaceEdit> we = computeWorkspaceEdit(r, sources, progressTask, changeAnnotationId);
|
||||
if (we.isPresent()) {
|
||||
CompletableFuture<WorkspaceEdit> editFuture = askForPreview ? askForPreview(we.get(), changeAnnotationId) : CompletableFuture.completedFuture(we.get());
|
||||
return editFuture.thenApply(Optional::of);
|
||||
}
|
||||
return CompletableFuture.completedFuture(Optional.empty());
|
||||
}
|
||||
|
||||
private CompletableFuture<WorkspaceEdit> askForPreview(WorkspaceEdit workspaceEdit, String changeAnnotationId) {
|
||||
return server.getClientCapabilities().thenApply(capabilities -> {
|
||||
WorkspaceEditChangeAnnotationSupportCapabilities changeAnnotationSupport = capabilities.getWorkspace().getWorkspaceEdit().getChangeAnnotationSupport();
|
||||
return changeAnnotationSupport != null && changeAnnotationSupport.getGroupsOnLabel() != null && changeAnnotationSupport.getGroupsOnLabel().booleanValue();
|
||||
}).thenCompose(supportsChangeAnnotation -> {
|
||||
if (supportsChangeAnnotation) {
|
||||
final MessageActionItem previewChanges = new MessageActionItem("Preview");
|
||||
final MessageActionItem applyChanges = new MessageActionItem("Apply");
|
||||
ShowMessageRequestParams messageParams = new ShowMessageRequestParams();
|
||||
messageParams.setType(MessageType.Info);
|
||||
messageParams.setMessage("Do you want to preview chnages before applying or apply right away?");
|
||||
messageParams.setActions(List.of(applyChanges, previewChanges));
|
||||
return server.getClient().showMessageRequest(messageParams).thenApply(previewChanges::equals);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}).thenApply(needsConfirmation -> {
|
||||
ChangeAnnotation changeAnnotation = workspaceEdit.getChangeAnnotations().get(changeAnnotationId);
|
||||
changeAnnotation.setNeedsConfirmation(needsConfirmation);
|
||||
return workspaceEdit;
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<WorkspaceEdit> computeWorkspaceEdit(Recipe r, IJavaProject project, IndefiniteProgressTask progressTask, boolean needsConfirmation) {
|
||||
Path absoluteProjectDir = Paths.get(project.getLocationUri());
|
||||
progressTask.progressEvent("Parsing files...");
|
||||
ProjectParser projectParser = createRewriteProjectParser(project,
|
||||
p -> {
|
||||
TextDocument doc = server.getTextDocumentService().getLatestSnapshot(p.toUri().toASCIIString());
|
||||
if (doc != null) {
|
||||
return new Parser.Input(p, () -> new ByteArrayInputStream(doc.get().getBytes()));
|
||||
}
|
||||
return null;
|
||||
});
|
||||
List<SourceFile> sources = projectParser.parse(absoluteProjectDir, new InMemoryExecutionContext(e -> log.error("Project Parsing error:", e)));
|
||||
private CompletableFuture<Object> applyEdit(Optional<WorkspaceEdit> we, IndefiniteProgressTask progressTask, String title) {
|
||||
if (we.isPresent()) {
|
||||
WorkspaceEdit workspaceEdit = we.get();
|
||||
if (progressTask != null) {
|
||||
progressTask.progressEvent("Applying document changes...");
|
||||
}
|
||||
return server.getClient().applyEdit(new ApplyWorkspaceEditParams(workspaceEdit, title)).thenCompose(res -> {
|
||||
if (res.isApplied()) {
|
||||
return CompletableFuture.completedFuture("success");
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
Optional<WorkspaceEdit> computeWorkspaceEdit(Recipe r, List<SourceFile> sources, IndefiniteProgressTask progressTask, String changeAnnotationId) {
|
||||
reportParseErrors(sources.stream().filter(ParseError.class::isInstance).map(ParseError.class::cast).collect(Collectors.toList()));
|
||||
progressTask.progressEvent("Computing changes...");
|
||||
if (progressTask != null) {
|
||||
progressTask.progressEvent("Computing changes...");
|
||||
}
|
||||
RecipeRun reciperun = r.run(new InMemoryLargeSourceSet(sources), new InMemoryExecutionContext(e -> log.error("Recipe execution failed", e)));
|
||||
List<Result> results = reciperun.getChangeset().getAllResults();
|
||||
ChangeAnnotation changeAnnotation = new ChangeAnnotation("Apply Recipe '" + r.getDisplayName() + "'");
|
||||
changeAnnotation.setNeedsConfirmation(needsConfirmation);
|
||||
return ORDocUtils.createWorkspaceEdit(server.getTextDocumentService(), results, changeAnnotation);
|
||||
return ORDocUtils.createWorkspaceEdit(server.getTextDocumentService(), results, changeAnnotationId).map(we -> {
|
||||
ChangeAnnotation changeAnnotation = new ChangeAnnotation(r.getDisplayName());
|
||||
we.setChangeAnnotations(Map.of(changeAnnotationId, changeAnnotation));
|
||||
return we;
|
||||
});
|
||||
}
|
||||
|
||||
private void reportParseErrors(List<ParseError> parseErrors) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022, 2023 VMware, Inc.
|
||||
* Copyright (c) 2022, 2024 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
|
||||
@@ -13,49 +13,36 @@ package org.springframework.ide.vscode.boot.java.rewrite;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.lsp4j.ChangeAnnotation;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.ResourceOperation;
|
||||
import org.eclipse.lsp4j.TextDocumentEdit;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.openrewrite.InMemoryExecutionContext;
|
||||
import org.openrewrite.Parser.Input;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.RecipeRun;
|
||||
import org.openrewrite.Result;
|
||||
import org.openrewrite.SourceFile;
|
||||
import org.openrewrite.internal.InMemoryLargeSourceSet;
|
||||
import org.openrewrite.internal.RecipeIntrospectionUtils;
|
||||
import org.openrewrite.java.JavaParser;
|
||||
import org.openrewrite.java.tree.J.CompilationUnit;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.PercentageProgressTask;
|
||||
import org.springframework.ide.vscode.commons.languageserver.IndefiniteProgressTask;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixHandler;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.CodeActionResolver;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.rewrite.ORDocUtils;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.RangeScopedRecipe;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -117,64 +104,34 @@ public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler
|
||||
public CompletableFuture<WorkspaceEdit> createEdit(JsonElement o) {
|
||||
FixDescriptor data = gson.fromJson(o, FixDescriptor.class);
|
||||
if (data != null && data.getRecipeId() != null) {
|
||||
return perform(data);
|
||||
return perform(data).thenApply(we -> we.orElse(null));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private WorkspaceEdit applyRecipe(Recipe r, IJavaProject project, List<CompilationUnit> cus, boolean needsConfirmation) {
|
||||
List<SourceFile> sources = cus.stream().map(cu -> (SourceFile) cu).collect(Collectors.toList());
|
||||
RecipeRun reciperun = r.run(new InMemoryLargeSourceSet(sources), new InMemoryExecutionContext());
|
||||
List<Result> results = reciperun.getChangeset().getAllResults();
|
||||
final String changeAnnotationId = UUID.randomUUID().toString();
|
||||
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 = server.getTextDocumentService().getLatestSnapshot(docUri.toASCIIString());
|
||||
if (doc == null) {
|
||||
doc = new TextDocument(docUri.toASCIIString(), LanguageId.JAVA, 0, res.getBefore() == null ? "" : res.getBefore().printAll());
|
||||
}
|
||||
return ORDocUtils.computeTextDocEdit(doc, res, changeAnnotationId);
|
||||
}).filter(e -> e.isPresent()).map(e -> e.get()).map(e -> Either.<TextDocumentEdit, ResourceOperation>forLeft(e)).collect(Collectors.toList());
|
||||
if (edits.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
WorkspaceEdit workspaceEdit = new WorkspaceEdit();
|
||||
ChangeAnnotation changeAnnotation = new ChangeAnnotation("Applying Recipe '" + r.getDisplayName() + "'");
|
||||
changeAnnotation.setNeedsConfirmation(needsConfirmation);
|
||||
workspaceEdit.setChangeAnnotations(Map.of(changeAnnotationId, changeAnnotation));
|
||||
workspaceEdit.setDocumentChanges(edits);
|
||||
return workspaceEdit;
|
||||
}
|
||||
|
||||
private CompletableFuture<WorkspaceEdit> perform(FixDescriptor data) {
|
||||
private CompletableFuture<Optional<WorkspaceEdit>> perform(FixDescriptor data) {
|
||||
Optional<IJavaProject> project = projectFinder.find(new TextDocumentIdentifier(data.getDocUris().get(0)));
|
||||
if (project.isPresent()) {
|
||||
boolean projectWide = data.getRecipeScope() == RecipeScope.PROJECT;
|
||||
return createRecipe(data).thenApply(r -> {
|
||||
IndefiniteProgressTask progress = server.getProgressService().createIndefiniteProgressTask(UUID.randomUUID().toString(), data.getLabel(), "Parsing files...");
|
||||
return createRecipe(data).thenCompose(r -> {
|
||||
if (r == null) {
|
||||
log.warn("Code Action failed to resolve. Could not create recipe created with id '" + data.getRecipeId() + "'.");
|
||||
}
|
||||
List<CompilationUnit> cus = Collections.emptyList();
|
||||
List<SourceFile> cus = new ArrayList<>();
|
||||
if (projectWide) {
|
||||
JavaParser jp = ORAstUtils.createJavaParserBuilder(project.get()).dependsOn(data.getTypeStubs()).build();
|
||||
List<Input> inputs = ORAstUtils.getParserInputs(server.getTextDocumentService(), project.get());
|
||||
PercentageProgressTask progress = server.getProgressService().createPercentageProgressTask(UUID.randomUUID().toString(), inputs.size() + 1, data.getLabel());
|
||||
try {
|
||||
cus = ORAstUtils.parseInputs(jp, inputs, s -> progress.increment());
|
||||
return applyRecipe(r, project.get(), cus, false);
|
||||
} finally {
|
||||
progress.setCurrent(progress.getTotal());
|
||||
progress.done();
|
||||
}
|
||||
cus.addAll(ORAstUtils.parseInputs(jp, inputs, null));
|
||||
} else {
|
||||
JavaParser jp = ORAstUtils.createJavaParserBuilder(project.get()).dependsOn(data.getTypeStubs()).build();
|
||||
List<Input> inputs = data.getDocUris().stream().map(URI::create).map(Paths::get).map(p -> ORAstUtils.getParserInput(server.getTextDocumentService(), p)).collect(Collectors.toList());
|
||||
cus = ORAstUtils.parseInputs(jp, inputs, null);
|
||||
return applyRecipe(r, project.get(), cus, false);
|
||||
cus.addAll(ORAstUtils.parseInputs(jp, inputs, null));
|
||||
}
|
||||
return recipeRepo.computeWorkspaceEditAwareOfPreview(r, cus, progress, projectWide).whenComplete((o, t) -> progress.done());
|
||||
});
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
return CompletableFuture.completedFuture(Optional.empty());
|
||||
}
|
||||
|
||||
private CompletableFuture<Optional<Class<?>>> findRecipeClass(String className) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022, 2023 VMware, Inc.
|
||||
* Copyright (c) 2022, 2024 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
|
||||
@@ -58,7 +58,7 @@ public class SpringBootUpgrade {
|
||||
Assert.isLegal(uri != null, "Project URI parameter must not be 'null'");
|
||||
Version targetVersion = Version.parse(((JsonElement) params.getArguments().get(1)).getAsString());
|
||||
Assert.isLegal(targetVersion != null, "Target Spring Boot version must not be 'null'");
|
||||
boolean needsConfirmation = params.getArguments().size() > 2 ? ((JsonElement) params.getArguments().get(2)).getAsBoolean() : false;
|
||||
boolean askForPreview = params.getArguments().size() > 2 ? ((JsonElement) params.getArguments().get(2)).getAsBoolean() : false;
|
||||
|
||||
IJavaProject project = projectFinder.find(new TextDocumentIdentifier(uri)).orElse(null);
|
||||
Assert.isLegal(project != null, "No Spring Boot project found for uri: " + uri);
|
||||
@@ -77,7 +77,7 @@ public class SpringBootUpgrade {
|
||||
createUpgradeRecipe(recipes, version, targetVersion),
|
||||
uri,
|
||||
UUID.randomUUID().toString(),
|
||||
needsConfirmation
|
||||
askForPreview
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2023 VMware, Inc.
|
||||
* Copyright (c) 2023, 2024 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
|
||||
@@ -76,7 +76,7 @@ public class UpdateBootVersion extends AbstractDiagnosticValidator {
|
||||
c.setTitle("Upgrade to Spring Boot " + targetVersion + " (executes the full project conversion recipe from OpenRewrite)");
|
||||
String commandId = SpringBootUpgrade.CMD_UPGRADE_SPRING_BOOT;
|
||||
c.setCommand(new Command("Upgrade to Version " + targetVersion, commandId,
|
||||
ImmutableList.of(javaProject.getLocationUri().toASCIIString(), targetVersion)));
|
||||
ImmutableList.of(javaProject.getLocationUri().toASCIIString(), targetVersion, true)));
|
||||
return c;
|
||||
}).ifPresent(actions::add);
|
||||
|
||||
@@ -109,7 +109,7 @@ public class UpdateBootVersion extends AbstractDiagnosticValidator {
|
||||
c.setTitle("Upgrade to Spring Boot " + targetVersion + " (executes the full project conversion recipe from OpenRewrite)");
|
||||
String commandId = SpringBootUpgrade.CMD_UPGRADE_SPRING_BOOT;
|
||||
c.setCommand(new Command("Upgrade to Version " + targetVersion, commandId,
|
||||
ImmutableList.of(javaProject.getLocationUri().toASCIIString(), targetVersion)));
|
||||
ImmutableList.of(javaProject.getLocationUri().toASCIIString(), targetVersion, true)));
|
||||
return c;
|
||||
}).ifPresent(actions::add);
|
||||
|
||||
@@ -138,7 +138,7 @@ public class UpdateBootVersion extends AbstractDiagnosticValidator {
|
||||
c.setTitle("Upgrade to Spring Boot " + latest.toString() + " (Maven dependency version changes only)");
|
||||
String commandId = SpringBootUpgrade.CMD_UPGRADE_SPRING_BOOT;
|
||||
c.setCommand(new Command("Upgrade to Version " + latest.toString(), commandId,
|
||||
ImmutableList.of(javaProject.getLocationUri().toASCIIString(), latest.toString())));
|
||||
ImmutableList.of(javaProject.getLocationUri().toASCIIString(), latest.toString(), false)));
|
||||
return c;
|
||||
}).ifPresent(actions::add);
|
||||
|
||||
|
||||
@@ -100,9 +100,8 @@ async function showRefactorings(uri: VSCode.Uri, filter: string) {
|
||||
}
|
||||
const choices = await showCurrentPathQuickPick(VSCode.commands.executeCommand('sts/rewrite/list', filter).then((cmds: RecipeDescriptor[]) => cmds.map(d => convertToQuickPickItem(d, false))), []);
|
||||
const recipeDescriptors = choices.filter(i => i.selected).map(convertToRecipeSelectionDescriptor);
|
||||
const needsConfirmation = await shwoNeedsConfirmation();
|
||||
if (recipeDescriptors.length) {
|
||||
VSCode.commands.executeCommand('sts/rewrite/execute', uri.toString(true), recipeDescriptors, needsConfirmation);
|
||||
VSCode.commands.executeCommand('sts/rewrite/execute', uri.toString(true), recipeDescriptors, true);
|
||||
} else {
|
||||
VSCode.window.showErrorMessage('No Recipes were selected!');
|
||||
}
|
||||
@@ -129,33 +128,6 @@ function convertToQuickPickItem(i: RecipeDescriptor, selected?: boolean): Recipe
|
||||
};
|
||||
}
|
||||
|
||||
function shwoNeedsConfirmation(): Thenable<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const previewPick = VSCode.window.createQuickPick<VSCode.QuickPickItem>();
|
||||
previewPick.title = 'Preview Before Applying?';
|
||||
previewPick.canSelectMany = false;
|
||||
|
||||
const applyItem = {
|
||||
label: "Apply",
|
||||
description: "Apply changes maded by a recipe"
|
||||
}
|
||||
const previewItem = {
|
||||
label: "Preview",
|
||||
description: "Preview and confirm changes made by a recipe before applying"
|
||||
}
|
||||
previewPick.items = [
|
||||
applyItem,
|
||||
previewItem
|
||||
];
|
||||
previewPick.show();
|
||||
|
||||
previewPick.onDidAccept(() => {
|
||||
previewPick.hide();
|
||||
resolve(previewPick.selectedItems[0] === previewItem);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showCurrentPathQuickPick(itemsPromise: Thenable<RecipeQuickPickItem[]>, itemsPath: RecipeQuickPickItem[]): Thenable<RecipeQuickPickItem[]> {
|
||||
const quickPick = VSCode.window.createQuickPick<RecipeQuickPickItem>();
|
||||
quickPick.title = 'Loading Recipes...';
|
||||
|
||||
Reference in New Issue
Block a user