Runtime load recipes yml/jar. Offscreen doc quick fix.
This commit is contained in:
@@ -131,6 +131,12 @@
|
||||
id="org.springframework.tooling.boot.ls.preferences"
|
||||
name="Spring Boot Language Server">
|
||||
</page>
|
||||
<page
|
||||
category="org.springframework.tooling.boot.ls.preferences"
|
||||
class="org.springframework.tooling.boot.ls.RewritePreferencePage"
|
||||
id="org.springframework.tooling.boot.ls.rewrite"
|
||||
name="Rewrite">
|
||||
</page>
|
||||
|
||||
</extension>
|
||||
|
||||
@@ -338,9 +344,13 @@
|
||||
<extension
|
||||
point="org.eclipse.ui.quickAccess">
|
||||
<computer
|
||||
class="org.springframework.tooling.boot.ls.commands.LiveProcessCommandsQuickAccessProvider"
|
||||
class="org.springframework.tooling.boot.ls.commands.RewriteCommandsQuickAccessProvider"
|
||||
name="Spring - Live Process Information"
|
||||
requiresUIAccess="false"/>
|
||||
<computer
|
||||
class="org.springframework.tooling.boot.ls.QuickAccessComputer1"
|
||||
name="Spring - Rewrite Recipes">
|
||||
</computer>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder.Contributor">
|
||||
|
||||
@@ -96,7 +96,6 @@ public class BootJavaPreferencesPage extends FieldEditorPreferencePage implement
|
||||
|
||||
addField(new BooleanFieldEditor(Constants.PREF_VALIDATION_SPEL_EXPRESSIONS, "SpEL Expression Syntax Validation", fieldEditorParent));
|
||||
|
||||
addField(new BooleanFieldEditor(Constants.PREF_REWRITE_RECONCILE, "Experimental reconciling for Java source based on Rewrite project", fieldEditorParent));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,4 +33,7 @@ public class Constants {
|
||||
|
||||
public static final String PREF_REWRITE_RECONCILE = "boot-java.rewrite.reconcile";
|
||||
|
||||
public static final String PREF_REWRITE_RECIPES_SCAN_FILES = "boot-java.rewrite.scan-files";
|
||||
|
||||
public static final String PREF_REWRITE_RECIPES_SCAN_DIRS = "boot-java.rewrite.scan-directories";
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ import org.eclipse.lsp4j.jsonrpc.messages.Message;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage;
|
||||
import org.eclipse.lsp4j.services.LanguageServer;
|
||||
import org.springframework.tooling.boot.ls.prefs.CategoryProblemsSeverityPrefsPage;
|
||||
import org.springframework.tooling.boot.ls.prefs.FileListEditor;
|
||||
import org.springframework.tooling.boot.ls.prefs.ProblemCategoryData;
|
||||
import org.springframework.tooling.boot.ls.prefs.ProblemCategoryData.CategoryToggleData;
|
||||
import org.springframework.tooling.ls.eclipse.commons.LanguageServerCommonsActivator;
|
||||
import org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder;
|
||||
import org.springsource.ide.eclipse.commons.boot.ls.remoteapps.RemoteBootAppsDataHolder.RemoteAppData;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.ValueListener;
|
||||
@@ -187,7 +187,12 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
bootJavaObj.put("change-detection", bootChangeDetection);
|
||||
bootJavaObj.put("validation", validation);
|
||||
bootJavaObj.put("remote-apps", getAllRemoteApps());
|
||||
bootJavaObj.put("rewrite", Map.of("reconcile", preferenceStore.getBoolean(Constants.PREF_REWRITE_RECONCILE)));
|
||||
|
||||
bootJavaObj.put("rewrite", Map.of(
|
||||
"reconcile", preferenceStore.getBoolean(Constants.PREF_REWRITE_RECONCILE),
|
||||
"scan-directories", FileListEditor.getValuesFromPreference(preferenceStore.getString(Constants.PREF_REWRITE_RECIPES_SCAN_DIRS)),
|
||||
"scan-files", FileListEditor.getValuesFromPreference(preferenceStore.getString(Constants.PREF_REWRITE_RECIPES_SCAN_FILES))
|
||||
));
|
||||
settings.put("boot-java", bootJavaObj);
|
||||
|
||||
putValidationPreferences(settings);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.springframework.tooling.boot.ls;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jface.preference.BooleanFieldEditor;
|
||||
import org.eclipse.jface.preference.FieldEditorPreferencePage;
|
||||
import org.eclipse.jface.preference.PathEditor;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.ui.IWorkbench;
|
||||
import org.eclipse.ui.IWorkbenchPreferencePage;
|
||||
import org.springframework.tooling.boot.ls.prefs.FileListEditor;
|
||||
|
||||
public class RewritePreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
|
||||
|
||||
@Override
|
||||
public void init(IWorkbench workbench) {
|
||||
setPreferenceStore(BootLanguageServerPlugin.getDefault().getPreferenceStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createFieldEditors() {
|
||||
Composite fieldEditorParent = getFieldEditorParent();
|
||||
|
||||
addField(new BooleanFieldEditor(Constants.PREF_REWRITE_RECONCILE, "Experimental reconciling for Java source based on Rewrite project", fieldEditorParent));
|
||||
|
||||
addField(new FileListEditor(Constants.PREF_REWRITE_RECIPES_SCAN_FILES, "JAR and YAML files to scan for Recipes", "Select JARs and YAML files:", fieldEditorParent, List.of("jar", "yml", "yaml")));
|
||||
|
||||
addField(new PathEditor(Constants.PREF_REWRITE_RECIPES_SCAN_DIRS, "Directories to scan for Recipes", "Select directory to scan for Recipes", fieldEditorParent));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*******************************************************************************
|
||||
* 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.tooling.boot.ls.commands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.lsp4e.LanguageServiceAccessor;
|
||||
import org.eclipse.lsp4j.ExecuteCommandParams;
|
||||
import org.eclipse.lsp4j.services.LanguageServer;
|
||||
import org.eclipse.ui.quickaccess.IQuickAccessComputer;
|
||||
import org.eclipse.ui.quickaccess.IQuickAccessComputerExtension;
|
||||
import org.eclipse.ui.quickaccess.QuickAccessElement;
|
||||
import org.springframework.tooling.boot.ls.BootLanguageServerPlugin;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RewriteCommandsQuickAccessProvider implements IQuickAccessComputer, IQuickAccessComputerExtension {
|
||||
|
||||
private static final String CMD_REWRITE_RELOAD = "sts/rewrite/reload";
|
||||
|
||||
@Override
|
||||
public QuickAccessElement[] computeElements(String query, IProgressMonitor monitor) {
|
||||
return new QuickAccessElement[] {
|
||||
new QuickAccessElement() {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "Reload Rewrite Recipes";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageDescriptor getImageDescriptor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return CMD_REWRITE_RELOAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<LanguageServer> usedLanguageServers = LanguageServiceAccessor.getActiveLanguageServers(serverCapabilities -> true);
|
||||
|
||||
if (usedLanguageServers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ExecuteCommandParams commandParams = new ExecuteCommandParams();
|
||||
commandParams.setCommand(CMD_REWRITE_RELOAD);
|
||||
|
||||
commandParams.setArguments(Collections.emptyList());
|
||||
|
||||
try {
|
||||
CompletableFuture.allOf(usedLanguageServers.stream().map(ls ->
|
||||
ls.getWorkspaceService().executeCommand(commandParams)).toArray(CompletableFuture[]::new)).get(2, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (Exception e) {
|
||||
BootLanguageServerPlugin.getDefault().getLog().error("Failed to reload Rewrite Recipes!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuickAccessElement[] computeElements() {
|
||||
return new QuickAccessElement[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsRefresh() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,6 +48,7 @@ import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RewriteRefactoringsHandler extends AbstractHandler {
|
||||
|
||||
private static class DurationTypeConverter implements JsonSerializer<Duration>, JsonDeserializer<Duration> {
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.osgi.framework.FrameworkUtil;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeDescriptor.OptionDescriptor;
|
||||
import org.springframework.tooling.boot.ls.commands.RecipeTreeModel.CheckedState;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class SelectRecipesDialog extends StatusDialog {
|
||||
|
||||
private static final int MARGIN = 5;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*******************************************************************************
|
||||
* 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.tooling.boot.ls.prefs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.jface.preference.PathEditor;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.FileDialog;
|
||||
|
||||
public class FileListEditor extends PathEditor {
|
||||
|
||||
private String lastPath;
|
||||
|
||||
private String dirChooserLabelText;
|
||||
|
||||
private List<String> fileFilters;
|
||||
|
||||
public FileListEditor(String name, String labelText,
|
||||
String dirChooserLabelText, Composite parent, List<String> fileFilters) {
|
||||
super(name, labelText, dirChooserLabelText, parent);
|
||||
this.dirChooserLabelText = dirChooserLabelText;
|
||||
this.fileFilters = fileFilters;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNewInputObject() {
|
||||
|
||||
FileDialog dialog = new FileDialog(getShell(), SWT.SHEET);
|
||||
dialog.setFilterExtensions(fileFilters.toArray(String[]::new));
|
||||
if (dirChooserLabelText != null) {
|
||||
dialog.setText(dirChooserLabelText);
|
||||
}
|
||||
if (lastPath != null) {
|
||||
if (new File(lastPath).exists()) {
|
||||
dialog.setFilterPath(lastPath);
|
||||
}
|
||||
}
|
||||
String file = dialog.open();
|
||||
if (file != null) {
|
||||
String parentFolder = new File(file).getParent();
|
||||
if (parentFolder == null) {
|
||||
return null;
|
||||
}
|
||||
lastPath = parentFolder;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
public static List<String> getValuesFromPreference(String rawValue) {
|
||||
StringTokenizer st = new StringTokenizer(rawValue, File.pathSeparator
|
||||
+ "\n\r");//$NON-NLS-1$
|
||||
ArrayList<String> l = new ArrayList<>();
|
||||
while (st.hasMoreElements()) {
|
||||
l.add((String)st.nextElement());
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,13 +31,16 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
|
||||
import org.eclipse.lsp4j.ApplyWorkspaceEditResponse;
|
||||
import org.eclipse.lsp4j.ClientCapabilities;
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
import org.eclipse.lsp4j.CodeActionKind;
|
||||
import org.eclipse.lsp4j.CodeActionOptions;
|
||||
import org.eclipse.lsp4j.CodeLensOptions;
|
||||
import org.eclipse.lsp4j.Command;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DiagnosticSeverity;
|
||||
import org.eclipse.lsp4j.ExecuteCommandOptions;
|
||||
@@ -94,6 +97,7 @@ import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -720,10 +724,21 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
|
||||
d.setSeverity(severity);
|
||||
d.setSource(getServer().EXTENSION_ID);
|
||||
List<QuickfixData<?>> fixes = problem.getQuickfixes();
|
||||
// Copy original diagnsotic without the data field to avoid stackoverflow is hashCode() method call
|
||||
Diagnostic refDiagnostic = new Diagnostic(d.getRange(), d.getMessage(), d.getSeverity(), d.getSource());
|
||||
if (CollectionUtil.hasElements(fixes)) {
|
||||
for (QuickfixData<?> fix : fixes) {
|
||||
quickfixes.add(new Quickfix<>(CODE_ACTION_COMMAND_ID, d, fix));
|
||||
}
|
||||
d.setData(fixes.stream().map(fix -> {
|
||||
CodeAction ca = new CodeAction();
|
||||
ca.setKind(CodeActionKind.QuickFix);
|
||||
ca.setTitle(fix.title);
|
||||
ca.setDiagnostics(List.of(refDiagnostic));
|
||||
ca.setCommand(new Command(
|
||||
fix.title,
|
||||
CODE_ACTION_COMMAND_ID,
|
||||
ImmutableList.of(fix.type.getId(), fix.params)
|
||||
));
|
||||
return ca;
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
diagnostics.add(d);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -81,11 +82,15 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.util.text.LazyTextDocument;
|
||||
import org.springframework.ide.vscode.commons.util.text.Region;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
public class SimpleTextDocumentService implements TextDocumentService, DocumentEventListenerManager {
|
||||
|
||||
@@ -430,22 +435,26 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE
|
||||
}
|
||||
}
|
||||
|
||||
private List<Either<Command, CodeAction>> computeCodeActions(CancelChecker cancelToken, CodeActionCapabilities capabilities, TrackedDocument doc, CodeActionParams params) {
|
||||
private List<Either<Command, CodeAction>> computeCodeActions(CancelChecker cancelToken, CodeActionCapabilities capabilities, TextDocument doc, CodeActionParams params) {
|
||||
Builder<Either<Command,CodeAction>> listBuilder = ImmutableList.builder();
|
||||
CodeActionContext context = params.getContext();
|
||||
if (!context.getDiagnostics().isEmpty() || (context.getOnly() != null && context.getOnly().contains(CodeActionKind.QuickFix))) {
|
||||
doc.getQuickfixes().stream()
|
||||
.filter((fix) -> fix.appliesTo(params.getRange(), context))
|
||||
.map(f -> f.getCodeAction(params.getContext()))
|
||||
.map(command -> Either.<Command, CodeAction>forRight(command))
|
||||
.forEach(listBuilder::add);
|
||||
params.getContext().getDiagnostics().forEach(d -> {
|
||||
if (d.getData() != null) {
|
||||
Type type = new TypeToken<List<CodeAction>>(){}.getType();
|
||||
List<CodeAction> codeActions = new GsonBuilder().create().fromJson((JsonElement)d.getData(), type);
|
||||
for (CodeAction ca : codeActions) {
|
||||
listBuilder.add(Either.forRight(ca));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (codeActionHandler != null) {
|
||||
try {
|
||||
int start = doc.getDocument().toOffset(params.getRange().getStart());
|
||||
int end = doc.getDocument().toOffset(params.getRange().getEnd());
|
||||
listBuilder.addAll(codeActionHandler.handle(cancelToken, capabilities, context, doc.getDocument(), new Region(start, end - start)));
|
||||
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 (Exception e) {
|
||||
log.error("Failed to compute quick refactorings", e);
|
||||
}
|
||||
@@ -469,14 +478,22 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE
|
||||
// this doesn't happen async, because it accesses the internal documents structure
|
||||
// and therefore needs to be executed as part of the main LSP message queue
|
||||
|
||||
TrackedDocument doc = documents.get(params.getTextDocument().getUri());
|
||||
String uri = params.getTextDocument().getUri();
|
||||
TrackedDocument trackedDoc = documents.get(uri);
|
||||
TextDocument doc = trackedDoc == null ? null : trackedDoc.getDocument();
|
||||
|
||||
if (doc == null) {
|
||||
if (uri.endsWith(".java")) {
|
||||
doc = new LazyTextDocument(uri, LanguageId.JAVA);
|
||||
}
|
||||
}
|
||||
|
||||
if (doc != null) {
|
||||
|
||||
final TextDocument d = doc;
|
||||
return server.getClientCapabilities()
|
||||
.thenApply(SimpleTextDocumentService::getCodeActionCapabilities)
|
||||
.thenComposeAsync(capabilities ->
|
||||
CompletableFutures.computeAsync(messageWorkerThreadPool, cancelToken -> computeCodeActions(cancelToken, capabilities, doc, params)));
|
||||
CompletableFutures.computeAsync(messageWorkerThreadPool, cancelToken -> computeCodeActions(cancelToken, capabilities, d, params)));
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(ImmutableList.of());
|
||||
}
|
||||
|
||||
22
headless-services/commons/commons-rewrite-test/pom.xml
Normal file
22
headless-services/commons/commons-rewrite-test/pom.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>qq</groupId>
|
||||
<artifactId>commons-rewrite-test</artifactId>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-parent</artifactId>
|
||||
<version>1.39.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-rewrite</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,73 @@
|
||||
/*******************************************************************************
|
||||
* 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.rewrite.test;
|
||||
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.Tree;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.J.MethodDeclaration;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemCategory;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemTypes;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
|
||||
public class HelloMethodRenameProblemDescriptor implements RecipeSpringJavaProblemDescriptor {
|
||||
|
||||
@Override
|
||||
public String getRecipeId() {
|
||||
return "org.springframework.rewrite.test.HelloMethodRenameRecipe";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel(RecipeScope s) {
|
||||
return RecipeCodeActionDescriptor.buildLabel("Switch hello method into bye", s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeScope[] getScopes() {
|
||||
return RecipeScope.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaVisitor<ExecutionContext> getMarkerVisitor() {
|
||||
return new JavaIsoVisitor<>() {
|
||||
|
||||
@Override
|
||||
public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, ExecutionContext p) {
|
||||
MethodDeclaration m = super.visitMethodDeclaration(method, p);
|
||||
if ("hello".equals(method.getSimpleName())) {
|
||||
FixAssistMarker marker = new FixAssistMarker(Tree.randomId()).withRecipeId(getRecipeId()).withScope(m.getMarkers().findFirst(Range.class).get());
|
||||
m = m.withName(m.getName().withMarkers(m.getName().getMarkers().add(marker)));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(IJavaProject project) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemType getProblemType() {
|
||||
return ProblemTypes.create("Hello Method!", ProblemSeverity.ERROR, ProblemCategory.NO_CATEGORY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
* 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.rewrite.test;
|
||||
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.TreeVisitor;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.tree.J.MethodDeclaration;
|
||||
import org.openrewrite.java.tree.J.MethodInvocation;
|
||||
|
||||
public class HelloMethodRenameRecipe extends Recipe {
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Rename hello method into bye";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TreeVisitor<?, ExecutionContext> getVisitor() {
|
||||
return new JavaIsoVisitor<>() {
|
||||
|
||||
@Override
|
||||
public MethodDeclaration visitMethodDeclaration(MethodDeclaration method, ExecutionContext p) {
|
||||
MethodDeclaration m = super.visitMethodDeclaration(method, p);
|
||||
if ("hello".equals(m.getSimpleName())) {
|
||||
m = m.withName(m.getName().withSimpleName("bye"));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodInvocation visitMethodInvocation(MethodInvocation method, ExecutionContext p) {
|
||||
MethodInvocation m = super.visitMethodInvocation(method, p);
|
||||
if ("hello".equals(m.getSimpleName())) {
|
||||
m = m.withName(m.getName().withSimpleName("bye"));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* 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.rewrite.test;
|
||||
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.java.ChangePackage;
|
||||
|
||||
public class OssPackageRecipe extends Recipe {
|
||||
|
||||
public OssPackageRecipe() {
|
||||
doNext(new ChangePackage("com.example", "org.example", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Test recipe class coming from the Jar";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*******************************************************************************
|
||||
* 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.rewrite.test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.CodeActionRepository;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
|
||||
public class StsTestCodeActionRepo extends CodeActionRepository {
|
||||
|
||||
@Override
|
||||
public List<RecipeCodeActionDescriptor> getCodeActionDescriptors() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecipeSpringJavaProblemDescriptor> getProblemDescriptors() {
|
||||
return List.of(new HelloMethodRenameProblemDescriptor());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
########################################################################################################################
|
||||
# Spring Data 3.0 io.micrometer.core.instrument.binder -> io.micrometer.binder
|
||||
type: specs.openrewrite.org/v1beta/recipe
|
||||
name: rewrite.test.jar.oss-package
|
||||
displayName: Example with OSS packages from YAML
|
||||
description: Switches app to OSS app
|
||||
recipeList:
|
||||
- org.openrewrite.java.ChangePackage:
|
||||
oldPackageName: com.example
|
||||
newPackageName: org.example
|
||||
recursive: true
|
||||
@@ -22,7 +22,18 @@
|
||||
<artifactId>commons-language-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-java</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/io.github.classgraph/classgraph -->
|
||||
<dependency>
|
||||
<groupId>io.github.classgraph</groupId>
|
||||
<artifactId>classgraph</artifactId>
|
||||
<version>4.8.149</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-properties</artifactId>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*******************************************************************************
|
||||
* 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.commons.rewrite.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class CodeActionRepository {
|
||||
|
||||
public abstract List<RecipeCodeActionDescriptor> getCodeActionDescriptors();
|
||||
|
||||
public abstract List<RecipeSpringJavaProblemDescriptor> getProblemDescriptors();
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite;
|
||||
package org.springframework.ide.vscode.commons.rewrite.config;
|
||||
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite;
|
||||
package org.springframework.ide.vscode.commons.rewrite.config;
|
||||
|
||||
public enum RecipeScope {
|
||||
NODE,
|
||||
@@ -8,9 +8,8 @@
|
||||
* Contributors:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.reconcile;
|
||||
package org.springframework.ide.vscode.commons.rewrite.config;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
|
||||
public interface RecipeSpringJavaProblemDescriptor extends RecipeCodeActionDescriptor {
|
||||
@@ -0,0 +1,209 @@
|
||||
/*******************************************************************************
|
||||
* 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.commons.rewrite.config;
|
||||
|
||||
import static org.openrewrite.internal.RecipeIntrospectionUtils.constructRecipe;
|
||||
import static org.openrewrite.internal.RecipeIntrospectionUtils.recipeDescriptorFromRecipe;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.openrewrite.Recipe;
|
||||
import org.openrewrite.config.CategoryDescriptor;
|
||||
import org.openrewrite.config.DeclarativeRecipe;
|
||||
import org.openrewrite.config.RecipeDescriptor;
|
||||
import org.openrewrite.config.RecipeExample;
|
||||
import org.openrewrite.config.ResourceLoader;
|
||||
import org.openrewrite.config.YamlResourceLoader;
|
||||
import org.openrewrite.internal.RecipeIntrospectionUtils;
|
||||
import org.openrewrite.style.NamedStyles;
|
||||
|
||||
import io.github.classgraph.ClassGraph;
|
||||
import io.github.classgraph.ClassInfo;
|
||||
import io.github.classgraph.ScanResult;
|
||||
|
||||
public class StsClasspathScanningLoader implements ResourceLoader, StsResourceLoader {
|
||||
|
||||
private final List<Recipe> recipes = new ArrayList<>();
|
||||
private final List<NamedStyles> styles = new ArrayList<>();
|
||||
|
||||
private final List<RecipeDescriptor> recipeDescriptors = new ArrayList<>();
|
||||
private final List<CategoryDescriptor> categoryDescriptors = new ArrayList<>();
|
||||
private final List<RecipeExample> recipeExamples = new ArrayList<>();
|
||||
|
||||
private final List<CodeActionRepository> codeActionRepos = new ArrayList<>();
|
||||
|
||||
public StsClasspathScanningLoader(Path p, Properties properties, ClassLoader classLoader) {
|
||||
if (Files.isDirectory(p)) {
|
||||
String dir = p.toString();
|
||||
|
||||
scanClasses(new ClassGraph()
|
||||
.acceptPaths(dir)
|
||||
.ignoreParentClassLoaders()
|
||||
.overrideClassLoaders(classLoader), classLoader);
|
||||
|
||||
scanYaml(new ClassGraph()
|
||||
.acceptPaths(dir)
|
||||
.ignoreParentClassLoaders()
|
||||
.overrideClassLoaders(classLoader)
|
||||
.acceptPaths("META-INF/rewrite"), properties, classLoader);
|
||||
|
||||
} else {
|
||||
String jarName = p.toFile().getName();
|
||||
|
||||
scanClasses(new ClassGraph()
|
||||
.acceptJars(jarName)
|
||||
.ignoreParentClassLoaders()
|
||||
.overrideClassLoaders(classLoader), classLoader);
|
||||
|
||||
scanYaml(new ClassGraph()
|
||||
.acceptJars(jarName)
|
||||
.ignoreParentClassLoaders()
|
||||
.overrideClassLoaders(classLoader)
|
||||
.acceptPaths("META-INF/rewrite"), properties, classLoader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public StsClasspathScanningLoader(Properties properties, String[] acceptPackages) {
|
||||
scanClasses(new ClassGraph().acceptPackages(acceptPackages), getClass().getClassLoader());
|
||||
scanYaml(new ClassGraph().acceptPaths("META-INF/rewrite"), properties, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a ClasspathScanningLoader scans the provided classload for recipes
|
||||
*
|
||||
* @param properties Yaml placeholder properties
|
||||
* @param classLoader Limit scan to classes loadable by this classloader
|
||||
*/
|
||||
public StsClasspathScanningLoader(Properties properties, ClassLoader classLoader) {
|
||||
scanClasses(new ClassGraph()
|
||||
.ignoreParentClassLoaders()
|
||||
.overrideClassLoaders(classLoader), classLoader);
|
||||
|
||||
scanYaml(new ClassGraph()
|
||||
.ignoreParentClassLoaders()
|
||||
.overrideClassLoaders(classLoader)
|
||||
.acceptPaths("META-INF/rewrite"), properties, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called _after_ scanClasses or the descriptors of declarative recipes will be missing any
|
||||
* non-declarative recipes they depend on that would be discovered by scanClasses
|
||||
*/
|
||||
private void scanYaml(ClassGraph classGraph, Properties properties, @Nullable ClassLoader classLoader) {
|
||||
try (ScanResult scanResult = classGraph.enableMemoryMapping().scan()) {
|
||||
List<YamlResourceLoader> yamlResourceLoaders = new ArrayList<>();
|
||||
|
||||
scanResult.getResourcesWithExtension("yml").forEachInputStreamIgnoringIOException((res, input) -> {
|
||||
yamlResourceLoaders.add(new YamlResourceLoader(input, res.getURI(), properties, classLoader));
|
||||
});
|
||||
// Extract in two passes so that the full list of recipes from all sources are known when computing recipe descriptors
|
||||
// Otherwise recipes which include recipes from other sources in their recipeList will have incomplete descriptors
|
||||
for(YamlResourceLoader resourceLoader : yamlResourceLoaders) {
|
||||
recipes.addAll(resourceLoader.listRecipes());
|
||||
categoryDescriptors.addAll(resourceLoader.listCategoryDescriptors());
|
||||
styles.addAll(resourceLoader.listStyles());
|
||||
recipeExamples.addAll(resourceLoader.listRecipeExamples());
|
||||
}
|
||||
for(YamlResourceLoader resourceLoader : yamlResourceLoaders) {
|
||||
recipeDescriptors.addAll(resourceLoader.listRecipeDescriptors(recipes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanClasses(ClassGraph classGraph, ClassLoader classLoader) {
|
||||
try (ScanResult result = classGraph
|
||||
.ignoreClassVisibility()
|
||||
.overrideClassLoaders(classLoader)
|
||||
.scan()) {
|
||||
|
||||
for (ClassInfo classInfo : result.getSubclasses(Recipe.class.getName())) {
|
||||
Class<?> recipeClass = classInfo.loadClass();
|
||||
if (recipeClass.getName().equals(DeclarativeRecipe.class.getName()) || recipeClass.getEnclosingClass() != null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Recipe recipe = constructRecipe(recipeClass);
|
||||
recipeDescriptors.add(recipeDescriptorFromRecipe(recipe));
|
||||
recipes.add(recipe);
|
||||
} catch (Exception e) {
|
||||
// logger.warn("Unable to configure {}", recipeClass.getName(), e);
|
||||
}
|
||||
}
|
||||
for (ClassInfo classInfo : result.getSubclasses(NamedStyles.class.getName())) {
|
||||
Class<?> styleClass = classInfo.loadClass();
|
||||
try {
|
||||
Constructor<?> constructor = RecipeIntrospectionUtils.getZeroArgsConstructor(styleClass);
|
||||
if(constructor != null) {
|
||||
constructor.setAccessible(true);
|
||||
styles.add((NamedStyles) constructor.newInstance());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// logger.warn("Unable to configure {}", styleClass.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
for (ClassInfo classInfo : result.getSubclasses(CodeActionRepository.class.getName())) {
|
||||
Class<?> codeActionRepoClass = classInfo.loadClass();
|
||||
Constructor<?> primaryConstructor = RecipeIntrospectionUtils.getZeroArgsConstructor(codeActionRepoClass);
|
||||
if (primaryConstructor == null) {
|
||||
//TODO: error!!!
|
||||
} else {
|
||||
try {
|
||||
CodeActionRepository repo = (CodeActionRepository) primaryConstructor.newInstance();
|
||||
codeActionRepos.add(repo);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Recipe> listRecipes() {
|
||||
return recipes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<RecipeDescriptor> listRecipeDescriptors() {
|
||||
return recipeDescriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CategoryDescriptor> listCategoryDescriptors() {
|
||||
return categoryDescriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NamedStyles> listStyles() {
|
||||
return styles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<RecipeExample> listRecipeExamples() {
|
||||
return recipeExamples;
|
||||
}
|
||||
|
||||
public List<CodeActionRepository> listCodeActionDescriptorsRepositories() {
|
||||
return codeActionRepos;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*******************************************************************************
|
||||
* 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.commons.rewrite.config;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.openrewrite.config.Environment;
|
||||
import org.openrewrite.config.ResourceLoader;
|
||||
|
||||
public class StsEnvironment extends Environment {
|
||||
|
||||
final private Supplier<Stream<CodeActionRepository>> codeActionRepos;
|
||||
|
||||
public StsEnvironment(Collection<? extends ResourceLoader> resourceLoaders) {
|
||||
super(resourceLoaders);
|
||||
codeActionRepos = () -> resourceLoaders.stream().filter(StsResourceLoader.class::isInstance).map(StsResourceLoader.class::cast).flatMap(l -> l.listCodeActionDescriptorsRepositories().stream());
|
||||
}
|
||||
|
||||
public static class Builder extends Environment.Builder {
|
||||
|
||||
final private Properties props;
|
||||
|
||||
public Builder(Properties properties) {
|
||||
super(properties);
|
||||
this.props = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.openrewrite.config.Environment.Builder scanRuntimeClasspath(String... acceptPackages) {
|
||||
return load(new StsClasspathScanningLoader(props, acceptPackages));
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.openrewrite.config.Environment.Builder scanClassLoader(ClassLoader classLoader) {
|
||||
return load(new StsClasspathScanningLoader(props, classLoader));
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.openrewrite.config.Environment.Builder scanJar(Path jar, ClassLoader classLoader) {
|
||||
return load(new StsClasspathScanningLoader(jar, props, classLoader));
|
||||
}
|
||||
|
||||
public org.openrewrite.config.Environment.Builder scanPath(Path dir, ClassLoader classLoader) {
|
||||
return load(new StsClasspathScanningLoader(dir, props, classLoader));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public StsEnvironment build() {
|
||||
try {
|
||||
Field f = Environment.Builder.class.getDeclaredField("resourceLoaders");
|
||||
f.setAccessible(true);
|
||||
return new StsEnvironment((Collection<ResourceLoader>) f.get(this));
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public List<RecipeCodeActionDescriptor> listCodeActionDescriptors() {
|
||||
return codeActionRepos.get().flatMap(r -> r.getCodeActionDescriptors().stream()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<RecipeSpringJavaProblemDescriptor> listProblemDescriptors() {
|
||||
return codeActionRepos.get().flatMap(r -> r.getProblemDescriptors().stream()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder(new Properties());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*******************************************************************************
|
||||
* 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.commons.rewrite.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openrewrite.config.ResourceLoader;
|
||||
|
||||
public interface StsResourceLoader extends ResourceLoader {
|
||||
|
||||
List<CodeActionRepository> listCodeActionDescriptorsRepositories();
|
||||
|
||||
|
||||
}
|
||||
@@ -6,12 +6,13 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.openrewrite.marker.Marker;
|
||||
import org.openrewrite.marker.Range;
|
||||
|
||||
public class FixAssistMarker implements Marker {
|
||||
|
||||
private UUID id;
|
||||
|
||||
private UUID scope;
|
||||
private Range scope;
|
||||
|
||||
private String recipeId;
|
||||
|
||||
@@ -34,12 +35,12 @@ public class FixAssistMarker implements Marker {
|
||||
return this;
|
||||
}
|
||||
|
||||
public FixAssistMarker withScope(UUID scope) {
|
||||
public FixAssistMarker withScope(Range scope) {
|
||||
this.scope = scope;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UUID getScope() {
|
||||
public Range getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
|
||||
@@ -329,15 +329,18 @@ public class ORAstUtils {
|
||||
|
||||
@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);
|
||||
}
|
||||
if (tree instanceof J) {
|
||||
J t = (J) tree;
|
||||
if (condition.test(t)) {
|
||||
makeVisitorNonTopLevel(visitor);
|
||||
t = visitor.visit(t, ctx, getCursor());
|
||||
for (TreeVisitor<J, ExecutionContext> v : getAfterVisitors(visitor)) {
|
||||
doAfterVisit(v);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
return super.visit(tree, ctx);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.app;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -162,7 +163,15 @@ public class BootJavaConfig implements InitializingBean {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
workspace.onDidChangeConfiguraton(this::handleConfigurationChange);
|
||||
}
|
||||
|
||||
public Set<String> getRecipeDirectories() {
|
||||
return settings.getStringSet("boot-java", "rewrite", "scan-directories");
|
||||
}
|
||||
|
||||
public Set<String> getRecipeFiles() {
|
||||
return settings.getStringSet("boot-java", "rewrite", "scan-files");
|
||||
}
|
||||
|
||||
public Settings getRawSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ public class BootLanguageServerBootApp {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean RewriteRecipeRepository rewriteRecipesRepository(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
|
||||
return new RewriteRecipeRepository(server, projectFinder);
|
||||
@Bean RewriteRecipeRepository rewriteRecipesRepository(SimpleLanguageServer server, JavaProjectFinder projectFinder, BootJavaConfig config) {
|
||||
return new RewriteRecipeRepository(server, projectFinder, config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents
|
||||
import org.springframework.ide.vscode.boot.java.links.JavaElementLocationProvider;
|
||||
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
|
||||
import org.springframework.ide.vscode.boot.java.livehover.v2.SpringProcessLiveDataProvider;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SymbolCache;
|
||||
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
|
||||
@@ -87,6 +88,7 @@ public class BootLanguageServerInitializer implements InitializingBean {
|
||||
@Autowired SpringProjectsValidations springProjectsValidations;
|
||||
@Autowired private JavaProjectFinder projectFinder;
|
||||
@Autowired private LanguageServerProperties configProps;
|
||||
@Autowired(required = false) private RewriteRecipeRepository recipesRepo;
|
||||
|
||||
@Qualifier("adHocProperties") @Autowired ProjectBasedPropertyIndexProvider adHocProperties;
|
||||
|
||||
@@ -170,21 +172,27 @@ public class BootLanguageServerInitializer implements InitializingBean {
|
||||
|
||||
components.getCodeActionProvider().ifPresent(documents::onCodeAction);
|
||||
|
||||
config.addListener(evt -> {
|
||||
components.getReconcileEngine().ifPresent(reconciler -> {
|
||||
log.info("A configuration changed, triggering reconcile on all open documents");
|
||||
for (TextDocument doc : server.getTextDocumentService().getAll()) {
|
||||
server.validateWith(doc.getId(), reconciler);
|
||||
}
|
||||
params.projectFinder.all().forEach(p -> validateProject(p, reconciler));
|
||||
});
|
||||
});
|
||||
config.addListener(evt -> reconcile());
|
||||
|
||||
if (recipesRepo != null) {
|
||||
recipesRepo.onRecipesLoaded(v -> reconcile());
|
||||
}
|
||||
|
||||
addSpringProjectsVersionValidation(params);
|
||||
|
||||
server.getWorkspaceService().getFileObserver().onFilesChanged(FILES_TO_WATCH_GLOB, this::handleFiles);
|
||||
server.getWorkspaceService().getFileObserver().onFilesCreated(FILES_TO_WATCH_GLOB, this::handleFiles);
|
||||
}
|
||||
|
||||
private void reconcile() {
|
||||
components.getReconcileEngine().ifPresent(reconciler -> {
|
||||
log.info("A configuration changed, triggering reconcile on all open documents");
|
||||
for (TextDocument doc : server.getTextDocumentService().getAll()) {
|
||||
server.validateWith(doc.getId(), reconciler);
|
||||
}
|
||||
params.projectFinder.all().forEach(p -> validateProject(p, reconciler));
|
||||
});
|
||||
}
|
||||
|
||||
public CompositeLanguageServerComponents getComponents() {
|
||||
Assert.notNull(components, "Not yet initialized, can't get components yet.");
|
||||
|
||||
@@ -27,9 +27,6 @@ public class RewriteConfig implements InitializingBean {
|
||||
@Autowired
|
||||
private SimpleLanguageServer server;
|
||||
|
||||
@Autowired
|
||||
private RewriteRecipeRepository recipeRepo;
|
||||
|
||||
@Autowired
|
||||
private RewriteRefactorings rewriteRefactorings;
|
||||
|
||||
@@ -41,15 +38,7 @@ public class RewriteConfig implements InitializingBean {
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
QuickfixRegistry registry = server.getQuickfixRegistry();
|
||||
|
||||
recipeRepo.loaded.thenAccept(v ->
|
||||
recipeRepo.getProblemRecipeDescriptors().forEach(d -> {
|
||||
if (recipeRepo.getRecipe(d.getRecipeId()).isPresent()) {
|
||||
registry.register(d.getRecipeId(), rewriteRefactorings);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
registry.register(RewriteRefactorings.REWRITE_RECIPE_QUICKFIX, rewriteRefactorings);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*******************************************************************************
|
||||
* 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.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.AutowiredFieldIntoConstructorParameterCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.BeanMethodsNotPublicCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.NoRequestMappingAnnotationCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.UnnecessarySpringExtensionCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.BeanMethodNotPublicProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NoAutowiredOnConstructorProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.PreciseBeanTypeProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.UnnecessarySpringExtensionProblem;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.CodeActionRepository;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
|
||||
public class BootCodeActionRepository extends CodeActionRepository {
|
||||
|
||||
@Override
|
||||
public List<RecipeCodeActionDescriptor> getCodeActionDescriptors() {
|
||||
return List.of(
|
||||
new AutowiredFieldIntoConstructorParameterCodeAction(),
|
||||
new BeanMethodsNotPublicCodeAction(),
|
||||
new NoRequestMappingAnnotationCodeAction(),
|
||||
new UnnecessarySpringExtensionCodeAction()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecipeSpringJavaProblemDescriptor> getProblemDescriptors() {
|
||||
return List.of(
|
||||
new BeanMethodNotPublicProblem(),
|
||||
new NoAutowiredOnConstructorProblem(),
|
||||
new UnnecessarySpringExtensionProblem(),
|
||||
new PreciseBeanTypeProblem()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,10 +37,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.JavaCodeActionHandler;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
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.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.util.text.IRegion;
|
||||
@@ -99,9 +101,6 @@ public class RewriteCodeActionHandler implements JavaCodeActionHandler {
|
||||
|
||||
try {
|
||||
|
||||
// Wait for recipe repo to load if not loaded - should be loaded by the time we get here.
|
||||
recipeRepo.loaded.get();
|
||||
|
||||
List<RecipeCodeActionDescriptor> descriptors = recipeRepo.getCodeActionRecipeDescriptors().stream()
|
||||
// If Recipe not present - don't show quick assist as it won't be handled without the Rewrite recipe present
|
||||
.filter(d -> recipeRepo.getRecipe(d.getRecipeId()).isPresent())
|
||||
@@ -177,7 +176,7 @@ public class RewriteCodeActionHandler implements JavaCodeActionHandler {
|
||||
m.getRecipeId(),
|
||||
doc.getUri(),
|
||||
s,
|
||||
m.getScope() == null ? null : m.getScope().toString(),
|
||||
m.getScope() == null ? null : m.getScope(),
|
||||
m.getParameters() == null ? Collections.emptyMap() : m.getParameters()
|
||||
));
|
||||
return ca;
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
package org.springframework.ide.vscode.boot.java.rewrite;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
@@ -20,9 +24,11 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -40,31 +46,27 @@ import org.openrewrite.Result;
|
||||
import org.openrewrite.SourceFile;
|
||||
import org.openrewrite.TreeVisitor;
|
||||
import org.openrewrite.Validated;
|
||||
import org.openrewrite.config.Environment;
|
||||
import org.openrewrite.config.RecipeDescriptor;
|
||||
import org.openrewrite.config.YamlResourceLoader;
|
||||
import org.openrewrite.internal.RecipeIntrospectionUtils;
|
||||
import org.openrewrite.java.JavaParser;
|
||||
import org.openrewrite.java.tree.J.CompilationUnit;
|
||||
import org.openrewrite.maven.MavenParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.AutowiredFieldIntoConstructorParameterCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.BeanMethodsNotPublicCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.NoRequestMappingAnnotationCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.UnnecessarySpringExtensionCodeAction;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.BeanMethodNotPublicProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.PreciseBeanTypeProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.NoAutowiredOnConstructorProblem;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.UnnecessarySpringExtensionProblem;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.commons.java.IClasspath;
|
||||
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.ListenerList;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.rewrite.LoadUtils;
|
||||
import org.springframework.ide.vscode.commons.rewrite.LoadUtils.DurationTypeConverter;
|
||||
import org.springframework.ide.vscode.commons.rewrite.ORDocUtils;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.StsEnvironment;
|
||||
import org.springframework.ide.vscode.commons.rewrite.maven.MavenProjectParser;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -76,6 +78,9 @@ import com.google.gson.JsonElement;
|
||||
|
||||
public class RewriteRecipeRepository {
|
||||
|
||||
private static final String CMD_REWRITE_RELOAD = "sts/rewrite/reload";
|
||||
private static final String CMD_REWRITE_EXECUTE = "sts/rewrite/execute";
|
||||
private static final String CMD_REWRITE_LIST = "sts/rewrite/list";
|
||||
private static final Logger log = LoggerFactory.getLogger(RewriteRecipeRepository.class);
|
||||
private static final String WORKSPACE_EXECUTE_COMMAND = "workspace/executeCommand";
|
||||
|
||||
@@ -84,11 +89,21 @@ public class RewriteRecipeRepository {
|
||||
final private SimpleLanguageServer server;
|
||||
|
||||
final private Map<String, Recipe> recipes;
|
||||
|
||||
final private List<Recipe> globalCommandRecipes;
|
||||
|
||||
final private JavaProjectFinder projectFinder;
|
||||
|
||||
final public CompletableFuture<Void> loaded;
|
||||
final private List<RecipeCodeActionDescriptor> codeActionDescriptors;
|
||||
|
||||
final private List<RecipeSpringJavaProblemDescriptor> javaProblemDescriptors;
|
||||
|
||||
final private ListenerList<Void> loadListeners;
|
||||
|
||||
private CompletableFuture<Void> loaded;
|
||||
|
||||
private Set<String> scanFiles = Collections.emptySet();
|
||||
private Set<String> scanDirs = Collections.emptySet();
|
||||
|
||||
static final Set<String> TOP_LEVEL_RECIPES = Set.of(
|
||||
"org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration",
|
||||
@@ -104,40 +119,62 @@ public class RewriteRecipeRepository {
|
||||
.registerTypeAdapter(Duration.class, new DurationTypeConverter())
|
||||
.create();
|
||||
|
||||
private List<RecipeCodeActionDescriptor> codeActionDescriptors = List.of(
|
||||
new AutowiredFieldIntoConstructorParameterCodeAction(),
|
||||
new BeanMethodsNotPublicCodeAction(),
|
||||
new NoRequestMappingAnnotationCodeAction(),
|
||||
new UnnecessarySpringExtensionCodeAction()
|
||||
);
|
||||
|
||||
private List<RecipeSpringJavaProblemDescriptor> javaProblemDescriptors = List.of(
|
||||
new BeanMethodNotPublicProblem(),
|
||||
new NoAutowiredOnConstructorProblem(),
|
||||
new UnnecessarySpringExtensionProblem(),
|
||||
new PreciseBeanTypeProblem()
|
||||
);
|
||||
|
||||
public RewriteRecipeRepository(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
|
||||
public RewriteRecipeRepository(SimpleLanguageServer server, JavaProjectFinder projectFinder, BootJavaConfig config) {
|
||||
this.server = server;
|
||||
this.projectFinder = projectFinder;
|
||||
this.recipes = new HashMap<>();
|
||||
this.globalCommandRecipes = new ArrayList<>();
|
||||
this.loaded = CompletableFuture.runAsync(this::loadRecipes);
|
||||
this.codeActionDescriptors = new ArrayList<>();
|
||||
this.javaProblemDescriptors = new ArrayList<>();
|
||||
this.loadListeners = new ListenerList<>();
|
||||
|
||||
server.doOnInitialized(() -> {
|
||||
this.scanDirs = config.getRecipeDirectories();
|
||||
this.scanFiles = config.getRecipeFiles();
|
||||
load().thenAccept(v -> registerCommands());
|
||||
config.addListener(l -> {
|
||||
if (!scanDirs.equals(config.getRecipeDirectories())
|
||||
|| !scanFiles.equals(config.getRecipeFiles())) {
|
||||
// Eclipse client sends one event for init and the other config changed event due to remote app value expr listener.
|
||||
// Therefore it is best to store the scanDirs here right after it is received, not during scan process or anything else done async
|
||||
scanDirs = config.getRecipeDirectories();
|
||||
scanFiles = config.getRecipeFiles();
|
||||
load();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void loadRecipes() {
|
||||
public CompletableFuture<Void> load() {
|
||||
return this.loaded = CompletableFuture.runAsync(() -> {
|
||||
clearRecipes();
|
||||
loadRecipes();
|
||||
loadListeners.fire(null);
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized void clearRecipes() {
|
||||
recipes.clear();
|
||||
globalCommandRecipes.clear();
|
||||
codeActionDescriptors.clear();
|
||||
javaProblemDescriptors.clear();
|
||||
}
|
||||
|
||||
private synchronized void loadRecipes() {
|
||||
try {
|
||||
server.getProgressService().progressBegin(RECIPES_LOADING_PROGRESS, "Loading Rewrite Recipes", null);
|
||||
log.info("Loading Rewrite Recipes...");
|
||||
for (Recipe r : Environment.builder().scanRuntimeClasspath().build().listRecipes()) {
|
||||
StsEnvironment env = createRewriteEnvironment();
|
||||
for (Recipe r : env.listRecipes()) {
|
||||
if (r.getName() != null) {
|
||||
if (recipes.containsKey(r.getName())) {
|
||||
log.error("Duplicate ids: '" + r.getName() + "'");
|
||||
}
|
||||
recipes.put(r.getName(), r);
|
||||
|
||||
if (TOP_LEVEL_RECIPES.contains(r.getName())) {
|
||||
if (TOP_LEVEL_RECIPES.contains(r.getName()) || r.getName().startsWith("rewrite.test.")
|
||||
|| r.getName().startsWith("org.rewrite.java.security")
|
||||
|| r.getName().startsWith("org.springframework.rewrite.test")) {
|
||||
Validated validation = Validated.invalid(null, null, null);
|
||||
try {
|
||||
validation = r.validate();
|
||||
@@ -150,14 +187,47 @@ public class RewriteRecipeRepository {
|
||||
}
|
||||
}
|
||||
}
|
||||
javaProblemDescriptors.addAll(env.listProblemDescriptors());
|
||||
codeActionDescriptors.addAll(env.listCodeActionDescriptors());
|
||||
log.info("Done loading Rewrite Recipes");
|
||||
server.doOnInitialized(() -> registerCommands());
|
||||
} catch (Throwable t) {
|
||||
server.getProgressService().progressDone(RECIPES_LOADING_PROGRESS);
|
||||
log.error("", t);
|
||||
} finally {
|
||||
server.getProgressService().progressDone(RECIPES_LOADING_PROGRESS);
|
||||
}
|
||||
}
|
||||
|
||||
private StsEnvironment createRewriteEnvironment() {
|
||||
StsEnvironment.Builder builder = (StsEnvironment.Builder) StsEnvironment.builder().scanRuntimeClasspath();
|
||||
for (String p : scanFiles) {
|
||||
try {
|
||||
Path f = Path.of(p);
|
||||
String pathStr = f.toString();
|
||||
if (pathStr.endsWith(".jar")) {
|
||||
URLClassLoader classLoader = new URLClassLoader(new URL[] { f.toUri().toURL() },
|
||||
getClass().getClassLoader());
|
||||
builder.scanJar(f, classLoader);
|
||||
} else if (pathStr.endsWith(".yml") || pathStr.endsWith(".yaml")) {
|
||||
builder.load(new YamlResourceLoader(new FileInputStream(f.toFile()), f.toUri(), new Properties()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Skipping folder " + p, e);
|
||||
}
|
||||
}
|
||||
for (String p : scanDirs) {
|
||||
try {
|
||||
Path d = Path.of(p);
|
||||
if (Files.isDirectory(d)) {
|
||||
URLClassLoader classLoader = new URLClassLoader(new URL[] { d.toUri().toURL()}, getClass().getClassLoader());
|
||||
builder.scanPath(d, classLoader);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Skipping folder " + p, e);
|
||||
}
|
||||
}
|
||||
return (StsEnvironment) builder.build();
|
||||
}
|
||||
|
||||
public Optional<Recipe> getRecipe(String name) {
|
||||
return Optional.ofNullable(recipes.get(name));
|
||||
}
|
||||
@@ -223,7 +293,7 @@ public class RewriteRecipeRepository {
|
||||
|
||||
Builder<Object> listBuilder = ImmutableList.builder();
|
||||
|
||||
server.onCommand("sts/rewrite/list", params -> {
|
||||
server.onCommand(CMD_REWRITE_LIST, params -> {
|
||||
JsonElement uri = (JsonElement) params.getArguments().get(0);
|
||||
return loaded.thenApply(v -> {
|
||||
if (uri == null) {
|
||||
@@ -233,9 +303,9 @@ public class RewriteRecipeRepository {
|
||||
}
|
||||
});
|
||||
});
|
||||
listBuilder.add("sts/rewrite/list");
|
||||
listBuilder.add(CMD_REWRITE_LIST);
|
||||
|
||||
server.onCommand("sts/rewrite/execute", params -> {
|
||||
server.onCommand(CMD_REWRITE_EXECUTE, params -> {
|
||||
String uri = ((JsonElement) params.getArguments().get(0)).getAsString();
|
||||
JsonElement recipesJson = ((JsonElement) params.getArguments().get(1));
|
||||
|
||||
@@ -254,7 +324,10 @@ public class RewriteRecipeRepository {
|
||||
return apply(aggregateRecipe, uri, progressToken);
|
||||
}
|
||||
});
|
||||
listBuilder.add("sts/rewrite/execute");
|
||||
listBuilder.add(CMD_REWRITE_EXECUTE);
|
||||
|
||||
server.onCommand(CMD_REWRITE_RELOAD, params -> load().thenApply((v) -> "executed"));
|
||||
listBuilder.add(CMD_REWRITE_RELOAD);
|
||||
|
||||
for (Recipe r : globalCommandRecipes) {
|
||||
listBuilder.add(createGlobalCommand(r));
|
||||
@@ -271,7 +344,6 @@ public class RewriteRecipeRepository {
|
||||
server.getClient().registerCapability(params).thenAccept((v) -> {
|
||||
server.onShutdown(() -> server.getClient().unregisterCapability(new UnregistrationParams(List.of(new Unregistration(registrationId, WORKSPACE_EXECUTE_COMMAND)))));
|
||||
log.info("Done registering commands for rewrite recipes");
|
||||
server.getProgressService().progressDone(RECIPES_LOADING_PROGRESS);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -370,6 +442,10 @@ public class RewriteRecipeRepository {
|
||||
}
|
||||
}
|
||||
|
||||
public void onRecipesLoaded(Consumer<Void> l) {
|
||||
loadListeners.add(l);
|
||||
}
|
||||
|
||||
// private static Recipe convert(Recipe r, RecipeDescriptor d) {
|
||||
// try {
|
||||
// if (d.selected) {
|
||||
|
||||
@@ -14,7 +14,6 @@ import java.io.ByteArrayInputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -39,7 +38,6 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.JavaReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RewriteRefactorings.Data;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.reconcile.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.Quickfix.QuickfixData;
|
||||
@@ -49,6 +47,8 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemC
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.ORAstUtils;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
@@ -103,24 +103,26 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
if (range != null) {
|
||||
RecipeSpringJavaProblemDescriptor recipeFixDescriptor = recipeRepo.getProblemRecipeDescriptor(m.getRecipeId());
|
||||
if (recipeFixDescriptor != null && recipeFixDescriptor.getScopes() != null && recipeRepo.getRecipe(recipeFixDescriptor.getRecipeId()).isPresent()) {
|
||||
return Arrays.stream(recipeFixDescriptor.getScopes()).map(s -> createProblemFromScope(doc, recipeFixDescriptor, s, m, range)).collect(Collectors.toList());
|
||||
return List.of(createProblemFromScope(doc, recipeFixDescriptor, m, range));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private ReconcileProblemImpl createProblemFromScope(IDocument doc, RecipeSpringJavaProblemDescriptor recipeFixDescriptor, RecipeScope s,
|
||||
private ReconcileProblemImpl createProblemFromScope(IDocument doc, RecipeSpringJavaProblemDescriptor recipeFixDescriptor,
|
||||
FixAssistMarker m, Range range) {
|
||||
ProblemType problemType = recipeFixDescriptor.getProblemType();
|
||||
ReconcileProblemImpl problem = new ReconcileProblemImpl(problemType, problemType.getLabel(), range.getStart().getOffset(), range.getEnd().getOffset() - range.getStart().getOffset());
|
||||
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(m.getRecipeId());
|
||||
if (quickfixType != null) {
|
||||
problem.addQuickfix(new QuickfixData<>(
|
||||
quickfixType,
|
||||
new Data(m.getRecipeId(), doc.getUri(), s, m.getScope().toString(), m.getParameters()),
|
||||
recipeFixDescriptor.getLabel(s)
|
||||
));
|
||||
QuickfixType quickfixType = quickfixRegistry.getQuickfixType(RewriteRefactorings.REWRITE_RECIPE_QUICKFIX);
|
||||
if (quickfixType != null && m.getRecipeId() != null) {
|
||||
for (RecipeScope s : recipeFixDescriptor.getScopes()) {
|
||||
problem.addQuickfix(new QuickfixData<>(
|
||||
quickfixType,
|
||||
new Data(m.getRecipeId(), doc.getUri(), s, m.getScope(), m.getParameters()),
|
||||
recipeFixDescriptor.getLabel(s)
|
||||
));
|
||||
}
|
||||
}
|
||||
return problem;
|
||||
}
|
||||
@@ -159,10 +161,6 @@ public class RewriteReconciler implements JavaReconciler {
|
||||
|
||||
private List<RecipeSpringJavaProblemDescriptor> getProblemRecipeDescriptors(IJavaProject project)
|
||||
throws InterruptedException, ExecutionException {
|
||||
// Wait for recipe repo to load if not loaded - should be loaded by the time we
|
||||
// get here.
|
||||
recipeRepo.loaded.get();
|
||||
|
||||
return recipeRepo.getProblemRecipeDescriptors().stream().filter(d -> d.getProblemType() != null).filter(d -> {
|
||||
switch (config.getProblemApplicability(d.getProblemType())) {
|
||||
case ON:
|
||||
|
||||
@@ -16,7 +16,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.lsp4j.CodeAction;
|
||||
@@ -31,6 +30,7 @@ import org.openrewrite.config.DeclarativeRecipe;
|
||||
import org.openrewrite.internal.RecipeIntrospectionUtils;
|
||||
import org.openrewrite.java.tree.J;
|
||||
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;
|
||||
@@ -40,6 +40,7 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixHa
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.CodeActionResolver;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
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.ORAstUtils;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -50,6 +51,8 @@ import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler {
|
||||
|
||||
public static final String REWRITE_RECIPE_QUICKFIX = "org.openrewrite.rewrite";
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RewriteRefactorings.class);
|
||||
|
||||
@@ -163,11 +166,18 @@ public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler
|
||||
}
|
||||
}
|
||||
if (d.recipeScope == RecipeScope.NODE) {
|
||||
UUID astNodeId = UUID.fromString(d.scope);
|
||||
if (astNodeId == null) {
|
||||
if (d.scope == null) {
|
||||
throw new IllegalArgumentException("Missing scope AST node!");
|
||||
} else {
|
||||
r = ORAstUtils.nodeRecipe(r, j -> j != null && astNodeId.equals(j.getId()));
|
||||
r = ORAstUtils.nodeRecipe(r, j -> {
|
||||
if (j != null) {
|
||||
Range range = j.getMarkers().findFirst(Range.class).orElse(null);
|
||||
if (range != null) {
|
||||
return d.scope.getStart().getOffset() <= range.getStart().getOffset() && range.getEnd().getOffset() <= d.scope.getEnd().getOffset();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
return r;
|
||||
@@ -177,9 +187,9 @@ public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler
|
||||
public String id;
|
||||
public String docUri;
|
||||
public RecipeScope recipeScope;
|
||||
public String scope;
|
||||
public Range scope;
|
||||
public Map<String, Object> params;
|
||||
public Data(String id, String docUri, RecipeScope recipeScope, String scope, Map<String, Object> params) {
|
||||
public Data(String id, String docUri, RecipeScope recipeScope, Range scope, Map<String, Object> params) {
|
||||
this.id = id;
|
||||
this.docUri = docUri;
|
||||
this.recipeScope = recipeScope;
|
||||
|
||||
@@ -24,9 +24,10 @@ import org.openrewrite.java.tree.J.ClassDeclaration;
|
||||
import org.openrewrite.java.tree.J.VariableDeclarations;
|
||||
import org.openrewrite.java.tree.JavaType.FullyQualified;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
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;
|
||||
|
||||
@@ -68,7 +69,7 @@ public class AutowiredFieldIntoConstructorParameterCodeAction implements RecipeC
|
||||
if (fqType != null && isApplicableType(fqType)) {
|
||||
m = m.withMarkers(m.getMarkers().add(new FixAssistMarker(Tree.randomId())
|
||||
.withRecipeId(getRecipeId())
|
||||
.withScope(classDeclaration.getId())
|
||||
.withScope(classDeclaration.getMarkers().findFirst(Range.class).get())
|
||||
.withParameters(Map.of("classFqName", fqType.getFullyQualifiedName(), "fieldName", multiVariable.getVariables().get(0).getSimpleName()))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
|
||||
public class BeanMethodsNotPublicCodeAction implements RecipeCodeActionDescriptor {
|
||||
@@ -60,7 +61,7 @@ public class BeanMethodsNotPublicCodeAction implements RecipeCodeActionDescripto
|
||||
// mark public modifier
|
||||
FixAssistMarker fixAssistMarker = new FixAssistMarker(Tree.randomId())
|
||||
.withRecipeId(ID)
|
||||
.withScope(m.getId());
|
||||
.withScope(m.getMarkers().findFirst(Range.class).get());
|
||||
m = m.withModifiers(ListUtils.map(m.getModifiers(), modifier -> {
|
||||
if (modifier.getType() == J.Modifier.Type.Public) {
|
||||
return modifier.withMarkers(modifier.getMarkers().add(fixAssistMarker));
|
||||
|
||||
@@ -18,9 +18,10 @@ import org.openrewrite.java.AnnotationMatcher;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
|
||||
public class NoRequestMappingAnnotationCodeAction implements RecipeCodeActionDescriptor {
|
||||
@@ -53,7 +54,7 @@ public class NoRequestMappingAnnotationCodeAction implements RecipeCodeActionDes
|
||||
if (REQUEST_MAPPING_ANNOTATION_MATCHER.matches(a) && getCursor().getParentOrThrow().getValue() instanceof J.MethodDeclaration) {
|
||||
FixAssistMarker fixAssistMarker = new FixAssistMarker(Tree.randomId())
|
||||
.withRecipeId(getRecipeId())
|
||||
.withScope(a.getId());
|
||||
.withScope(a.getMarkers().findFirst(Range.class).get());
|
||||
a = a.withMarkers(a.getMarkers().add(fixAssistMarker));
|
||||
}
|
||||
return a;
|
||||
|
||||
@@ -14,7 +14,6 @@ import static org.springframework.ide.vscode.commons.java.SpringProjectUtil.spri
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.openrewrite.ExecutionContext;
|
||||
import org.openrewrite.Tree;
|
||||
@@ -22,12 +21,13 @@ import org.openrewrite.internal.ListUtils;
|
||||
import org.openrewrite.java.AnnotationMatcher;
|
||||
import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.openrewrite.java.tree.J.ClassDeclaration;
|
||||
import org.openrewrite.java.tree.JavaType.FullyQualified;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
|
||||
public class UnnecessarySpringExtensionCodeAction implements RecipeCodeActionDescriptor {
|
||||
@@ -80,10 +80,10 @@ public class UnnecessarySpringExtensionCodeAction implements RecipeCodeActionDes
|
||||
FullyQualified fq = TypeUtils.asFullyQualified(a.getType());
|
||||
return fq != null && SPRING_BOOT_TEST_ANNOTATIONS.contains(fq.getFullyQualifiedName());
|
||||
})) {
|
||||
UUID id = c.getId();
|
||||
Range range = c.getMarkers().findFirst(Range.class).get();
|
||||
c = c.withLeadingAnnotations(ListUtils.map(c.getLeadingAnnotations(), a -> {
|
||||
if (SPRING_EXTENSION_ANNOTATIN_MATCHER.matches(a)) {
|
||||
return a.withMarkers(a.getMarkers().add(new FixAssistMarker(Tree.randomId()).withRecipeId(ID).withScope(id)));
|
||||
return a.withMarkers(a.getMarkers().add(new FixAssistMarker(Tree.randomId()).withRecipeId(ID).withScope(range)));
|
||||
}
|
||||
return a;
|
||||
}));
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.BeanMethodsNotPublicCodeAction;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
|
||||
public class BeanMethodNotPublicProblem extends BeanMethodsNotPublicCodeAction implements RecipeSpringJavaProblemDescriptor {
|
||||
|
||||
|
||||
@@ -21,12 +21,14 @@ import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.J.ClassDeclaration;
|
||||
import org.openrewrite.java.tree.J.MethodDeclaration;
|
||||
import org.openrewrite.java.tree.JavaType.FullyQualified;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.openrewrite.java.tree.Statement;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.AnnotationHierarchies;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
|
||||
@@ -76,7 +78,7 @@ public class NoAutowiredOnConstructorProblem implements RecipeSpringJavaProblemD
|
||||
MethodDeclaration constructor = (MethodDeclaration) s;
|
||||
FixAssistMarker fixAssistMarker = new FixAssistMarker(Tree.randomId())
|
||||
.withRecipeId(ID)
|
||||
.withScope(getCursor().firstEnclosing(ClassDeclaration.class).getId());
|
||||
.withScope(getCursor().firstEnclosing(ClassDeclaration.class).getMarkers().findFirst(Range.class).get());
|
||||
constructor = constructor.withLeadingAnnotations(ListUtils.map(constructor.getLeadingAnnotations(), a -> {
|
||||
if (TypeUtils.isOfClassType(a.getType(), Annotations.AUTOWIRED)) {
|
||||
a = a.withMarkers(a.getMarkers().add(fixAssistMarker));
|
||||
|
||||
@@ -19,12 +19,14 @@ import org.openrewrite.java.JavaIsoVisitor;
|
||||
import org.openrewrite.java.JavaVisitor;
|
||||
import org.openrewrite.java.tree.J;
|
||||
import org.openrewrite.java.tree.J.Return;
|
||||
import org.openrewrite.marker.Range;
|
||||
import org.openrewrite.java.tree.JavaType;
|
||||
import org.openrewrite.java.tree.TypeUtils;
|
||||
import org.springframework.ide.vscode.boot.java.Boot3JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeCodeActionDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
import org.springframework.ide.vscode.commons.rewrite.java.FixAssistMarker;
|
||||
|
||||
public class PreciseBeanTypeProblem implements RecipeSpringJavaProblemDescriptor {
|
||||
@@ -60,7 +62,7 @@ public class PreciseBeanTypeProblem implements RecipeSpringJavaProblemDescriptor
|
||||
if ((o instanceof JavaType.FullyQualified && m.getReturnTypeExpression().getType() instanceof JavaType.FullyQualified)
|
||||
|| (o instanceof JavaType.Array && m.getReturnTypeExpression().getType() instanceof JavaType.Array)) {
|
||||
m = m.withReturnTypeExpression(m.getReturnTypeExpression().withMarkers(m.getReturnTypeExpression().getMarkers().add(
|
||||
new FixAssistMarker(Tree.randomId()).withScope(m.getId()).withRecipeId(getRecipeId()))));
|
||||
new FixAssistMarker(Tree.randomId()).withScope(m.getMarkers().findFirst(Range.class).get()).withRecipeId(getRecipeId()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
package org.springframework.ide.vscode.boot.java.rewrite.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.RecipeScope;
|
||||
import org.springframework.ide.vscode.boot.java.rewrite.codeaction.UnnecessarySpringExtensionCodeAction;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeScope;
|
||||
import org.springframework.ide.vscode.commons.rewrite.config.RecipeSpringJavaProblemDescriptor;
|
||||
|
||||
public class UnnecessarySpringExtensionProblem extends UnnecessarySpringExtensionCodeAction
|
||||
implements RecipeSpringJavaProblemDescriptor {
|
||||
|
||||
@@ -211,6 +211,7 @@ export function activate(
|
||||
context: VSCode.ExtensionContext
|
||||
) {
|
||||
context.subscriptions.push(
|
||||
VSCode.commands.registerCommand('vscode-spring-boot.rewrite.list', liveHoverConnectHandler)
|
||||
VSCode.commands.registerCommand('vscode-spring-boot.rewrite.list', liveHoverConnectHandler),
|
||||
VSCode.commands.registerCommand('vscode-spring-boot.rewrite.reload', () => VSCode.commands.executeCommand('sts/rewrite/reload'))
|
||||
);
|
||||
}
|
||||
@@ -93,6 +93,11 @@
|
||||
"command": "vscode-spring-boot.rewrite.list",
|
||||
"category": "Spring Boot",
|
||||
"title": "Rewrite Refactorings..."
|
||||
},
|
||||
{
|
||||
"command": "vscode-spring-boot.rewrite.reload",
|
||||
"title": "Reload Rewrite Recipes, Code Actions, Problem and Quick Fix Descriptors",
|
||||
"category": "Spring Boot"
|
||||
}
|
||||
],
|
||||
"configuration": [
|
||||
@@ -106,11 +111,6 @@
|
||||
"default": false,
|
||||
"description": "Experimental support for Rewrite recipes refactoring the whole maven projects via commands"
|
||||
},
|
||||
"boot-java.rewrite.reconcile": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Experimental reconciling for Java source based on Rewrite project"
|
||||
},
|
||||
"boot-java.live-information.automatic-connection.on": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
@@ -188,6 +188,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "rewrite",
|
||||
"title": "Rewrite",
|
||||
"order": 400,
|
||||
"properties": {
|
||||
"boot-java.rewrite.reconcile": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Experimental reconciling for Java source based on Rewrite project"
|
||||
},
|
||||
"boot-java.rewrite.scan-files": {
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "JAR and YAML files to scan for recipes, code actions, problem and quick fix descriptors"
|
||||
},
|
||||
"boot-java.rewrite.scan-dirs": {
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Java project output folders to scan for recipes"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ls",
|
||||
"title": "Language Server",
|
||||
|
||||
Reference in New Issue
Block a user