From b8a3c26bd6e1e4cb3e865e001182b7016dc2e06f Mon Sep 17 00:00:00 2001 From: David Barbet Date: Wed, 15 Nov 2023 17:49:17 -0800 Subject: [PATCH 1/5] Enable automatic nuget restore on the client --- package.json | 5 +++++ src/lsptoolshost/restore.ts | 28 ++++++++++++++++++------ src/lsptoolshost/roslynLanguageServer.ts | 8 +++++++ src/lsptoolshost/roslynProtocol.ts | 19 +++++++++++++--- src/main.ts | 2 +- 5 files changed, 51 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 3f78bee94..5180ede6f 100644 --- a/package.json +++ b/package.json @@ -1742,6 +1742,11 @@ "default": null, "description": "Sets a path where MSBuild binary logs are written to when loading projects, to help diagnose loading errors." }, + "dotnet.projects.enableAutomaticRestore": { + "type": "boolean", + "default": true, + "description": "Sets whether or not automatic nuget restore is enabled if the project system detects assets are missing." + }, "razor.languageServer.directory": { "type": "string", "scope": "machine-overridable", diff --git a/src/lsptoolshost/restore.ts b/src/lsptoolshost/restore.ts index 6cf34697e..0b6075714 100644 --- a/src/lsptoolshost/restore.ts +++ b/src/lsptoolshost/restore.ts @@ -5,7 +5,13 @@ import * as vscode from 'vscode'; import { RoslynLanguageServer } from './roslynLanguageServer'; -import { RestorableProjects, RestoreParams, RestorePartialResult, RestoreRequest } from './roslynProtocol'; +import { + RestorableProjects, + RestoreParams, + RestorePartialResult, + RestoreRequest, + UnresolvedProjectDependenciesNotification, +} from './roslynProtocol'; import path = require('path'); let _restoreInProgress = false; @@ -22,10 +28,15 @@ export function registerRestoreCommands( ); context.subscriptions.push( vscode.commands.registerCommand('dotnet.restore.all', async (): Promise => { - return restore(languageServer, restoreChannel); + return restore(languageServer, restoreChannel, [], true); }) ); + + languageServer.registerOnRequest(UnresolvedProjectDependenciesNotification.type, async (params) => { + await restore(languageServer, restoreChannel, params.projectFilePaths, false); + }); } + async function chooseProjectAndRestore( languageServer: RoslynLanguageServer, restoreChannel: vscode.OutputChannel @@ -49,22 +60,25 @@ async function chooseProjectAndRestore( return; } - await restore(languageServer, restoreChannel, pickedItem.description); + await restore(languageServer, restoreChannel, [pickedItem.description!], true); } -async function restore( +export async function restore( languageServer: RoslynLanguageServer, restoreChannel: vscode.OutputChannel, - projectFile?: string + projectFiles: string[], + showOutput: boolean ): Promise { if (_restoreInProgress) { vscode.window.showErrorMessage(vscode.l10n.t('Restore already in progress')); return; } _restoreInProgress = true; - restoreChannel.show(true); + if (showOutput) { + restoreChannel.show(true); + } - const request: RestoreParams = { projectFilePath: projectFile }; + const request: RestoreParams = { projectFilePaths: projectFiles }; await vscode.window .withProgress( { diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 38cc801a4..176167149 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -27,6 +27,7 @@ import { MessageTransports, RAL, CancellationToken, + RequestHandler, } from 'vscode-languageclient/node'; import { PlatformInformation } from '../shared/platform'; import { readConfigurations } from './configurationMiddleware'; @@ -319,6 +320,13 @@ export class RoslynLanguageServer { return response; } + public registerOnRequest( + type: RequestType, + handler: RequestHandler + ) { + this._languageClient.addDisposable(this._languageClient.onRequest(type, handler)); + } + public async registerSolutionSnapshot(token: vscode.CancellationToken): Promise { const response = await this.sendRequest0(RoslynProtocol.RegisterSolutionSnapshotRequest.type, token); if (response) { diff --git a/src/lsptoolshost/roslynProtocol.ts b/src/lsptoolshost/roslynProtocol.ts index 2d58906c1..0d7fa8eda 100644 --- a/src/lsptoolshost/roslynProtocol.ts +++ b/src/lsptoolshost/roslynProtocol.ts @@ -152,10 +152,10 @@ export interface NamedPipeInformation { export interface RestoreParams extends lsp.WorkDoneProgressParams, lsp.PartialResultParams { /** - * An optional file path to restore. - * If none is specified, the solution (or all loaded projects) are restored. + * The set of projects to restore. + * If none are specified, the solution (or all loaded projects) are restored. */ - projectFilePath?: string; + projectFilePaths: string[]; } export interface RestorePartialResult { @@ -163,6 +163,13 @@ export interface RestorePartialResult { message: string; } +export interface UnresolvedProjectDependenciesParams { + /** + * The set of projects that have unresolved dependencies and require a restore. + */ + projectFilePaths: string[]; +} + export namespace WorkspaceDebugConfigurationRequest { export const method = 'workspace/debugConfiguration'; export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer; @@ -260,3 +267,9 @@ export namespace RestorableProjects { export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer; export const type = new lsp.RequestType0(method); } + +export namespace UnresolvedProjectDependenciesNotification { + export const method = 'workspace/_roslyn_unresolvedProjectDependencies'; + export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.serverToClient; + export const type = new lsp.RequestType(method); +} diff --git a/src/main.ts b/src/main.ts index 7998132bd..07899f3e1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -83,9 +83,9 @@ export async function activate( // ensure it gets properly disposed. Upon disposal the events will be flushed. context.subscriptions.push(reporter); - const csharpChannel = vscode.window.createOutputChannel('C#'); const dotnetTestChannel = vscode.window.createOutputChannel('.NET Test Log'); const dotnetChannel = vscode.window.createOutputChannel('.NET NuGet Restore'); + const csharpChannel = vscode.window.createOutputChannel('C#'); const csharpchannelObserver = new CsharpChannelObserver(csharpChannel); const csharpLogObserver = new CsharpLoggerObserver(csharpChannel); eventStream.subscribe(csharpchannelObserver.post); From 4f20608cfe21c2bc5d04bcfa7d876aa4be5aa93a Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 28 Nov 2023 13:38:03 -0800 Subject: [PATCH 2/5] Review feedback --- src/lsptoolshost/restore.ts | 4 ++-- src/lsptoolshost/roslynProtocol.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lsptoolshost/restore.ts b/src/lsptoolshost/restore.ts index 0b6075714..3a20664f9 100644 --- a/src/lsptoolshost/restore.ts +++ b/src/lsptoolshost/restore.ts @@ -10,7 +10,7 @@ import { RestoreParams, RestorePartialResult, RestoreRequest, - UnresolvedProjectDependenciesNotification, + ProjectHasUnresolvedDependenciesNotification, } from './roslynProtocol'; import path = require('path'); @@ -32,7 +32,7 @@ export function registerRestoreCommands( }) ); - languageServer.registerOnRequest(UnresolvedProjectDependenciesNotification.type, async (params) => { + languageServer.registerOnRequest(ProjectHasUnresolvedDependenciesNotification.type, async (params) => { await restore(languageServer, restoreChannel, params.projectFilePaths, false); }); } diff --git a/src/lsptoolshost/roslynProtocol.ts b/src/lsptoolshost/roslynProtocol.ts index 0d7fa8eda..7e734ca26 100644 --- a/src/lsptoolshost/roslynProtocol.ts +++ b/src/lsptoolshost/roslynProtocol.ts @@ -268,8 +268,8 @@ export namespace RestorableProjects { export const type = new lsp.RequestType0(method); } -export namespace UnresolvedProjectDependenciesNotification { - export const method = 'workspace/_roslyn_unresolvedProjectDependencies'; +export namespace ProjectHasUnresolvedDependenciesNotification { + export const method = 'workspace/_roslyn_projectHasUnresolvedDependencies'; export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.serverToClient; export const type = new lsp.RequestType(method); } From 19828dbb89e91d2b0aa6ed53f9fc519f77461461 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 4 Dec 2023 14:20:25 -0800 Subject: [PATCH 3/5] More localization --- package.json | 2 +- package.nls.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5180ede6f..99d0a1585 100644 --- a/package.json +++ b/package.json @@ -1745,7 +1745,7 @@ "dotnet.projects.enableAutomaticRestore": { "type": "boolean", "default": true, - "description": "Sets whether or not automatic nuget restore is enabled if the project system detects assets are missing." + "description": "%configuration.dotnet.projects.enableAutomaticRestore%" }, "razor.languageServer.directory": { "type": "string", diff --git a/package.nls.json b/package.nls.json index fedc83a97..1e3deecef 100644 --- a/package.nls.json +++ b/package.nls.json @@ -31,6 +31,7 @@ "configuration.dotnet.server.trace": "Sets the logging level for the language server", "configuration.dotnet.server.extensionPaths": "Override for path to language server --extension arguments", "configuration.dotnet.server.crashDumpPath": "Sets a folder path where crash dumps are written to if the language server crashes. Must be writeable by the user.", + "configuration.dotnet.projects.enableAutomaticRestore": "Enables automatic NuGet restore if the extension detects assets are missing.", "configuration.dotnet.preferCSharpExtension": "Forces projects to load with the C# extension only. This can be useful when using legacy project types that are not supported by C# Dev Kit. (Requires window reload)", "configuration.dotnet.implementType.insertionBehavior": "The insertion location of properties, events, and methods When implement interface or abstract class.", "configuration.dotnet.implementType.insertionBehavior.withOtherMembersOfTheSameKind": "Place them with other members of the same kind.", From 2325fae8005c70bcb9a85aec7a1a362e42cd88ab Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 4 Dec 2023 14:40:59 -0800 Subject: [PATCH 4/5] Rename --- src/lsptoolshost/restore.ts | 4 ++-- src/lsptoolshost/roslynProtocol.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lsptoolshost/restore.ts b/src/lsptoolshost/restore.ts index 3a20664f9..1aa32cdb0 100644 --- a/src/lsptoolshost/restore.ts +++ b/src/lsptoolshost/restore.ts @@ -10,7 +10,7 @@ import { RestoreParams, RestorePartialResult, RestoreRequest, - ProjectHasUnresolvedDependenciesNotification, + ProjectHasUnresolvedDependenciesRequest, } from './roslynProtocol'; import path = require('path'); @@ -32,7 +32,7 @@ export function registerRestoreCommands( }) ); - languageServer.registerOnRequest(ProjectHasUnresolvedDependenciesNotification.type, async (params) => { + languageServer.registerOnRequest(ProjectHasUnresolvedDependenciesRequest.type, async (params) => { await restore(languageServer, restoreChannel, params.projectFilePaths, false); }); } diff --git a/src/lsptoolshost/roslynProtocol.ts b/src/lsptoolshost/roslynProtocol.ts index 7e734ca26..70fba0a01 100644 --- a/src/lsptoolshost/roslynProtocol.ts +++ b/src/lsptoolshost/roslynProtocol.ts @@ -268,7 +268,7 @@ export namespace RestorableProjects { export const type = new lsp.RequestType0(method); } -export namespace ProjectHasUnresolvedDependenciesNotification { +export namespace ProjectHasUnresolvedDependenciesRequest { export const method = 'workspace/_roslyn_projectHasUnresolvedDependencies'; export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.serverToClient; export const type = new lsp.RequestType(method); From bd054288de2d7ba00f38aed6d3dfeec514c2d449 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Mon, 4 Dec 2023 17:06:49 -0800 Subject: [PATCH 5/5] Update Roslyn version --- CHANGELOG.md | 11 ++++++++++- package.json | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5abb2224d..a712c3eb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,16 @@ - [O# Parity] Nuget restore [#5725](https://github.com/dotnet/vscode-csharp/issues/5725) - Debug from .csproj and .sln [#5876](https://github.com/dotnet/vscode-csharp/issues/5876) -## Latest +## 2.12.19 +* Update Roslyn to 4.9.0-3.23604.10 (PR: [#6676](https://github.com/dotnet/vscode-csharp/pull/6676)) + * Pass through folders for additional files (PR: [#71061](https://github.com/dotnet/roslyn/pull/71061)) + * Automatically detect missing NuGet packages and restore (PR: [#70851](https://github.com/dotnet/roslyn/pull/70851)) + * Enable route embedded language features in vscode (PR: [#70927](https://github.com/dotnet/roslyn/pull/70927)) +* Add automatic nuget restore support to C# standalone (PR: [#6676](https://github.com/dotnet/vscode-csharp/pull/6676)) +* Update required VSCode version to 1.75.0 (PR: [#6711](https://github.com/dotnet/vscode-csharp/pull/6711)) +* Update debugger docs to point to official documentation (PR: [#6674](https://github.com/dotnet/vscode-csharp/pull/6674)) + +## 2.12.19 * Update Roslyn to 4.9.0-2.23563.2 (PR: [#6664](https://github.com/dotnet/vscode-csharp/pull/6664)) * Implement textDocument/prepareRename to show error in invalid rename locations (PR: [#70724](https://github.com/dotnet/roslyn/pull/70724)) * Improve Hover markdown on 'await' keyword (PR: [#70629](https://github.com/dotnet/roslyn/pull/70629)) diff --git a/package.json b/package.json index 99d0a1585..09e552b1e 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ } }, "defaults": { - "roslyn": "4.9.0-2.23571.2", + "roslyn": "4.9.0-3.23604.10", "omniSharp": "1.39.10", "razor": "7.0.0-preview.23528.1", "razorOmnisharp": "7.0.0-preview.23363.1",