Skip to content

Commit

Permalink
Add formatMultipleRanges to DocumentRangeFormattingFeature (#1253)
Browse files Browse the repository at this point in the history
* Try formatMultipleRanges

* Add /rangesFormatting support

* Specify known properties

* .. and in testServer

* add cap+tags, rename option
  • Loading branch information
c-claeys authored Jun 26, 2023
1 parent f932967 commit 7c161d5
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 10 deletions.
3 changes: 2 additions & 1 deletion client-node-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@
"sinon": "^11.1.2",
"uuid": "^8.3.2",
"vscode-test": "^1.6.1"
}
},
"enabledApiProposals": ["formatMultipleRanges"]
}
4 changes: 3 additions & 1 deletion client-node-tests/src/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ suite('Client integration', () => {
resolveProvider: true
},
documentFormattingProvider: true,
documentRangeFormattingProvider: true,
documentRangeFormattingProvider: {
rangesSupport: true
},
documentOnTypeFormattingProvider: {
firstTriggerCharacter: ':'
},
Expand Down
4 changes: 3 additions & 1 deletion client-node-tests/src/servers/testServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ connection.onInitialize((params: InitializeParams): any => {
resolveProvider: true
},
documentFormattingProvider: true,
documentRangeFormattingProvider: true,
documentRangeFormattingProvider: {
rangesSupport: true
},
documentOnTypeFormattingProvider: {
firstTriggerCharacter: ':'
},
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"bugs": {
"url": "https://github.com/Microsoft/vscode-languageserver-node/issues"
},
"enabledApiProposals": [],
"enabledApiProposals": ["formatMultipleRanges"],
"main": "./lib/node/main.js",
"browser": {
"./lib/node/main.js": "./lib/browser/main.js"
Expand Down
7 changes: 7 additions & 0 deletions client/src/common/codeConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export interface Converter {
asRange(value: code.Range): proto.Range;
asRange(value: code.Range | undefined | null): proto.Range | undefined | null;

asRanges(values: readonly code.Range[]): proto.Range[];

asLocation(value: null): null;
asLocation(value: undefined): undefined;
asLocation(value: code.Location): proto.Location;
Expand Down Expand Up @@ -441,6 +443,10 @@ export function createConverter(uriConverter?: URIConverter): Converter {
return { start: asPosition(value.start), end: asPosition(value.end) };
}

function asRanges(values: readonly code.Range[]): proto.Range[] {
return values.map(asRange as (item: code.Range) => proto.Range);
}

function asLocation(value: code.Location): proto.Location;
function asLocation(value: undefined): undefined;
function asLocation(value: null): null;
Expand Down Expand Up @@ -959,6 +965,7 @@ export function createConverter(uriConverter?: URIConverter): Converter {
asSignatureHelpParams,
asWorkerPosition,
asRange,
asRanges,
asPosition,
asPositions,
asPositionsSync,
Expand Down
39 changes: 36 additions & 3 deletions client/src/common/formatting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/// <reference path="../../typings/vscode.proposed.formatMultipleRanges.d.ts" />

import {
languages as Languages, Disposable, TextDocument, ProviderResult, Range as VRange, Position as VPosition, TextEdit as VTextEdit, FormattingOptions as VFormattingOptions,
DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider, workspace as Workspace, OnTypeFormattingEditProvider
} from 'vscode';

import {
ClientCapabilities, CancellationToken, ServerCapabilities, DocumentSelector, DocumentHighlightRegistrationOptions, DocumentFormattingOptions, DocumentFormattingRequest, TextDocumentRegistrationOptions, DocumentFormattingParams, DocumentRangeFormattingRegistrationOptions, DocumentRangeFormattingOptions, DocumentRangeFormattingRequest, DocumentRangeFormattingParams, DocumentOnTypeFormattingOptions, DocumentOnTypeFormattingRegistrationOptions, DocumentOnTypeFormattingRequest, DocumentOnTypeFormattingParams} from 'vscode-languageserver-protocol';
ClientCapabilities, CancellationToken, ServerCapabilities, DocumentSelector, DocumentHighlightRegistrationOptions, DocumentFormattingOptions, DocumentFormattingRequest, TextDocumentRegistrationOptions, DocumentFormattingParams, DocumentRangeFormattingRegistrationOptions, DocumentRangeFormattingOptions, DocumentRangeFormattingRequest, DocumentRangeFormattingParams, DocumentRangesFormattingRequest, DocumentRangesFormattingParams, DocumentOnTypeFormattingOptions, DocumentOnTypeFormattingRegistrationOptions, DocumentOnTypeFormattingRequest, DocumentOnTypeFormattingParams} from 'vscode-languageserver-protocol';

import * as UUID from './utils/uuid';

Expand All @@ -36,6 +37,10 @@ export interface ProvideDocumentRangeFormattingEditsSignature {
(this: void, document: TextDocument, range: VRange, options: VFormattingOptions, token: CancellationToken): ProviderResult<VTextEdit[]>;
}

export interface ProvideDocumentRangesFormattingEditsSignature {
(this: void, document: TextDocument, ranges: VRange[], options: VFormattingOptions, token: CancellationToken): ProviderResult<VTextEdit[]>;
}

export interface ProvideOnTypeFormattingEditsSignature {
(this: void, document: TextDocument, position: VPosition, ch: string, options: VFormattingOptions, token: CancellationToken): ProviderResult<VTextEdit[]>;
}
Expand All @@ -44,6 +49,7 @@ export interface ProvideOnTypeFormattingEditsSignature {
export interface FormattingMiddleware {
provideDocumentFormattingEdits?: (this: void, document: TextDocument, options: VFormattingOptions, token: CancellationToken, next: ProvideDocumentFormattingEditsSignature) => ProviderResult<VTextEdit[]>;
provideDocumentRangeFormattingEdits?: (this: void, document: TextDocument, range: VRange, options: VFormattingOptions, token: CancellationToken, next: ProvideDocumentRangeFormattingEditsSignature) => ProviderResult<VTextEdit[]>;
provideDocumentRangesFormattingEdits?: (this: void, document: TextDocument, range: VRange[], options: VFormattingOptions, token: CancellationToken, next: ProvideDocumentRangesFormattingEditsSignature) => ProviderResult<VTextEdit[]>;
provideOnTypeFormattingEdits?: (this: void, document: TextDocument, position: VPosition, ch: string, options: VFormattingOptions, token: CancellationToken, next: ProvideOnTypeFormattingEditsSignature) => ProviderResult<VTextEdit[]>;
}

Expand Down Expand Up @@ -102,7 +108,9 @@ export class DocumentRangeFormattingFeature extends TextDocumentLanguageFeature<
}

public fillClientCapabilities(capabilities: ClientCapabilities): void {
ensure(ensure(capabilities, 'textDocument')!, 'rangeFormatting')!.dynamicRegistration = true;
const capability = ensure(ensure(capabilities, 'textDocument')!, 'rangeFormatting')!;
capability.dynamicRegistration = true;
capability.rangesSupport = true;
}

public initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector): void {
Expand All @@ -113,7 +121,7 @@ export class DocumentRangeFormattingFeature extends TextDocumentLanguageFeature<
this.register({ id: UUID.generateUuid(), registerOptions: options });
}

protected registerLanguageProvider(options: TextDocumentRegistrationOptions): [Disposable, DocumentRangeFormattingEditProvider] {
protected registerLanguageProvider(options: DocumentRangeFormattingRegistrationOptions): [Disposable, DocumentRangeFormattingEditProvider] {
const selector = options.documentSelector!;
const provider: DocumentRangeFormattingEditProvider = {
provideDocumentRangeFormattingEdits: (document, range, options, token) => {
Expand All @@ -139,6 +147,31 @@ export class DocumentRangeFormattingFeature extends TextDocumentLanguageFeature<
: provideDocumentRangeFormattingEdits(document, range, options, token);
}
};

if (options.rangesSupport) {
provider.provideDocumentRangesFormattingEdits = (document, ranges, options, token) => {
const client = this._client;
const provideDocumentRangesFormattingEdits: ProvideDocumentRangesFormattingEditsSignature = (document, ranges, options, token) => {
const params: DocumentRangesFormattingParams = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
ranges: client.code2ProtocolConverter.asRanges(ranges),
options: client.code2ProtocolConverter.asFormattingOptions(options, FileFormattingOptions.fromConfiguration(document))
};
return client.sendRequest(DocumentRangesFormattingRequest.type, params, token).then((result) => {
if (token.isCancellationRequested) {
return null;
}
return client.protocol2CodeConverter.asTextEdits(result, token);
}, (error) => {
return client.handleFailedRequest(DocumentRangesFormattingRequest.type, token, error, null);
});
};
const middleware = client.middleware;
return middleware.provideDocumentRangesFormattingEdits
? middleware.provideDocumentRangesFormattingEdits(document, ranges, options, token, provideDocumentRangesFormattingEdits)
: provideDocumentRangesFormattingEdits(document, ranges, options, token);
};
}
return [Languages.registerDocumentRangeFormattingEditProvider(this._client.protocol2CodeConverter.asDocumentSelector(selector), provider), provider];
}
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/node/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import semverSatisfies = require('semver/functions/satisfies');
export * from 'vscode-languageserver-protocol/node';
export * from '../common/api';

const REQUIRED_VSCODE_VERSION = '^1.68.0'; // do not change format, updated by `updateVSCode` script
const REQUIRED_VSCODE_VERSION = '^1.78.0'; // do not change format, updated by `updateVSCode` script

export enum TransportKind {
stdio,
Expand Down
29 changes: 29 additions & 0 deletions client/typings/vscode.proposed.formatMultipleRanges.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

declare module 'vscode' {

// https://github.com/microsoft/vscode/issues/158776


export interface DocumentRangeFormattingEditProvider {

/**
* Provide formatting edits for multiple ranges in a document.
*
* The given ranges are hints and providers can decide to format a smaller
* or larger range. Often this is done by adjusting the start and end
* of the range to full syntax nodes.
*
* @param document The document in which the command was invoked.
* @param ranges The ranges which should be formatted.
* @param options Options controlling formatting.
* @param token A cancellation token.
* @return A set of text edits or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined`, `null`, or an empty array.
*/
provideDocumentRangesFormattingEdits?(document: TextDocument, ranges: Range[], options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]>;
}
}
97 changes: 96 additions & 1 deletion protocol/metaModel.json
Original file line number Diff line number Diff line change
Expand Up @@ -1706,6 +1706,37 @@
},
"documentation": "A request to format a range in a document."
},
{
"method": "textDocument/rangesFormatting",
"result": {
"kind": "or",
"items": [
{
"kind": "array",
"element": {
"kind": "reference",
"name": "TextEdit"
}
},
{
"kind": "base",
"name": "null"
}
]
},
"messageDirection": "clientToServer",
"params": {
"kind": "reference",
"name": "DocumentRangesFormattingParams"
},
"registrationOptions": {
"kind": "reference",
"name": "DocumentRangeFormattingRegistrationOptions"
},
"documentation": "A request to format ranges in a document.\n\n@since 3.18.0\n@proposed",
"since": "3.18.0",
"proposed": true
},
{
"method": "textDocument/onTypeFormatting",
"result": {
Expand Down Expand Up @@ -5982,6 +6013,47 @@
],
"documentation": "Registration options for a {@link DocumentRangeFormattingRequest}."
},
{
"name": "DocumentRangesFormattingParams",
"properties": [
{
"name": "textDocument",
"type": {
"kind": "reference",
"name": "TextDocumentIdentifier"
},
"documentation": "The document to format."
},
{
"name": "ranges",
"type": {
"kind": "array",
"element": {
"kind": "reference",
"name": "Range"
}
},
"documentation": "The ranges to format"
},
{
"name": "options",
"type": {
"kind": "reference",
"name": "FormattingOptions"
},
"documentation": "The format options"
}
],
"mixins": [
{
"kind": "reference",
"name": "WorkDoneProgressParams"
}
],
"documentation": "The parameters of a {@link DocumentRangesFormattingRequest}.\n\n@since 3.18.0\n@proposed",
"since": "3.18.0",
"proposed": true
},
{
"name": "DocumentOnTypeFormattingParams",
"properties": [
Expand Down Expand Up @@ -9477,7 +9549,19 @@
},
{
"name": "DocumentRangeFormattingOptions",
"properties": [],
"properties": [
{
"name": "rangesSupport",
"type": {
"kind": "base",
"name": "boolean"
},
"optional": true,
"documentation": "Whether the server supports formatting multiple ranges at once.\n\n@since 3.18.0\n@proposed",
"since": "3.18.0",
"proposed": true
}
],
"mixins": [
{
"kind": "reference",
Expand Down Expand Up @@ -12193,6 +12277,17 @@
},
"optional": true,
"documentation": "Whether range formatting supports dynamic registration."
},
{
"name": "rangesSupport",
"type": {
"kind": "base",
"name": "boolean"
},
"optional": true,
"documentation": "Whether the client supports formatting multiple ranges at once.\n\n@since 3.18.0\n@proposed",
"since": "3.18.0",
"proposed": true
}
],
"documentation": "Client capabilities of a {@link DocumentRangeFormattingRequest}."
Expand Down
50 changes: 50 additions & 0 deletions protocol/src/common/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3426,6 +3426,14 @@ export interface DocumentRangeFormattingClientCapabilities {
* Whether range formatting supports dynamic registration.
*/
dynamicRegistration?: boolean;

/**
* Whether the client supports formatting multiple ranges at once.
*
* @since 3.18.0
* @proposed
*/
rangesSupport?: boolean;
}

/**
Expand All @@ -3448,10 +3456,40 @@ export interface DocumentRangeFormattingParams extends WorkDoneProgressParams {
options: FormattingOptions;
}

/**
* The parameters of a {@link DocumentRangesFormattingRequest}.
*
* @since 3.18.0
* @proposed
*/
export interface DocumentRangesFormattingParams extends WorkDoneProgressParams {
/**
* The document to format.
*/
textDocument: TextDocumentIdentifier;

/**
* The ranges to format
*/
ranges: Range[];

/**
* The format options
*/
options: FormattingOptions;
}

/**
* Provider options for a {@link DocumentRangeFormattingRequest}.
*/
export interface DocumentRangeFormattingOptions extends WorkDoneProgressOptions {
/**
* Whether the server supports formatting multiple ranges at once.
*
* @since 3.18.0
* @proposed
*/
rangesSupport?: boolean;
}

/**
Expand All @@ -3469,6 +3507,18 @@ export namespace DocumentRangeFormattingRequest {
export const type = new ProtocolRequestType<DocumentRangeFormattingParams, TextEdit[] | null, never, void, DocumentRangeFormattingRegistrationOptions>(method);
}

/**
* A request to format ranges in a document.
*
* @since 3.18.0
* @proposed
*/
export namespace DocumentRangesFormattingRequest {
export const method: 'textDocument/rangesFormatting' = 'textDocument/rangesFormatting';
export const messageDirection: MessageDirection = MessageDirection.clientToServer;
export const type = new ProtocolRequestType<DocumentRangesFormattingParams, TextEdit[] | null, never, void, DocumentRangeFormattingRegistrationOptions>(method);
}

/**
* Client capabilities of a {@link DocumentOnTypeFormattingRequest}.
*/
Expand Down
Loading

0 comments on commit 7c161d5

Please sign in to comment.