Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a Progress support API for lemminx extension #1563

Merged
merged 1 commit into from
Aug 2, 2023
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 @@ -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();
}
}