Skip to content
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
- Diagnostics related feature requests and improvements [#5951](https://github.com/dotnet/vscode-csharp/issues/5951)
- Debug from .csproj and .sln [#5876](https://github.com/dotnet/vscode-csharp/issues/5876)

# 2.152.x

# 11.1.x
* Require C# Dev Kit version 11 or later (PR: [#9776](https://github.com/dotnet/vscode-csharp/pull/9776))
* Update Roslyn to 5.12.0-1.26465.4 (PR: [#9772](https://github.com/dotnet/vscode-csharp/pull/9772))
* Avoid cache misses due to cancellation in deprioritized analyzer cache (PR: [#85222](https://github.com/dotnet/roslyn/pull/85222))
* Move the LanguageServerProjectLoader over to our priority queue (PR: [#85272](https://github.com/dotnet/roslyn/pull/85272))
Expand Down
2 changes: 2 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ stages:
os: linux
# Prefer the dotnet from the container.
installDotNet: false
runDevKitTests: false
testVSCodeVersion: $(testVSCodeVersion)
pool:
name: NetCore-Public
Expand All @@ -102,6 +103,7 @@ stages:
os: linux
# Prefer the dotnet from the container.
installDotNet: false
runDevKitTests: false
testVSCodeVersion: $(testVSCodeVersion)
pool:
name: NetCore-Public
Expand Down
11 changes: 8 additions & 3 deletions azure-pipelines/test-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ parameters:
type: boolean
- name: testVSCodeVersion
type: string
- name: runDevKitTests
type: boolean
# Re-enable once the C# Dev Kit v11 prerelease integration test failures are fixed.
default: false

jobs:
- job:
Expand All @@ -21,9 +25,10 @@ jobs:
CSharpIntegrationTests:
npmCommand: test:integration:csharp
isIntegration: true
DevKitTests:
npmCommand: test:integration:devkit
isIntegration: true
${{ if parameters.runDevKitTests }}:
DevKitTests:
npmCommand: test:integration:devkit
isIntegration: true
RazorCohostTests:
npmCommand: test:integration:razor:cohost
isIntegration: true
Expand Down
2 changes: 2 additions & 0 deletions l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"Update and reload": "Update and reload",
"The {0} extension requires at least {1} of the .NET Install Tool ({2}) extension. Please update to continue": "The {0} extension requires at least {1} of the .NET Install Tool ({2}) extension. Please update to continue",
"Version {0} of the .NET Install Tool ({1}) was not found, {2} will not activate.": "Version {0} of the .NET Install Tool ({1}) was not found, {2} will not activate.",
"C# Dev Kit version 11 or later is required. Please switch to the pre-release version of the C# Dev Kit.": "C# Dev Kit version 11 or later is required. Please switch to the pre-release version of the C# Dev Kit.",
"Open C# Dev Kit": "Open C# Dev Kit",
".NET Test Log": ".NET Test Log",
".NET NuGet Restore": ".NET NuGet Restore",
"Cannot create .NET debug configurations. No workspace folder was selected.": "Cannot create .NET debug configurations. No workspace folder was selected.",
Expand Down
32 changes: 32 additions & 0 deletions src/checkCSharpDevKitVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { major } from 'semver';
import { CSharpDevKitExports } from './csharpDevKitExports';
import { csharpDevkitExtensionId } from './utils/getCSharpDevKit';

const requiredCSharpDevKitMajorVersion = 11;

export async function checkCSharpDevKitVersion(
csharpDevKitExtension: vscode.Extension<CSharpDevKitExports> | undefined
): Promise<void> {
if (
!csharpDevKitExtension ||
major(csharpDevKitExtension.packageJSON.version) >= requiredCSharpDevKitMajorVersion
Comment thread
dibarbet marked this conversation as resolved.
) {
return;
}

const message = vscode.l10n.t(
'C# Dev Kit version 11 or later is required. Please switch to the pre-release version of the C# Dev Kit.'
);
const openCSharpDevKit = vscode.l10n.t('Open C# Dev Kit');
const selection = await vscode.window.showErrorMessage(message, { modal: true }, openCSharpDevKit);
if (selection === openCSharpDevKit) {
await vscode.commands.executeCommand('extension.open', csharpDevkitExtensionId);
}
throw new Error(message);
}
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { checkDotNetRuntimeExtensionVersion } from './checkDotNetRuntimeExtensio
import { checkIsSupportedPlatform } from './checkSupportedPlatform';
import { activateRoslyn } from './activateRoslyn';
import { LimitedActivationStatus } from './shared/limitedActivationStatus';
import { checkCSharpDevKitVersion } from './checkCSharpDevKitVersion';

export async function activate(
context: vscode.ExtensionContext
Expand Down Expand Up @@ -71,6 +72,7 @@ export async function activate(
const requiredPackageIds: string[] = ['Debugger', 'Razor'];

const csharpDevkitExtension = getCSharpDevKit();
await checkCSharpDevKitVersion(csharpDevkitExtension);
const useOmnisharpServer = !csharpDevkitExtension && commonOptions.useOmnisharpServer;
if (useOmnisharpServer) {
requiredPackageIds.push('OmniSharp');
Expand Down
2 changes: 1 addition & 1 deletion tasks/tests/omnisharptestTasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async function runOmnisharpJestIntegrationTest(
CODE_WORKSPACE_ROOT: rootPath,
OMNISHARP_ENGINE: engine,
OMNISHARP_LOCATION: process.env.OMNISHARP_LOCATION,
CODE_DISABLE_EXTENSIONS: 'true',
CODE_DISABLE_CSHARP_DEV_KIT: 'true',
};

await runJestIntegrationTest(testAssetName, testFolder, workspaceFile, suiteName, env);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
navigate,
openFileInWorkspaceAsync,
testIfCSharp,
testIfDevKit,
} from './integrationHelpers';
import { describe, beforeAll, beforeEach, afterAll, test, expect, afterEach } from '@jest/globals';

Expand Down Expand Up @@ -219,7 +218,8 @@ describe(`Go To Definition Tests`, () => {
);
});

testIfDevKit('Navigates to definition in source link', async () => {
// Re-enable when the C# Dev Kit v11 Source Link bug is fixed.
test.skip('Navigates to definition in source link', async () => {
await openFileInWorkspaceAsync(path.join('test', 'UnitTest1.cs'));

// Get definitions
Expand All @@ -245,7 +245,8 @@ describe(`Go To Definition Tests`, () => {
expect(vscode.window.activeTextEditor?.document.uri.path.toLowerCase()).toContain('symbolcache');
});

testIfDevKit('Navigates from definition in source link source goes to source link', async () => {
// Re-enable when the C# Dev Kit v11 Source Link bug is fixed.
test.skip('Navigates from definition in source link source goes to source link', async () => {
await openFileInWorkspaceAsync(path.join('test', 'UnitTest1.cs'));

// Get definitions
Expand Down
56 changes: 56 additions & 0 deletions test/lsptoolshost/unitTests/checkCSharpDevKitVersion.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { beforeEach, describe, expect, jest, test } from '@jest/globals';
import { checkCSharpDevKitVersion } from '../../../src/checkCSharpDevKitVersion';
import { CSharpDevKitExports } from '../../../src/csharpDevKitExports';

describe('C# Dev Kit version check', () => {
beforeEach(() => {
jest.restoreAllMocks();
});

test('allows activation when C# Dev Kit is not installed', async () => {
const showErrorMessage = jest.spyOn(vscode.window, 'showErrorMessage');

await checkCSharpDevKitVersion(undefined);

expect(showErrorMessage).not.toHaveBeenCalled();
});

test.each(['11.0.0', '11.0.0-pre.1', '12.0.0'])('allows activation with C# Dev Kit version %s', async (version) => {
const showErrorMessage = jest.spyOn(vscode.window, 'showErrorMessage');

await checkCSharpDevKitVersion(createExtension(version));

expect(showErrorMessage).not.toHaveBeenCalled();
});

test('blocks activation with an older C# Dev Kit version', async () => {
const showErrorMessage = jest.spyOn(vscode.window, 'showErrorMessage').mockResolvedValue(undefined);

await expect(checkCSharpDevKitVersion(createExtension('10.9.99'))).rejects.toThrow(
'C# Dev Kit version 11 or later is required. Please switch to the pre-release version of the C# Dev Kit.'
);
expect(showErrorMessage).toHaveBeenCalledTimes(1);
expect(showErrorMessage).toHaveBeenCalledWith(expect.any(String), { modal: true }, 'Open C# Dev Kit');
});

test('opens C# Dev Kit when requested', async () => {
jest.spyOn(vscode.window, 'showErrorMessage').mockResolvedValue('Open C# Dev Kit' as never);
const executeCommand = jest.spyOn(vscode.commands, 'executeCommand').mockResolvedValue(undefined);

await expect(checkCSharpDevKitVersion(createExtension('10.9.99'))).rejects.toThrow();

expect(executeCommand).toHaveBeenCalledWith('extension.open', 'ms-dotnettools.csdevkit');
});
});

function createExtension(version: string): vscode.Extension<CSharpDevKitExports> {
return {
packageJSON: { version },
} as vscode.Extension<CSharpDevKitExports>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describeIfNotRazorOrGenerator(`WorkspaceSymbolProvider: ${testAssetWorkspace.des
await omnisharpConfig.update('minFindSymbolsFilterLength', 2);

const symbols = await GetWorkspaceSymbols('P');
expect(symbols.length).toEqual(0);
expect(symbols).toEqual([]);
});

test('Returns elements when minimum filter length is configured and search term is longer or equal', async function () {
Expand Down
59 changes: 59 additions & 0 deletions test/tasks/vscodeLauncher.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as cp from 'child_process';
import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron';
import { beforeEach, describe, expect, jest, test } from '@jest/globals';
import { prepareVSCodeAndExecuteTests } from '../vscodeLauncher';

jest.mock('child_process');
jest.mock('@vscode/test-electron');

describe('VS Code test launcher', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.mocked(downloadAndUnzipVSCode).mockResolvedValue('code');
jest.mocked(resolveCliArgsFromVSCodeExecutablePath).mockReturnValue(['code']);
jest.mocked(runTests).mockResolvedValue(0);
jest.mocked(cp.spawnSync).mockReturnValue({
pid: 1,
output: [],
stdout: '',
stderr: '',
status: 0,
signal: null,
});
});

test.each([
{ flag: undefined, disabled: false },
{ flag: 'false', disabled: false },
{ flag: 'true', disabled: true },
])('CODE_DISABLE_CSHARP_DEV_KIT=$flag disables Dev Kit: $disabled', async ({ flag, disabled }) => {
const env = { CODE_DISABLE_CSHARP_DEV_KIT: flag };

await expect(prepareVSCodeAndExecuteTests('extension', 'tests', 'workspace', 'user-data', env)).resolves.toBe(
0
);

expect(runTests).toHaveBeenCalledTimes(1);
const options = jest.mocked(runTests).mock.calls[0][0];
expect(options.extensionDevelopmentPath).toBe('extension');
expect(options.extensionTestsPath).toBe('tests');
expect(options.extensionTestsEnv).toBe(env);
expect(options.launchArgs).toEqual(
expect.arrayContaining([
'workspace',
'-n',
'--user-data-dir',
'user-data',
'--log',
'ms-dotnettools.csharp:trace',
])
);
expect(options.launchArgs?.includes('--disable-extension=ms-dotnettools.csdevkit')).toBe(disabled);
expect(options.launchArgs).not.toContain('--disable-extensions');
});
});
9 changes: 7 additions & 2 deletions test/vscodeLauncher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ export async function prepareVSCodeAndExecuteTests(

// Different test runs may want to have Dev Kit be active or in-active.
// Rather than having to uninstall Dev Kit between different test runs, we use workspace settings
// to control which extensions are active - and we always install Dev Kit.
// and launch arguments to control which extensions are active - and we always install Dev Kit.
const extensionsToInstall = [
'ms-dotnettools.vscode-dotnet-runtime@3.0.0',
'ms-dotnettools.csharp',
'ms-dotnettools.csdevkit@1.92.5',
'ms-dotnettools.csdevkit@11.0.2',
];

await installExtensions(extensionsToInstall, cli, args);
Expand All @@ -56,6 +56,11 @@ export async function prepareVSCodeAndExecuteTests(
}

const launchArgs = [workspacePath, '-n', '--user-data-dir', userDataDir, '--log', 'ms-dotnettools.csharp:trace'];
if (env.CODE_DISABLE_CSHARP_DEV_KIT === 'true') {
// Disabling all extensions would also disable C#'s required .NET runtime extension.
launchArgs.push('--disable-extension=ms-dotnettools.csdevkit');
}

if (process.platform === 'linux') {
// CI containers have a small /dev/shm allocation, which can cause the renderer to crash.
launchArgs.push('--disable-dev-shm-usage');
Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "2.152",
"version": "11.1",
Comment thread
dibarbet marked this conversation as resolved.
Comment thread
dibarbet marked this conversation as resolved.
"publicReleaseRefSpec": [
"^refs/heads/release$",
"^refs/heads/prerelease$",
Expand Down
Loading