From d0250e82cf84e1ef20607697f247a9044181468c Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 11 Sep 2023 16:57:54 +1000 Subject: [PATCH] Allow Razor to format new documents via Roslyn --- src/lsptoolshost/razorCommands.ts | 15 ++++++ .../razorFormatNewFileHandler.ts | 52 +++++++++++++++++++ .../serializableFormatNewFileParams.ts | 12 +++++ 3 files changed, 79 insertions(+) create mode 100644 src/razor/src/formatNewFile/razorFormatNewFileHandler.ts create mode 100644 src/razor/src/formatNewFile/serializableFormatNewFileParams.ts diff --git a/src/lsptoolshost/razorCommands.ts b/src/lsptoolshost/razorCommands.ts index aa44ada80..8a3c5abf4 100644 --- a/src/lsptoolshost/razorCommands.ts +++ b/src/lsptoolshost/razorCommands.ts @@ -26,6 +26,7 @@ import { } from 'vscode-languageclient/node'; import SerializableSimplifyMethodParams from '../razor/src/simplify/serializableSimplifyMethodParams'; import { TextEdit } from 'vscode-html-languageservice'; +import { SerializableFormatNewFileParams } from '../razor/src/formatNewFile/serializableFormatNewFileParams'; // These are commands that are invoked by the Razor extension, and are used to send LSP requests to the Roslyn LSP server export const roslynDidChangeCommand = 'roslyn.changeRazorCSharp'; @@ -36,6 +37,7 @@ export const resolveCodeActionCommand = 'roslyn.resolveCodeAction'; export const provideCompletionsCommand = 'roslyn.provideCompletions'; export const resolveCompletionsCommand = 'roslyn.resolveCompletion'; export const roslynSimplifyMethodCommand = 'roslyn.simplifyMethod'; +export const roslynFormatNewFileCommand = 'roslyn.formatNewFile'; export const razorInitializeCommand = 'razor.initialize'; export function registerRazorCommands(context: vscode.ExtensionContext, languageServer: RoslynLanguageServer) { @@ -70,6 +72,19 @@ export function registerRazorCommands(context: vscode.ExtensionContext, language } ) ); + context.subscriptions.push( + vscode.commands.registerCommand( + roslynFormatNewFileCommand, + async (request: SerializableFormatNewFileParams) => { + const formatNewFileRequestType = new RequestType< + SerializableFormatNewFileParams, + string | undefined, + any + >('roslyn/formatNewFile'); + return await languageServer.sendRequest(formatNewFileRequestType, request, CancellationToken.None); + } + ) + ); // The VS Code API for code actions (and the vscode.CodeAction type) doesn't support everything that LSP supports, // namely the data property, which Razor needs to identify which code actions are on their allow list, so we need diff --git a/src/razor/src/formatNewFile/razorFormatNewFileHandler.ts b/src/razor/src/formatNewFile/razorFormatNewFileHandler.ts new file mode 100644 index 000000000..998cd618d --- /dev/null +++ b/src/razor/src/formatNewFile/razorFormatNewFileHandler.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { RequestType } from 'vscode-languageclient'; +import { RazorLanguageServerClient } from '../razorLanguageServerClient'; +import { RazorDocumentManager } from '../document/razorDocumentManager'; +import { RazorLanguageServiceClient } from '../razorLanguageServiceClient'; +import { RazorLanguageFeatureBase } from '../razorLanguageFeatureBase'; +import { RazorDocumentSynchronizer } from '../document/razorDocumentSynchronizer'; +import { RazorLogger } from '../razorLogger'; +import { SerializableFormatNewFileParams } from './serializableFormatNewFileParams'; +import { roslynFormatNewFileCommand } from '../../../lsptoolshost/razorCommands'; + +export class RazorFormatNewFileHandler extends RazorLanguageFeatureBase { + private static readonly razorFormatNewFileCommand = 'razor/formatNewFile'; + private formatNewFileRequestType: RequestType = + new RequestType(RazorFormatNewFileHandler.razorFormatNewFileCommand); + + constructor( + documentSynchronizer: RazorDocumentSynchronizer, + protected readonly serverClient: RazorLanguageServerClient, + protected readonly serviceClient: RazorLanguageServiceClient, + protected readonly documentManager: RazorDocumentManager, + protected readonly logger: RazorLogger + ) { + super(documentSynchronizer, documentManager, serviceClient, logger); + } + + public async register() { + await this.serverClient.onRequestWithParams( + this.formatNewFileRequestType, + async (request: SerializableFormatNewFileParams, token: vscode.CancellationToken) => + this.getFormatNewFile(request, token) + ); + } + + private async getFormatNewFile( + request: SerializableFormatNewFileParams, + _: vscode.CancellationToken + ): Promise { + if (!this.documentManager.roslynActivated) { + return undefined; + } + + const response: string | undefined = await vscode.commands.executeCommand(roslynFormatNewFileCommand, request); + + return response; + } +} diff --git a/src/razor/src/formatNewFile/serializableFormatNewFileParams.ts b/src/razor/src/formatNewFile/serializableFormatNewFileParams.ts new file mode 100644 index 000000000..26227a24f --- /dev/null +++ b/src/razor/src/formatNewFile/serializableFormatNewFileParams.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { SerializableTextDocumentIdentifier } from '../rpc/serializableTextDocumentIdentifier'; + +export interface SerializableFormatNewFileParams { + project: SerializableTextDocumentIdentifier; + document: SerializableTextDocumentIdentifier; + contents: string; +}