Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ public String toMajorMinorVersionStr() {
return sb.toString();
}

public String toMajorMinorPatchVersionStr() {
StringBuilder sb = new StringBuilder();
sb.append(major);
sb.append('.');
sb.append(minor);
sb.append('.');
sb.append(patch);
return sb.toString();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,11 @@ public static List<CompilationUnit> parse(JavaParser parser, Iterable<Path> sour
});
}

public static List<SourceFile> parseInputs(JavaParser parser, List<Parser.Input> inputs, Consumer<SourceFile> parseCallback) {
ExecutionContext ctx = new InMemoryExecutionContext(ORAstUtils::logExceptionWhileParsing);
public static ExecutionContext createDefaultContext() {
return new InMemoryExecutionContext(ORAstUtils::logExceptionWhileParsing);
}

public static List<SourceFile> parseInputs(JavaParser parser, ExecutionContext ctx, List<Parser.Input> inputs, Consumer<SourceFile> parseCallback) {
ctx.putMessage(JavaParser.SKIP_SOURCE_SET_TYPE_GENERATION, true);
ctx.putMessage(ExecutionContext.REQUIRE_PRINT_EQUALS_INPUT, false);
if (parseCallback != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2024 Pivotal, Inc.
* Copyright (c) 2018, 2026 Pivotal, 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
Expand Down Expand Up @@ -38,6 +38,7 @@
import org.springframework.ide.vscode.boot.maven.PomLanguageServerComponents;
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
import org.springframework.ide.vscode.boot.properties.BootPropertiesLanguageServerComponents;
import org.springframework.ide.vscode.boot.validation.generations.MavenMetadataProvider;
import org.springframework.ide.vscode.boot.validation.generations.SpringProjectsProvider;
import org.springframework.ide.vscode.boot.xml.SpringXMLLanguageServerComponents;
import org.springframework.ide.vscode.commons.java.IJavaProject;
Expand Down Expand Up @@ -130,7 +131,7 @@ public void afterPropertiesSet() throws Exception {
new BootJavaLanguageServerComponents(appContext),
new SpringXMLLanguageServerComponents(server, springIndexer, params, config, appContext.getBean(SpelReconciler.class)),
new SpringFactoriesLanguageServerComponents(projectFinder, springIndexer, config),
new PomLanguageServerComponents(server, projectFinder, params.projectObserver, appContext.getBean(SpringProjectsProvider.class)),
new PomLanguageServerComponents(server, projectFinder, params.projectObserver, appContext.getBean(SpringProjectsProvider.class), appContext.getBean(MavenMetadataProvider.class)),
new JpaQueryPropertiesLanguageServerComponents(server.getTextDocumentService(), projectFinder, appContext.getBean(JpqlSemanticTokens.class),
appContext.getBean(HqlSemanticTokens.class), appContext.getBean(JpqlSupportState.class), (Reconciler) appContext.getBean("hqlReconciler"), (Reconciler) appContext.getBean("jpqlReconciler"))
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.app;

import java.net.URI;
import java.util.List;
import java.util.Optional;

Expand All @@ -23,6 +24,7 @@
import org.springframework.ide.vscode.boot.java.rewrite.SpringBootUpgrade;
import org.springframework.ide.vscode.boot.validation.BootVersionValidationEngine;
import org.springframework.ide.vscode.boot.validation.generations.GenerationsValidator;
import org.springframework.ide.vscode.boot.validation.generations.MavenMetadataProvider;
import org.springframework.ide.vscode.boot.validation.generations.ProjectVersionDiagnosticProvider;
import org.springframework.ide.vscode.boot.validation.generations.SpringCloudCompatibilityValidator;
import org.springframework.ide.vscode.boot.validation.generations.SpringIoProjectsProvider;
Expand All @@ -39,8 +41,12 @@ public class BootVersionValidationConfig {

private static final Logger log = LoggerFactory.getLogger(BootVersionValidationConfig.class);

@Bean UpdateBootVersion updateBootVersion(SimpleLanguageServer server, Optional<SpringBootUpgrade> bootUpgradeOpt, SpringProjectsProvider projectsProvider) {
return new UpdateBootVersion(server.getDiagnosticSeverityProvider(), bootUpgradeOpt, projectsProvider);
@Bean MavenMetadataProvider mavenMetadataProvider(SimpleLanguageServer server) {
return new MavenMetadataProvider(server.getWorkspaceService().getFileObserver());
}

@Bean UpdateBootVersion updateBootVersion(SimpleLanguageServer server, Optional<SpringBootUpgrade> bootUpgradeOpt, SpringProjectsProvider projectsProvider, MavenMetadataProvider mavenMetadataProvider) {
return new UpdateBootVersion(server.getDiagnosticSeverityProvider(), bootUpgradeOpt, projectsProvider, mavenMetadataProvider);
}

@Bean SpringIoProjectsProvider springProjectsProvider(SimpleLanguageServer server, BootJavaConfig config, RestTemplateFactory restTemplateFactory) {
Expand All @@ -64,7 +70,7 @@ public class BootVersionValidationConfig {
@Bean
ProjectReconcileScheduler bootVersionValidationScheduler(SimpleLanguageServer server,
JavaProjectFinder projectFinder, BootJavaConfig config, ProjectObserver projectObserver,
ProjectVersionDiagnosticProvider diagnosticProvider) {
ProjectVersionDiagnosticProvider diagnosticProvider, MavenMetadataProvider mavenMetadataProvider) {
return new ProjectReconcileScheduler(server,
new BootVersionValidationEngine(server, config, projectObserver, projectFinder, diagnosticProvider),
projectFinder) {
Expand All @@ -73,6 +79,20 @@ ProjectReconcileScheduler bootVersionValidationScheduler(SimpleLanguageServer se
protected void init() {
super.init();
config.addListener(evt -> scheduleValidationForAllProjects());

mavenMetadataProvider.addListener(uriStr -> {
try {
URI uri = URI.create(uriStr);
for (IJavaProject project : projectFinder.all()) {
if (project.getProjectBuild() != null && uri.equals(project.getProjectBuild().getBuildFile())) {
scheduleValidation(project);
}
}
} catch (Exception e) {
log.error("Failed to process build file change for URI: " + uriStr, e);
}
});

projectObserver.addListener(new ProjectObserver.Listener() {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand All @@ -30,6 +31,7 @@
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.WorkspaceEditChangeAnnotationSupportCapabilities;
import org.openrewrite.ExecutionContext;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.ParseExceptionResult;
import org.openrewrite.Parser;
Expand All @@ -40,7 +42,9 @@
import org.openrewrite.config.Environment;
import org.openrewrite.internal.InMemoryLargeSourceSet;
import org.openrewrite.java.JavaParser;
import org.openrewrite.maven.MavenExecutionContextView;
import org.openrewrite.maven.MavenParser;
import org.openrewrite.maven.MavenSettings;
import org.openrewrite.tree.ParseError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -109,18 +113,27 @@ public CompletableFuture<Optional<Recipe>> getRecipe(String name) {
return recipes().thenApply(recipes -> Optional.ofNullable(recipes.get(name)));
}

private MavenExecutionContextView createContext(Consumer<Throwable> onError) {
MavenExecutionContextView ctx = MavenExecutionContextView.view(new InMemoryExecutionContext(onError));
MavenSettings settings = MavenSettings.readMavenSettingsFromDisk(ctx);
String[] profiles = settings.getActiveProfiles() == null ? new String[0] : settings.getActiveProfiles().getActiveProfiles().toArray(String[]::new);
ctx.setMavenSettings(settings, profiles);
return ctx;
}

@SuppressWarnings("unchecked")
CompletableFuture<Object> applyToBuildFiles(Recipe r, String uri, String progressToken, boolean askForPreview) {
return projectFinder.find(new TextDocumentIdentifier(uri)).map(p -> {
final IndefiniteProgressTask progressTask = server.getProgressService().createIndefiniteProgressTask(progressToken, r.getDisplayName(), "Initiated...");
final IJavaProject project = p;
ExecutionContext ctx = createContext(e -> log.error("Project Parsing error:", e));
return CompletableFuture.supplyAsync(() -> {
Path absoluteProjectDir = Paths.get(project.getLocationUri());
progressTask.progressEvent("Parsing files...");
ProjectParser projectParser = getProjectParser(project);
return (List<SourceFile>) projectParser.parseBuildFiles(absoluteProjectDir, new InMemoryExecutionContext(e -> log.error("Project Parsing error:", e)));
return (List<SourceFile>) projectParser.parseBuildFiles(absoluteProjectDir, ctx);
})
.thenCompose(sources -> computeWorkspaceEditAwareOfPreview(r, sources, progressTask, askForPreview))
.thenCompose(sources -> computeWorkspaceEditAwareOfPreview(r, ctx, sources, progressTask, askForPreview))
.thenCompose(we -> applyEdit(we, progressTask, r.getDisplayName()))
.whenComplete((o,t) -> progressTask.done());
}).orElse(CompletableFuture.failedFuture(new IllegalArgumentException("Cannot find Spring Boot project for uri: " + uri)));
Expand All @@ -136,19 +149,20 @@ CompletableFuture<Object> apply(Recipe r, String uri, String progressToken, bool
Path absoluteProjectDir = Paths.get(project.getLocationUri());
progressTask.progressEvent("Parsing files...");
ProjectParser projectParser = getProjectParser(project);
List<SourceFile> sources = projectParser.parse(absoluteProjectDir, new InMemoryExecutionContext(e -> log.error("Project Parsing error:", e)));
ExecutionContext ctx = createContext(e -> log.error("Project Parsing error:", e));
List<SourceFile> sources = projectParser.parse(absoluteProjectDir, ctx);

return computeWorkspaceEditAwareOfPreview(r, sources, progressTask, askForPreview)
return computeWorkspaceEditAwareOfPreview(r, ctx, sources, progressTask, askForPreview)
.thenCompose(we -> applyEdit(we, progressTask, r.getDisplayName()));
} else {
return CompletableFuture.failedFuture(new IllegalArgumentException("Cannot find Spring Boot project for uri: " + uri));
}
}).whenComplete((o,t) -> progressTask.done());
}

CompletableFuture<Optional<WorkspaceEdit>> computeWorkspaceEditAwareOfPreview(Recipe r, List<SourceFile> sources, IndefiniteProgressTask progressTask, boolean askForPreview) {
CompletableFuture<Optional<WorkspaceEdit>> computeWorkspaceEditAwareOfPreview(Recipe r, ExecutionContext ctx, List<SourceFile> sources, IndefiniteProgressTask progressTask, boolean askForPreview) {
String changeAnnotationId = UUID.randomUUID().toString();
Optional<WorkspaceEdit> we = computeWorkspaceEdit(r, sources, progressTask, changeAnnotationId);
Optional<WorkspaceEdit> we = computeWorkspaceEdit(r, ctx, sources, progressTask, changeAnnotationId);
if (we.isPresent()) {
return askForPreview ? askForPreview(we.get(), changeAnnotationId) : CompletableFuture.completedFuture(we);
}
Expand Down Expand Up @@ -204,12 +218,12 @@ private CompletableFuture<Object> applyEdit(Optional<WorkspaceEdit> we, Indefini
}
}

Optional<WorkspaceEdit> computeWorkspaceEdit(Recipe r, List<SourceFile> sources, IndefiniteProgressTask progressTask, String changeAnnotationId) {
Optional<WorkspaceEdit> computeWorkspaceEdit(Recipe r, ExecutionContext ctx, List<SourceFile> sources, IndefiniteProgressTask progressTask, String changeAnnotationId) {
reportParseErrors(sources.stream().filter(ParseError.class::isInstance).map(ParseError.class::cast).collect(Collectors.toList()));
if (progressTask != null) {
progressTask.progressEvent("Computing changes...");
}
RecipeRun reciperun = r.run(new InMemoryLargeSourceSet(sources), new InMemoryExecutionContext(e -> log.error("Recipe execution failed", e)));
RecipeRun reciperun = r.run(new InMemoryLargeSourceSet(sources), ctx);
List<Result> results = reciperun.getChangeset().getAllResults();
return ORDocUtils.createWorkspaceEdit(server.getTextDocumentService(), results, changeAnnotationId).map(we -> {
ChangeAnnotation changeAnnotation = new ChangeAnnotation(r.getDisplayName());
Expand All @@ -236,7 +250,7 @@ private void reportParseErrors(List<ParseError> parseErrors) {
private static ProjectParser createRewriteProjectParser(IJavaProject jp, Function<Path, Parser.Input> inputProvider) {
switch (jp.getProjectBuild().getType()) {
case ProjectBuild.MAVEN_PROJECT_TYPE:
MavenParser.Builder mavenParserBuilder = MavenParser.builder();
MavenParser.Builder mavenParserBuilder = MavenParser.builder().skipDependencyResolution(true);
return new MavenIJavaProjectParser(jp, JavaParser.fromJavaVersion(), inputProvider, mavenParserBuilder);
default:
throw new IllegalStateException("The project is neither Maven nor Gradle!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Parser.Input;
import org.openrewrite.Recipe;
import org.openrewrite.SourceFile;
Expand Down Expand Up @@ -126,16 +127,17 @@ private CompletableFuture<Optional<WorkspaceEdit>> perform(FixDescriptor data) {
log.warn("Code Action failed to resolve. Could not create recipe created with id '" + data.getRecipeId() + "'.");
}
List<SourceFile> cus = new ArrayList<>();
ExecutionContext ctx = ORAstUtils.createDefaultContext();
if (projectWide) {
JavaParser jp = ORAstUtils.createJavaParserBuilder(project.get()).dependsOn(data.getTypeStubs()).build();
List<Input> inputs = ORAstUtils.getParserInputs(server.getTextDocumentService(), project.get());
cus.addAll(ORAstUtils.parseInputs(jp, inputs, null));
cus.addAll(ORAstUtils.parseInputs(jp, ctx, inputs, null));
} else {
JavaParser jp = ORAstUtils.createJavaParserBuilder(project.get()).dependsOn(data.getTypeStubs()).build();
List<Input> inputs = data.getDocUris().stream().map(URI::create).map(Paths::get).map(p -> ORAstUtils.getParserInput(server.getTextDocumentService(), p)).filter(Objects::nonNull).collect(Collectors.toList());
cus.addAll(ORAstUtils.parseInputs(jp, inputs, null));
cus.addAll(ORAstUtils.parseInputs(jp, ctx, inputs, null));
}
return recipeRepo.computeWorkspaceEditAwareOfPreview(r, cus, progress, projectWide).whenComplete((o, t) -> progress.done());
return recipeRepo.computeWorkspaceEditAwareOfPreview(r, ctx, cus, progress, projectWide).whenComplete((o, t) -> progress.done());
}).exceptionally(t -> {
progress.done();
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ private Recipe createUpgradeRecipe(Version version, Version targetVersion) {

if (version.getMajor() == targetVersion.getMajor() && version.getMinor() == targetVersion.getMinor()) {
// patch version upgrade - treat as pom versions only upgrade
recipe.getRecipeList().add(new org.openrewrite.maven.UpgradeDependencyVersion("org.springframework.boot", "*", version.getMajor() + "." + version.getMinor() + ".x", null, null, null));
recipe.getRecipeList().add(new UpgradeParentVersion("org.springframework.boot", "spring-boot-starter-parent", version.getMajor() + "." + version.getMinor() + ".x", null, null));
recipe.getRecipeList().add(new org.openrewrite.maven.UpgradeDependencyVersion("org.springframework.boot", "*", targetVersion.toMajorMinorPatchVersionStr(), null, null, null));
recipe.getRecipeList().add(new UpgradeParentVersion("org.springframework.boot", "spring-boot-starter-parent", targetVersion.toMajorMinorPatchVersionStr(), null, null));
}

if (recipe.getRecipeList().isEmpty()) {
Expand Down
Loading
Loading