diff --git a/CHANGELOG.md b/CHANGELOG.md index 81dfd0730..f9b854c47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ - Debug from .csproj and .sln [#5876](https://github.com/dotnet/vscode-csharp/issues/5876) ## Latest +* 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.23571.2 (PR: [#6681](https://github.com/dotnet/vscode-csharp/pull/6681)) * Workaround vscode bug with returning defaultBehavior from prepareRename (PR: [#70840](https://github.com/dotnet/roslyn/pull/70840)) * Implement textDocument/prepareRename to show error in invalid rename locations (PR: [#70724](https://github.com/dotnet/roslyn/pull/70724)) diff --git a/package.json b/package.json index d8b32a05c..33e56d9db 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", @@ -1731,6 +1731,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": "%configuration.dotnet.projects.enableAutomaticRestore%" + }, "razor.languageServer.directory": { "type": "string", "scope": "machine-overridable", 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.", diff --git a/src/lsptoolshost/restore.ts b/src/lsptoolshost/restore.ts index 6cf34697e..1aa32cdb0 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, + ProjectHasUnresolvedDependenciesRequest, +} 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(ProjectHasUnresolvedDependenciesRequest.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..70fba0a01 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 ProjectHasUnresolvedDependenciesRequest { + export const method = 'workspace/_roslyn_projectHasUnresolvedDependencies'; + 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);