Adopt title in the progress notification in lsp

This commit is contained in:
aboyko
2022-07-19 15:14:03 -04:00
parent 3b678ce9ab
commit e002ddf6fb
11 changed files with 117 additions and 79 deletions

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 Pivotal, Inc.
* Copyright (c) 2017, 2022 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
@@ -71,7 +71,7 @@ public abstract class AbstractFileToProjectCache<P extends IJavaProject> extends
final String taskId = getProgressId();
final ProgressService progressService = server.getProgressService();
if (progressService != null) {
progressService.progressEvent(taskId, "Updating data for project `" + project.getElementName() + "'");
progressService.progressBegin(taskId, "Updating data for project", "'" + project.getElementName() + "'");
}
if (async) {
CompletableFuture.supplyAsync(() -> update(project)).thenAccept((changed) -> afterUpdate(project, changed, notify, taskId));
@@ -84,7 +84,7 @@ public abstract class AbstractFileToProjectCache<P extends IJavaProject> extends
private void afterUpdate(P project, boolean changed, boolean notify, String taskId) {
final ProgressService progressService = server.getProgressService();
if (progressService != null) {
progressService.progressEvent(taskId, null);
progressService.progressDone(taskId);
}
if (changed || alwaysFireEventOnUpdate) {
if (notify) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2019 Pivotal, Inc.
* Copyright (c) 2016, 2022 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
@@ -15,23 +15,34 @@ public interface ProgressService {
public static ProgressService NO_PROGRESS = new ProgressService() {
@Override
public void progressBegin(String taskId, String title, String message) {
}
@Override
public void progressEvent(String taskId, String statusMsg) {
}
@Override
public void progressDone(String taskId) {
}
};
/**
* Sends a progress event to the LSP client. A taskId is an arbirary id
* 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'. Only a single 'statusMsg' is associated
* with a given taskId at any one time. Each event updates the message shown
* 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
*/
void progressBegin(String taskId, String title, String message);
/**
* Sends a progress event to the LSP client. Each event updates the message shown
* to the user replacing the old one.
* <p>
* Updating the message to 'null' erases the previous message without showing
* a new one.
* <p>
* More than one message may be shown simultaneously to the user, if they
* have different taskId.
*
@@ -39,6 +50,13 @@ public interface ProgressService {
* @param statusMsg
*/
void progressEvent(String taskId, String statusMsg);
/**
* Send the event to the LSP client to end progress for passed id
*
* @param taskId the id of the task in progress
*/
void progressDone(String taskId);
default ProgressTask createProgressTask(String taskId) {
return new ProgressTask(taskId, this);

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Pivotal, Inc.
* Copyright (c) 2019, 2022 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
@@ -26,13 +26,17 @@ public class ProgressTask {
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() {
this.service.progressEvent(taskId, null);
this.service.progressDone(taskId);
}
}

View File

@@ -133,46 +133,54 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, LanguageC
private ConcurrentHashMap<String, Boolean> activeTaskIDs = new ConcurrentHashMap<>();
@Override
public void progressEvent(String taskId, String statusMsg) {
public void progressBegin(String taskId, String title, String message) {
STS4LanguageClient client = SimpleLanguageServer.this.client;
if (client!=null) {
if (statusMsg == null) {
progressDone(taskId);
return;
}
if (client != null) {
boolean isNew = activeTaskIDs.put(taskId, true) == null;
if (isNew) {
// New taskId, new progress
WorkDoneProgressCreateParams params = new WorkDoneProgressCreateParams();
params.setToken(taskId);
SimpleLanguageServer.this.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(statusMsg);
SimpleLanguageServer.this.client.notifyProgress(progressParams);
});
} else {
// Already exists
if (!isNew) {
log.error("Progress for task id '{}' already exists", taskId);
}
WorkDoneProgressCreateParams params = new WorkDoneProgressCreateParams();
params.setToken(taskId);
client.createProgress(params).thenAccept((p) -> {
ProgressParams progressParams = new ProgressParams();
progressParams.setToken(taskId);
WorkDoneProgressReport report = new WorkDoneProgressReport();
WorkDoneProgressBegin report = new WorkDoneProgressBegin();
report.setCancellable(false);
progressParams.setValue(Either.forLeft(report));
report.setMessage(statusMsg);
SimpleLanguageServer.this.client.notifyProgress(progressParams);
}
report.setMessage(message);
report.setTitle(title);
client.notifyProgress(progressParams);
});
}
}
private void progressDone(String taskId) {
if (activeTaskIDs.remove(taskId)) {
@Override
public void progressEvent(String taskId, String statusMsg) {
STS4LanguageClient client = SimpleLanguageServer.this.client;
if (client != null) {
if (!activeTaskIDs.containsKey(taskId)) {
log.error("Progress for task id '{}' does NOT exist!", taskId);
return;
}
ProgressParams progressParams = new ProgressParams();
progressParams.setToken(taskId);
WorkDoneProgressReport report = new WorkDoneProgressReport();
progressParams.setValue(Either.forLeft(report));
report.setMessage(statusMsg);
client.notifyProgress(progressParams);
}
}
@Override
public void progressDone(String taskId) {
STS4LanguageClient client = SimpleLanguageServer.this.client;
if (client != null && activeTaskIDs.remove(taskId)) {
ProgressParams progressParams = new ProgressParams();
progressParams.setToken(taskId);
WorkDoneProgressEnd report = new WorkDoneProgressEnd();
progressParams.setValue(Either.forLeft(report));
SimpleLanguageServer.this.client.notifyProgress(progressParams);
client.notifyProgress(progressParams);
}
}
};

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2019 Pivotal, Inc.
* Copyright (c) 2017, 2022 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,7 +16,6 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -174,7 +173,7 @@ public class MavenProjectCacheTest {
progressDone.set(true);
return null;
}
}).when(progressService).progressEvent(any(String.class), (String) isNull());
}).when(progressService).progressDone(any(String.class));
when(server.getProgressService()).thenReturn(progressService);
@@ -223,7 +222,7 @@ public class MavenProjectCacheTest {
progressDone.set(true);
return null;
}
}).when(progressService).progressEvent(any(String.class), (String) isNull());
}).when(progressService).progressDone(any(String.class));
when(server.getProgressService()).thenReturn(progressService);

