Progress for project reconciling

This commit is contained in:
aboyko
2023-02-27 17:43:20 -05:00
parent 71f87227f5
commit 2f743fe9a8
16 changed files with 263 additions and 80 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Pivotal, Inc.
* Copyright (c) 2019, 2023 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
@@ -16,26 +16,18 @@ package org.springframework.ide.vscode.commons.languageserver;
* This handler can be used for long-running progress that requires message updates to the same task.
*
*/
public class ProgressTask {
public abstract class AbstractProgressTask {
private final String taskId;
private final ProgressService service;
protected final String taskId;
protected final ProgressService service;
public ProgressTask(String taskId, ProgressService service) {
public AbstractProgressTask(String taskId, ProgressService service) {
this.taskId = taskId;
this.service = service;
}
public void progressBegin(String title, String statusMsg) {
this.service.progressBegin(taskId, title, statusMsg);
}
public void progressEvent(String statusMsg) {
this.service.progressEvent(taskId, statusMsg);
}
public void progressDone() {
public void done() {
this.service.progressDone(taskId);
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver;
import org.eclipse.lsp4j.WorkDoneProgressBegin;
import org.eclipse.lsp4j.WorkDoneProgressReport;
public class IndefiniteProgressTask extends AbstractProgressTask {
public IndefiniteProgressTask(String taskId, ProgressService service, String title, String message) {
super(taskId, service);
progressBegin(title, message);
}
private void progressBegin(String title, String message) {
WorkDoneProgressBegin report = new WorkDoneProgressBegin();
report.setTitle(title);
report.setCancellable(false);
if (message != null && !message.isEmpty()) {
report.setMessage(message);
}
service.progressBegin(taskId, report);
}
public void progressEvent(String statusMsg) {
WorkDoneProgressReport report = new WorkDoneProgressReport();
report.setMessage(statusMsg);
service.progressEvent(taskId, report);
}
}

View File

@@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver;
import org.eclipse.lsp4j.WorkDoneProgressBegin;
import org.eclipse.lsp4j.WorkDoneProgressReport;
import org.springframework.ide.vscode.commons.languageserver.util.LspClient;
/**
* Eclipse progress requires sending total work units number with the begin progress message. The number is any intger.
* VScode and likely other LSP clients require the begin progress message to have 0 and progress is assumed to be between 0 and 100.
* This class takes care of these differences.
*
* @author aboyko
*
*/
public class PercentageProgressTask extends AbstractProgressTask {
private int total;
private int current;
private int currentPercentage;
public PercentageProgressTask(String taskId, ProgressService service, int total, String title) {
super(taskId, service);
this.total = total;
this.current = 0;
begin(title);
}
private void begin(String title) {
WorkDoneProgressBegin progressBegin = new WorkDoneProgressBegin();
progressBegin.setPercentage(LspClient.currentClient() == LspClient.Client.ECLIPSE ? 100 : 0);
progressBegin.setCancellable(false);
progressBegin.setTitle(title);
service.progressBegin(taskId, progressBegin);
}
public int getTotal() {
return total;
}
public int getCurrent() {
return current;
}
public void setCurrent(int current) {
if (current > total) {
throw new IllegalArgumentException();
}
this.current = current;
reportCurrent();
}
private void reportPercent(int percent) {
if (percent > currentPercentage) {
currentPercentage = percent;
WorkDoneProgressReport r = new WorkDoneProgressReport();
r.setPercentage(percent);
service.progressEvent(taskId, r);
}
}
private void reportCurrent() {
reportPercent(current * 100 / total);
}
public void increment() {
if (current >= total) {
throw new IllegalStateException();
}
current++;
reportCurrent();
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2022 Pivotal, Inc.
* Copyright (c) 2016, 2023 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
@@ -11,16 +11,19 @@
package org.springframework.ide.vscode.commons.languageserver;
import org.eclipse.lsp4j.WorkDoneProgressBegin;
import org.eclipse.lsp4j.WorkDoneProgressReport;
public interface ProgressService {
public static ProgressService NO_PROGRESS = new ProgressService() {
@Override
public void progressBegin(String taskId, String title, String message) {
public void progressBegin(String taskId, WorkDoneProgressBegin report) {
}
@Override
public void progressEvent(String taskId, String statusMsg) {
public void progressEvent(String taskId, WorkDoneProgressReport report) {
}
@Override
@@ -37,8 +40,28 @@ public interface ProgressService {
* id for some kind of 'long running job'
* @param title progress main title, i.e. "Indexing", "Loading"
* @param message detail for the title, i.e. subtask in progress at the moment
* @deprecated Use {@link #progressBegin(String, WorkDoneProgressBegin)}
*/
void progressBegin(String taskId, String title, String message);
default void progressBegin(String taskId, String title, String message) {
WorkDoneProgressBegin report = new WorkDoneProgressBegin();
report.setCancellable(false);
if (message != null && !message.isEmpty()) {
report.setMessage(message);
}
report.setTitle(title);
progressBegin(taskId, report);
}
/**
* Sends an event to start progress to the LSP client.
*
* @param taskId is an arbitrary id
* that can be chosen by the caller. The purpose of the id is to be a 'unique'
* id for some kind of 'long running job'
* @param report the report either string messages or percentage
*/
void progressBegin(String taskId, WorkDoneProgressBegin report);
/**
* Sends a progress event to the LSP client. Each event updates the message shown
@@ -48,8 +71,25 @@ public interface ProgressService {
*
* @param taskId
* @param statusMsg
*
* @deprecated Use {@link #progressEvent(String, WorkDoneProgressReport)}
*/
void progressEvent(String taskId, String statusMsg);
default void progressEvent(String taskId, String statusMsg) {
WorkDoneProgressReport report = new WorkDoneProgressReport();
report.setMessage(statusMsg);
progressEvent(taskId, report);
}
/**
* Sends a progress event to the LSP client. Each event updates the message shown
* to the user replacing the old one.
* More than one message may be shown simultaneously to the user, if they
* have different taskId.
*
* @param taskId
* @param report
*/
void progressEvent(String taskId, WorkDoneProgressReport report);
/**
* Send the event to the LSP client to end progress for passed id
@@ -58,8 +98,12 @@ public interface ProgressService {
*/
void progressDone(String taskId);
default ProgressTask createProgressTask(String taskId) {
return new ProgressTask(taskId, this);
default IndefiniteProgressTask createIndefiniteProgressTask(String taskId, String title, String message) {
return new IndefiniteProgressTask(taskId, this, title, message);
}
default PercentageProgressTask createPercentageProgressTask(String taskId, int totalWork, String title) {
return new PercentageProgressTask(taskId, this, totalWork, title);
}
}

View File

@@ -149,8 +149,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
private ConcurrentHashMap<String, Boolean> activeTaskIDs = new ConcurrentHashMap<>();
@Override
public void progressBegin(String taskId, String title, String message) {
public void progressBegin(String taskId, WorkDoneProgressBegin report) {
STS4LanguageClient client = SimpleLanguageServer.this.client;
if (client != null) {
boolean isNew = activeTaskIDs.put(taskId, true) == null;
@@ -162,18 +161,13 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
client.createProgress(params).thenAccept((p) -> {
ProgressParams progressParams = new ProgressParams();
progressParams.setToken(taskId);
WorkDoneProgressBegin report = new WorkDoneProgressBegin();
report.setCancellable(false);
progressParams.setValue(Either.forLeft(report));
report.setMessage(message);
report.setTitle(title);
client.notifyProgress(progressParams);
});
}
}
@Override
public void progressEvent(String taskId, String statusMsg) {
public void progressEvent(String taskId, WorkDoneProgressReport report) {
STS4LanguageClient client = SimpleLanguageServer.this.client;
if (client != null) {
if (!activeTaskIDs.containsKey(taskId)) {
@@ -182,9 +176,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
}
ProgressParams progressParams = new ProgressParams();
progressParams.setToken(taskId);
WorkDoneProgressReport report = new WorkDoneProgressReport();
progressParams.setValue(Either.forLeft(report));
report.setMessage(statusMsg);
client.notifyProgress(progressParams);
}
}

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -29,6 +30,7 @@ import org.openrewrite.ExecutionContext;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.Parser;
import org.openrewrite.Recipe;
import org.openrewrite.SourceFile;
import org.openrewrite.Tree;
import org.openrewrite.TreeVisitor;
import org.openrewrite.internal.RecipeIntrospectionUtils;
@@ -40,6 +42,7 @@ import org.openrewrite.java.UpdateSourcePositions;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.CompilationUnit;
import org.openrewrite.marker.Range;
import org.openrewrite.tree.ParsingExecutionContextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
@@ -245,7 +248,7 @@ public class ORAstUtils {
}
}
public static List<CompilationUnit> parse(SimpleTextDocumentService documents, IJavaProject project) {
public static List<CompilationUnit> parse(SimpleTextDocumentService documents, IJavaProject project, Consumer<SourceFile> parseCallback) {
List<Parser.Input> inputs = IClasspathUtil.getProjectJavaSourceFolders(project.getClasspath()).flatMap(folder -> {
try {
return Files.walk(folder.toPath());
@@ -269,7 +272,7 @@ public class ORAstUtils {
}
}).collect(Collectors.toList());
JavaParser javaParser = createJavaParser(project);
return ORAstUtils.parseInputs(javaParser, inputs);
return ORAstUtils.parseInputs(javaParser, inputs, parseCallback);
}
public static List<CompilationUnit> parse(JavaParser parser, Iterable<Path> sourceFiles) {
@@ -291,9 +294,14 @@ public class ORAstUtils {
return finalCus;
}
public static List<CompilationUnit> parseInputs(JavaParser parser, Iterable<Parser.Input> inputs) {
InMemoryExecutionContext ctx = new InMemoryExecutionContext(ORAstUtils::logExceptionWhileParsing);
public static List<CompilationUnit> parseInputs(JavaParser parser, Iterable<Parser.Input> inputs, Consumer<SourceFile> parseCallback) {
ExecutionContext ctx = new InMemoryExecutionContext(ORAstUtils::logExceptionWhileParsing);
ctx.putMessage(JavaParser.SKIP_SOURCE_SET_TYPE_GENERATION, true);
if (parseCallback != null) {
ParsingExecutionContextView parseContext = ParsingExecutionContextView.view(ctx);
parseContext.setParsingListener((input, source) -> parseCallback.accept(source));
ctx = parseContext;
}
List<CompilationUnit> cus = Collections.emptyList();
long start = System.currentTimeMillis();
synchronized (parser) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, Inc.
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,10 +11,11 @@
package org.springframework.ide.vscode.boot.common;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
public interface IJavaProjectReconcileEngine {
void reconcile(IJavaProject project);
void reconcile(IJavaProject project, ProgressService progressService);
void clear(IJavaProject project);

View File

@@ -77,7 +77,7 @@ public abstract class ProjectReconcileScheduler {
if (projectReconcileRequests.remove(uri) != null) {
projectFinder.find(new TextDocumentIdentifier(uri.toASCIIString())).ifPresent(p -> {
reconciler.clear(project);
reconciler.reconcile(p);
reconciler.reconcile(p, getServer().getProgressService());
});
}
})

View File

@@ -28,6 +28,8 @@ import org.springframework.ide.vscode.boot.common.IJavaProjectReconcileEngine;
import org.springframework.ide.vscode.boot.java.reconcilers.JavaReconciler;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.PercentageProgressTask;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
@@ -114,7 +116,7 @@ public class BootJavaReconcileEngine implements IReconcileEngine, IJavaProjectRe
}
@Override
public void reconcile(IJavaProject project) {
public void reconcile(IJavaProject project, ProgressService progressService) {
Stream<Path> files = IClasspathUtil.getProjectJavaSourceFolders(project.getClasspath()).flatMap(folder -> {
try {
return Files.walk(folder.toPath()).filter(Files::isRegularFile);
@@ -134,10 +136,21 @@ public class BootJavaReconcileEngine implements IReconcileEngine, IJavaProjectRe
.collect(Collectors.toMap(d -> d, d -> server.createProblemCollector(d)));
problemCollectors.values().forEach(c -> c.beginCollecting());
int totalWork = 0;
for (JavaReconciler jr : javaReconcilers) {
totalWork += jr.getTotalWorkUnits(docs);
}
PercentageProgressTask progressTask = progressService.createPercentageProgressTask(
"reconcile-java-" + project.getElementName(),
totalWork,
"Reconciling Spring Java for '" + project.getElementName() + "'"
);
for (JavaReconciler jr : javaReconcilers) {
try {
Map<IDocument, Collection<ReconcileProblem>> problems = jr.reconcile(project, docs);
Map<IDocument, Collection<ReconcileProblem>> problems = jr.reconcile(project, docs, () -> progressTask.increment());
problems.entrySet().forEach(e -> {
IProblemCollector collector = problemCollectors.get(e.getKey());
e.getValue().forEach(p -> collector.accept(p));
@@ -147,6 +160,7 @@ public class BootJavaReconcileEngine implements IReconcileEngine, IJavaProjectRe
}
}
progressTask.done();
problemCollectors.values().forEach(c -> c.endCollecting());
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Pivotal, Inc.
* Copyright (c) 2019, 2023 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
@@ -19,8 +19,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.app.BootJavaConfig;
import org.springframework.ide.vscode.commons.languageserver.DiagnosticService;
import org.springframework.ide.vscode.commons.languageserver.IndefiniteProgressTask;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.ProgressTask;
import org.springframework.ide.vscode.commons.languageserver.util.ShowMessageException;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
@@ -93,11 +93,8 @@ public class SpringProcessConnectorService {
connector.addConnectorChangeListener(connectorListener);
try {
final ProgressTask progressTask = getProgressTask(
"spring-process-connector-service-connect-" + processKey);
progressTask.progressBegin("Connect", null);
final IndefiniteProgressTask progressTask = getProgressTask(
"spring-process-connector-service-connect-" + processKey, "Connect", null);
scheduleConnect(progressTask, processKey, connector, 0, TimeUnit.SECONDS, 0);
}
catch (Exception e) {
@@ -110,10 +107,8 @@ public class SpringProcessConnectorService {
SpringProcessConnector connector = this.connectors.get(springProcessParams.getProcessKey());
if (connector != null) {
final ProgressTask progressTask = getProgressTask(
"spring-process-connector-service-refresh-data-" + springProcessParams.getProcessKey());
progressTask.progressBegin("Refresh", null);
final IndefiniteProgressTask progressTask = getProgressTask(
"spring-process-connector-service-refresh-data-" + springProcessParams.getProcessKey(), "Refresh", null);
scheduleRefresh(progressTask, springProcessParams, connector, 0, TimeUnit.SECONDS, 0);
}
@@ -140,11 +135,9 @@ public class SpringProcessConnectorService {
this.connectedSuccess.put(processKey, false);
if (connector != null) {
final ProgressTask progressTask = getProgressTask(
"spring-process-connector-service-disconnect-" + processKey);
final IndefiniteProgressTask progressTask = getProgressTask(
"spring-process-connector-service-disconnect-" + processKey, "Disconnect", null);
progressTask.progressBegin("Disconnect", null);
scheduleDisconnect(progressTask, processKey, connector, 0, TimeUnit.SECONDS, 0);
}
}
@@ -165,7 +158,7 @@ public class SpringProcessConnectorService {
return processID;
}
private void scheduleConnect(ProgressTask progressTask, String processKey, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) {
private void scheduleConnect(IndefiniteProgressTask progressTask, String processKey, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) {
String progressMessage = "Connecting to process: " + processKey + " - retry no: " + retryNo;
log.info(progressMessage);
@@ -174,7 +167,7 @@ public class SpringProcessConnectorService {
try {
progressTask.progressEvent(progressMessage);
connector.connect();
progressTask.progressDone();
progressTask.done();
refreshProcess(new SpringProcessParams(processKey, "", "", ""));
refreshProcess(new SpringProcessParams(processKey, METRICS, MEMORY, ""));
@@ -186,7 +179,7 @@ public class SpringProcessConnectorService {
if (retryNo < maxRetryCount && isKnownProcessKey(processKey)) {
scheduleConnect(progressTask, processKey, connector, retryDelayInSeconds, TimeUnit.SECONDS, retryNo + 1);
} else {
progressTask.progressDone();
progressTask.done();
// Send message to client if maximum retries reached on error
if (isKnownProcessKey(processKey)) {
@@ -198,7 +191,7 @@ public class SpringProcessConnectorService {
}, delay, unit);
}
private void scheduleDisconnect(ProgressTask progressTask, String processKey, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) {
private void scheduleDisconnect(IndefiniteProgressTask progressTask, String processKey, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) {
String message = "Disconnect from process: " + processKey + " - retry no: " + retryNo;
log.info(message);
@@ -207,7 +200,7 @@ public class SpringProcessConnectorService {
try {
progressTask.progressEvent(message);
connector.disconnect();
progressTask.progressDone();
progressTask.done();
}
catch (Exception e) {
log.info("problem occured during process disconnect", e);
@@ -215,7 +208,7 @@ public class SpringProcessConnectorService {
if (retryNo < maxRetryCount) {
scheduleDisconnect(progressTask, processKey, connector, retryDelayInSeconds, TimeUnit.SECONDS, retryNo + 1);
} else {
progressTask.progressDone();
progressTask.done();
// Send message to client if maximum retries reached on error
diagnosticService.diagnosticEvent(ShowMessageException
@@ -226,7 +219,7 @@ public class SpringProcessConnectorService {
}, delay, unit);
}
private void scheduleRefresh(ProgressTask progressTask, SpringProcessParams springProcessParams, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) {
private void scheduleRefresh(IndefiniteProgressTask progressTask, SpringProcessParams springProcessParams, SpringProcessConnector connector, long delay, TimeUnit unit, int retryNo) {
String processKey = springProcessParams.getProcessKey();
String endpoint = springProcessParams.getEndpoint();
String metricName = springProcessParams.getMetricName();
@@ -271,7 +264,7 @@ public class SpringProcessConnectorService {
this.connectedSuccess.put(processKey, true);
}
}
progressTask.progressDone();
progressTask.done();
}
catch (Exception e) {
@@ -282,7 +275,7 @@ public class SpringProcessConnectorService {
retryNo + 1);
}
else {
progressTask.progressDone();
progressTask.done();
// Send message to client if maximum retries reached on error
if (isKnownProcessKey(processKey)) {
@@ -298,7 +291,7 @@ public class SpringProcessConnectorService {
}, delay, unit);
}
private ProgressTask getProgressTask(String prefixId) {
return this.progressService.createProgressTask(prefixId + progressIdKey++);
private IndefiniteProgressTask getProgressTask(String prefixId, String title, String message) {
return this.progressService.createIndefiniteProgressTask(prefixId + progressIdKey++, title, message);
}
}

View File

@@ -24,6 +24,10 @@ public interface JavaReconciler {
void reconcile(IJavaProject project, IDocument doc, IProblemCollector problemCollector);
Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs);
Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs, Runnable incrementProgress);
default int getTotalWorkUnits(List<TextDocument> docs) {
return 0;
}
}

View File

@@ -156,7 +156,7 @@ public class JdtReconciler implements JavaReconciler {
}
@Override
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs) {
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs, Runnable incrementProgress) {
if (config.isRewriteReconcileEnabled()) {
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2022 VMware, Inc.
* Copyright (c) 2022, 2023 VMware, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -238,7 +238,7 @@ public class RewriteCompilationUnitCache implements DocumentContentProvider, Dis
throw new IllegalStateException("Unexpected error fetching document content");
}
});
List<CompilationUnit> cus = ORAstUtils.parseInputs(javaParser, List.of(input));
List<CompilationUnit> cus = ORAstUtils.parseInputs(javaParser, List.of(input), null);
CompilationUnit cu = cus.get(0);
if (cu != null) {

View File

@@ -136,7 +136,7 @@ public class RewriteReconciler implements JavaReconciler {
}
@Override
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs) {
public Map<IDocument, Collection<ReconcileProblem>> reconcile(IJavaProject project, List<TextDocument> docs, Runnable incrementProgress) {
if (!config.isRewriteReconcileEnabled()) {
return Collections.emptyMap();
@@ -156,11 +156,12 @@ public class RewriteReconciler implements JavaReconciler {
mainSources.add(d);
}
}
JavaParser javaParser = ORAstUtils.createJavaParser(project);
javaParser.setSourceSet(MavenProjectParser.MAIN);
allProblems.putAll(doReconcile(project, mainSources, javaParser));
allProblems.putAll(doReconcile(project, mainSources, javaParser, incrementProgress));
javaParser.setSourceSet(MavenProjectParser.TEST);
allProblems.putAll(doReconcile(project, testSources, javaParser));
allProblems.putAll(doReconcile(project, testSources, javaParser, incrementProgress));
long end = System.currentTimeMillis();
log.info("reconciling project (OpenRewrite): " + project.getElementName() + " - " + docs.size() + " done in " + (end - start) + "ms");
@@ -168,6 +169,7 @@ public class RewriteReconciler implements JavaReconciler {
return allProblems;
}
// Parse all at once
// private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs,
// Function<TextDocument, IProblemCollector> problemCollectorFactory, JavaParser javaParser) {
@@ -240,7 +242,7 @@ public class RewriteReconciler implements JavaReconciler {
private static final int BATCH = 50;
// Parse in batches and share the parser
private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs, JavaParser javaParser) {
private Map<IDocument, Collection<ReconcileProblem>> doReconcile(IJavaProject project, List<TextDocument> docs, JavaParser javaParser, Runnable incrementProgress) {
Map<IDocument, Collection<ReconcileProblem>> allProblems = new HashMap<>();
if (javaParser != null && config.isRewriteReconcileEnabled()) {
try {
@@ -255,7 +257,7 @@ public class RewriteReconciler implements JavaReconciler {
List<CompilationUnit> cus = ORAstUtils.parseInputs(javaParser,
batchList.stream().map(d -> new Parser.Input(Paths.get(URI.create(d.getUri())), () -> {
return new ByteArrayInputStream(d.get().getBytes());
})).collect(Collectors.toList()));
})).collect(Collectors.toList()), source -> incrementProgress.run());
/*
* If exception occurs during parsing inputs the list of inputs would become shorter than the list of corresponding documents
@@ -275,6 +277,7 @@ public class RewriteReconciler implements JavaReconciler {
} else {
log.warn("(OpenRewrite) Failed to parse source for " + sourcePath);
}
incrementProgress.run();
}
}
@@ -327,5 +330,9 @@ public class RewriteReconciler implements JavaReconciler {
}.visit(cu, new InMemoryExecutionContext(e -> log.error("", e)));
}
}
public int getTotalWorkUnits(List<TextDocument> docs) {
return docs.size() * 2;
}
}

View File

@@ -140,7 +140,8 @@ public class RewriteRefactorings implements CodeActionResolver, QuickfixHandler
boolean projectWide = data.getRecipeScope() == RecipeScope.PROJECT;
Recipe r = createRecipe(data);
if (projectWide) {
return applyRecipe(r, project.get(), ORAstUtils.parse(documents, project.get()));
//TODO: progress here as well.
return applyRecipe(r, project.get(), ORAstUtils.parse(documents, project.get(), null));
} else {
List<CompilationUnit> cus = data.getDocUris().stream().map(docUri -> cuCache.getCU(project.get(), URI.create(docUri))).filter(Objects::nonNull).collect(Collectors.toList());
return applyRecipe(r, project.get(), cus);

View File

@@ -20,6 +20,7 @@ import org.springframework.ide.vscode.boot.common.IJavaProjectReconcileEngine;
import org.springframework.ide.vscode.boot.validation.generations.ProjectVersionDiagnosticProvider;
import org.springframework.ide.vscode.boot.validation.generations.ProjectVersionDiagnosticProvider.DiagnosticResult;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
@@ -39,7 +40,7 @@ public class BootVersionValidationEngine implements IJavaProjectReconcileEngine
this.diagnosticProvider = diagnosticProvider;
}
public void reconcile(IJavaProject project) {
public void reconcile(IJavaProject project, ProgressService progressService) {
if (config.isBootVersionValidationEnabled()) {
log.debug("validating Spring Boot version on project: " + project.getElementName());
long start = System.currentTimeMillis();