Skip to content

Commit

Permalink
Merge pull request #261 from Xanewok/window-progress
Browse files Browse the repository at this point in the history
Add proposed window/progress extension
  • Loading branch information
dbaeumer authored Apr 12, 2019
2 parents ca214b0 + 382a4c6 commit dbe6494
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 1 deletion.
2 changes: 2 additions & 0 deletions client/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { WorkspaceFoldersFeature } from './workspaceFolders';
import { FoldingRangeFeature } from './foldingRange';
import { DeclarationFeature } from './declaration';
import { SelectionRangeFeature } from './selectionRange.proposed';
import { WindowProgressFeature } from './progress.proposed';
import { CallHierarchyFeature } from './callHierarchy.proposed';

import * as Is from './utils/is';
Expand Down Expand Up @@ -512,6 +513,7 @@ export namespace ProposedFeatures {
export function createAll(client: BaseLanguageClient): (StaticFeature | DynamicFeature<any>)[] {
let result: (StaticFeature | DynamicFeature<any>)[] = [
new SelectionRangeFeature(client),
new WindowProgressFeature(client)
new CallHierarchyFeature(client)
];
return result;
Expand Down
86 changes: 86 additions & 0 deletions client/src/progress.proposed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';

import { window, Progress, ProgressLocation } from 'vscode';

import { BaseLanguageClient, StaticFeature } from './client';
import { ClientCapabilities, Proposed } from 'vscode-languageserver-protocol';

export class WindowProgressFeature implements StaticFeature {
private _progresses: Map<string, WindowProgress> = new Map<string, WindowProgress>();

constructor(private _client: BaseLanguageClient) {}

public fillClientCapabilities(capabilities: ClientCapabilities): void {
let windowProgressCapabilities = capabilities as Proposed.WindowProgressClientCapabilities;

windowProgressCapabilities.window = windowProgressCapabilities.window || {};
windowProgressCapabilities.window.progress = true;
}

public initialize(): void {
let client = this._client;
let progresses = this._progresses;

let handler = function (params: Proposed.ProgressParams) {
let progress = progresses.get(params.id);
if (progress !== undefined) {
progress.updateProgress(params);
} else {
window.withProgress({ location: ProgressLocation.Window }, p => {
progress = new WindowProgress(p);
progresses.set(params.id, progress);

progress.updateProgress(params);
return progress.promise;
});
}
// In both cases progress shouldn't be undefined, but make the compiler happy.
if (params.done && progress !== undefined) {
progress.finish();
progresses.delete(params.id);
}
};

client.onNotification(Proposed.WindowProgressNotification.type, handler);
}
}

class WindowProgress {
public promise: Promise<{}>;
private resolve: (value?: {} | PromiseLike<{}> | undefined) => void;
private reject: (reason?: any) => void;

private progress: Progress<{ message?: string; }>;

private title: string;
private message: string | undefined;

constructor(progress: Progress<{ message?: string; }>) {
this.progress = progress;

this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}

public updateProgress(params: Proposed.ProgressParams) {
this.title = params.title;
this.message = params.message || this.message;

const details = this.message ? ` (${this.message})` : '';
this.progress.report({message: `${this.title}${details}`});
}

public finish() {
this.resolve();
}

public cancel() {
this.reject();
}
}
10 changes: 9 additions & 1 deletion protocol/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export * from './protocol';
export { FoldingRangeParams as FoldingRangeRequestParam } from './protocol'; // for backward compatibility

import * as callHierarchy from './protocol.callHierarchy.proposed';
import * as progress from './protocol.progress.proposed';
import * as sr from './protocol.selectionRange.proposed';

export namespace Proposed {
Expand Down Expand Up @@ -68,6 +69,13 @@ export namespace Proposed {
export type CallHierarchyDirection = callHierarchy.CallHierarchyDirection;
export type CallHierarchyItem = callHierarchy.CallHierarchyItem;
export type CallHierarchyCall = callHierarchy.CallHierarchyCall;

export type WindowProgressClientCapabilities = progress.WindowProgressClientCapabilities;
export type ProgressParams = progress.ProgressParams;
export namespace WindowProgressNotification {
export const type = progress.WindowProgressNotification.type;
export type HandlerSignature = progress.WindowProgressNotification.HandlerSignature;
}
}

export interface ProtocolConnection {
Expand Down Expand Up @@ -233,4 +241,4 @@ export type ProtocolConnetion = ProtocolConnection;

export function createProtocolConnection(reader: MessageReader, writer: MessageWriter, logger: Logger, strategy?: ConnectionStrategy): ProtocolConnection {
return createMessageConnection(reader, writer, logger, strategy);
}
}
63 changes: 63 additions & 0 deletions protocol/src/protocol.progress.proposed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#### Reporting server task progress

Many tools are capable of performing some background task processing or data streaming. From a UX point of view, it's good to report both the fact that the tool is performing some background work, but also report the progress being made for it. To realize that and to provide a simple proposal based on which the feature can be later improved, the following additions are proposed:

_Client Capabilities_:

The client sets the following capability if it is supporting notifying task progress.

```ts
/**
* Experimental client capabilities.
*/
experimental: {
/**
* The client has support for reporting progress.
*/
progress?: boolean;
}
```

##### Window Progress Notification
_Notification_:

The `window/progress` notification is sent from the server to the client to ask the client to indicate progress.

* method: 'window/progress'
* params: `ProgressParams` defined as follows:
```ts
export interface ProgressParams {
/**
* A unique identifier to associate multiple progress notifications with
* the same progress.
*/
id: string;

/**
* Mandatory title of the progress operation. Used to briefly inform about
* the kind of operation being performed.
* Examples: "Indexing" or "Linking dependencies".
*/
title: string;

/**
* Optional, more detailed associated progress message. Contains
* complementary information to the `title`.
* Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
* If unset, the previous progress message (if any) is still valid.
*/
message?: string;

/**
* Optional progress percentage to display (value 100 is considered 100%).
* If unset, the previous progress percentage (if any) is still valid.
*/
percentage?: number;

/**
* Set to true on the final progress update.
* No more progress notifications with the same ID should be sent.
*/
done?: boolean;
}
```
62 changes: 62 additions & 0 deletions protocol/src/protocol.progress.proposed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';

import { NotificationType, NotificationHandler } from 'vscode-jsonrpc';

export interface WindowProgressClientCapabilities {
/**
* Window specific client capabilities.
*/
window?: {
/**
* Whether client supports handling progress notifications.
*/
progress?: boolean;
}
}

export interface ProgressParams {
/**
* A unique identifier to associate multiple progress notifications with the same progress.
*/
id: string;

/**
* Mandatory title of the progress operation. Used to briefly inform about
* the kind of operation being performed.
* Examples: "Indexing" or "Linking dependencies".
*/
title: string;

/**
* Optional, more detailed associated progress message. Contains
* complementary information to the `title`.
* Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
* If unset, the previous progress message (if any) is still valid.
*/
message?: string;

/**
* Optional progress percentage to display (value 100 is considered 100%).
* If unset, the previous progress percentage (if any) is still valid.
*/
percentage?: number;

/**
* Set to true on the final progress update.
* No more progress notifications with the same ID should be sent.
*/
done?: boolean;
}

/**
* The `window/progress` notification is sent from the server to the client
* to inform the client about ongoing progress.
*/
export namespace WindowProgressNotification {
export const type = new NotificationType<ProgressParams, void>('window/progress');
export type HandlerSignature = NotificationHandler<ProgressParams>;
}
15 changes: 15 additions & 0 deletions protocol/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,16 @@ export interface TextDocumentClientCapabilities {
};
}

/**
* Window specific client capabilities.
*/
export interface WindowClientCapabilities {
/**
* Whether client supports handling progress notifications.
*/
progress?: boolean;
}

/**
* Defines the capabilities provided by the client.
*/
Expand All @@ -659,6 +669,11 @@ export interface _ClientCapabilities {
*/
textDocument?: TextDocumentClientCapabilities;

/**
* Window specific client capabilities.
*/
window?: WindowClientCapabilities;

/**
* Experimental client capabilities.
*/
Expand Down

0 comments on commit dbe6494

Please sign in to comment.