diff --git a/.vscode/launch.json b/.vscode/launch.json
index d83318d936..1b65dacf85 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -41,7 +41,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/featureTests"
],
@@ -63,7 +65,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/singleCsproj",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -78,7 +82,8 @@
},
"sourceMaps": true,
"outFiles": [
- "${workspaceRoot}/dist/*.js"
+ "${workspaceRoot}/dist/*.js",
+ "${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
@@ -88,7 +93,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/BasicRazorApp2_1",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -108,7 +115,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -124,7 +133,8 @@
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
- "${workspaceRoot}/dist/*.js"
+ "${workspaceRoot}/dist/*.js",
+ "${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
@@ -134,7 +144,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/singleCsproj",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -150,7 +162,8 @@
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
- "${workspaceRoot}/dist/*.js"
+ "${workspaceRoot}/dist/*.js",
+ "${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
@@ -160,7 +173,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/BasicRazorApp2_1",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -180,7 +195,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -195,7 +212,8 @@
},
"sourceMaps": true,
"outFiles": [
- "${workspaceRoot}/dist/*.js"
+ "${workspaceRoot}/dist/*.js",
+ "${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
@@ -205,7 +223,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/slnFilterWithCsproj",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -219,7 +239,8 @@
},
"sourceMaps": true,
"outFiles": [
- "${workspaceRoot}/dist/*.js"
+ "${workspaceRoot}/dist/*.js",
+ "${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
@@ -229,7 +250,9 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
- "--disable-extensions",
+ // Create a temp profile that has no extensions / user settings.
+ // This allows us to only have the C# extension + the dotnet runtime installer extension dependency.
+ "--profile-temp",
"${workspaceRoot}/test/integrationTests/testAssets/slnWithGenerator",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test/integrationTests"
@@ -243,7 +266,8 @@
},
"sourceMaps": true,
"outFiles": [
- "${workspaceRoot}/dist/*.js"
+ "${workspaceRoot}/dist/*.js",
+ "${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 742a01e475..af9fc956f6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,7 +23,7 @@ To **test** do the following: `npm run test` or F5 in VS Code with th
### Using a locally developed Roslyn server
-https://github.com/dotnet/roslyn contains the server implementation. Follow the instructions there to build the repo as normal. Once built, the server executable will be located in the build output directory, typically
+https://github.com/dotnet/roslyn contains the server implementation. Follow the instructions there to build the repo as normal. Once built, the server executable will be located in the build output directory, typically
`$roslynRepoRoot/artifacts/bin/Microsoft.CodeAnalysis.LanguageServer/Debug/net7.0/Microsoft.CodeAnalysis.LanguageServer.exe`
@@ -31,6 +31,16 @@ depending on which configuration is built. Then, launch the extension here and
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.
+### Using a locally developed Razor server
+
+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
+
+`$razorRepoRoot/artifacts/bin/rzls/Debug/net7.0`
+
+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.
+
+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.trace` to `Verbose` to get more log messages in the output window
+
### Creating VSIXs
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.
@@ -42,4 +52,4 @@ To update the version of the roslyn server used by the extension do the followin
2. In the official build stage, look for the `Publish Assets` step. In there you will see it publishing the `Microsoft.CodeAnalysis.LanguageServer` package with some version, e.g. `4.6.0-3.23158.4`. Take note of that version number.
3. In the [package.json](package.json) inside the `defaults` section update the `roslyn` key to point to the version number you found above in step 2.
4. Build and test the change (make sure to run `gulp installDependencies` to get the new version!). If everything looks good, submit a PR.
- * Adding new package versions might require authentication, run with the `--interactive` flag to login. You may need to install [azure artifacts nuget credential provider](https://github.com/microsoft/artifacts-credprovider#installation-on-windows) to run interactive authentication.
\ No newline at end of file
+ * Adding new package versions might require authentication, run with the `--interactive` flag to login. You may need to install [azure artifacts nuget credential provider](https://github.com/microsoft/artifacts-credprovider#installation-on-windows) to run interactive authentication.
diff --git a/package.json b/package.json
index 95491ca75a..ade7df82c9 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"displayName": "C#",
"author": "Microsoft Corporation",
"license": "SEE LICENSE IN RuntimeLicenses/license.txt",
+ "qna": "https://github.com/dotnet/vscode-csharp/issues",
"icon": "images/csharpIcon.png",
"preview": false,
"bugs": {
@@ -35,7 +36,7 @@
}
},
"defaults": {
- "roslyn": "4.7.0-3.23316.4",
+ "roslyn": "4.7.0-3.23326.2",
"omniSharp": "1.39.6",
"razor": "7.0.0-preview.23275.2"
},
diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts
index ba17ea9c11..edee850ef2 100644
--- a/src/lsptoolshost/roslynLanguageServer.ts
+++ b/src/lsptoolshost/roslynLanguageServer.ts
@@ -433,7 +433,7 @@ export class RoslynLanguageServer {
if (serverPath.endsWith('.dll')) {
// If we were given a path to a dll, launch that via dotnet.
const argsWithPath = [ serverPath ].concat(args);
- childProcess = cp.spawn('dotnet', argsWithPath, cpOptions);
+ childProcess = cp.spawn(dotnetExecutablePath, argsWithPath, cpOptions);
} else {
// Otherwise assume we were given a path to an executable.
childProcess = cp.spawn(serverPath, args, cpOptions);
diff --git a/src/razor/src/Completion/RazorCompletionItemProvider.ts b/src/razor/src/Completion/RazorCompletionItemProvider.ts
index 029735744b..a4c177ac22 100644
--- a/src/razor/src/Completion/RazorCompletionItemProvider.ts
+++ b/src/razor/src/Completion/RazorCompletionItemProvider.ts
@@ -13,7 +13,7 @@ import { getUriPath } from '../UriPaths';
import { ProvisionalCompletionOrchestrator } from './ProvisionalCompletionOrchestrator';
import { LanguageKind } from '../RPC/LanguageKind';
import { RoslynLanguageServer } from '../../../lsptoolshost/roslynLanguageServer';
-import { CompletionItem, CompletionParams, CompletionTriggerKind } from 'vscode-languageclient';
+import { CompletionItem, CompletionList, CompletionParams, CompletionTriggerKind, MarkupContent } from 'vscode-languageclient';
import { UriConverter } from '../../../lsptoolshost/uriConverter';
import * as RazorConventions from '../RazorConventions';
import { MappingHelpers } from '../Mapping/MappingHelpers';
@@ -35,11 +35,6 @@ export class RazorCompletionItemProvider
let completions: vscode.CompletionList | vscode.CompletionItem[];
- // For CSharp, completions need to keep the "data" field
- // on the completion item for lazily resolving the edits in
- // the resolveCompletionItem step. Using the vs code command
- // drops that field because it doesn't exist in the declared vs code
- // CompletionItem type.
if (language === LanguageKind.CSharp) {
const params: CompletionParams = {
context: {
@@ -52,6 +47,11 @@ export class RazorCompletionItemProvider
position: projectedPosition
};
+ // For CSharp, completions need to keep the "data" field on the
+ // completion item for lazily resolving the edits in the
+ // resolveCompletionItem step. Using the vs code command drops
+ // that field because it doesn't exist in the declared vs code
+ // CompletionItem type.
completions = await vscode
.commands
.executeCommand(
@@ -71,6 +71,8 @@ export class RazorCompletionItemProvider
completions instanceof Array ? completions // was vscode.CompletionItem[]
: completions ? completions.items // was vscode.CompletionList
: [];
+
+ const data = (completions)?.itemDefaults?.data;
// There are times when the generated code will not line up with the content of the .razor/.cshtml file.
// Therefore, we need to offset all completion items' characters by a certain amount in order
@@ -79,7 +81,7 @@ export class RazorCompletionItemProvider
const completionCharacterOffset = projectedPosition.character - hostDocumentPosition.character;
for (const completionItem of completionItems) {
const doc = completionItem.documentation as vscode.MarkdownString;
- if (doc) {
+ if (doc && doc.value) {
// Without this, the documentation doesn't get rendered in the editor.
const newDoc = new vscode.MarkdownString(doc.value);
newDoc.isTrusted = doc.isTrusted;
@@ -128,6 +130,10 @@ export class RazorCompletionItemProvider
completionItem.insertText = intellicodeCompletion.textEditText;
}
}
+
+ if (!(completionItem).data) {
+ (completionItem).data = data;
+ }
}
const isIncomplete = completions instanceof Array ? false
@@ -204,6 +210,13 @@ export class RazorCompletionItemProvider
item = newItem;
+ // The documentation object Roslyn returns is a MarkupContent,
+ // which we need to convert to a MarkdownString.
+ const markupContent = ((item.documentation));
+ if (markupContent && markupContent.value) {
+ item.documentation = new vscode.MarkdownString(markupContent.value);
+ }
+
if (item.command && item.command.arguments?.length === 4) {
let uri = vscode.Uri.parse(item.command.arguments[0]);
@@ -238,4 +251,3 @@ function getTriggerKind(triggerKind: vscode.CompletionTriggerKind): CompletionTr
}
}
-
diff --git a/test/integrationTests/integrationHelpers.ts b/test/integrationTests/integrationHelpers.ts
index 439d429357..f86464076c 100644
--- a/test/integrationTests/integrationHelpers.ts
+++ b/test/integrationTests/integrationHelpers.ts
@@ -16,6 +16,14 @@ export interface ActivationResult {
}
export async function activateCSharpExtension(): Promise {
+ // Ensure the dependent extension exists - when launching via F5 launch.json we can't install the extension prior to opening vscode.
+ const vscodeDotnetRuntimeExtensionId = "ms-dotnettools.vscode-dotnet-runtime";
+ let dotnetRuntimeExtension = vscode.extensions.getExtension(vscodeDotnetRuntimeExtensionId);
+ if (!dotnetRuntimeExtension) {
+ await vscode.commands.executeCommand("workbench.extensions.installExtension", vscodeDotnetRuntimeExtensionId);
+ await vscode.commands.executeCommand("workbench.action.reloadWindow");
+ }
+
const configuration = vscode.workspace.getConfiguration();
configuration.update('omnisharp.enableLspDriver', process.env.OMNISHARP_DRIVER === 'lsp' ? true : false);
if (process.env.OMNISHARP_LOCATION) {