Merge pull request #163190 from c-claeys/multirange-formatting

Add support for multiRange formatting
This commit is contained in:
Johannes Rieken 2023-03-30 17:12:14 +02:00 committed by GitHub
commit 9ab7b1477a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 88 additions and 12 deletions

View file

@ -1182,6 +1182,10 @@ export interface FormattingOptions {
* Prefer spaces over tabs.
*/
insertSpaces: boolean;
/**
* The list of multiple ranges to format at once, if the provider supports it.
*/
ranges?: Range[];
}
/**
* The document formatting provider interface defines the contract between extensions and
@ -1213,6 +1217,8 @@ export interface DocumentRangeFormattingEditProvider {
readonly displayName?: string;
readonly canFormatMultipleRanges: boolean;
/**
* Provide formatting edits for a range in a document.
*

View file

@ -217,11 +217,23 @@ export async function formatDocumentRangesWithProvider(
const allEdits: TextEdit[] = [];
const rawEditsList: TextEdit[][] = [];
try {
for (const range of ranges) {
if (cts.token.isCancellationRequested) {
return true;
if (provider.canFormatMultipleRanges) {
logService.trace(`[format][provideDocumentRangeFormattingEdits] (request)`, provider.extensionId?.value, ranges);
const result = (await provider.provideDocumentRangeFormattingEdits(
model,
ranges[0],
{ ...model.getFormattingOptions(), ranges },
cts.token
)) || [];
logService.trace(`[format][provideDocumentRangeFormattingEdits] (response)`, provider.extensionId?.value, result);
rawEditsList.push(result);
} else {
for (const range of ranges) {
if (cts.token.isCancellationRequested) {
return true;
}
rawEditsList.push(await computeEdits(range));
}
rawEditsList.push(await computeEdits(range));
}
for (let i = 0; i < ranges.length; ++i) {

5
src/vs/monaco.d.ts vendored
View file

@ -7174,6 +7174,10 @@ declare namespace monaco.languages {
* Prefer spaces over tabs.
*/
insertSpaces: boolean;
/**
* The list of multiple ranges to format at once, if the provider supports it.
*/
ranges?: Range[];
}
/**
@ -7194,6 +7198,7 @@ declare namespace monaco.languages {
*/
export interface DocumentRangeFormattingEditProvider {
readonly displayName?: string;
readonly canFormatMultipleRanges: boolean;
/**
* Provide formatting edits for a range in a document.
*

View file

@ -32,7 +32,7 @@ import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'
import * as search from 'vs/workbench/contrib/search/common/search';
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape } from '../common/extHost.protocol';
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape, IRangeFormattingProviderMetadataDto } from '../common/extHost.protocol';
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
export class MainThreadLanguageFeatures extends Disposable implements MainThreadLanguageFeaturesShape {
@ -401,10 +401,11 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
}));
}
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void {
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string, metadata: IRangeFormattingProviderMetadataDto): void {
this._registrations.set(handle, this._languageFeaturesService.documentRangeFormattingEditProvider.register(selector, <languages.DocumentRangeFormattingEditProvider>{
extensionId,
displayName,
canFormatMultipleRanges: metadata.canFormatMultipleRanges,
provideDocumentRangeFormattingEdits: (model: ITextModel, range: EditorRange, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined> => {
return this._proxy.$provideDocumentRangeFormattingEdits(handle, model.uri, range, options, token);
}

View file

@ -536,8 +536,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentFormattingEditProvider(extension, checkSelector(selector), provider);
},
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(extension, checkSelector(selector), provider);
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider, metadata?: vscode.DocumentRangeFormattingEditProviderMetadata): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(extension, checkSelector(selector), provider, metadata);
},
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable {
return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(extension, checkSelector(selector), provider, [firstTriggerCharacter].concat(moreTriggerCharacters));

View file

@ -356,6 +356,10 @@ export interface IDocumentFilterDto {
notebookType?: string;
}
export interface IRangeFormattingProviderMetadataDto {
readonly canFormatMultipleRanges?: boolean;
}
export interface ISignatureHelpProviderMetadataDto {
readonly triggerCharacters: readonly string[];
readonly retriggerCharacters: readonly string[];
@ -388,7 +392,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string, supportsResolve: boolean): void;
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean, pasteMimeTypes: readonly string[]): void;
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string, metadata: IRangeFormattingProviderMetadataDto): void;
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
$registerNavigateTypeSupport(handle: number, supportsResolve: boolean): void;
$registerRenameSupport(handle: number, selector: IDocumentFilterDto[], supportsResolveInitialValues: boolean): void;

View file

@ -33,7 +33,7 @@ import { Cache } from './cache';
import { StopWatch } from 'vs/base/common/stopwatch';
import { isCancellationError, NotImplementedError } from 'vs/base/common/errors';
import { raceCancellationError } from 'vs/base/common/async';
import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { checkProposedApiEnabled, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
// --- adapter
@ -2055,9 +2055,13 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options, token), undefined, token);
}
registerDocumentRangeFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
registerDocumentRangeFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider, metadata?: vscode.DocumentRangeFormattingEditProviderMetadata): vscode.Disposable {
const canFormatMultipleRanges = metadata?.canFormatMultipleRanges ?? false;
if (canFormatMultipleRanges) {
checkProposedApiEnabled(extension, 'formatMultipleRanges');
}
const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider), extension);
this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector), extension.identifier, extension.displayName || extension.name);
this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector), extension.identifier, extension.displayName || extension.name, metadata ?? { canFormatMultipleRanges: false });
return this._createDisposable(handle);
}

View file

@ -37,6 +37,7 @@ export const allApiProposals = Object.freeze({
fileComments: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.fileComments.d.ts',
fileSearchProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.fileSearchProvider.d.ts',
findTextInFiles: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.findTextInFiles.d.ts',
formatMultipleRanges: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.formatMultipleRanges.d.ts',
fsChunks: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.fsChunks.d.ts',
getSessions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.getSessions.d.ts',
idToken: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.idToken.d.ts',

View file

@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------------------------
* 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
/**
* Metadata about a registered {@linkcode DocumentRangeFormattingEditProvider}.
*/
export interface DocumentRangeFormattingEditProviderMetadata {
/**
* `true` if the range formatting provider supports formatting multiple ranges at once.
*/
readonly canFormatMultipleRanges?: boolean;
}
export interface FormattingOptions2 {
/**
* The list of multiple ranges to format at once, if the provider supports it.
*/
// TODO@API should this all ranges or all except for the first range?
// TODO@API needs a name that is more descriptive
ranges?: Range[];
[key: string]: boolean | number | string | undefined | object;
}
export interface DocumentRangeFormattingEditProvider {
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions & FormattingOptions2, token: CancellationToken): ProviderResult<TextEdit[]>;
}
export namespace languages {
/**
*
* @param metadata Metadata about the provider.
*/
export function registerDocumentRangeFormattingEditProvider(selector: DocumentSelector, provider: DocumentRangeFormattingEditProvider, metadata?: DocumentRangeFormattingEditProviderMetadata): Disposable;
}
}