Skip to content

Commit

Permalink
Provide a Progress support API for lemminx extension
Browse files Browse the repository at this point in the history
Fixes #1562

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Aug 2, 2023
1 parent 2b0fe29 commit acab0cf
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
*/
package org.eclipse.lemminx;

import static org.eclipse.lsp4j.jsonrpc.CompletableFutures.computeAsync;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
Expand All @@ -30,6 +28,7 @@
import org.eclipse.lemminx.client.ExtendedClientCapabilities;
import org.eclipse.lemminx.commons.ModelTextDocument;
import org.eclipse.lemminx.commons.ParentProcessWatcher.ProcessLanguageServer;
import org.eclipse.lemminx.commons.progress.ProgressSupport;
import org.eclipse.lemminx.customservice.ActionableNotification;
import org.eclipse.lemminx.customservice.AutoCloseTagResponse;
import org.eclipse.lemminx.customservice.XMLLanguageClientAPI;
Expand Down Expand Up @@ -67,9 +66,13 @@
import org.eclipse.lsp4j.MessageParams;
import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.ProgressParams;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.SetTraceParams;
import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.eclipse.lsp4j.WorkDoneProgressCreateParams;
import org.eclipse.lsp4j.WorkDoneProgressNotification;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.eclipse.lsp4j.services.WorkspaceService;
Expand All @@ -79,7 +82,7 @@
*
*/
public class XMLLanguageServer implements ProcessLanguageServer, XMLLanguageServerAPI, IXMLDocumentProvider,
IXMLNotificationService, IXMLValidationService {
IXMLNotificationService, IXMLValidationService, ProgressSupport {

private static final Logger LOGGER = Logger.getLogger(XMLLanguageServer.class.getName());

Expand All @@ -101,6 +104,7 @@ public XMLLanguageServer() {
xmlLanguageService.setNotificationService(this);
xmlLanguageService.setCommandService(xmlWorkspaceService);
xmlLanguageService.setValidationService(this);
xmlLanguageService.setProgressSupport(this);

delayer = Executors.newScheduledThreadPool(1);
}
Expand Down Expand Up @@ -356,4 +360,20 @@ public void setTrace(SetTraceParams params) {
// to avoid having error in vscode, the method is implemented
// FIXME : implement the behavior of this method.
}

@Override
public boolean isWorkDoneProgressSupported() {
return capabilityManager.getClientCapabilities().isWorkDoneProgressSupported();
}

@Override
public CompletableFuture<Void> createProgress(WorkDoneProgressCreateParams params) {
return getLanguageClient().createProgress(params);
}

@Override
public void notifyProgress(String progressId, WorkDoneProgressNotification notification) {
ProgressParams params = new ProgressParams(Either.forLeft(progressId), Either.forRight(notification));
getLanguageClient().notifyProgress(params);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.lemminx.commons.progress;

import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;

import org.eclipse.lsp4j.WorkDoneProgressBegin;
import org.eclipse.lsp4j.WorkDoneProgressCreateParams;
import org.eclipse.lsp4j.WorkDoneProgressEnd;
import org.eclipse.lsp4j.WorkDoneProgressReport;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4j.jsonrpc.messages.Either;

/**
* Progress monitor which wraps the LSP progress API to simplify the
* implementation of progress.
*
* @author Angelo ZERR
*
*/
public class ProgressMonitor implements CancelChecker {

private final String progressId;

private final ProgressSupport progressSupport;

private CompletableFuture<Void> future;

public ProgressMonitor(ProgressSupport progressSupport) {
this(UUID.randomUUID().toString(), progressSupport);
}

public ProgressMonitor(String progressId, ProgressSupport progressSupport) {
this.progressId = progressId;
this.progressSupport = progressSupport;

// Initialize progress
WorkDoneProgressCreateParams create = new WorkDoneProgressCreateParams(Either.forLeft(progressId));
future = progressSupport.createProgress(create);
}

public void begin(String title, String message, Integer percentage, Boolean cancellable) {
// Start progress
WorkDoneProgressBegin begin = new WorkDoneProgressBegin();
begin.setTitle(title);
begin.setMessage(message);
begin.setPercentage(percentage);
begin.setCancellable(cancellable);
progressSupport.notifyProgress(progressId, begin);
}

public void report(String message, Integer percentage, Boolean cancellable) {
// report message
WorkDoneProgressReport report = new WorkDoneProgressReport();
report.setMessage(message);
report.setPercentage(percentage);
report.setCancellable(cancellable);
progressSupport.notifyProgress(progressId, report);
}

public void end(String message) {
WorkDoneProgressEnd end = new WorkDoneProgressEnd();
end.setMessage(message);
progressSupport.notifyProgress(progressId, end);
}

@Override
public void checkCanceled() {
if (future != null && future.isCancelled()) {
throw new CancellationException();
}
}

@Override
public boolean isCanceled() {
return future != null ? future.isCancelled() : true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.lemminx.commons.progress;

import java.util.concurrent.CompletableFuture;

import org.eclipse.lsp4j.WorkDoneProgressCreateParams;
import org.eclipse.lsp4j.WorkDoneProgressNotification;

/**
* LSP Progress support API.
*
* @author Angelo ZERR
*
*/
public interface ProgressSupport {

default ProgressMonitor createProgressMonitor() {
if (!isWorkDoneProgressSupported()) {
return null;
}
return new ProgressMonitor(this);
}

default ProgressMonitor createProgressMonitor(String progressId) {
if (!isWorkDoneProgressSupported()) {
return null;
}
return new ProgressMonitor(progressId, this);
}

/**
* Returns true if the LSP client can support LSP progress and false otherwise.
*
* @return true if the LSP client can support LSP progress and false otherwise.
*/
boolean isWorkDoneProgressSupported();

/**
* Create a progress.
*
* @param params the progress create parameters
* @return
*/
CompletableFuture<Void> createProgress(WorkDoneProgressCreateParams params);

/**
* Notify the the progress notification with the given process id.
*
* @param progressId the progress id.
* @param notification the progress notification.
*/
void notifyProgress(String progressId, WorkDoneProgressNotification notification);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.lemminx.commons.progress.ProgressSupport;
import org.eclipse.lemminx.services.IXMLDocumentProvider;
import org.eclipse.lemminx.services.IXMLNotificationService;
import org.eclipse.lemminx.services.IXMLValidationService;
Expand Down Expand Up @@ -70,7 +71,8 @@ public class XMLExtensionsRegistry implements IComponentProvider {
private IXMLDocumentProvider documentProvider;
private IXMLValidationService validationService;
private IXMLCommandService commandService;

private ProgressSupport progressSupport;

private InitializeParams params;

private ISaveContext initialSaveContext;
Expand Down Expand Up @@ -552,5 +554,13 @@ public TelemetryManager getTelemetryManager() {
public void setTelemetryManager(TelemetryManager telemetryManager) {
this.telemetryManager = telemetryManager;
}

public void setProgressSupport(ProgressSupport progressSupport) {
this.progressSupport = progressSupport;
}

public ProgressSupport getProgressSupport() {
return progressSupport;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,9 @@ public boolean shouldLanguageServerExitOnShutdown() {
}
return extendedCapabilities.shouldLanguageServerExitOnShutdown();
}

public boolean isWorkDoneProgressSupported() {
return v3Supported && capabilities.getWindow() != null && capabilities.getWindow().getWorkDoneProgress() != null
&& capabilities.getWindow().getWorkDoneProgress().booleanValue();
}
}

0 comments on commit acab0cf

Please sign in to comment.