View File

@@ -91,6 +91,13 @@
<version>${rewrite-spring-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openrewrite.recipe/rewrite-migrate-java -->
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-migrate-java</artifactId>
<version>${rewrite-java-migration.version}</version>
</dependency>
</dependencies>

View File

@@ -109,8 +109,9 @@
<commons-codec-version>1.13</commons-codec-version>
<!-- Rewrite specific properties -->
<rewrite-version>7.24.1</rewrite-version>
<rewrite-spring-version>4.22.1</rewrite-spring-version>
<rewrite-version>7.26.1</rewrite-version>
<rewrite-spring-version>4.23.0</rewrite-spring-version>
<rewrite-java-migration.version>1.8.0</rewrite-java-migration.version>
<rewrite-jackson.version>2.13.2</rewrite-jackson.version>
<signing.skip>true</signing.skip>

View File

@@ -126,7 +126,7 @@ public class RewriteRecipeRepository {
private void loadRecipes() {
try {
server.getProgressService().progressEvent(RECIPES_LOADING_PROGRESS, "Loading Rewrite Recipes...");
server.getProgressService().progressBegin(RECIPES_LOADING_PROGRESS, "Loading Rewrite Recipes", null);
log.info("Loading Rewrite Recipes...");
for (Recipe r : Environment.builder().scanRuntimeClasspath().build().listRecipes()) {
if (r.getName() != null) {
@@ -151,7 +151,7 @@ public class RewriteRecipeRepository {
log.info("Done loading Rewrite Recipes");
server.doOnInitialized(() -> registerCommands());
} catch (Throwable t) {
server.getProgressService().progressEvent(RECIPES_LOADING_PROGRESS, null);
server.getProgressService().progressDone(RECIPES_LOADING_PROGRESS);
log.error("", t);
}
}
@@ -263,7 +263,7 @@ 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().progressEvent(RECIPES_LOADING_PROGRESS, null);
server.getProgressService().progressDone(RECIPES_LOADING_PROGRESS);
});
}
@@ -280,7 +280,7 @@ public class RewriteRecipeRepository {
private CompletableFuture<Object> apply(Recipe r, String uri, String progressToken) {
return CompletableFuture.supplyAsync(() -> {
server.getProgressService().progressEvent(progressToken, r.getDisplayName() + ": initiated...");
server.getProgressService().progressBegin(progressToken, r.getDisplayName(), "Initiated...");
return projectFinder.find(new TextDocumentIdentifier(uri));
}).thenCompose(p -> {
if (p.isPresent()) {
@@ -288,24 +288,23 @@ public class RewriteRecipeRepository {
Optional<WorkspaceEdit> edit = apply(r, p.get());
return CompletableFuture.completedFuture(edit).thenCompose(we -> {
if (we.isPresent()) {
server.getProgressService().progressEvent(progressToken,
r.getDisplayName() + ": applying document changes...");
server.getProgressService().progressEvent(progressToken, "Applying document changes...");
return server.getClient().applyEdit(new ApplyWorkspaceEditParams(we.get(), r.getDisplayName())).thenCompose(res -> {
if (res.isApplied()) {
server.getProgressService().progressEvent(progressToken, null);
server.getProgressService().progressDone(progressToken);
return CompletableFuture.completedFuture("success");
} else {
server.getProgressService().progressEvent(progressToken, null);
server.getProgressService().progressDone(progressToken);
return CompletableFuture.completedFuture(null);
}
});
} else {
server.getProgressService().progressEvent(progressToken, null);
server.getProgressService().progressDone(progressToken);
return CompletableFuture.completedFuture(null);
}
});
} catch (Throwable t) {
server.getProgressService().progressEvent(progressToken, null);
server.getProgressService().progressDone(progressToken);
throw t;
}
}
@@ -315,12 +314,11 @@ public class RewriteRecipeRepository {
private Optional<WorkspaceEdit> apply(Recipe r, IJavaProject project) {
Path absoluteProjectDir = Paths.get(project.getLocationUri());
server.getProgressService().progressEvent(r.getName(), r.getDisplayName() + ": parsing files...");
server.getProgressService().progressEvent(r.getName(), "Parsing files...");
MavenProjectParser projectParser = createRewriteMavenParser(absoluteProjectDir,
new InMemoryExecutionContext());
List<SourceFile> sources = projectParser.parse(absoluteProjectDir, getClasspathEntries(project));
server.getProgressService().progressEvent(r.getName(),
r.getDisplayName() + ": computing changes...");
server.getProgressService().progressEvent(r.getName(), "Computing changes...");
List<Result> results = r.run(sources, new InMemoryExecutionContext(e -> log.error("", e)));
return ORDocUtils.createWorkspaceEdit(absoluteProjectDir, server.getTextDocumentService(), results);
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2017 Pivotal, Inc.
* Copyright (c) 2014, 2022 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
@@ -12,13 +12,14 @@ package org.springframework.ide.vscode.boot.metadata;
import java.util.concurrent.ExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.metadata.util.Listener;
import org.springframework.ide.vscode.boot.metadata.util.ListenerManager;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@@ -33,6 +34,8 @@ import com.google.common.collect.ImmutableList;
* @author Kris De Volder
*/
public class SpringPropertiesIndexManager extends ListenerManager<Listener<SpringPropertiesIndexManager>> {
private static final Logger log = LoggerFactory.getLogger(SpringPropertiesIndexManager.class);
private Cache<IJavaProject, SpringPropertyIndex> indexes;
private final ValueProviderRegistry valueProviders;
@@ -56,27 +59,27 @@ public class SpringPropertiesIndexManager extends ListenerManager<Listener<Sprin
try {
return indexes.get(project, () -> initIndex(project, progressService));
} catch (ExecutionException e) {
Log.log(e);
log.error("", e);
return null;
}
}
private SpringPropertyIndex initIndex(IJavaProject project, ProgressService progressService) {
Log.info("Indexing Spring Boot Properties for "+project.getElementName());
log.info("Indexing Spring Boot Properties for {}", project.getElementName());
String progressId = getProgressId();
if (progressService != null) {
progressService.progressEvent(progressId, "Indexing Spring Boot Properties...");
progressService.progressBegin(progressId, "Indexing Spring Boot Properties", null);
}
SpringPropertyIndex index = new SpringPropertyIndex(valueProviders, project.getClasspath());
if (progressService != null) {
progressService.progressEvent(progressId, null);
progressService.progressDone(progressId);
}
Log.info("Indexing Spring Boot Properties for "+project.getElementName()+" DONE");
Log.info("Indexed "+index.size()+" properties.");
log.info("Indexing Spring Boot Properties for {} DONE", project.getElementName());
log.info("Indexed {} properties.", index.size());
return index;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2022 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
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils.test;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -63,13 +63,13 @@ public class SpringPropertyIndexTest {
ProgressService progressService = mock(ProgressService.class);
propertyIndexProvider.setProgressService(progressService);
propertyIndexProvider.getIndex(doc);
verify(progressService, atLeastOnce()).progressEvent(anyObject(), anyObject());
verify(progressService, atLeastOnce()).progressBegin(any(), any(), any());
// Should be cached now, so progress service should not be touched
progressService = mock(ProgressService.class);
propertyIndexProvider.setProgressService(progressService);
propertyIndexProvider.getIndex(doc);
verify(progressService, never()).progressEvent(anyObject(), anyObject());
verify(progressService, never()).progressBegin(any(), any(), any());
// Change POM file for the project
harness.changeFile(new File(directory, MavenCore.POM_XML).toURI().toString());
@@ -78,7 +78,7 @@ public class SpringPropertyIndexTest {
progressService = mock(ProgressService.class);
propertyIndexProvider.setProgressService(progressService);
propertyIndexProvider.getIndex(doc);
verify(progressService, atLeastOnce()).progressEvent(anyObject(), anyObject());
verify(progressService, atLeastOnce()).progressBegin(any(), any(), any());
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2022 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
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.test;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -64,13 +64,13 @@ public class SpringPropertiesIndexTest {
ProgressService progressService = mock(ProgressService.class);
propertyIndexProvider.setProgressService(progressService);
propertyIndexProvider.getIndex(doc);
verify(progressService, atLeastOnce()).progressEvent(anyObject(), anyObject());
verify(progressService, atLeastOnce()).progressBegin(any(), any(), any());
// Should be cached now, so progress service should not be touched
progressService = mock(ProgressService.class);
propertyIndexProvider.setProgressService(progressService);
propertyIndexProvider.getIndex(doc);
verify(progressService, never()).progressEvent(anyObject(), anyObject());
verify(progressService, never()).progressBegin(any(), any(), any());
// Change POM file for the project
harness.changeFile(new File(directory, MavenCore.POM_XML).toURI().toString());
@@ -79,7 +79,7 @@ public class SpringPropertiesIndexTest {
progressService = mock(ProgressService.class);
propertyIndexProvider.setProgressService(progressService);
propertyIndexProvider.getIndex(doc);
verify(progressService, atLeastOnce()).progressEvent(anyObject(), anyObject());
verify(progressService, atLeastOnce()).progressBegin(any(), any(), any());
}
}