Skip to content

Commit c3f7c03

Browse files
authored
Merge pull request #6824 from dibarbet/snap_main
Snap main to release
2 parents bcdc565 + 8aba1b0 commit c3f7c03

12 files changed

+642
-105
lines changed

CHANGELOG.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
## Known Issues
22

3-
- In version 2.15.30 only, .NET 6.0 projects fail to load if only the 6.0 SDK is installed [#6801](https://github.com/dotnet/vscode-csharp/issues/6801)
4-
- If you are trying to load a project that uses the 6.0 SDK, and you do not have any higher SDKs installed, you might get an error message like "Exception thrown while loading (project name) System.Exception: The server disconnected unexpectedly." In that case, try installing a 7.0 SDK as well, which should mitigate the issue. Other workarounds are available in the bug link if needed.
53
- Diagnostics related feature requests and improvements [#5951](https://github.com/dotnet/vscode-csharp/issues/5951)
6-
- [O# Parity] Nested code code action support for code fixes and refactorings [#5735](https://github.com/dotnet/vscode-csharp/issues/5735)
7-
- [O# Parity] Nuget restore [#5725](https://github.com/dotnet/vscode-csharp/issues/5725)
84
- Debug from .csproj and .sln [#5876](https://github.com/dotnet/vscode-csharp/issues/5876)
95

6+
## Latest
7+
* Update Roslyn to 4.10.0-1.24069.13 (PR: [#6823](https://github.com/dotnet/vscode-csharp/pull/6823))
8+
* Fix request metric logging (PR: [#71734](https://github.com/dotnet/roslyn/pull/71734))
9+
* Fix issue loading .NET 6.0 projects when only the 6.0 SDK is installed (PR: [#71597](https://github.com/dotnet/roslyn/pull/71597))
10+
1011
## 2.15.30
1112
* Update Roslyn to 4.10.0-1.24058.1 (PR: [#6791](https://github.com/dotnet/vscode-csharp/pull/6791))
1213
* Fix error when a source generated file was present in find references or go to definition requests (PR: [#71395](https://github.com/dotnet/roslyn/pull/71395))

CONTRIBUTING.md

Lines changed: 124 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,150 @@
1-
## Local development
1+
## Table of Contents
22

3-
### Pre-requisites
3+
- [Setting Up Local Development Environment](#setting-up-local-development-environment)
4+
- [Prerequisites for Development](#prerequisites-for-development)
5+
- [Building, Running, and Testing the Repository](#building-running-and-testing-the-repository)
6+
- [Setting Up Local Language Servers](#setting-up-local-language-servers)
7+
- [Roslyn](#roslyn)
8+
- [Razor](#razor)
9+
- [Debugging Local Language Servers](#debugging-local-language-servers)
10+
- [Configuring Local Language Servers](#configuring-local-language-servers)
11+
- [Finding the `settings.json` file for your workspace](#finding-the-settingsjson-file-for-your-workspace)
12+
- [Configuring Roslyn Language Server](#configuring-roslyn-language-server)
13+
- [Configuring Razor Language Server](#configuring-razor-language-server)
14+
- [Creating VSIX Packages for the Extension](#creating-vsix-packages-for-the-extension)
15+
- [Updating the `Roslyn` Language Server Version](#updating-the-roslyn-language-server-version)
416

5-
First install:
17+
## Setting Up Local Development Environment
18+
19+
Setting up your local development environment for the vscode-csharp repository involves several steps. This guide will walk you through the process.
20+
21+
### Prerequisites for Development
22+
23+
Before you start, make sure you have the following software installed on your machine:
624

725
* Node.js ([v18.17.0 LTS](https://nodejs.org/en/blog/release/v18.17.0) is recommended).
826
* Npm (The version shipped with node is fine)
927
* .NET 7.0 SDK (dotnet should be on your path)
1028

11-
### Build and run the extension
29+
Once you have these installed, you can navigate to the cloned vscode-csharp repository to proceed with building, running, and testing the repository.
30+
31+
### Building, Running, and Testing the Repository
32+
33+
Follow these steps to build, run, and test the repository:
34+
35+
#### Building
36+
37+
1. Run `npm i` - This command installs the project dependencies.
38+
2. Run `npm i -g gulp` - This command installs Gulp globally.
39+
3. Run `gulp installDependencies` - This command downloads the various dependencies as specified by the version in the [package.json](package.json) file.
40+
4. Run `code .` - This command opens the project in Visual Studio Code.
41+
42+
#### Running
43+
44+
After completing the build steps:
45+
46+
1. Run `npm run watch` (Optional) - This command watches for code changes.
47+
2. Press <kbd>Ctrl+Shift+D</kbd> to open the Run view in VS Code and ensure `Launch Extension` is selected.
48+
3. Start debugging by pressing <kbd>F5</kbd>.
49+
50+
#### Testing
51+
52+
To run tests:
53+
54+
1. Execute `npm run test` or press <kbd>F5</kbd> in VS Code with the "Launch Tests" debug configuration selected.
55+
2. For integration tests, select either of the two 'current file' integration tests (one for roslyn and one for razor), from the drop-down and press <kbd>F5</kbd> to start debugging:
56+
- For Roslyn Server: `Launch Current File slnWithCsproj Integration Tests`
57+
- For Razor Server: `Launch Current File BasicRazorApp2_1 Integration Tests`
58+
59+
These will allow you to actually debug the test, but the 'Razor integration tests' configuration does not.
60+
61+
### Setting Up Local Language Servers
62+
63+
This section shows how to set up local Razor or Roslyn language servers for debugging with the VSCode C# extension.
64+
65+
#### Roslyn
66+
67+
1. Clone the [Roslyn repository](https://github.com/dotnet/roslyn). This repository contains the Roslyn server implementation.
68+
2. Follow the build instructions provided in the repository.
69+
70+
The server DLL is typically at `$roslynRepoRoot/artifacts/bin/Microsoft.CodeAnalysis.LanguageServer/Debug/net7.0/Microsoft.CodeAnalysis.LanguageServer.dll`, but this may vary based on the built configuration.
71+
72+
#### Razor
73+
74+
1. Clone the [Razor repository](https://github.com/dotnet/razor). This repository contains the Razor server implementation.
75+
2. Follow the build instructions provided in the repository.
76+
77+
The server DLL is typically at `$razorRepoRoot/artifacts/bin/rzls/Debug/net8.0`.
78+
79+
### Debugging Local Language Servers
80+
81+
Before running the language servers, familiarize yourself with the steps in the [Configuring Local Language Servers](#configuring-local-language-servers) section to configure either the Roslyn or Razor language servers for debugging .
82+
83+
**Note**: You would only need to configure this for the workspace you wish to debug, NOT for the repo root of vscode-csharp repo.
84+
85+
Follow these steps to enable debugging:
86+
87+
1. Press `Ctrl+Shift+D` and then `F5` to launch the extension. This will open a new VS Code instance for `vscode-csharp` repo.
88+
2. In the new VS Code instance, open the project or solution you want to debug.
89+
3. Follow instructions in [Configuring Local Language Servers](#configuring-local-language-servers) to find and configure the workspace settings for the language server you want to debug.
90+
4. Ensure the language server is fully built in Debug mode.
91+
5. Meanwhile in a Visual Studio instance open the `.sln` solution file for the language server you want to debug. Keep this instance open for use in a later step.
92+
6. Back on VS Code, press `Ctrl+Shift+P` and select `Reload Window`. This ensures the changes made in step 3 are applied.
93+
7. After reloading, a window will pop up prompting you to select or open a Visual Studio instance. Now, select the instance you opened in step 5.
94+
8. The language server will now trigger a breakpoint on `Debugger.Launch()` when it starts.
95+
96+
### Configuring Local Language Servers
97+
98+
This section provides instructions on how to debug locally built Roslyn and Razor language servers. You can do this by either directly editing the `settings.json` file of your workspace or through the VSCode settings interface.
1299

13-
To run and develop the extension do the following:
100+
#### Finding the `settings.json` file for your workspace
101+
- Open the Command Palette with `Ctrl+Shift+P` (or `Cmd+Shift+P` on macOS)
102+
- Type "Preferences: Open Workspace Settings"
103+
- Select the option that appears.
104+
- In the Workspace Settings tab, in the upper right corner, you'll see an icon that looks like a document with an arrow, which is the "Open Settings (JSON)" button.
105+
- Click on this button to open the `settings.json` file.
14106

15-
* Run `npm i`
16-
* Run `npm i -g gulp`
17-
* Run `gulp installDependencies` (this will download the various dependencies as specified by the version in the [package.json](package.json))
18-
* Open in Visual Studio Code (`code .`)
19-
* _Optional:_ run `npm run watch`, make code changes
20-
* Press <kbd>F5</kbd> to debug
107+
#### Configuring Roslyn Language Server
21108

22-
To **test** do the following: `npm run test` or <kbd>F5</kbd> in VS Code with the "Launch Tests" debug configuration.
109+
In your workspace `settings.json` file, add the following lines:
23110

24-
### Using a locally developed Roslyn server
111+
```json
112+
"dotnet.server.waitForDebugger": true,
113+
"dotnet.server.path": "<roslynRepoRoot>/artifacts/bin/Microsoft.CodeAnalysis.LanguageServer/Debug/net7.0/Microsoft.CodeAnalysis.LanguageServer.dll"
114+
```
25115

26-
https://github.com/dotnet/roslyn contains the server implementation. Follow the instructions there to build the repo as normal. Once built, the server DLL will be located in the build output directory, typically
116+
Replace <roslynRepoRoot> with the actual path to your Roslyn repository.
27117

28-
`$roslynRepoRoot/artifacts/bin/Microsoft.CodeAnalysis.LanguageServer/Debug/net7.0/Microsoft.CodeAnalysis.LanguageServer.dll`
118+
Or, in VSCode settings (`Ctrl+,`):
29119

30-
depending on which configuration is built. Then, launch the extension here and change the VSCode setting `dotnet.server.path` to point to the Roslyn dll path you built above and restart the language server.
120+
1. Search for `dotnet server`.
121+
2. Set `dotnet.server.path` to the path of your Roslyn DLL.
122+
3. Enable `dotnet.server.waitForDebugger`.
31123

32-
If you need to debug the server, you can set the VSCode setting `dotnet.server.waitForDebugger` to true. This will trigger a `Debugger.Launch()` on the server side as it starts.
124+
#### Configuring Razor Language Server
33125

34-
### Using a locally developed Razor server
126+
In your workspace settings.json file, add the following lines:
35127

36-
https://github.com/dotnet/razor contains the server implementation. Follow the instructions there to build the repo as normal. Once built, the server will be located in the build output directory, typically
128+
```json
129+
"razor.languageServer.debug": true,
130+
"razor.languageServer.directory": "<razorRepoRoot>/artifacts/bin/rzls/Debug/net8.0",
131+
"razor.server.trace": "Debug"
132+
```
37133

38-
`$razorRepoRoot/artifacts/bin/rzls/Debug/net7.0`
134+
Replace `$razorRepoRoot` with your actual values.
39135

40-
depending on which configuration is built. Then, launch the extension here and change the VSCode setting `razor.languageServer.directory` to point to the Razor executable path you built above and reload the window.
136+
Or, in VSCode settings (`Ctrl+,`):
41137

42-
If you need to debug the server, you can set the VSCode setting `razor.languageServer.debug` to true. This will trigger a `Debugger.Launch()` on the server side as it starts. You can also set `razor.server.trace` to `Debug` to get more log messages in the output window
138+
1. Search for `Razor`.
139+
2. Set `razor.languageServer.directory` to the path of your Razor DLL.
140+
3. Enable `razor.languageServer.debug`.
141+
4. Set `razor.server.trace` to `Debug`. This gives you more detailed log messages in the output window.
43142

44-
### Creating VSIXs
143+
## Creating VSIX Packages for the Extension
45144

46-
VSIXs can be created using the gulp command `gulp vsix:release:package`. This will create all the platform specific VSIXs that you can then install manually in VSCode.
145+
To package this extension, we need to create VSIX Packages. The VSIX packages can be created using the gulp command `gulp vsix:release:package`. This will create all the platform specific VSIXs that you can then install manually in VSCode.
47146

48-
## Updating the Roslyn server version
147+
## Updating the `Roslyn` Language Server Version
49148

50149
To update the version of the roslyn server used by the extension do the following:
51150
1. Find the the Roslyn signed build you want from [here](https://dnceng.visualstudio.com/internal/_build?definitionId=327&_a=summary). Typically the latest successful build of main is fine.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
}
3838
},
3939
"defaults": {
40-
"roslyn": "4.10.0-1.24058.1",
40+
"roslyn": "4.10.0-1.24069.13",
4141
"omniSharp": "1.39.11",
4242
"razor": "7.0.0-preview.23627.2",
4343
"razorOmnisharp": "7.0.0-preview.23363.1",
@@ -4878,7 +4878,8 @@
48784878
"hiddenWhen": "true",
48794879
"languages": [
48804880
"csharp"
4881-
]
4881+
],
4882+
"aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"
48824883
}
48834884
],
48844885
"semanticTokenTypes": [

src/lsptoolshost/commands.ts

Lines changed: 54 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -103,75 +103,72 @@ async function completionComplexEdit(
103103
newOffset: number,
104104
outputChannel: vscode.OutputChannel
105105
): Promise<void> {
106-
let success = false;
107-
const uri = UriConverter.deserialize(uriStr);
108-
const editor = vscode.window.visibleTextEditors.find(
109-
(editor) => editor.document.uri.path === uri.path || editor.document.uri.fsPath === uri.fsPath
110-
);
111-
112-
if (editor !== undefined) {
113-
const newRange = editor.document.validateRange(
114-
new vscode.Range(
115-
textEdit.range.start.line,
116-
textEdit.range.start.character,
117-
textEdit.range.end.line,
118-
textEdit.range.end.character
119-
)
120-
);
106+
const componentName = '[roslyn.client.completionComplexEdit]';
121107

122-
// HACK:
123-
// ApplyEdit would fail the first time it's called when an item was committed with text modifying commit char (e.g. space, '(', etc.)
124-
// so we retry a couple time here as a tempory workaround. We need to either figure our the reason of the failure, and/or try the
125-
// approach of sending another edit request to server with updated document.
126-
for (let i = 0; i < 3; i++) {
127-
if (isSnippetString) {
128-
editor.selection = new vscode.Selection(newRange.start, newRange.end);
129-
success = await editor.insertSnippet(new vscode.SnippetString(textEdit.newText));
130-
} else {
131-
const edit = new vscode.WorkspaceEdit();
132-
const newTextEdit = vscode.TextEdit.replace(newRange, textEdit.newText);
133-
edit.set(editor.document.uri, [newTextEdit]);
134-
success = await vscode.workspace.applyEdit(edit);
135-
136-
if (success && newOffset >= 0) {
137-
const newPosition = editor.document.positionAt(newOffset);
138-
editor.selections = [new vscode.Selection(newPosition, newPosition)];
139-
}
140-
}
108+
// Find TextDocument, opening if needed.
109+
const document = await vscode.workspace.openTextDocument(uriStr);
110+
if (document === undefined) {
111+
outputAndThrow(outputChannel, `${componentName} Can't open document with path: '${uriStr}'`);
112+
}
141113

142-
if (success) {
143-
break;
144-
}
114+
// Use editor if we need to deal with selection or snippets.
115+
let editor: vscode.TextEditor | undefined = undefined;
116+
if (isSnippetString || newOffset >= 0) {
117+
editor = await vscode.window.showTextDocument(document);
118+
if (editor === undefined) {
119+
outputAndThrow(outputChannel, `${componentName} Editor unavailable for document with path: '${uriStr}'`);
145120
}
146121
}
147122

148-
if (!success) {
149-
const componentName = '[roslyn.client.completionComplexEdit]';
150-
const errorMessage = 'Failed to make a complex text edit for completion.';
151-
outputChannel.show();
152-
outputChannel.appendLine(`${componentName} ${errorMessage}`);
123+
const newRange = document.validateRange(
124+
new vscode.Range(
125+
textEdit.range.start.line,
126+
textEdit.range.start.character,
127+
textEdit.range.end.line,
128+
textEdit.range.end.character
129+
)
130+
);
153131

154-
if (editor === undefined) {
155-
outputChannel.appendLine(
156-
`${componentName} Can't find visible document with uri.fsPath: '${uri.fsPath}' and uri.path: '${uri.path}'`
157-
);
158-
159-
outputChannel.appendLine(`${componentName} URIs of all visible documents:`);
160-
for (const visibleEditor of vscode.window.visibleTextEditors) {
161-
outputChannel.appendLine(
162-
`${componentName} - uri.fsPath: '${visibleEditor.document.uri.fsPath}' and uri.path: '${visibleEditor.document.uri.path}'`
163-
);
164-
}
132+
// HACK:
133+
// ApplyEdit would fail the first time it's called when an item was committed with text modifying commit char (e.g. space, '(', etc.)
134+
// so we retry a couple time here as a tempory workaround. We need to either figure our the reason of the failure, and/or try the
135+
// approach of sending another edit request to server with updated document.
136+
let success = false;
137+
for (let i = 0; i < 3; i++) {
138+
if (isSnippetString) {
139+
editor!.selection = new vscode.Selection(newRange.start, newRange.end);
140+
success = await editor!.insertSnippet(new vscode.SnippetString(textEdit.newText));
165141
} else {
166-
outputChannel.appendLine(
167-
`${componentName} ${isSnippetString ? 'TextEditor.insertSnippet' : 'workspace.applyEdit'} failed.`
168-
);
142+
const edit = new vscode.WorkspaceEdit();
143+
const newTextEdit = vscode.TextEdit.replace(newRange, textEdit.newText);
144+
edit.set(document.uri, [newTextEdit]);
145+
success = await vscode.workspace.applyEdit(edit);
146+
147+
if (success && newOffset >= 0) {
148+
const newPosition = document.positionAt(newOffset);
149+
editor!.selections = [new vscode.Selection(newPosition, newPosition)];
150+
}
151+
}
152+
153+
if (success) {
154+
return;
169155
}
156+
}
170157

171-
throw new Error(`${componentName} ${errorMessage}`);
158+
if (!success) {
159+
outputAndThrow(
160+
outputChannel,
161+
`${componentName} ${isSnippetString ? 'TextEditor.insertSnippet' : 'workspace.applyEdit'} failed.`
162+
);
172163
}
173164
}
174165

166+
function outputAndThrow(outputChannel: vscode.OutputChannel, message: string): void {
167+
outputChannel.show();
168+
outputChannel.appendLine(message);
169+
throw new Error(message);
170+
}
171+
175172
async function openSolution(languageServer: RoslynLanguageServer): Promise<vscode.Uri | undefined> {
176173
if (!vscode.workspace.workspaceFolders) {
177174
return undefined;

src/lsptoolshost/onAutoInsert.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,15 @@ export function registerOnAutoInsert(languageServer: RoslynLanguageServer) {
4040

4141
source.cancel();
4242
source = new vscode.CancellationTokenSource();
43-
await applyAutoInsertEdit(e, changeTrimmed, languageServer, source.token);
43+
try {
44+
await applyAutoInsertEdit(e, changeTrimmed, languageServer, source.token);
45+
} catch (e) {
46+
if (e instanceof vscode.CancellationError) {
47+
return;
48+
}
49+
50+
throw e;
51+
}
4452
}
4553
});
4654
}

src/lsptoolshost/restore.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,19 @@ async function chooseProjectAndRestore(
4141
languageServer: RoslynLanguageServer,
4242
restoreChannel: vscode.OutputChannel
4343
): Promise<void> {
44-
const projects = await languageServer.sendRequest0(
45-
RestorableProjects.type,
46-
new vscode.CancellationTokenSource().token
47-
);
44+
let projects: string[];
45+
try {
46+
projects = await languageServer.sendRequest0(
47+
RestorableProjects.type,
48+
new vscode.CancellationTokenSource().token
49+
);
50+
} catch (e) {
51+
if (e instanceof vscode.CancellationError) {
52+
return;
53+
}
54+
55+
throw e;
56+
}
4857

4958
const items = projects.map((p) => {
5059
const projectName = path.basename(p);

0 commit comments

Comments
 (0)