diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java index d4bcb3a62..cd8383466 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java @@ -59,9 +59,9 @@ import org.springframework.ide.eclipse.boot.dash.model.RunState; import org.springframework.ide.eclipse.boot.dash.model.remote.ChildBearing; import org.springframework.ide.eclipse.boot.dash.model.remote.RefreshStateTracker; import org.springframework.ide.eclipse.boot.dash.util.LineBasedStreamGobler; -import org.springframework.ide.eclipse.boot.launch.util.BootDebugUITools; import org.springframework.ide.eclipse.boot.launch.util.PortFinder; import org.springframework.ide.eclipse.boot.util.JavaProjectUtil; +import org.springsource.ide.eclipse.commons.core.CoreUtil; import org.springsource.ide.eclipse.commons.core.pstore.PropertyStoreApi; import org.springsource.ide.eclipse.commons.frameworks.core.util.JobUtil; import org.springsource.ide.eclipse.commons.frameworks.core.util.StringUtils; @@ -197,7 +197,7 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, DockerDeployment deployment = deployment(); RunState desiredRunState = deployment.getRunState(); if (desiredRunState.isActive() - && !BootDebugUITools.promptForProjectSave(project)) { + && !CoreUtil.promptForProjectSave(project)) { return new CompletableFuture(); } } catch (Exception e) { diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java index 6026481b7..73dd50d1c 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.launch/src/org/springframework/ide/eclipse/boot/launch/util/BootDebugUITools.java @@ -184,57 +184,4 @@ public class BootDebugUITools { job.schedule(); } - /* - * - * The following constants are copied from LaunchConfigurationDelegate - * - * - */ - - /** - * Constant to define debug.core for the status codes - * - * @since 3.2 - */ - private static final String DEBUG_CORE = "org.eclipse.debug.core"; - - /** - * Constant to define debug.ui for the status codes - * - * @since 3.2 - */ - private static final String DEBUG_UI = "org.eclipse.debug.ui"; - - /** - * Status code for which a UI prompter is registered. - */ - protected static final IStatus promptStatus = new Status(IStatus.INFO, DEBUG_UI, 200, "", null); - - /** - * Status code for which a prompter will ask the user to save any/all of the dirty editors which have only to do - * with this launch (scoping them to the current launch/build) - * - * @since 3.2 - */ - protected static final IStatus saveScopedDirtyEditors = new Status(IStatus.INFO, DEBUG_CORE, 222, "", null); - - /** - * Derived from {@link LaunchConfigurationDelegate} - * @param project - * @return true if project was saved. False if canceled - * @throws Exception - */ - public static boolean promptForProjectSave(IProject project) throws Exception { - IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus); - - if(prompter != null) { - IProject[] projects = new IProject[] {project}; - ILaunchConfiguration configuration = null; - if(!((Boolean)prompter.handleStatus(saveScopedDirtyEditors, new Object[]{configuration, projects})).booleanValue()) { - return false; - } - } - return true; - } - } diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF index f46f6b9a3..4bcbfd9a9 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/META-INF/MANIFEST.MF @@ -34,7 +34,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.springsource.ide.eclipse.commons.boot.ls, org.springframework.ide.eclipse.editor.support, com.google.guava, - org.eclipse.core.expressions + org.eclipse.core.expressions, + org.springsource.ide.eclipse.commons.core;bundle-version="4.17.0" Import-Package: com.google.common.base, com.google.common.collect, com.google.gson;version="2.7.0", diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java index e987fabf3..1716238f8 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/commands/RewriteRefactoringsHandler.java @@ -37,6 +37,7 @@ 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.springsource.ide.eclipse.commons.core.CoreUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -85,71 +86,75 @@ public class RewriteRefactoringsHandler extends AbstractHandler { } else if (o instanceof IAdaptable) { project = ((IAdaptable) o).getAdapter(IProject.class); } - if (project != null) { - List<@NonNull LanguageServer> usedLanguageServers = LanguageServiceAccessor - .getActiveLanguageServers(serverCapabilities -> true); + try { + if (project != null && CoreUtil.promptForProjectSave(project)) { + List<@NonNull LanguageServer> usedLanguageServers = LanguageServiceAccessor + .getActiveLanguageServers(serverCapabilities -> true); - if (!usedLanguageServers.isEmpty()) { - final String uri = project.getLocationURI().toString(); - ExecuteCommandParams commandParams = new ExecuteCommandParams(); - commandParams.setCommand(REWRITE_REFACTORINGS_LIST); - commandParams.setArguments(List.of(uri)); + if (!usedLanguageServers.isEmpty()) { + final String uri = project.getLocationURI().toString(); + ExecuteCommandParams commandParams = new ExecuteCommandParams(); + commandParams.setCommand(REWRITE_REFACTORINGS_LIST); + commandParams.setArguments(List.of(uri)); - try { - List allRewriteRecipesJson = new ArrayList<>(); - List syncRecipesJson = Collections.synchronizedList(allRewriteRecipesJson); - CompletableFuture.allOf(usedLanguageServers.stream() - .map(ls -> ls.getWorkspaceService().executeCommand(commandParams).thenAccept(or -> { - if (or != null) { - syncRecipesJson.add(or); - } - }).exceptionally(t -> null)) - .toArray(CompletableFuture[]::new)).thenRun(() -> { - allRewriteRecipesJson.stream().filter(List.class::isInstance).map(List.class::cast).findFirst().ifPresent(obj -> { - RecipeDescriptor[] descriptors = serializationGson.fromJson(serializationGson.toJson(obj), RecipeDescriptor[].class); - - PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { - RecipeTreeModel recipesModel = new RecipeTreeModel(descriptors); - int returnCode = new SelectRecipesDialog(Display.getCurrent().getActiveShell(), recipesModel).open(); - if (returnCode == Window.OK) { - try { - RecipeDescriptor recipeToApply = recipesModel.getSelectedRecipeDescriptors(); - PlatformUI.getWorkbench().getProgressService().run(true, false, monitor -> { - try { - if (!usedLanguageServers.isEmpty()) { - monitor.beginTask("Applying recipe '" + recipeToApply.displayName + "'", IProgressMonitor.UNKNOWN); - ExecuteCommandParams cmdParams = new ExecuteCommandParams(); - cmdParams.setCommand(REWRITE_REFACTORINGS_EXEC); - cmdParams.setArguments(List.of( - uri, - serializationGson.toJsonTree(recipeToApply) - )); - - CompletableFuture.allOf(usedLanguageServers.stream() - .map(ls -> ls.getWorkspaceService().executeCommand(cmdParams)) - .toArray(CompletableFuture[]::new)).get(); + try { + List allRewriteRecipesJson = new ArrayList<>(); + List syncRecipesJson = Collections.synchronizedList(allRewriteRecipesJson); + CompletableFuture.allOf(usedLanguageServers.stream() + .map(ls -> ls.getWorkspaceService().executeCommand(commandParams).thenAccept(or -> { + if (or != null) { + syncRecipesJson.add(or); + } + }).exceptionally(t -> null)) + .toArray(CompletableFuture[]::new)).thenRun(() -> { + allRewriteRecipesJson.stream().filter(List.class::isInstance).map(List.class::cast).findFirst().ifPresent(obj -> { + RecipeDescriptor[] descriptors = serializationGson.fromJson(serializationGson.toJson(obj), RecipeDescriptor[].class); + + PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { + RecipeTreeModel recipesModel = new RecipeTreeModel(descriptors); + int returnCode = new SelectRecipesDialog(Display.getCurrent().getActiveShell(), recipesModel).open(); + if (returnCode == Window.OK) { + try { + RecipeDescriptor recipeToApply = recipesModel.getSelectedRecipeDescriptors(); + PlatformUI.getWorkbench().getProgressService().run(true, false, monitor -> { + try { + if (!usedLanguageServers.isEmpty()) { + monitor.beginTask("Applying recipe '" + recipeToApply.displayName + "'", IProgressMonitor.UNKNOWN); + ExecuteCommandParams cmdParams = new ExecuteCommandParams(); + cmdParams.setCommand(REWRITE_REFACTORINGS_EXEC); + cmdParams.setArguments(List.of( + uri, + serializationGson.toJsonTree(recipeToApply) + )); + + CompletableFuture.allOf(usedLanguageServers.stream() + .map(ls -> ls.getWorkspaceService().executeCommand(cmdParams)) + .toArray(CompletableFuture[]::new)).get(); + } + } catch (Exception e) { + throw new InvocationTargetException(e); + } finally { + monitor.done(); } - } catch (Exception e) { - throw new InvocationTargetException(e); - } finally { - monitor.done(); - } - }); - - } catch (CoreException | InvocationTargetException | InterruptedException e) { - BootLanguageServerPlugin.getDefault().getLog().error(e.getMessage(), e); - MessageDialog.openError(Display.getCurrent().getActiveShell(), "Error", "Failed to apply Rewrite recipe(s). See error log for more details."); + }); + + } catch (CoreException | InvocationTargetException | InterruptedException e) { + BootLanguageServerPlugin.getDefault().getLog().error(e.getMessage(), e); + MessageDialog.openError(Display.getCurrent().getActiveShell(), "Error", "Failed to apply Rewrite recipe(s). See error log for more details."); + } } - } + }); }); + }); - - }); - } catch (Exception e) { - throw new ExecutionException("Failed to apply Rewrite recipe(s)", e); + } catch (Exception e) { + throw new ExecutionException("Failed to apply Rewrite recipe(s)", e); + } } - } + } + } catch (Exception e) { + throw new ExecutionException("Failed to save project resource(s)", e); } return null; } diff --git a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CoreUtil.java b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CoreUtil.java index 177798edd..a6d450489 100644 --- a/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CoreUtil.java +++ b/eclipse-language-servers/org.springsource.ide.eclipse.commons.core/src/org/springsource/ide/eclipse/commons/core/CoreUtil.java @@ -12,7 +12,14 @@ package org.springsource.ide.eclipse.commons.core; import java.util.Properties; +import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.IStatusHandler; +import org.eclipse.debug.core.model.LaunchConfigurationDelegate; /** * @author Steffen Pingel @@ -24,7 +31,7 @@ public class CoreUtil { * properties. Placeholders use the following format: * ${key}. If the key is not found in properties * the placeholder is retained. - * + * * @param text the text * @param properties key value pairs for substitution * @return the substituted text @@ -56,4 +63,58 @@ public class CoreUtil { return sb.toString(); } + /* + * + * The following constants are copied from LaunchConfigurationDelegate + * + * + */ + + /** + * Constant to define debug.core for the status codes + * + * @since 3.2 + */ + private static final String DEBUG_CORE = "org.eclipse.debug.core"; + + /** + * Constant to define debug.ui for the status codes + * + * @since 3.2 + */ + private static final String DEBUG_UI = "org.eclipse.debug.ui"; + + /** + * Status code for which a UI prompter is registered. + */ + protected static final IStatus promptStatus = new Status(IStatus.INFO, DEBUG_UI, 200, "", null); + + /** + * Status code for which a prompter will ask the user to save any/all of the dirty editors which have only to do + * with this launch (scoping them to the current launch/build) + * + * @since 3.2 + */ + protected static final IStatus saveScopedDirtyEditors = new Status(IStatus.INFO, DEBUG_CORE, 222, "", null); + + /** + * Derived from {@link LaunchConfigurationDelegate} + * @param project + * @return true if project was saved. False if canceled + * @throws Exception + */ + public static boolean promptForProjectSave(IProject project) throws Exception { + IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus); + + if(prompter != null) { + IProject[] projects = new IProject[] {project}; + ILaunchConfiguration configuration = null; + if(!((Boolean)prompter.handleStatus(saveScopedDirtyEditors, new Object[]{configuration, projects})).booleanValue()) { + return false; + } + } + return true; + } + + } diff --git a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/maven/MavenProjectParser.java b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/maven/MavenProjectParser.java index 6892e7b13..97f500f69 100644 --- a/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/maven/MavenProjectParser.java +++ b/headless-services/commons/commons-rewrite/src/main/java/org/springframework/ide/vscode/commons/rewrite/maven/MavenProjectParser.java @@ -12,6 +12,7 @@ package org.springframework.ide.vscode.commons.rewrite.maven; import static org.openrewrite.Tree.randomId; +import java.io.ByteArrayInputStream; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; @@ -26,12 +27,14 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.function.BiPredicate; +import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.openrewrite.ExecutionContext; +import org.openrewrite.Parser; import org.openrewrite.SourceFile; import org.openrewrite.internal.ListUtils; import org.openrewrite.java.JavaParser; @@ -65,13 +68,16 @@ public class MavenProjectParser { private final MavenParser mavenParser; private final JavaParser.Builder javaParserBuilder; private final ExecutionContext ctx; + private final Function parserInputProvider; public MavenProjectParser(MavenParser.Builder mavenParserBuilder, JavaParser.Builder javaParserBuilder, - ExecutionContext ctx) { + ExecutionContext ctx, + Function parserInputProvider) { this.mavenParser = mavenParserBuilder.build(); this.javaParserBuilder = javaParserBuilder; this.ctx = ctx; + this.parserInputProvider = parserInputProvider; } /** @@ -98,7 +104,7 @@ public class MavenProjectParser { * @return A list of source files that have been parsed from the root folder */ public List parse(Path projectDirectory, List dependencies) { - List mavens = mavenParser.parse(getMavenPoms(projectDirectory, ctx), projectDirectory, ctx); + List mavens = mavenParser.parseInputs(getMavenPoms(projectDirectory, ctx, parserInputProvider), projectDirectory, ctx); List sorted = sort(mavens); // Filter out pom files inside target folders. (Naive implementation.) @@ -119,18 +125,18 @@ public class MavenProjectParser { // List dependencies = downloadArtifacts(getResolvedPom(maven).getDependencies().get(Scope.Compile)); javaParser.setSourceSet("main"); javaParser.setClasspath(dependencies); - sourceFiles.addAll(ListUtils.map(javaParser.parse( - getJavaSources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, ctx), addProvenance(projectProvenance))); + sourceFiles.addAll(ListUtils.map(javaParser.parseInputs( + getJavaSources(getModel(maven).getRequested(), projectDirectory, ctx, parserInputProvider), projectDirectory, ctx), addProvenance(projectProvenance))); //Resources in the src/main should also have the main source set attached to them. - parseResources(getResources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, sourceFiles, projectProvenance, javaParser.getSourceSet(ctx)); + parseResources(getResources(getModel(maven).getRequested(), projectDirectory, ctx, parserInputProvider), projectDirectory, sourceFiles, projectProvenance, javaParser.getSourceSet(ctx)); // List testDependencies = downloadArtifacts(maven.getModel().getDependencies(Scope.Test)); javaParser.setSourceSet("test"); // javaParser.setClasspath(testDependencies); - sourceFiles.addAll(ListUtils.map(javaParser.parse( - getTestJavaSources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, ctx), addProvenance(projectProvenance))); + sourceFiles.addAll(ListUtils.map(javaParser.parseInputs( + getTestJavaSources(getModel(maven).getRequested(), projectDirectory, ctx, parserInputProvider), projectDirectory, ctx), addProvenance(projectProvenance))); //Resources in the src/test should also have the test source set attached to them. - parseResources(getTestResources(getModel(maven).getRequested(), projectDirectory, ctx), projectDirectory, sourceFiles, projectProvenance, javaParser.getSourceSet(ctx)); + parseResources(getTestResources(getModel(maven).getRequested(), projectDirectory, ctx, parserInputProvider), projectDirectory, sourceFiles, projectProvenance, javaParser.getSourceSet(ctx)); } return sourceFiles; @@ -180,34 +186,34 @@ public class MavenProjectParser { ); } - private void parseResources(List resources, Path projectDirectory, List sourceFiles, List projectProvenance, JavaSourceSet sourceSet) { + private void parseResources(List resources, Path projectDirectory, List sourceFiles, List projectProvenance, JavaSourceSet sourceSet) { List provenance = new ArrayList<>(projectProvenance); provenance.add(sourceSet); - sourceFiles.addAll(ListUtils.map(new XmlParser().parse( + sourceFiles.addAll(ListUtils.map(new XmlParser().parseInputs( resources.stream() - .filter(p -> p.getFileName().toString().endsWith(".xml") || - p.getFileName().toString().endsWith(".wsdl") || - p.getFileName().toString().endsWith(".xhtml") || - p.getFileName().toString().endsWith(".xsd") || - p.getFileName().toString().endsWith(".xsl") || - p.getFileName().toString().endsWith(".xslt")) + .filter(p -> p.getPath().getFileName().toString().endsWith(".xml") || + p.getPath().getFileName().toString().endsWith(".wsdl") || + p.getPath().getFileName().toString().endsWith(".xhtml") || + p.getPath().getFileName().toString().endsWith(".xsd") || + p.getPath().getFileName().toString().endsWith(".xsl") || + p.getPath().getFileName().toString().endsWith(".xslt")) .collect(Collectors.toList()), projectDirectory, ctx ), addProvenance(provenance))); - sourceFiles.addAll(ListUtils.map(new YamlParser().parse( + sourceFiles.addAll(ListUtils.map(new YamlParser().parseInputs( resources.stream() - .filter(p -> p.getFileName().toString().endsWith(".yml") || p.getFileName().toString().endsWith(".yaml")) + .filter(p -> p.getPath().getFileName().toString().endsWith(".yml") || p.getPath().getFileName().toString().endsWith(".yaml")) .collect(Collectors.toList()), projectDirectory, ctx ), addProvenance(provenance))); - sourceFiles.addAll(ListUtils.map(new PropertiesParser().parse( + sourceFiles.addAll(ListUtils.map(new PropertiesParser().parseInputs( resources.stream() - .filter(p -> p.getFileName().toString().endsWith(".properties")) + .filter(p -> p.getPath().getFileName().toString().endsWith(".properties")) .collect(Collectors.toList()), projectDirectory, ctx @@ -281,7 +287,7 @@ public class MavenProjectParser { }).findFirst().isPresent(); } - private static List getSources(Path srcDir, ExecutionContext ctx, String... fileTypes) { + private static List getSources(Path srcDir, ExecutionContext ctx, Function parserInputProvider, String... fileTypes) { if (!srcDir.toFile().exists()) { return List.of(); } @@ -289,16 +295,31 @@ public class MavenProjectParser { BiPredicate predicate = (p, bfa) -> bfa.isRegularFile() && Arrays.stream(fileTypes).anyMatch(type -> p.getFileName().toString().endsWith(type)); try { - return Files.find(srcDir, 999, predicate).collect(Collectors.toList()); + return Files.find(srcDir, 999, predicate).map(p -> { + Parser.Input in = null; + if (parserInputProvider != null) { + in = parserInputProvider.apply(p); + } + if (in == null) { + in = new Parser.Input(p, () -> { + try { + return Files.newInputStream(p); + } catch (IOException e) { + return new ByteArrayInputStream(new byte[0]); + } + }); + } + return in; + }).collect(Collectors.toList()); } catch (IOException e) { ctx.getOnError().accept(e); return List.of(); } } - public static List getMavenPoms(Path projectDir, ExecutionContext ctx) { - return getSources(projectDir, ctx, "pom.xml").stream() - .filter(p -> p.getFileName().toString().equals("pom.xml") && + public static List getMavenPoms(Path projectDir, ExecutionContext ctx, Function parserInputProvider) { + return getSources(projectDir, ctx, parserInputProvider, "pom.xml").stream() + .filter(p -> p.getPath().getFileName().toString().equals("pom.xml") && !p.toString().contains("/src/")) .collect(Collectors.toList()); } @@ -312,36 +333,36 @@ public class MavenProjectParser { return maven.getMarkers().findFirst(MavenResolutionResult.class).orElse(null); } - private static List getJavaSources(Pom pom, Path projectDir, ExecutionContext ctx) { + private static List getJavaSources(Pom pom, Path projectDir, ExecutionContext ctx, Function parserInputProvider) { if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) { return List.of(); } return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "main", "java")), - ctx, ".java"); + ctx, parserInputProvider, ".java"); } - private static List getTestJavaSources(Pom pom, Path projectDir, ExecutionContext ctx) { + private static List getTestJavaSources(Pom pom, Path projectDir, ExecutionContext ctx, Function parserInputProvider) { if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) { return List.of(); } return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "test", "java")), - ctx, ".java"); + ctx, parserInputProvider, ".java"); } - private static List getResources(Pom pom, Path projectDir, ExecutionContext ctx) { + private static List getResources(Pom pom, Path projectDir, ExecutionContext ctx, Function parserInputProvider) { if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) { return List.of(); } return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "main", "resources")), - ctx, ".properties", ".xml", ".yml", ".yaml"); + ctx, parserInputProvider, ".properties", ".xml", ".yml", ".yaml"); } - private static List getTestResources(Pom pom, Path projectDir, ExecutionContext ctx) { + private static List getTestResources(Pom pom, Path projectDir, ExecutionContext ctx, Function parserInputProvider) { if (pom.getPackaging() != null && !"jar".equals(pom.getPackaging()) && !"bundle".equals(pom.getPackaging())) { return List.of(); } return getSources(projectDir.resolve(pom.getSourcePath()).getParent().resolve(Paths.get("src", "test", "resources")), - ctx, ".properties", ".xml", ".yml", ".yaml"); + ctx, parserInputProvider, ".properties", ".xml", ".yml", ".yaml"); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java index b6c51858f..90066f971 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRecipeRepository.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.rewrite; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.net.URL; @@ -29,6 +30,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -42,6 +44,7 @@ import org.eclipse.lsp4j.UnregistrationParams; import org.eclipse.lsp4j.WorkspaceEdit; import org.openrewrite.ExecutionContext; import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.Parser; import org.openrewrite.Recipe; import org.openrewrite.RecipeRun; import org.openrewrite.Result; @@ -72,6 +75,7 @@ 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.StsEnvironment; import org.springframework.ide.vscode.commons.rewrite.maven.MavenProjectParser; +import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; @@ -421,7 +425,13 @@ public class RewriteRecipeRepository implements ApplicationContextAware { Path absoluteProjectDir = Paths.get(project.getLocationUri()); server.getProgressService().progressEvent(r.getName(), "Parsing files..."); MavenProjectParser projectParser = createRewriteMavenParser(absoluteProjectDir, - new InMemoryExecutionContext()); + new InMemoryExecutionContext(), p -> { + TextDocument doc = server.getTextDocumentService().getLatestSnapshot(p.toUri().toString()); + if (doc != null) { + return new Parser.Input(p, () -> new ByteArrayInputStream(doc.get().getBytes())); + } + return null; + }); List sources = projectParser.parse(absoluteProjectDir, getClasspathEntries(project)); server.getProgressService().progressEvent(r.getName(), "Computing changes..."); RecipeRun reciperun = r.run(sources, new InMemoryExecutionContext(e -> log.error("", e))); @@ -443,14 +453,15 @@ public class RewriteRecipeRepository implements ApplicationContextAware { return Collections.emptyList(); } - private static MavenProjectParser createRewriteMavenParser(Path absoluteProjectDir, ExecutionContext context) { + private static MavenProjectParser createRewriteMavenParser(Path absoluteProjectDir, ExecutionContext context, Function inputProvider) { MavenParser.Builder mavenParserBuilder = MavenParser.builder() .mavenConfig(absoluteProjectDir.resolve(".mvn/maven.config")); MavenProjectParser mavenProjectParser = new MavenProjectParser( mavenParserBuilder, JavaParser.fromJavaVersion(), - context + context, + inputProvider ); return mavenProjectParser; }