Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
# 2.76.x

# 2.75.x
* Bump Razor to 10.0.0-preview.25228.4 (PR: [#8225](https://github.com/dotnet/vscode-csharp/pull/8225))
* Don't return null if we couldn't sync the document for breakpoint validation (PR: [#11790](https://github.com/dotnet/razor/pull/11790))
* Add VS Code IMappingService (PR: [#11760](https://github.com/dotnet/razor/pull/11760))
* Fix cases where there is a space in the URI (PR: [#11745](https://github.com/dotnet/razor/pull/11745))
* Bump Roslyn to 5.0.0-1.25224.9 (PR: [#8211](https://github.com/dotnet/vscode-csharp/pull/8211))
* Update ICSharpCode.Decompiler to 9.1.0.7988(PR: [#78270](https://github.com/dotnet/roslyn/pull/78270))
* Reduce allocations in NamespaceSymbol.GetExtensionContainers(PR: [#78243](https://github.com/dotnet/roslyn/pull/78243))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"defaults": {
"roslyn": "5.0.0-1.25224.9",
"omniSharp": "1.39.12",
"razor": "10.0.0-preview.25228.3",
"razor": "10.0.0-preview.25228.4",
"razorOmnisharp": "7.0.0-preview.23363.1",
"xamlTools": "17.14.36010.33"
},
Expand Down
89 changes: 66 additions & 23 deletions src/lsptoolshost/razor/razorEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,51 +24,94 @@ import { DocumentColorHandler } from '../../razor/src/documentColor/documentColo
import { razorOptions } from '../../shared/options';
import { ColorPresentationHandler } from '../../razor/src/colorPresentation/colorPresentationHandler';
import { ColorPresentation } from 'vscode-html-languageservice';
import { DynamicFileInfoHandler } from '../../razor/src/dynamicFile/dynamicFileInfoHandler';
import { ProvideDynamicFileParams } from '../../razor/src/dynamicFile/provideDynamicFileParams';
import { ProvideDynamicFileResponse } from '../../razor/src/dynamicFile/provideDynamicFileResponse';
import { RazorMapSpansParams } from '../../razor/src/mapping/razorMapSpansParams';
import { RazorMapSpansResponse } from '../../razor/src/mapping/razorMapSpansResponse';
import { MappingHandler } from '../../razor/src/mapping/mappingHandler';
import { RazorMapTextChangesParams } from '../../razor/src/mapping/razorMapTextChangesParams';
import { RazorMapTextChangesResponse } from '../../razor/src/mapping/razorMapTextChangesResponse';

export function registerRazorEndpoints(
context: vscode.ExtensionContext,
languageServer: RoslynLanguageServer,
roslynLanguageServer: RoslynLanguageServer,
razorLogger: RazorLogger,
platformInfo: PlatformInformation
) {
const logNotificationType = new NotificationType<LogMessageParams>('razor/log');
languageServer.registerOnNotificationWithParams(logNotificationType, (params) =>
roslynLanguageServer.registerOnNotificationWithParams(logNotificationType, (params) =>
razorLogger.log(params.message, params.type)
);

if (!razorOptions.cohostingEnabled) {
return;
if (razorOptions.cohostingEnabled) {
registerCohostingEndpoints();
} else {
registerNonCohostingEndpoints();
}

const documentManager = new HtmlDocumentManager(platformInfo, razorLogger);
context.subscriptions.push(documentManager.register());
return;

registerRequestHandler<HtmlUpdateParameters, void>('razor/updateHtml', async (params) => {
const uri = UriConverter.deserialize(params.textDocument.uri);
await documentManager.updateDocumentText(uri, params.text);
});
//
// Local Functions
//
function registerCohostingEndpoints() {
const documentManager = new HtmlDocumentManager(platformInfo, razorLogger);
context.subscriptions.push(documentManager.register());

registerRequestHandler<DocumentColorParams, ColorInformation[]>(DocumentColorRequest.method, async (params) => {
const uri = UriConverter.deserialize(params.textDocument.uri);
const document = await documentManager.getDocument(uri);

return await DocumentColorHandler.doDocumentColorRequest(document.uri);
});
registerRequestHandler<HtmlUpdateParameters, void>('razor/updateHtml', async (params) => {
const uri = UriConverter.deserialize(params.textDocument.uri);
await documentManager.updateDocumentText(uri, params.text);
});

registerRequestHandler<ColorPresentationParams, ColorPresentation[]>(
ColorPresentationRequest.method,
async (params) => {
registerRequestHandler<DocumentColorParams, ColorInformation[]>(DocumentColorRequest.method, async (params) => {
const uri = UriConverter.deserialize(params.textDocument.uri);
const document = await documentManager.getDocument(uri);

return await ColorPresentationHandler.doColorPresentationRequest(document.uri, params);
}
);
return await DocumentColorHandler.doDocumentColorRequest(document.uri);
});

registerRequestHandler<ColorPresentationParams, ColorPresentation[]>(
ColorPresentationRequest.method,
async (params) => {
const uri = UriConverter.deserialize(params.textDocument.uri);
const document = await documentManager.getDocument(uri);

return await ColorPresentationHandler.doColorPresentationRequest(document.uri, params);
}
);
}

function registerNonCohostingEndpoints() {
registerRequestHandler<ProvideDynamicFileParams, ProvideDynamicFileResponse>(
'razor/provideDynamicFileInfo',
async (params) =>
vscode.commands.executeCommand(DynamicFileInfoHandler.provideDynamicFileInfoCommand, params)
);

registerRequestHandler<ProvideDynamicFileParams, ProvideDynamicFileResponse>(
'razor/removeDynamicFileInfo',
async (params) =>
vscode.commands.executeCommand(DynamicFileInfoHandler.provideDynamicFileInfoCommand, params)
);
registerRequestHandler<RazorMapSpansParams, RazorMapSpansResponse>('razor/mapSpans', async (params) => {
return await vscode.commands.executeCommand<RazorMapSpansResponse>(MappingHandler.MapSpansCommand, params);
});
registerRequestHandler<RazorMapTextChangesParams, RazorMapTextChangesResponse>(
'razor/mapTextChanges',
async (params) => {
return await vscode.commands.executeCommand<RazorMapTextChangesResponse>(
MappingHandler.MapChangesCommand,
params
);
}
);
}

// Helper method that registers a request handler, and logs errors to the Razor logger.
function registerRequestHandler<Params, Result>(method: string, invocation: (params: Params) => Promise<Result>) {
const requestType = new RequestType<Params, Result, Error>(method);
languageServer.registerOnRequest(requestType, async (params) => {
roslynLanguageServer.registerOnRequest(requestType, async (params) => {
try {
return await invocation(params);
} catch (error) {
Expand Down
12 changes: 12 additions & 0 deletions src/razor/src/document/razorDocumentManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ export class RazorDocumentManager implements IRazorDocumentManager {
return document;
}

public async getDocumentForCSharpUri(csharpUri: vscode.Uri): Promise<IRazorDocument | undefined> {
const csharpPath = csharpUri.fsPath ?? csharpUri.path;

return this.documents.find((document) => {
if (this.platformInfo.isLinux()) {
return document.csharpDocument.path === csharpPath;
}

return document.csharpDocument.path.localeCompare(csharpPath, undefined, { sensitivity: 'base' }) === 0;
});
}

public async getActiveDocument(): Promise<IRazorDocument | null> {
if (!vscode.window.activeTextEditor) {
return null;
Expand Down
28 changes: 16 additions & 12 deletions src/razor/src/dynamicFile/dynamicFileInfoHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { RazorDynamicFileChangedParams } from './dynamicFileUpdatedParams';
import { TextDocumentIdentifier } from 'vscode-languageserver-protocol';
import { razorTextChange } from './razorTextChange';
import { razorTextSpan } from './razorTextSpan';
import { razorOptions } from '../../../shared/options';

// Handles Razor generated doc communication between the Roslyn workspace and Razor.
// didChange behavior for Razor generated docs is handled in the RazorDocumentManager.
Expand All @@ -39,18 +40,21 @@ export class DynamicFileInfoHandler {
await this.removeDynamicFileInfo(request);
}
);
this.documentManager.onChange(async (e) => {
// Ignore any updates without text changes. This is important for perf since sending an update to roslyn does
// a round trip for producing nothing new and causes a lot of churn in solution updates.
if (e.kind == RazorDocumentChangeKind.csharpChanged && !e.document.isOpen && e.changes.length > 0) {
const uriString = UriConverter.serialize(e.document.uri);
const identifier = TextDocumentIdentifier.create(uriString);
await vscode.commands.executeCommand(
DynamicFileInfoHandler.dynamicFileUpdatedCommand,
new RazorDynamicFileChangedParams(identifier)
);
}
});

if (!razorOptions.cohostingEnabled) {
this.documentManager.onChange(async (e) => {
// Ignore any updates without text changes. This is important for perf since sending an update to roslyn does
// a round trip for producing nothing new and causes a lot of churn in solution updates.
if (e.kind == RazorDocumentChangeKind.csharpChanged && !e.document.isOpen && e.changes.length > 0) {
const uriString = UriConverter.serialize(e.document.uri);
const identifier = TextDocumentIdentifier.create(uriString);
await vscode.commands.executeCommand(
DynamicFileInfoHandler.dynamicFileUpdatedCommand,
new RazorDynamicFileChangedParams(identifier)
);
}
});
}
}

// Given Razor document URIs, returns associated generated doc URIs
Expand Down
8 changes: 6 additions & 2 deletions src/razor/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { InlayHintHandler } from './inlayHint/inlayHintHandler';
import { InlayHintResolveHandler } from './inlayHint/inlayHintResolveHandler';
import { getComponentPaths } from '../../lsptoolshost/extensions/builtInComponents';
import { BlazorDebugConfigurationProvider } from './blazorDebug/blazorDebugConfigurationProvider';
import { MappingHandler } from './mapping/mappingHandler';

// We specifically need to take a reference to a particular instance of the vscode namespace,
// otherwise providers attempt to operate on the null extension.
Expand Down Expand Up @@ -123,15 +124,15 @@ export async function activate(
logger
);

const languageServiceClient = new RazorLanguageServiceClient(languageServerClient);

const documentManager = new RazorDocumentManager(
languageServerClient,
logger,
razorTelemetryReporter,
platformInfo
);

const languageServiceClient = new RazorLanguageServiceClient(languageServerClient, documentManager);

const documentSynchronizer = new RazorDocumentSynchronizer(documentManager, logger);
reportTelemetryForDocuments(documentManager, razorTelemetryReporter);
const languageConfiguration = new RazorLanguageConfiguration();
Expand Down Expand Up @@ -261,6 +262,8 @@ export async function activate(
logger
);

const mappingHandler = new MappingHandler(languageServiceClient);

localRegistrations.push(
languageConfiguration.register(),
vscodeType.languages.registerSignatureHelpProvider(RazorLanguage.id, signatureHelpProvider, '(', ','),
Expand Down Expand Up @@ -298,6 +301,7 @@ export async function activate(
completionHandler.register(),
razorSimplifyMethodHandler.register(),
razorFormatNewFileHandler.register(),
mappingHandler.register(),
]);
});

Expand Down
32 changes: 32 additions & 0 deletions src/razor/src/mapping/mappingHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* 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 { RazorLanguageServiceClient } from '../razorLanguageServiceClient';
import { RazorMapSpansParams } from './razorMapSpansParams';
import { RazorMapTextChangesParams } from './razorMapTextChangesParams';

export class MappingHandler {
public static readonly MapSpansCommand = 'razor.mapSpansCommand';
public static readonly MapChangesCommand = 'razor.mapChangesCommand';

constructor(private readonly languageServiceClient: RazorLanguageServiceClient) {}

public async register(): Promise<vscode.Disposable> {
return vscode.Disposable.from(
...[
vscode.commands.registerCommand(MappingHandler.MapSpansCommand, async (params: RazorMapSpansParams) => {
return this.languageServiceClient.mapSpans(params);
}),
vscode.commands.registerCommand(
MappingHandler.MapChangesCommand,
async (params: RazorMapTextChangesParams) => {
return this.languageServiceClient.mapTextChanges(params);
}
),
]
);
}
}
2 changes: 1 addition & 1 deletion src/razor/src/mapping/mappingHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { RazorLanguageServiceClient } from '../razorLanguageServiceClient';
import { RazorLogger } from '../razorLogger';

export class MappingHelpers {
public readonly language = 'Razor';
public static readonly language = 'Razor';

public static async remapGeneratedFileWorkspaceEdit(
workspaceEdit: vscode.WorkspaceEdit,
Expand Down
11 changes: 11 additions & 0 deletions src/razor/src/mapping/razorMapSpansParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { Range, TextDocumentIdentifier } from 'vscode-languageserver-protocol';

// Matches https://github.com/dotnet/razor/blob/main/src/Razor/src/Microsoft.VisualStudioCode.RazorExtension/Services/RazorMapSpansParams.cs
export class RazorMapSpansParams {
constructor(public readonly csharpDocument: TextDocumentIdentifier, public readonly ranges: Range[]) {}
}
19 changes: 19 additions & 0 deletions src/razor/src/mapping/razorMapSpansResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { TextDocumentIdentifier } from 'vscode-languageserver-types';
import { razorTextSpan } from '../dynamicFile/razorTextSpan';
import { SerializableRange } from '../rpc/serializableRange';

// matches https://github.com/dotnet/razor/blob/main/src/Razor/src/Microsoft.VisualStudioCode.RazorExtension/Services/RazorMapSpansResponse.cs
export class RazorMapSpansResponse {
static empty: RazorMapSpansResponse = new RazorMapSpansResponse([], [], { uri: '' });

constructor(
public readonly ranges: SerializableRange[],
public readonly spans: razorTextSpan[],
public readonly razorDocument: TextDocumentIdentifier
) {}
}
14 changes: 14 additions & 0 deletions src/razor/src/mapping/razorMapTextChangesParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TextDocumentIdentifier } from 'vscode-languageserver-types';
import { razorTextChange } from '../dynamicFile/razorTextChange';

// Matches https://github.com/dotnet/razor/blob/401f6f8632a7e0320bc12804fa7e9659b3b3aeab/src/Razor/src/Microsoft.VisualStudioCode.RazorExtension/Services/RazorMapTextChangesParams.cs
export class RazorMapTextChangesParams {
constructor(
public readonly csharpDocument: TextDocumentIdentifier,
public readonly textChanges: razorTextChange[]
) {}
}
15 changes: 15 additions & 0 deletions src/razor/src/mapping/razorMapTextChangesResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TextDocumentIdentifier } from 'vscode-languageserver-types';
import { razorTextChange } from '../dynamicFile/razorTextChange';

// Matches https://github.com/dotnet/razor/blob/401f6f8632a7e0320bc12804fa7e9659b3b3aeab/src/Razor/src/Microsoft.VisualStudioCode.RazorExtension/Services/RazorMapTextChangesResponse.cs
export class RazorMapTextChangesResponse {
static empty: RazorMapTextChangesResponse | PromiseLike<RazorMapTextChangesResponse>;
constructor(
public readonly razorDocument: TextDocumentIdentifier,
public readonly textChanges: razorTextChange[]
) {}
}
16 changes: 16 additions & 0 deletions src/razor/src/mapping/razorMapToDocumentEditsParams.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 { Uri } from 'vscode';
import { razorTextChange } from '../dynamicFile/razorTextChange';
import { LanguageKind } from '../rpc/languageKind';

// Matches https://github.com/dotnet/razor/blob/401f6f8632a7e0320bc12804fa7e9659b3b3aeab/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/DocumentMapping/RazorMapToDocumentEditsParams.cs
export class RazorMapToDocumentEditsParams {
constructor(
public readonly kind: LanguageKind,
public readonly razorDocumentUri: Uri,
public readonly textChanges: razorTextChange[]
) {}
}
10 changes: 10 additions & 0 deletions src/razor/src/mapping/razorMapToDocumentEditsResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { razorTextChange } from '../dynamicFile/razorTextChange';

// Matches https://github.com/dotnet/razor/blob/401f6f8632a7e0320bc12804fa7e9659b3b3aeab/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/DocumentMapping/RazorMapToDocumentEditsResponse.cs
export class RazorMapToDocumentEditsResponse {
constructor(public readonly textChanges: razorTextChange[], public readonly hostDocumentVersion: number) {}
}
Loading
Loading