Skip to content

Commit

Permalink
Merge pull request #5897 from dibarbet/unit_testing
Browse files Browse the repository at this point in the history
Implement client side code for run tests command
  • Loading branch information
dibarbet authored Jul 20, 2023
2 parents f62d8f1 + a1f4c9a commit 2d1e6cb
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 30 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
}
},
"defaults": {
"roslyn": "4.8.0-1.23367.7",
"roslyn": "4.8.0-1.23369.14",
"omniSharp": "1.39.7",
"razor": "7.0.0-preview.23328.2",
"razorOmnisharp": "7.0.0-preview.23363.1"
Expand Down Expand Up @@ -92,6 +92,7 @@
"strip-bom": "5.0.0",
"strip-bom-buf": "2.0.0",
"tmp": "0.0.33",
"uuid": "^9.0.0",
"vscode-html-languageservice": "^5.0.1",
"vscode-js-debug-browsers": "^1.0.5",
"vscode-jsonrpc": "8.2.0-next.0",
Expand All @@ -115,6 +116,7 @@
"@types/node": "16.11.38",
"@types/semver": "5.5.0",
"@types/tmp": "0.0.33",
"@types/uuid": "^9.0.1",
"@types/unzipper": "^0.9.1",
"@types/vscode": "1.69.0",
"@types/yauzl": "2.10.0",
Expand Down
31 changes: 31 additions & 0 deletions src/lsptoolshost/roslynLanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import * as cp from 'child_process';
import * as uuid from 'uuid';
import { registerCommands } from './commands';
import { registerDebugger } from './debugger';
import { UriConverter } from './uriConverter';
Expand Down Expand Up @@ -36,6 +37,8 @@ import {
CompletionRequest,
CompletionResolveRequest,
CompletionItem,
PartialResultParams,
ProtocolRequestType,
} from 'vscode-languageclient/node';
import { PlatformInformation } from '../shared/platform';
import { readConfigurations } from './configurationMiddleware';
Expand All @@ -57,6 +60,7 @@ import { randomUUID } from 'crypto';
import { DotnetRuntimeExtensionResolver } from './dotnetRuntimeExtensionResolver';
import { IHostExecutableResolver } from '../shared/constants/IHostExecutableResolver';
import { RoslynLanguageClient } from './roslynLanguageClient';
import { registerUnitTestingCommands } from './unitTesting';

let _languageServer: RoslynLanguageServer;
let _channel: vscode.OutputChannel;
Expand Down Expand Up @@ -269,6 +273,28 @@ export class RoslynLanguageServer {
return response;
}

public async sendRequestWithProgress<P extends PartialResultParams, R, PR, E, RO>(
type: ProtocolRequestType<P, R, PR, E, RO>,
params: P,
onProgress: (p: PR) => Promise<any>,
cancellationToken?: vscode.CancellationToken
): Promise<R> {
if (!this._languageClient) {
throw new Error('Tried to send request while server is not started.');
}
// Generate a UUID for our partial result token and apply it to our request.
const partialResultToken: string = uuid.v4();
params.partialResultToken = partialResultToken;
// Register the callback for progress events.
const disposable = this._languageClient.onProgress(type, partialResultToken, async (partialResult) => {
await onProgress(partialResult);
});
const response = await this._languageClient
.sendRequest(type, params, cancellationToken)
.finally(() => disposable.dispose());
return response;
}

/**
* Sends an LSP notification to the server with a given method and parameters.
*/
Expand Down Expand Up @@ -425,6 +451,8 @@ export class RoslynLanguageServer {
// shouldn't this arg only be set if it's running with CSDevKit?
args.push('--telemetryLevel', this.telemetryReporter.telemetryLevel);

args.push('--extensionLogDirectory', this.context.logUri.fsPath);

let childProcess: cp.ChildProcessWithoutNullStreams;
const cpOptions: cp.SpawnOptionsWithoutStdio = {
detached: true,
Expand Down Expand Up @@ -591,6 +619,7 @@ export async function activateRoslynLanguageServer(
platformInfo: PlatformInformation,
optionProvider: OptionProvider,
outputChannel: vscode.OutputChannel,
dotnetTestChannel: vscode.OutputChannel,
reporter: TelemetryReporter
) {
// Create a channel for outputting general logs from the language server.
Expand All @@ -606,6 +635,8 @@ export async function activateRoslynLanguageServer(

registerRazorCommands(context, _languageServer);

registerUnitTestingCommands(context, _languageServer, dotnetTestChannel);

// Register any needed debugger components that need to communicate with the language server.
registerDebugger(context, _languageServer, platformInfo, optionProvider, _channel);

Expand Down
96 changes: 68 additions & 28 deletions src/lsptoolshost/roslynProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,15 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import {
FormattingOptions,
InsertTextFormat,
MessageDirection,
NotificationType,
Position,
RequestType,
RequestType0,
TextDocumentIdentifier,
TextEdit,
URI,
integer,
} from 'vscode-languageserver-protocol';
import * as lsp from 'vscode-languageserver-protocol';

export interface WorkspaceDebugConfigurationParams {
/**
* Workspace path containing the solution/projects to get debug information for.
* This will be important eventually for multi-workspace support.
* If not provided, configurations are returned for the workspace the server was initialized for.
*/
workspacePath: URI | undefined;
workspacePath: lsp.URI | undefined;
}

export interface ProjectDebugConfiguration {
Expand Down Expand Up @@ -59,44 +47,96 @@ export interface ProjectDebugConfiguration {
}

export interface OnAutoInsertParams {
_vs_textDocument: TextDocumentIdentifier;
_vs_position: Position;
_vs_textDocument: lsp.TextDocumentIdentifier;
_vs_position: lsp.Position;
_vs_ch: string;
_vs_options: FormattingOptions;
_vs_options: lsp.FormattingOptions;
}

export interface OnAutoInsertResponseItem {
_vs_textEditFormat: InsertTextFormat;
_vs_textEdit: TextEdit;
_vs_textEditFormat: lsp.InsertTextFormat;
_vs_textEdit: lsp.TextEdit;
}

export interface RegisterSolutionSnapshotResponseItem {
/**
* Represents a solution snapshot.
*/
id: integer;
id: lsp.integer;
}

export interface RunTestsParams extends lsp.WorkDoneProgressParams, lsp.PartialResultParams {
/**
* The text document containing the tests to run.
*/
textDocument: lsp.TextDocumentIdentifier;

/**
* The range encompasing the test methods to run.
* Note that this does not have to only include tests, for example this could be a range representing a class.
*/
range: lsp.Range;
}

export interface TestProgress {
/**
* The total number of tests passed at the time of the report.
*/
testsPassed: number;
/**
* The total number of tests failed at the time of the report.
*/
testsFailed: number;
/**
* The total number of tests skipped at the time of the report.
*/
testsSkipped: number;
/**
* The total number of tests that will eventually be run.
*/
totalTests: number;
}

export interface RunTestsPartialResult {
stage: string;
message: string;
progress?: TestProgress;
}

export namespace WorkspaceDebugConfigurationRequest {
export const method = 'workspace/debugConfiguration';
export const messageDirection: MessageDirection = MessageDirection.clientToServer;
export const type = new RequestType<WorkspaceDebugConfigurationParams, ProjectDebugConfiguration[], void>(method);
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer;
export const type = new lsp.RequestType<WorkspaceDebugConfigurationParams, ProjectDebugConfiguration[], void>(
method
);
}

export namespace OnAutoInsertRequest {
export const method = 'textDocument/_vs_onAutoInsert';
export const messageDirection: MessageDirection = MessageDirection.clientToServer;
export const type = new RequestType<OnAutoInsertParams, OnAutoInsertResponseItem, void>(method);
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer;
export const type = new lsp.RequestType<OnAutoInsertParams, OnAutoInsertResponseItem, void>(method);
}

export namespace RegisterSolutionSnapshotRequest {
export const method = 'workspace/_vs_registerSolutionSnapshot';
export const messageDirection: MessageDirection = MessageDirection.clientToServer;
export const type = new RequestType0<RegisterSolutionSnapshotResponseItem, void>(method);
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer;
export const type = new lsp.RequestType0<RegisterSolutionSnapshotResponseItem, void>(method);
}

export namespace ProjectInitializationCompleteNotification {
export const method = 'workspace/projectInitializationComplete';
export const messageDirection: MessageDirection = MessageDirection.serverToClient;
export const type = new NotificationType(method);
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.serverToClient;
export const type = new lsp.NotificationType(method);
}

export namespace RunTestsRequest {
export const method = 'textDocument/runTests';
export const messageDirection: lsp.MessageDirection = lsp.MessageDirection.clientToServer;
export const type = new lsp.ProtocolRequestType<
RunTestsParams,
RunTestsPartialResult[],
RunTestsPartialResult,
void,
void
>(method);
}
Loading

0 comments on commit 2d1e6cb

Please sign in to comment.