From f63e1703f36a8397dcf51a7297f05ad867e89f37 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Mon, 12 Aug 2024 14:41:19 -0700 Subject: [PATCH 1/3] Fix handling files with non-Ascii characters by sending a TextDocumentIdentifier for dynamic file requests/responses --- src/lsptoolshost/roslynLanguageServer.ts | 11 ++++- .../services/projectContextService.ts | 4 +- src/lsptoolshost/uriConverter.ts | 2 +- .../src/dynamicFile/dynamicFileInfoHandler.ts | 45 +++++++++---------- .../dynamicFile/provideDynamicFileParams.ts | 5 ++- .../dynamicFile/provideDynamicFileResponse.ts | 5 ++- .../dynamicFile/removeDynamicFileParams.ts | 5 ++- 7 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 675c35d16..b46507392 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -66,6 +66,8 @@ import { getComponentPaths } from './builtInComponents'; import { OnAutoInsertFeature } from './onAutoInsertFeature'; import { registerLanguageStatusItems } from './languageStatusBar'; import { ProjectContextService } from './services/projectContextService'; +import { ProvideDynamicFileResponse } from '../razor/src/dynamicFile/provideDynamicFileResponse'; +import { ProvideDynamicFileParams } from '../razor/src/dynamicFile/provideDynamicFileParams'; let _channel: vscode.OutputChannel; let _traceChannel: vscode.OutputChannel; @@ -730,11 +732,16 @@ export class RoslynLanguageServer { }; } + private ProvideDyanmicFileInfoType: RequestType = + new RequestType(RoslynLanguageServer.provideRazorDynamicFileInfoMethodName); + private registerDynamicFileInfo() { // When the Roslyn language server sends a request for Razor dynamic file info, we forward that request along to Razor via // a command. - this._languageClient.onRequest(RoslynLanguageServer.provideRazorDynamicFileInfoMethodName, async (request) => - vscode.commands.executeCommand(DynamicFileInfoHandler.provideDynamicFileInfoCommand, request) + this._languageClient.onRequest( + this.ProvideDyanmicFileInfoType, + async (request) => + vscode.commands.executeCommand(DynamicFileInfoHandler.provideDynamicFileInfoCommand, request) ); this._languageClient.onNotification( RoslynLanguageServer.removeRazorDynamicFileInfoMethodName, diff --git a/src/lsptoolshost/services/projectContextService.ts b/src/lsptoolshost/services/projectContextService.ts index cb2d1621e..ddddba91a 100644 --- a/src/lsptoolshost/services/projectContextService.ts +++ b/src/lsptoolshost/services/projectContextService.ts @@ -85,10 +85,10 @@ export class ProjectContextService { private async getVirtualCSharpUri(uri: vscode.Uri): Promise { const response = await vscode.commands.executeCommand( DynamicFileInfoHandler.provideDynamicFileInfoCommand, - new ProvideDynamicFileParams([uri.fsPath]) + new ProvideDynamicFileParams({ uri: UriConverter.serialize(uri) }) ); - const responseUri = response.generatedFiles[0]; + const responseUri = response.csharpDocument?.uri; if (!responseUri) { return undefined; } diff --git a/src/lsptoolshost/uriConverter.ts b/src/lsptoolshost/uriConverter.ts index f212fda9e..88c648599 100644 --- a/src/lsptoolshost/uriConverter.ts +++ b/src/lsptoolshost/uriConverter.ts @@ -24,6 +24,6 @@ export class UriConverter { } public static deserialize(value: string): vscode.Uri { - return vscode.Uri.parse(value); + return vscode.Uri.parse(value, true); } } diff --git a/src/razor/src/dynamicFile/dynamicFileInfoHandler.ts b/src/razor/src/dynamicFile/dynamicFileInfoHandler.ts index f540a9433..b84afa81f 100644 --- a/src/razor/src/dynamicFile/dynamicFileInfoHandler.ts +++ b/src/razor/src/dynamicFile/dynamicFileInfoHandler.ts @@ -36,23 +36,21 @@ export class DynamicFileInfoHandler { } // Given Razor document URIs, returns associated generated doc URIs - private async provideDynamicFileInfo(request: ProvideDynamicFileParams): Promise { - const uris = request.razorFiles; - const virtualUris = new Array(); + private async provideDynamicFileInfo( + request: ProvideDynamicFileParams + ): Promise { + let virtualUri: DocumentUri | null = null; try { - for (const razorDocumentPath of uris) { - const vscodeUri = vscode.Uri.file(razorDocumentPath); - const razorDocument = await this.documentManager.getDocument(vscodeUri); - if (razorDocument === undefined) { - virtualUris.push(null); - this.logger.logWarning( - `Could not find Razor document ${razorDocumentPath}; adding null as a placeholder in URI array.` - ); - } else { - // Retrieve generated doc URIs for each Razor URI we are given - const virtualCsharpUri = UriConverter.serialize(razorDocument.csharpDocument.uri); - virtualUris.push(virtualCsharpUri); - } + const vscodeUri = vscode.Uri.parse(request.razorDocument.uri, true); + const razorDocument = await this.documentManager.getDocument(vscodeUri); + if (razorDocument === undefined) { + this.logger.logWarning( + `Could not find Razor document ${vscodeUri.fsPath}; adding null as a placeholder in URI array.` + ); + } else { + // Retrieve generated doc URIs for each Razor URI we are given + const virtualCsharpUri = UriConverter.serialize(razorDocument.csharpDocument.uri); + virtualUri = virtualCsharpUri; } this.documentManager.roslynActivated = true; @@ -64,17 +62,18 @@ export class DynamicFileInfoHandler { this.logger.logWarning(`${DynamicFileInfoHandler.provideDynamicFileInfoCommand} failed with ${error}`); } - return new ProvideDynamicFileResponse(virtualUris); + if (virtualUri) { + return new ProvideDynamicFileResponse({ uri: virtualUri }); + } + + return null; } private async removeDynamicFileInfo(request: RemoveDynamicFileParams) { try { - const uris = request.razorFiles; - for (const razorDocumentPath of uris) { - const vscodeUri = vscode.Uri.file(razorDocumentPath); - if (this.documentManager.isRazorDocumentOpenInCSharpWorkspace(vscodeUri)) { - this.documentManager.didCloseRazorCSharpDocument(vscodeUri); - } + const vscodeUri = UriConverter.deserialize(request.csharpDocument.uri); + if (this.documentManager.isRazorDocumentOpenInCSharpWorkspace(vscodeUri)) { + this.documentManager.didCloseRazorCSharpDocument(vscodeUri); } } catch (error) { this.logger.logWarning(`${DynamicFileInfoHandler.removeDynamicFileInfoCommand} failed with ${error}`); diff --git a/src/razor/src/dynamicFile/provideDynamicFileParams.ts b/src/razor/src/dynamicFile/provideDynamicFileParams.ts index 7674fd30e..58241b99b 100644 --- a/src/razor/src/dynamicFile/provideDynamicFileParams.ts +++ b/src/razor/src/dynamicFile/provideDynamicFileParams.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DocumentUri } from 'vscode-languageclient/node'; +import { TextDocumentIdentifier } from 'vscode-languageserver-protocol'; +// matches https://github.com/dotnet/roslyn/blob/9e91ca6590450e66e0041ee3135bbf044ac0687a/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs#L22 export class ProvideDynamicFileParams { - constructor(public readonly razorFiles: DocumentUri[]) {} + constructor(public readonly razorDocument: TextDocumentIdentifier) {} } diff --git a/src/razor/src/dynamicFile/provideDynamicFileResponse.ts b/src/razor/src/dynamicFile/provideDynamicFileResponse.ts index 5ada17002..7be8d1f01 100644 --- a/src/razor/src/dynamicFile/provideDynamicFileResponse.ts +++ b/src/razor/src/dynamicFile/provideDynamicFileResponse.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DocumentUri } from 'vscode-languageclient/node'; +import { TextDocumentIdentifier } from 'vscode-languageclient/node'; +// matches https://github.com/dotnet/roslyn/blob/9e91ca6590450e66e0041ee3135bbf044ac0687a/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs#L28 export class ProvideDynamicFileResponse { - constructor(public readonly generatedFiles: (DocumentUri | null)[]) {} + constructor(public readonly csharpDocument: TextDocumentIdentifier | null) {} } diff --git a/src/razor/src/dynamicFile/removeDynamicFileParams.ts b/src/razor/src/dynamicFile/removeDynamicFileParams.ts index d4cc3cf9a..279ee2414 100644 --- a/src/razor/src/dynamicFile/removeDynamicFileParams.ts +++ b/src/razor/src/dynamicFile/removeDynamicFileParams.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DocumentUri } from 'vscode-languageclient/node'; +import { TextDocumentIdentifier } from 'vscode-languageclient/node'; +// matches https://github.com/dotnet/roslyn/blob/9e91ca6590450e66e0041ee3135bbf044ac0687a/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs#L28 export class RemoveDynamicFileParams { - constructor(public readonly razorFiles: DocumentUri[]) {} + constructor(public readonly csharpDocument: TextDocumentIdentifier) {} } From bd5699c44c5ce5b08526084d1fc5f78ba49f55c0 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Tue, 13 Aug 2024 14:53:36 -0700 Subject: [PATCH 2/3] Bump Roslyn --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 06620ab3d..6fe6b4255 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ } }, "defaults": { - "roslyn": "4.12.0-2.24408.4", + "roslyn": "4.12.0-2.24413.3", "omniSharp": "1.39.11", "razor": "9.0.0-preview.24366.2", "razorOmnisharp": "7.0.0-preview.23363.1", From b7dd2ffe6ecd9e0b175c26fe4ffb941aee013272 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 13 Aug 2024 16:29:14 -0700 Subject: [PATCH 3/3] Update Roslyn again to 4.12.0-2.24413.5 --- CHANGELOG.md | 7 ++++++- package.json | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6153faae7..03684989d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,12 @@ - Debug from .csproj and .sln [#5876](https://github.com/dotnet/vscode-csharp/issues/5876) # Latest -* Bump Roslyn to 4.12.0-2.24408.4 (PR: [#7429](https://github.com/dotnet/vscode-csharp/pull/7429)) +* Fix handling Razor files with non-ascii characters (PR: [#7442](https://github.com/dotnet/vscode-csharp/pull/7442)) +* Bump Roslyn to 4.12.0-2.24413.5 (PR: [#7442](https://github.com/dotnet/vscode-csharp/pull/7442)) + * Fix URI comparisons for different casing (PR: [#74746](https://github.com/dotnet/roslyn/pull/74746)) + * Remove implicit unsafe cast in foreach(PR: [#74747](https://github.com/dotnet/roslyn/pull/74747)) + * Send a TextDocumentidentifier for razor dynamic file requests/responses (PR: [#74727](https://github.com/dotnet/roslyn/pull/74727)) + * Fix issues with VSCode LSP EA causing handlers to fail to load (PR: [#74700](https://github.com/dotnet/roslyn/pull/74700)) * Reduce allocations in SyntaxEquivalence.AreEquivalent by using a more appropriate pooling mechanism for the stack it uses to walk trees. (PR: [#74610](https://github.com/dotnet/roslyn/pull/74610)) * Reduce allocations in SyntaxNodeExtensions.GetMembers to instead execute a given lambda over the collection. (PR: [#74628](https://github.com/dotnet/roslyn/pull/74628)) * Modify ISyntaxFacts methods to allocate less (PR: [#74596](https://github.com/dotnet/roslyn/pull/74596)) diff --git a/package.json b/package.json index 6fe6b4255..372b8afa1 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ } }, "defaults": { - "roslyn": "4.12.0-2.24413.3", + "roslyn": "4.12.0-2.24413.5", "omniSharp": "1.39.11", "razor": "9.0.0-preview.24366.2", "razorOmnisharp": "7.0.0-preview.23363.1",