Skip to content

Commit

Permalink
fix: Support customize progress notifications UI
Browse files Browse the repository at this point in the history
Fixes redhat-developer#772

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Jan 28, 2025
1 parent 806cf7c commit 29c31d2
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 24 deletions.
8 changes: 8 additions & 0 deletions docs/LSPApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The [LSPClientFeatures](https://github.com/redhat-developer/lsp4ij/blob/main/src
- [LSP hover feature](#lsp-hover-feature)
- [LSP implementation feature](#lsp-implementation-feature)
- [LSP inlayHint feature](#lsp-inlayHint-feature)
- [LSP progress feature](#lsp-progress-feature)
- [LSP references feature](#lsp-references-feature)
- [LSP rename feature](#lsp-rename-feature)
- [LSP semanticTokens feature](#lsp-semanticTokens-feature)
Expand Down Expand Up @@ -439,6 +440,13 @@ Integrates the LSP [`textDocument/selectionRange`](https://microsoft.github.io/l
| boolean isEnabled(PsiFile file) | Returns `true` if the LSP feature is enabled for the given file and `false` otherwise. | `true` |
| boolean isSupported(PsiFile file) | Returns `true` if the LSP feature is supported for the given file and `false` otherwise. <br/>This supported state is called after starting the language server, which matches the file and user with the LSP server capabilities. | Check the server capability |

## LSP Progress Feature

| API | Description | Default Behaviour |
|-----------------------------------------------------------------|-----------------------------------------------------------------|-------------------|
| String getProgressTaskTitle(String title) | Returns the progress task title. | |
| void updateMessage(String message, ProgressIndicator indicator) | Update the given progress indicator text with the given message | |

## LSP References Feature

| API | Description | Default Behaviour |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public class LSPClientFeatures implements Disposable, FileUriSupport {

private LSPInlayHintFeature inlayHintFeature;

private LSPProgressFeature progressFeature;

private LSPReferencesFeature referencesFeature;

private LSPRenameFeature renameFeature;
Expand Down Expand Up @@ -790,6 +792,38 @@ public final LSPClientFeatures setInlayHintFeature(@NotNull LSPInlayHintFeature
return this;
}

/**
* Returns the LSP progress feature.
*
* @return the LSP progress feature.
*/
@NotNull
public final LSPProgressFeature getProgressFeature() {
if (progressFeature == null) {
initProgressFeature();
}
return progressFeature;
}

private synchronized void initProgressFeature() {
if (progressFeature != null) {
return;
}
setProgressFeature(new LSPProgressFeature());
}

/**
* Initialize the LSP progress feature.
*
* @param progressFeature the LSP progress feature.
* @return the LSP client features.
*/
public final LSPClientFeatures setProgressFeature(@NotNull LSPProgressFeature progressFeature) {
progressFeature.setClientFeatures(this);
this.progressFeature = progressFeature;
return this;
}

/**
* Returns the LSP references feature.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/

package com.redhat.devtools.lsp4ij.client.features;

import com.intellij.lang.LanguageFormatting;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*******************************************************************************
* Copyright (c) 2025 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.lsp4ij.client.features;

import com.intellij.openapi.progress.ProgressIndicator;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.WorkDoneProgressBegin;
import org.eclipse.lsp4j.WorkDoneProgressEnd;
import org.eclipse.lsp4j.WorkDoneProgressReport;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* LSP progress feature.
*/
@ApiStatus.Experimental
public class LSPProgressFeature extends AbstractLSPFeature {

private @Nullable ServerCapabilities serverCapabilities;

@Override
public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities) {
this.serverCapabilities = serverCapabilities;
}

/**
* Returns the progress task title.
*
* @param title coming from the {@link WorkDoneProgressBegin#getTitle()}.
* @return the progress task title.
*/
public String getProgressTaskTitle(@NotNull String title) {
String name = getServerDefinition().getDisplayName();
return name + ": " + title;
}

/**
* On progress begin.
*
* @param begin the LSP {@link WorkDoneProgressBegin}.
* @param progressIndicator the progress indicator.
*/
public void onProgressBegin(@NotNull WorkDoneProgressBegin begin,
@NotNull ProgressIndicator progressIndicator) {
Integer percentage = begin.getPercentage();
progressIndicator.setIndeterminate(percentage == null);
updateProgressIndicator(begin.getMessage(), percentage, progressIndicator);
}

/**
* On progress report.
*
* @param report the LSP {@link WorkDoneProgressReport}.
* @param progressIndicator the progress indicator.
*/
public void onProgressReport(@NotNull WorkDoneProgressReport report,
@NotNull ProgressIndicator progressIndicator) {
updateProgressIndicator(report.getMessage(), report.getPercentage(), progressIndicator);
}

/**
* On progress end.
*
* @param end the LSP {@link WorkDoneProgressEnd}.
*/
public void onProgressEnd(@NotNull WorkDoneProgressEnd end) {
// Do nothing
}

/**
* Update text and fraction of the given progress indicator.
*
* @param message the text to display and null otherwise.
* @param percentage the fraction and null otherwise.
* @param progressIndicator the progress indicator.
*/
protected void updateProgressIndicator(@Nullable String message,
@Nullable Integer percentage,
@NotNull ProgressIndicator progressIndicator) {
if (message != null && !message.isBlank()) {
updateMessage(message, progressIndicator);
}
if (percentage != null) {
progressIndicator.setFraction(percentage.doubleValue() / 100);
}
}

/**
* Update the given progress indicator text with the given message.
*
* @param message the message.
* @param progressIndicator the progress indicator.
*/
protected void updateMessage(@NotNull String message,
@NotNull ProgressIndicator progressIndicator) {
progressIndicator.setText2(message);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageServer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -72,8 +71,8 @@ private void createTask(LSPProgressInfo progressInfo) {
progressMap.remove(token);
return;
}
String name = this.languageServerWrapper.getServerDefinition().getDisplayName();
String title = name + ": " + progressInfo.getTitle();
String title = languageServerWrapper.getClientFeatures().getProgressFeature()
.getProgressTaskTitle(progressInfo.getTitle());
boolean cancellable = progressInfo.isCancellable();
ProgressManager.getInstance().run(new Task.Backgroundable(languageServerWrapper.getProject(), title, cancellable) {
@Override
Expand Down Expand Up @@ -106,9 +105,9 @@ public void run(@NotNull ProgressIndicator indicator) {
WorkDoneProgressKind kind = progressNotification.getKind();
switch (kind) {
case begin -> // 'begin' has been notified
begin((WorkDoneProgressBegin) progressNotification, indicator);
onProgressBegin((WorkDoneProgressBegin) progressNotification, indicator);
case report -> // 'report' has been notified
report((WorkDoneProgressReport) progressNotification, indicator);
onProgressReport((WorkDoneProgressReport) progressNotification, indicator);
}
}
}
Expand All @@ -123,27 +122,21 @@ private boolean isProgressAlive(LSPProgressInfo progressInfo) {
return progressInfo.isDone() || progressInfo.isCancelled() || isDisposed();
}

private void begin(@NotNull WorkDoneProgressBegin begin,
@NotNull ProgressIndicator progressIndicator) {
Integer percentage = begin.getPercentage();
progressIndicator.setIndeterminate(percentage == null);
updateProgressIndicator(begin.getMessage(), percentage, progressIndicator);
private void onProgressBegin(@NotNull WorkDoneProgressBegin begin,
@NotNull ProgressIndicator progressIndicator) {
languageServerWrapper.getClientFeatures().getProgressFeature()
.onProgressBegin(begin, progressIndicator);
}

private void report(@NotNull WorkDoneProgressReport report,
@NotNull ProgressIndicator progressIndicator) {
updateProgressIndicator(report.getMessage(), report.getPercentage(), progressIndicator);
private void onProgressReport(@NotNull WorkDoneProgressReport report,
@NotNull ProgressIndicator progressIndicator) {
languageServerWrapper.getClientFeatures().getProgressFeature()
.onProgressReport(report, progressIndicator);
}

private void updateProgressIndicator(@Nullable String message,
@Nullable Integer percentage,
@NotNull ProgressIndicator progressIndicator) {
if (message != null && !message.isBlank()) {
progressIndicator.setText2(message);
}
if (percentage != null) {
progressIndicator.setFraction(percentage.doubleValue() / 100);
}
private void onProgressEnd(@NotNull WorkDoneProgressEnd end) {
languageServerWrapper.getClientFeatures().getProgressFeature()
.onProgressEnd(end);
}

/**
Expand Down Expand Up @@ -197,7 +190,11 @@ public void notifyProgress(final @NotNull ProgressParams params) {
// the Task with the 'begin' title.
createTask(progress);
}
case end -> progress.setDone(true);
case end -> {
WorkDoneProgressEnd end = (WorkDoneProgressEnd) progressNotification;
onProgressEnd(end);
progress.setDone(true);
}
}
}

Expand Down

0 comments on commit 29c31d2

Please sign in to comment.