Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 39 additions & 15 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
],
Expand All @@ -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"
Expand All @@ -78,7 +82,8 @@
},
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/*.js"
"${workspaceRoot}/dist/*.js",
"${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -124,7 +133,8 @@
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/*.js"
"${workspaceRoot}/dist/*.js",
"${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
Expand All @@ -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"
Expand All @@ -150,7 +162,8 @@
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/*.js"
"${workspaceRoot}/dist/*.js",
"${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -195,7 +212,8 @@
},
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/*.js"
"${workspaceRoot}/dist/*.js",
"${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
Expand All @@ -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"
Expand All @@ -219,7 +239,8 @@
},
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/*.js"
"${workspaceRoot}/dist/*.js",
"${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
Expand All @@ -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"
Expand All @@ -243,7 +266,8 @@
},
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/*.js"
"${workspaceRoot}/dist/*.js",
"${workspaceRoot}/out/test/**/*.js"
],
"preLaunchTask": "buildDev"
},
Expand Down
14 changes: 12 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,24 @@ To **test** do the following: `npm run test` or <kbd>F5</kbd> 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`

depending on which configuration is built. Then, launch the extension here and change the VSCode setting `dotnet.server.path` to point to the Roslyn executable path you built above and restart the language server.

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.
Expand All @@ -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.
* 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.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion src/lsptoolshost/roslynLanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 20 additions & 8 deletions src/razor/src/Completion/RazorCompletionItemProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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: {
Expand All @@ -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<vscode.CompletionList | vscode.CompletionItem[]>(
Expand All @@ -71,6 +71,8 @@ export class RazorCompletionItemProvider
completions instanceof Array ? completions // was vscode.CompletionItem[]
: completions ? completions.items // was vscode.CompletionList
: [];

const data = (<CompletionList>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
Expand All @@ -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;
Expand Down Expand Up @@ -128,6 +130,10 @@ export class RazorCompletionItemProvider
completionItem.insertText = intellicodeCompletion.textEditText;
}
}

if (!(<CompletionItem>completionItem).data) {
(<CompletionItem>completionItem).data = data;
}
}

const isIncomplete = completions instanceof Array ? false
Expand Down Expand Up @@ -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 = <MarkupContent>(<unknown>(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]);

Expand Down Expand Up @@ -238,4 +251,3 @@ function getTriggerKind(triggerKind: vscode.CompletionTriggerKind): CompletionTr

}
}

8 changes: 8 additions & 0 deletions test/integrationTests/integrationHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ export interface ActivationResult {
}

export async function activateCSharpExtension(): Promise<ActivationResult> {
// 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<OmnisharpExtensionExports>(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) {
Expand Down