Skip to content

Commit

Permalink
Wait for operations on the server to improve integration test startup
Browse files Browse the repository at this point in the history
  • Loading branch information
dibarbet committed Oct 12, 2023
1 parent b71740c commit 464abd2
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 21 deletions.
28 changes: 8 additions & 20 deletions test/integrationTests/integrationHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import * as vscode from 'vscode';
import * as path from 'path';
import { CSharpExtensionExports } from '../../src/csharpExtensionExports';
import { existsSync } from 'fs';
import { ServerStateChange } from '../../src/lsptoolshost/serverStateChange';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import { WaitForAsyncOperationsRequest } from './testHooks';

export async function activateCSharpExtension(): Promise<void> {
// Ensure the dependent extension exists - when launching via F5 launch.json we can't install the extension prior to opening vscode.
Expand All @@ -28,31 +28,14 @@ export async function activateCSharpExtension(): Promise<void> {
// Run a restore manually to make sure the project is up to date since we don't have automatic restore.
await testAssetWorkspace.restoreLspToolsHostAsync();

// If the extension is already active, we need to restart it to ensure we start with a clean server state.
// For example, a previous test may have changed configs, deleted restored packages or made other changes that would put it in an invalid state.
let shouldRestart = false;
if (csharpExtension.isActive) {
shouldRestart = true;
}

// Explicitly await the extension activation even if completed so that we capture any errors it threw during activation.
await csharpExtension.activate();
await csharpExtension.exports.initializationFinished();
console.log('ms-dotnettools.csharp activated');
console.log(`Extension Log Directory: ${csharpExtension.exports.logDirectory}`);

if (shouldRestart) {
// Register to wait for initialization events and restart the server.
const waitForInitialProjectLoad = new Promise<void>((resolve, _) => {
csharpExtension.exports.experimental.languageServerEvents.onServerStateChange(async (state) => {
if (state === ServerStateChange.ProjectInitializationComplete) {
resolve();
}
});
});
await vscode.commands.executeCommand('dotnet.restartServer');
await waitForInitialProjectLoad;
}
await waitForAllAsyncOperationsAsync(csharpExtension.exports);
console.log('Async operations completed');
}

export async function openFileInWorkspaceAsync(relativeFilePath: string): Promise<void> {
Expand All @@ -73,6 +56,11 @@ export function isSlnWithGenerator(workspace: typeof vscode.workspace) {
return isGivenSln(workspace, 'slnWithGenerator');
}

export async function waitForAllAsyncOperationsAsync(exports: CSharpExtensionExports): Promise<void> {
const source = new vscode.CancellationTokenSource();
await exports.experimental.sendServerRequest(WaitForAsyncOperationsRequest.type, { operations: [] }, source.token);
}

function isGivenSln(workspace: typeof vscode.workspace, expectedProjectFileName: string) {
const primeWorkspace = workspace.workspaceFolders![0];
const projectFileName = primeWorkspace.uri.fsPath.split(path.sep).pop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"dotnet.defaultSolution": "b_SecondInOrder_SlnFile.sln",
"dotnet.server.trace": "Trace",
"dotnet.server.useOmnisharp": false,
"omnisharp.enableLspDriver": false,
"omnisharp.enableLspDriver": false,
"dotnet.server.path": "C:\\Users\\dabarbet\\source\\repos\\roslyn\\artifacts\\bin\\Microsoft.CodeAnalysis.LanguageServer\\Debug\\net7.0\\Microsoft.CodeAnalysis.LanguageServer.dll"
}
}
23 changes: 23 additions & 0 deletions test/integrationTests/testHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as lsp from 'vscode-languageserver-protocol';

export interface WaitForAsyncOperationsParams {
/**
* The operations to wait for.
*/
operations: string[];
}

export interface WaitForAsyncOperationsResponse {
result: boolean;
}

export namespace WaitForAsyncOperationsRequest {
export const method = 'workspace/waitForAsyncOperations';
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer;
export const type = new lsp.RequestType<WaitForAsyncOperationsParams, WaitForAsyncOperationsResponse, void>(method);
}

0 comments on commit 464abd2

Please sign in to comment.