Skip to content

Commit

Permalink
Update to use the new formatting method names, and fix range bug
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwengier committed May 4, 2023
1 parent 3fca197 commit 5995c10
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 147 deletions.
105 changes: 88 additions & 17 deletions src/razor/src/Formatting/FormattingHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,26 @@

import * as vscode from 'vscode';
import { RequestType } from 'vscode-languageclient';
import { IRazorDocument } from '../Document/IRazorDocument';
import { RazorDocumentManager } from '../Document/RazorDocumentManager';
import { RazorDocumentSynchronizer } from '../Document/RazorDocumentSynchronizer';
import { RazorLanguageServerClient } from '../RazorLanguageServerClient';
import { RazorLogger } from '../RazorLogger';
import { convertTextEditToSerializable, SerializableTextEdit } from '../RPC/SerializableTextEdit';
import { SerializableFormattingParams } from './SerializableFormattingParams';
import { SerializableFormattingResponse } from './SerializableFormattingResponse';
import { SerializableOnTypeFormattingParams } from './SerializableOnTypeFormattingParams';

export class FormattingHandler {
private static readonly provideFormattingEndpoint = 'textDocument/formatting';
private static readonly provideFormattingEndpoint = 'razor/htmlFormatting';
private static readonly provideOnTypeFormattingEndpoint = 'razor/htmlOnTypeFormatting';
private formattingRequestType: RequestType<SerializableFormattingParams, SerializableFormattingResponse, any> = new RequestType(FormattingHandler.provideFormattingEndpoint);
private onTypeFormattingRequestType: RequestType<SerializableOnTypeFormattingParams, SerializableFormattingResponse, any> = new RequestType(FormattingHandler.provideOnTypeFormattingEndpoint);
private emptyFormattingResponse = new SerializableFormattingResponse();

constructor(
private readonly documentManager: RazorDocumentManager,
private readonly documentSynchronizer: RazorDocumentSynchronizer,
private readonly serverClient: RazorLanguageServerClient,
private readonly logger: RazorLogger) { }

Expand All @@ -27,6 +33,10 @@ export class FormattingHandler {
this.serverClient.onRequestWithParams<SerializableFormattingParams, SerializableFormattingResponse, any>(
this.formattingRequestType,
async (request, token) => this.provideFormatting(request, token));
// tslint:disable-next-line: no-floating-promises
this.serverClient.onRequestWithParams<SerializableOnTypeFormattingParams, SerializableFormattingResponse, any>(
this.onTypeFormattingRequestType,
async (request, token) => this.provideOnTypeFormatting(request, token));
}

private async provideFormatting(
Expand All @@ -39,6 +49,12 @@ export class FormattingHandler {
return this.emptyFormattingResponse;
}

const textDocument = await vscode.workspace.openTextDocument(razorDocumentUri);
const synchronized = await this.documentSynchronizer.trySynchronizeProjectedDocument(textDocument, razorDocument.csharpDocument, formattingParams.hostDocumentVersion, cancellationToken);
if (!synchronized) {
return this.emptyFormattingResponse;
}

const virtualHtmlUri = razorDocument.htmlDocument.uri;

const textEdits = await vscode.commands.executeCommand<vscode.TextEdit[]>(
Expand All @@ -50,24 +66,47 @@ export class FormattingHandler {
return this.emptyFormattingResponse;
}

const htmlDocText = razorDocument.htmlDocument.getContent();
const zeroBasedLineCount = this.countLines(htmlDocText);
const serializableTextEdits = Array<SerializableTextEdit>();
for (let textEdit of textEdits) {
// The below workaround is needed due to a bug on the HTML side where
// they'll sometimes send us an end position that exceeds the length
// of the document. Tracked by https://github.com/microsoft/vscode/issues/175298.
if (textEdit.range.end.line > zeroBasedLineCount) {
const lastLineLength = this.getLastLineLength(htmlDocText);
const updatedEndPosition = new vscode.Position(zeroBasedLineCount, lastLineLength);
const updatedRange = new vscode.Range(textEdit.range.start, updatedEndPosition);
textEdit = new vscode.TextEdit(updatedRange, textEdit.newText);
}
const serializableTextEdits = this.sanitizeTextEdits(razorDocument, textEdits);

return new SerializableFormattingResponse(serializableTextEdits);
} catch (error) {
this.logger.logWarning(`${FormattingHandler.provideFormattingEndpoint} failed with ${error}`);
}

const serializableTextEdit = convertTextEditToSerializable(textEdit);
serializableTextEdits.push(serializableTextEdit);
return this.emptyFormattingResponse;
}

private async provideOnTypeFormatting(
formattingParams: SerializableOnTypeFormattingParams,
cancellationToken: vscode.CancellationToken) {
try {
const razorDocumentUri = vscode.Uri.parse(formattingParams.textDocument.uri);
const razorDocument = await this.documentManager.getDocument(razorDocumentUri);
if (razorDocument === undefined) {
return this.emptyFormattingResponse;
}

const textDocument = await vscode.workspace.openTextDocument(razorDocumentUri);
const synchronized = await this.documentSynchronizer.trySynchronizeProjectedDocument(textDocument, razorDocument.csharpDocument, formattingParams.hostDocumentVersion, cancellationToken);
if (!synchronized) {
return this.emptyFormattingResponse;
}

const virtualHtmlUri = razorDocument.htmlDocument.uri;

const textEdits = await vscode.commands.executeCommand<vscode.TextEdit[]>(
'vscode.executeFormatOnTypeProvider',
virtualHtmlUri,
formattingParams.position,
formattingParams.ch,
formattingParams.options);

if (textEdits === undefined) {
return this.emptyFormattingResponse;
}

const serializableTextEdits = this.sanitizeTextEdits(razorDocument, textEdits);

return new SerializableFormattingResponse(serializableTextEdits);
} catch (error) {
this.logger.logWarning(`${FormattingHandler.provideFormattingEndpoint} failed with ${error}`);
Expand All @@ -76,6 +115,38 @@ export class FormattingHandler {
return this.emptyFormattingResponse;
}

private sanitizeTextEdits(razorDocument: IRazorDocument, textEdits: vscode.TextEdit[]) {
const htmlDocText = razorDocument.htmlDocument.getContent();
const zeroBasedLineCount = this.countLines(htmlDocText);
const serializableTextEdits = Array<SerializableTextEdit>();
for (let textEdit of textEdits) {
// The below workaround is needed due to a bug on the HTML side where
// they'll sometimes send us an end position that exceeds the length
// of the document. Tracked by https://github.com/microsoft/vscode/issues/175298.
if (textEdit.range.end.line > zeroBasedLineCount ||
textEdit.range.start.line > zeroBasedLineCount) {
const lastLineLength = this.getLastLineLength(htmlDocText);
const updatedPosition = new vscode.Position(zeroBasedLineCount, lastLineLength);

let start = textEdit.range.start;
let end = textEdit.range.end;
if (textEdit.range.start.line > zeroBasedLineCount) {
start = updatedPosition;
}

if (textEdit.range.end.line > zeroBasedLineCount) {
end = updatedPosition;
}
const updatedRange = new vscode.Range(start, end);
textEdit = new vscode.TextEdit(updatedRange, textEdit.newText);
}

const serializableTextEdit = convertTextEditToSerializable(textEdit);
serializableTextEdits.push(serializableTextEdit);
}
return serializableTextEdits;
}

private countLines(text: string) {
let lineCount = 0;
for (const i of text) {
Expand Down Expand Up @@ -103,4 +174,4 @@ export class FormattingHandler {

return currentLineLength;
}
}
}
15 changes: 0 additions & 15 deletions src/razor/src/Formatting/RazorDocumentRangeFormattingRequest.ts

This file was deleted.

11 changes: 0 additions & 11 deletions src/razor/src/Formatting/RazorDocumentRangeFormattingResponse.ts

This file was deleted.

19 changes: 0 additions & 19 deletions src/razor/src/Formatting/RazorFormatOnTypeProvider.ts

This file was deleted.

73 changes: 0 additions & 73 deletions src/razor/src/Formatting/RazorFormattingFeature.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/razor/src/Formatting/SerializableFormattingParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as vscode from 'vscode';
import { SerializableTextDocumentIdentifier } from './../RPC/SerializableTextDocumentIdentifier';

export interface SerializableFormattingParams {
hostDocumentVersion: number;
textDocument: SerializableTextDocumentIdentifier;
options: vscode.FormattingOptions;
}
16 changes: 16 additions & 0 deletions src/razor/src/Formatting/SerializableOnTypeFormattingParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* --------------------------------------------------------------------------------------------
* 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 { SerializablePosition } from '../RPC/SerializablePosition';
import { SerializableTextDocumentIdentifier } from './../RPC/SerializableTextDocumentIdentifier';

export interface SerializableOnTypeFormattingParams {
hostDocumentVersion: number;
textDocument: SerializableTextDocumentIdentifier;
ch: string;
position: SerializablePosition;
options: vscode.FormattingOptions;
}
13 changes: 1 addition & 12 deletions src/razor/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ import { reportTelemetryForDocuments } from './DocumentTelemetryListener';
import { DynamicFileInfoHandler } from './DynamicFile/DynamicFileInfoHandler';
import { FoldingRangeHandler } from './Folding/FoldingRangeHandler';
import { FormattingHandler } from './Formatting/FormattingHandler';
import { RazorFormatOnTypeProvider } from './Formatting/RazorFormatOnTypeProvider';
import { RazorFormattingFeature } from './Formatting/RazorFormattingFeature';
import { HostEventStream } from './HostEventStream';
import { RazorHoverProvider } from './Hover/RazorHoverProvider';
import { RazorHtmlFeature } from './Html/RazorHtmlFeature';
Expand Down Expand Up @@ -70,7 +68,6 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC
const htmlFeature = new RazorHtmlFeature(documentManager, languageServiceClient, eventEmitterFactory, logger);
const localRegistrations: vscode.Disposable[] = [];
const reportIssueCommand = new ReportIssueCommand(vscodeType, documentManager, logger);
const razorFormattingFeature = new RazorFormattingFeature(languageServerClient, documentManager, logger);
const razorCodeActionRunner = new RazorCodeActionRunner(languageServerClient, logger);
const codeActionsHandler = new CodeActionsHandler(documentManager, documentSynchronizer, languageServerClient, logger);

Expand Down Expand Up @@ -102,6 +99,7 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC
logger);
const formattingHandler = new FormattingHandler(
documentManager,
documentSynchronizer,
languageServerClient,
logger);

Expand Down Expand Up @@ -151,7 +149,6 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC
documentManager,
languageServiceClient,
logger);
const onTypeFormattingEditProvider = new RazorFormatOnTypeProvider();
const razorDiagnosticHandler = new RazorDiagnosticHandler(documentSynchronizer, languageServerClient, languageServiceClient, documentManager, logger);

localRegistrations.push(
Expand Down Expand Up @@ -186,13 +183,6 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC
vscodeType.languages.registerDocumentHighlightProvider(
RazorLanguage.id,
documentHighlightProvider),
// Our OnTypeFormatter doesn't do anything at the moment, but it's needed so
// VS Code doesn't throw an exception when it tries to send us an
// OnTypeFormatting request.
vscodeType.languages.registerOnTypeFormattingEditProvider(
RazorLanguage.documentSelector,
onTypeFormattingEditProvider,
''),
documentManager.register(),
csharpFeature.register(),
htmlFeature.register(),
Expand All @@ -206,7 +196,6 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC
await proposedApisFeature.register(vscodeType, localRegistrations);
}

razorFormattingFeature.register();
razorCodeActionRunner.register();
colorPresentationHandler.register();
documentColorHandler.register();
Expand Down

0 comments on commit 5995c10

Please sign in to comment.