Minimize size of messages for fetching and executing recipes
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src/"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
|
||||
org.eclipse.jdt.core.compiler.compliance=11
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
|
||||
org.eclipse.jdt.core.compiler.compliance=17
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
|
||||
org.eclipse.jdt.core.compiler.release=enabled
|
||||
org.eclipse.jdt.core.compiler.source=11
|
||||
org.eclipse.jdt.core.compiler.source=17
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, Inc.
|
||||
* Copyright (c) 2022, 2023 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
|
||||
@@ -10,12 +10,16 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.boot.ls.commands;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
class RecipeDescriptor {
|
||||
final class RecipeDescriptor {
|
||||
|
||||
enum CheckedState {
|
||||
UNCHECKED,
|
||||
CHECKED,
|
||||
GRAYED
|
||||
}
|
||||
|
||||
String name;
|
||||
|
||||
@@ -25,45 +29,29 @@ class RecipeDescriptor {
|
||||
|
||||
Set<String> tags;
|
||||
|
||||
Duration estimatedEffortPerOccurrence;
|
||||
|
||||
List<OptionDescriptor> options;
|
||||
|
||||
List<String> languages;
|
||||
|
||||
List<RecipeDescriptor> recipeList;
|
||||
|
||||
URI source;
|
||||
|
||||
RecipeDescriptor getCopyWithoutSubRecipes() {
|
||||
RecipeDescriptor copy = new RecipeDescriptor();
|
||||
copy.name = name;
|
||||
copy.displayName = displayName;
|
||||
copy.description = description;
|
||||
copy.tags = tags;
|
||||
copy.estimatedEffortPerOccurrence = estimatedEffortPerOccurrence;
|
||||
copy.options = options;
|
||||
copy.languages = languages;
|
||||
copy.source = source;
|
||||
return copy;
|
||||
}
|
||||
|
||||
static class OptionDescriptor {
|
||||
boolean hasSubRecipes = false;
|
||||
|
||||
RecipeDescriptor parent;
|
||||
|
||||
CheckedState checked = CheckedState.UNCHECKED;
|
||||
|
||||
String name;
|
||||
|
||||
String type;
|
||||
|
||||
String displayName;
|
||||
|
||||
String description;
|
||||
|
||||
String example;
|
||||
|
||||
List<String> valid;
|
||||
|
||||
boolean required;
|
||||
|
||||
Object value;
|
||||
}
|
||||
record OptionDescriptor(
|
||||
String name,
|
||||
String type,
|
||||
String displayName,
|
||||
String description,
|
||||
String example,
|
||||
List<String> valid,
|
||||
boolean required,
|
||||
Object value
|
||||
) {}
|
||||
|
||||
record RecipeSelection(boolean selected, String id, RecipeSelection[] subselection) {}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, Inc.
|
||||
* Copyright (c) 2022, 2023 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
|
||||
@@ -10,55 +10,48 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.boot.ls.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.lsp4j.ExecuteCommandParams;
|
||||
import org.eclipse.lsp4j.services.WorkspaceService;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeDescriptor.CheckedState;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeDescriptor.RecipeSelection;
|
||||
|
||||
|
||||
public class RecipeTreeModel {
|
||||
|
||||
public enum CheckedState {
|
||||
UNCHECKED,
|
||||
CHECKED,
|
||||
GRAYED
|
||||
}
|
||||
private static final String REWRITE_REFACTORINGS_LIST = "sts/rewrite/list";
|
||||
private static final String REWRITE_REFACTORINGS_SUBLIST = "sts/rewrite/sublist";
|
||||
|
||||
private RecipeDescriptor[] recipeDescriptors;
|
||||
private Map<RecipeDescriptor, RecipeDescriptor> parentMap = new IdentityHashMap<>();
|
||||
private Map<RecipeDescriptor, CheckedState> checkedMap = new IdentityHashMap<>();
|
||||
|
||||
RecipeTreeModel(RecipeDescriptor[] recipeDescriptors) {
|
||||
this.recipeDescriptors = recipeDescriptors;
|
||||
for (RecipeDescriptor d : recipeDescriptors) {
|
||||
initParentMap(d);
|
||||
}
|
||||
}
|
||||
|
||||
private void initParentMap(RecipeDescriptor d) {
|
||||
if (d.recipeList != null) {
|
||||
for (RecipeDescriptor dc : d.recipeList) {
|
||||
parentMap.put(dc, d);
|
||||
initParentMap(dc);
|
||||
}
|
||||
}
|
||||
final private WorkspaceService workspaceService;
|
||||
final private String recipeFilter;
|
||||
|
||||
RecipeTreeModel(WorkspaceService workspaceService, String recipeFilter) {
|
||||
this.workspaceService = workspaceService;
|
||||
this.recipeFilter = recipeFilter;
|
||||
}
|
||||
|
||||
public void check(RecipeDescriptor d) {
|
||||
if (simpleCheck(d)) {
|
||||
inferCheckedStateFromChildren(parentMap.get(d));
|
||||
inferCheckedStateFromChildren(d.parent);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean simpleCheck(RecipeDescriptor d) {
|
||||
if (checkedMap.get(d) != CheckedState.CHECKED) {
|
||||
checkedMap.put(d, CheckedState.CHECKED);
|
||||
for (RecipeDescriptor dc : d.recipeList) {
|
||||
simpleCheck(dc);
|
||||
if (d.checked != CheckedState.CHECKED) {
|
||||
d.checked = CheckedState.CHECKED;
|
||||
if (d.recipeList != null) {
|
||||
for (RecipeDescriptor dc : d.recipeList) {
|
||||
simpleCheck(dc);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -67,32 +60,29 @@ public class RecipeTreeModel {
|
||||
|
||||
public void uncheck(RecipeDescriptor d) {
|
||||
if (simpleUncheck(d)) {
|
||||
inferCheckedStateFromChildren(parentMap.get(d));
|
||||
inferCheckedStateFromChildren(d.parent);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean simpleUncheck(RecipeDescriptor d) {
|
||||
if (checkedMap.get(d) != CheckedState.UNCHECKED) {
|
||||
checkedMap.put(d, CheckedState.UNCHECKED);
|
||||
for (RecipeDescriptor dc : d.recipeList) {
|
||||
simpleUncheck(dc);
|
||||
if (d.checked != CheckedState.UNCHECKED) {
|
||||
d.checked = CheckedState.UNCHECKED;
|
||||
if (d.recipeList != null) {
|
||||
for (RecipeDescriptor dc : d.recipeList) {
|
||||
simpleUncheck(dc);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CheckedState getCheckedState(RecipeDescriptor d) {
|
||||
CheckedState state = checkedMap.get(d);
|
||||
return state == null ? CheckedState.UNCHECKED : state;
|
||||
}
|
||||
|
||||
private void inferCheckedStateFromChildren(RecipeDescriptor d) {
|
||||
if (d != null && d.recipeList != null) {
|
||||
boolean all = true;
|
||||
boolean none = true;
|
||||
for (RecipeDescriptor child : d.recipeList) {
|
||||
CheckedState childState = getCheckedState(child);
|
||||
CheckedState childState = child.checked;
|
||||
if (childState == CheckedState.UNCHECKED) {
|
||||
all = false;
|
||||
} else {
|
||||
@@ -105,9 +95,9 @@ public class RecipeTreeModel {
|
||||
} else if (none) {
|
||||
inferredState = CheckedState.UNCHECKED;
|
||||
}
|
||||
if (getCheckedState(d) != inferredState) {
|
||||
checkedMap.put(d, inferredState);
|
||||
inferCheckedStateFromChildren(parentMap.get(d));
|
||||
if (d.checked != inferredState) {
|
||||
d.checked = inferredState;
|
||||
inferCheckedStateFromChildren(d.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,32 +106,70 @@ public class RecipeTreeModel {
|
||||
return recipeDescriptors;
|
||||
}
|
||||
|
||||
public RecipeDescriptor getSelectedRecipeDescriptors() throws CoreException {
|
||||
RecipeDescriptor[] recipes = Arrays.stream(recipeDescriptors).map(this::copySelectedDescriptor).filter(Objects::nonNull).toArray(RecipeDescriptor[]::new);
|
||||
if (recipes.length == 0) {
|
||||
throw new CoreException(Status.error("No recipes selected"));
|
||||
} else if (recipes.length == 1) {
|
||||
return recipes[0];
|
||||
} else {
|
||||
RecipeDescriptor aggregate = new RecipeDescriptor();
|
||||
aggregate.name = recipes.length + " recipes";
|
||||
aggregate.displayName = recipes.length + " recipes";
|
||||
aggregate.description = "Multiple recipes to be applied. Number of recipes " + recipes.length;
|
||||
aggregate.tags = Arrays.stream(recipes).flatMap(r -> r.tags.stream()).collect(Collectors.toSet());
|
||||
aggregate.recipeList = Arrays.asList(recipes);
|
||||
return aggregate;
|
||||
public RecipeSelection[] getRecipeSelection() throws CoreException {
|
||||
List<RecipeSelection> rootSelected = new ArrayList<>();
|
||||
for (int i = 0; i < recipeDescriptors.length; i++) {
|
||||
if (recipeDescriptors[i].checked != CheckedState.UNCHECKED) {
|
||||
rootSelected.add(new RecipeSelection(true, recipeDescriptors[i].name, createRecipeSelection(recipeDescriptors[i])));
|
||||
}
|
||||
}
|
||||
if (rootSelected.isEmpty()) {
|
||||
throw new CoreException(Status.error("No recipes selected"));
|
||||
}
|
||||
return rootSelected.toArray(new RecipeSelection[rootSelected.size()]);
|
||||
}
|
||||
|
||||
private RecipeDescriptor copySelectedDescriptor(RecipeDescriptor d) {
|
||||
if (getCheckedState(d) != CheckedState.UNCHECKED) {
|
||||
RecipeDescriptor copy = d.getCopyWithoutSubRecipes();
|
||||
if (d.recipeList != null) {
|
||||
copy.recipeList = d.recipeList.stream().map(this::copySelectedDescriptor).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
return copy;
|
||||
private RecipeSelection[] createRecipeSelection(RecipeDescriptor d) {
|
||||
if (d.recipeList != null) {
|
||||
return d.recipeList.stream()
|
||||
.map(s -> new RecipeSelection(s.checked != CheckedState.UNCHECKED, s.name, createRecipeSelection(s)))
|
||||
.toArray(RecipeSelection[]::new);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
CompletableFuture<Void> fetchSubrecipes(RecipeDescriptor descriptor) {
|
||||
RecipeDescriptor d = descriptor;
|
||||
LinkedList<Integer> indexPath = new LinkedList<>();
|
||||
for (; d.parent != null; d = d.parent) {
|
||||
indexPath.addFirst(d.parent.recipeList.indexOf(d));
|
||||
}
|
||||
ExecuteCommandParams commandParams = new ExecuteCommandParams();
|
||||
commandParams.setCommand(REWRITE_REFACTORINGS_SUBLIST);
|
||||
commandParams.setArguments(List.of(d.name, indexPath));
|
||||
return workspaceService.executeCommand(commandParams).thenAccept(json -> {
|
||||
RecipeDescriptor[] fetchedDescriptors = RewriteRefactoringsHandler.SERIALIZATION_GSON.fromJson(RewriteRefactoringsHandler.SERIALIZATION_GSON.toJson(json), RecipeDescriptor[].class);
|
||||
for (RecipeDescriptor fd : fetchedDescriptors) {
|
||||
fd.parent = descriptor;
|
||||
fd.checked = descriptor.checked != CheckedState.UNCHECKED ? CheckedState.CHECKED : CheckedState.UNCHECKED;
|
||||
}
|
||||
descriptor.recipeList = Arrays.asList(fetchedDescriptors);
|
||||
});
|
||||
}
|
||||
|
||||
CompletableFuture<Void> fetchRootRecipes() {
|
||||
ExecuteCommandParams commandParams = new ExecuteCommandParams();
|
||||
commandParams.setCommand(REWRITE_REFACTORINGS_LIST);
|
||||
commandParams.setArguments(List.of(recipeFilter));
|
||||
return workspaceService.executeCommand(commandParams).thenAccept(json -> {
|
||||
recipeDescriptors = RewriteRefactoringsHandler.SERIALIZATION_GSON.fromJson(RewriteRefactoringsHandler.SERIALIZATION_GSON.toJson(json), RecipeDescriptor[].class);
|
||||
});
|
||||
}
|
||||
|
||||
String getSelectedRecipeDisplayName() {
|
||||
List<RecipeDescriptor> rootSelected = new ArrayList<>();
|
||||
for (int i = 0; i < recipeDescriptors.length; i++) {
|
||||
if (recipeDescriptors[i].checked != CheckedState.UNCHECKED) {
|
||||
rootSelected.add(recipeDescriptors[i]);
|
||||
}
|
||||
}
|
||||
if (rootSelected.isEmpty()) {
|
||||
return "No Recipes Selected";
|
||||
} else if (rootSelected.size() == 1) {
|
||||
return rootSelected.get(0).displayName;
|
||||
} else {
|
||||
return "%s recipes".formatted(rootSelected.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
package org.springframework.tooling.boot.ls.commands;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.commands.AbstractHandler;
|
||||
@@ -37,17 +33,11 @@ import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.handlers.HandlerUtil;
|
||||
import org.springframework.tooling.boot.ls.BootLanguageServerPlugin;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeDescriptor.RecipeSelection;
|
||||
import org.springsource.ide.eclipse.commons.core.CoreUtil;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RewriteRefactoringsHandler extends AbstractHandler {
|
||||
@@ -58,25 +48,11 @@ public class RewriteRefactoringsHandler extends AbstractHandler {
|
||||
NON_BOOT_UPGRADE
|
||||
}
|
||||
|
||||
private static class DurationTypeConverter implements JsonSerializer<Duration>, JsonDeserializer<Duration> {
|
||||
@Override
|
||||
public JsonElement serialize(Duration src, Type srcType, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.toNanos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration deserialize(JsonElement json, Type type, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return Duration.ofNanos(json.getAsLong());
|
||||
}
|
||||
}
|
||||
|
||||
private static Gson serializationGson = new GsonBuilder()
|
||||
.registerTypeAdapter(Duration.class, new DurationTypeConverter())
|
||||
static final Gson SERIALIZATION_GSON = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
|
||||
private static final String REWRITE_REFACTORINGS_LIST = "sts/rewrite/list";
|
||||
private static final String REWRITE_REFACTORINGS_EXEC = "sts/rewrite/execute";
|
||||
|
||||
private RecipeFilter recipeFilter;
|
||||
@@ -106,41 +82,26 @@ public class RewriteRefactoringsHandler extends AbstractHandler {
|
||||
if (project != null && CoreUtil.promptForProjectSave(project)) {
|
||||
LanguageServerDefinition def = LanguageServersRegistry.getInstance().getDefinition(BootLanguageServerPlugin.BOOT_LS_DEFINITION_ID);
|
||||
Assert.isLegal(def != null, "No definition found for Boot Language Server");
|
||||
|
||||
final String uri = project.getLocationURI().toASCIIString();
|
||||
ExecuteCommandParams commandParams = new ExecuteCommandParams();
|
||||
commandParams.setCommand(REWRITE_REFACTORINGS_LIST);
|
||||
commandParams.setArguments(List.of(uri, recipeFilter.toString()));
|
||||
|
||||
|
||||
try {
|
||||
List<Object> allRewriteRecipesJson = new ArrayList<>();
|
||||
List<Object> syncRecipesJson = Collections.synchronizedList(allRewriteRecipesJson);
|
||||
|
||||
LanguageServers.forProject(project).withPreferredServer(def).computeFirst(ls ->
|
||||
ls.getWorkspaceService().executeCommand(commandParams).thenAccept(or -> {
|
||||
if (or != null) {
|
||||
syncRecipesJson.add(or);
|
||||
}
|
||||
})
|
||||
.thenRun(() -> {
|
||||
allRewriteRecipesJson.stream().filter(List.class::isInstance).map(List.class::cast).findFirst().ifPresent(obj -> {
|
||||
RecipeDescriptor[] descriptors = serializationGson.fromJson(serializationGson.toJson(obj), RecipeDescriptor[].class);
|
||||
LanguageServers.forProject(project).withPreferredServer(def).computeFirst(ls -> {
|
||||
|
||||
PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
|
||||
RecipeTreeModel recipesModel = new RecipeTreeModel(descriptors);
|
||||
RecipeTreeModel recipesModel = new RecipeTreeModel(ls.getWorkspaceService(), recipeFilter.toString());
|
||||
int returnCode = new SelectRecipesDialog(Display.getCurrent().getActiveShell(), recipesModel).open();
|
||||
if (returnCode == Window.OK) {
|
||||
try {
|
||||
RecipeDescriptor recipeToApply = recipesModel.getSelectedRecipeDescriptors();
|
||||
final RecipeSelection[] recipeSelection = recipesModel.getRecipeSelection();
|
||||
PlatformUI.getWorkbench().getProgressService().run(true, false, monitor -> {
|
||||
try {
|
||||
monitor.beginTask("Applying recipe '" + recipeToApply.displayName + "'", IProgressMonitor.UNKNOWN);
|
||||
monitor.beginTask("Applying recipe '%s'...".formatted(recipesModel.getSelectedRecipeDisplayName()), IProgressMonitor.UNKNOWN);
|
||||
ExecuteCommandParams cmdParams = new ExecuteCommandParams();
|
||||
cmdParams.setCommand(REWRITE_REFACTORINGS_EXEC);
|
||||
cmdParams.setArguments(List.of(
|
||||
uri,
|
||||
serializationGson.toJsonTree(recipeToApply)
|
||||
SERIALIZATION_GSON.toJsonTree(recipeSelection)
|
||||
));
|
||||
|
||||
ls.getWorkspaceService().executeCommand(cmdParams).get();
|
||||
@@ -157,8 +118,9 @@ public class RewriteRefactoringsHandler extends AbstractHandler {
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}));
|
||||
return null;
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new ExecutionException("Failed to apply Rewrite recipe(s)", e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022 VMware, Inc.
|
||||
* Copyright (c) 2022, 2023 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
|
||||
@@ -43,7 +43,7 @@ import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.osgi.framework.FrameworkUtil;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeDescriptor.OptionDescriptor;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeTreeModel.CheckedState;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeDescriptor.CheckedState;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class SelectRecipesDialog extends StatusDialog {
|
||||
@@ -51,6 +51,7 @@ public class SelectRecipesDialog extends StatusDialog {
|
||||
private static final int MARGIN = 5;
|
||||
private static final String SELECT_REWRITE_RECIPE_S_FROM_THE_LIST = "Select Rewrite Recipe(s) from the list";
|
||||
private static String fgStyleSheet;
|
||||
private static final Object LOADING = new Object();
|
||||
|
||||
private RecipeTreeModel model;
|
||||
|
||||
@@ -76,37 +77,55 @@ public class SelectRecipesDialog extends StatusDialog {
|
||||
|
||||
@Override
|
||||
public Object[] getElements(Object inputElement) {
|
||||
if (inputElement instanceof RecipeTreeModel) {
|
||||
return ((RecipeTreeModel) inputElement).getRecipeDescriptors();
|
||||
if (inputElement instanceof RecipeTreeModel model) {
|
||||
if (model.getRecipeDescriptors() == null) {
|
||||
model.fetchRootRecipes().thenAccept(v -> {
|
||||
PlatformUI.getWorkbench().getDisplay().asyncExec(() -> treeViewer.refresh());
|
||||
});
|
||||
return new Object[] { LOADING };
|
||||
} else {
|
||||
return model.getRecipeDescriptors();
|
||||
}
|
||||
|
||||
}
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getChildren(Object parentElement) {
|
||||
if (parentElement instanceof RecipeDescriptor) {
|
||||
RecipeDescriptor r = (RecipeDescriptor) parentElement;
|
||||
return r.recipeList.toArray(new RecipeDescriptor[r.recipeList.size()]);
|
||||
if (parentElement instanceof RecipeDescriptor r) {
|
||||
if (r.hasSubRecipes) {
|
||||
if (r.recipeList == null) {
|
||||
model.fetchSubrecipes(r).thenAccept(v -> PlatformUI.getWorkbench().getDisplay().asyncExec(() -> treeViewer.refresh(r)));
|
||||
return new Object[] { LOADING };
|
||||
} else {
|
||||
return r.recipeList.toArray(new RecipeDescriptor[r.recipeList.size()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new RecipeDescriptor[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getParent(Object element) {
|
||||
if (element instanceof RecipeDescriptor r) {
|
||||
return r.parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChildren(Object element) {
|
||||
if (element instanceof RecipeDescriptor) {
|
||||
RecipeDescriptor r = (RecipeDescriptor) element;
|
||||
return r.recipeList != null && !r.recipeList.isEmpty();
|
||||
if (element instanceof RecipeDescriptor r) {
|
||||
return r.hasSubRecipes;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
treeViewer.setLabelProvider(LabelProvider.createTextProvider(input -> {
|
||||
if (input instanceof RecipeDescriptor) {
|
||||
if (input == LOADING) {
|
||||
return "Loading...";
|
||||
} else if (input instanceof RecipeDescriptor) {
|
||||
return ((RecipeDescriptor)input).displayName;
|
||||
}
|
||||
return "unknown";
|
||||
@@ -117,7 +136,7 @@ public class SelectRecipesDialog extends StatusDialog {
|
||||
public boolean isGrayed(Object element) {
|
||||
if (element instanceof RecipeDescriptor) {
|
||||
RecipeDescriptor r = (RecipeDescriptor) element;
|
||||
return model.getCheckedState(r) == CheckedState.GRAYED;
|
||||
return r.checked == CheckedState.GRAYED;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -126,7 +145,7 @@ public class SelectRecipesDialog extends StatusDialog {
|
||||
public boolean isChecked(Object element) {
|
||||
if (element instanceof RecipeDescriptor) {
|
||||
RecipeDescriptor r = (RecipeDescriptor) element;
|
||||
return model.getCheckedState(r) != CheckedState.UNCHECKED;
|
||||
return r.checked != CheckedState.UNCHECKED;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -168,7 +187,7 @@ public class SelectRecipesDialog extends StatusDialog {
|
||||
// Replace browser's built-in context menu with none
|
||||
docViewer.setMenu(new Menu(getShell(), SWT.NONE));
|
||||
|
||||
docViewer.setText(wrapHtml("Select a Recipe on the left to read description"));
|
||||
docViewer.setText(wrapHtml("Select a Recipe on the left to read description"));
|
||||
|
||||
|
||||
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
|
||||
@@ -200,7 +219,7 @@ public class SelectRecipesDialog extends StatusDialog {
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
boolean anythingSelected = Arrays.stream(model.getRecipeDescriptors()).anyMatch(d -> model.getCheckedState(d) != CheckedState.UNCHECKED);
|
||||
boolean anythingSelected = model.getRecipeDescriptors() != null && Arrays.stream(model.getRecipeDescriptors()).anyMatch(d -> d.checked != CheckedState.UNCHECKED);
|
||||
updateStatus(anythingSelected ? Status.info(SELECT_REWRITE_RECIPE_S_FROM_THE_LIST) : Status.error(SELECT_REWRITE_RECIPE_S_FROM_THE_LIST));
|
||||
}
|
||||
|
||||
@@ -211,12 +230,12 @@ public class SelectRecipesDialog extends StatusDialog {
|
||||
sb.append("</p>");
|
||||
sb.append("<ul>");
|
||||
for (OptionDescriptor option : r.options) {
|
||||
if (option.value != null) {
|
||||
if (option.value() != null) {
|
||||
sb.append("<li>");
|
||||
sb.append("<pre>");
|
||||
sb.append(option.value);
|
||||
sb.append(option.value());
|
||||
sb.append("</pre>");
|
||||
sb.append(option.description);
|
||||
sb.append(option.description());
|
||||
sb.append("</li>");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user