From 1dc6111fbad17e7a5724a0231ce608cb07080bce Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Thu, 11 Jan 2024 10:47:48 -0500 Subject: [PATCH] Switch to built-in VS Code test UI unconditionally --- README.md | 7 - extensions/ql-vscode/README.md | 2 - extensions/ql-vscode/package-lock.json | 27 -- extensions/ql-vscode/package.json | 3 - extensions/ql-vscode/src/common/commands.ts | 11 +- extensions/ql-vscode/src/extension.ts | 29 +-- .../src/query-testing/test-adapter.ts | 238 ------------------ .../src/query-testing/test-manager-base.ts | 3 +- .../src/query-testing/test-tree-node.ts | 9 - .../ql-vscode/src/query-testing/test-ui.ts | 71 ------ .../jest-runner-installed-extensions.ts | 18 +- 11 files changed, 11 insertions(+), 407 deletions(-) delete mode 100644 extensions/ql-vscode/src/query-testing/test-tree-node.ts delete mode 100644 extensions/ql-vscode/src/query-testing/test-ui.ts diff --git a/README.md b/README.md index f5dc1b9e8..03b564f5a 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,6 @@ To see what has changed in the last few versions of the extension, see the [Chan This project will track new feature development in CodeQL and, whenever appropriate, bring that functionality to the Visual Studio Code experience. -## Dependencies - -This extension depends on the following two extensions for required functionality. They will be installed automatically when you install VS Code CodeQL. - -- [Test Adapter Converter](https://marketplace.visualstudio.com/items?itemName=ms-vscode.test-adapter-converter) -- [Test Explorer UI](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-test-explorer) - ## Contributing This project welcomes contributions. See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to build, install, and contribute. diff --git a/extensions/ql-vscode/README.md b/extensions/ql-vscode/README.md index 7558d27cf..91c0016fc 100644 --- a/extensions/ql-vscode/README.md +++ b/extensions/ql-vscode/README.md @@ -17,8 +17,6 @@ For information about other configurations, see the separate [CodeQL help](https ### Quick start: Installing and configuring the extension 1. [Install the extension](#installing-the-extension). - *Note: vscode-codeql installs the following dependencies for required functionality: [Test Adapter Converter](https://marketplace.visualstudio.com/items?itemName=ms-vscode.test-adapter-converter), [Test Explorer UI](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-test-explorer).* - 1. [Check access to the CodeQL CLI](#checking-access-to-the-codeql-cli). 1. [Clone the CodeQL starter workspace](#cloning-the-codeql-starter-workspace). diff --git a/extensions/ql-vscode/package-lock.json b/extensions/ql-vscode/package-lock.json index fcc53e582..e79cf467c 100644 --- a/extensions/ql-vscode/package-lock.json +++ b/extensions/ql-vscode/package-lock.json @@ -40,8 +40,6 @@ "vscode-extension-telemetry": "^0.1.6", "vscode-jsonrpc": "^8.0.2", "vscode-languageclient": "^8.0.2", - "vscode-test-adapter-api": "^1.7.0", - "vscode-test-adapter-util": "^0.7.0", "yauzl": "^2.10.0", "zip-a-folder": "^3.1.3" }, @@ -31984,31 +31982,6 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.3.tgz", "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==" }, - "node_modules/vscode-test-adapter-api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/vscode-test-adapter-api/-/vscode-test-adapter-api-1.9.0.tgz", - "integrity": "sha512-lltjehUP0J9H3R/HBctjlqeUCwn2t9Lbhj2Y500ib+j5Y4H3hw+hVTzuSsfw16LtxY37knlU39QIlasa7svzOQ==", - "engines": { - "vscode": "^1.23.0" - } - }, - "node_modules/vscode-test-adapter-util": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/vscode-test-adapter-util/-/vscode-test-adapter-util-0.7.1.tgz", - "integrity": "sha512-OZZvLDDNhayVVISyTmgUntOhMzl6j9/wVGfNqI2zuR5bQIziTQlDs9W29dFXDTGXZOxazS6uiHkrr86BKDzYUA==", - "dependencies": { - "tslib": "^1.11.1", - "vscode-test-adapter-api": "^1.8.0" - }, - "engines": { - "vscode": "^1.24.0" - } - }, - "node_modules/vscode-test-adapter-util/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index 1fa606758..b905707fe 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -21,7 +21,6 @@ "Programming Languages" ], "extensionDependencies": [ - "hbenl.vscode-test-explorer", "vscode.git" ], "capabilities": { @@ -1938,8 +1937,6 @@ "vscode-extension-telemetry": "^0.1.6", "vscode-jsonrpc": "^8.0.2", "vscode-languageclient": "^8.0.2", - "vscode-test-adapter-api": "^1.7.0", - "vscode-test-adapter-util": "^0.7.0", "yauzl": "^2.10.0", "zip-a-folder": "^3.1.3" }, diff --git a/extensions/ql-vscode/src/common/commands.ts b/extensions/ql-vscode/src/common/commands.ts index dbd640b3b..57c471ec7 100644 --- a/extensions/ql-vscode/src/common/commands.ts +++ b/extensions/ql-vscode/src/common/commands.ts @@ -1,10 +1,9 @@ import type { CommandManager } from "../packages/commands"; -import type { Uri, Range, TextDocumentShowOptions } from "vscode"; +import type { Uri, Range, TextDocumentShowOptions, TestItem } from "vscode"; import type { AstItem } from "../language-support"; import type { DbTreeViewItem } from "../databases/ui/db-tree-view-item"; import type { DatabaseItem } from "../databases/local-databases"; import type { QueryHistoryInfo } from "../query-history/query-history-info"; -import type { TestTreeNode } from "../query-testing/test-tree-node"; import type { VariantAnalysis, VariantAnalysisScannedRepository, @@ -334,11 +333,9 @@ export type SummaryLanguageSupportCommands = { }; export type TestUICommands = { - "codeQLTests.showOutputDifferences": (node: TestTreeNode) => Promise; - "codeQLTests.acceptOutput": (node: TestTreeNode) => Promise; - "codeQLTests.acceptOutputContextTestItem": ( - node: TestTreeNode, - ) => Promise; + "codeQLTests.showOutputDifferences": (node: TestItem) => Promise; + "codeQLTests.acceptOutput": (node: TestItem) => Promise; + "codeQLTests.acceptOutputContextTestItem": (node: TestItem) => Promise; }; export type MockGitHubApiServerCommands = { diff --git a/extensions/ql-vscode/src/extension.ts b/extensions/ql-vscode/src/extension.ts index 8a2ce6a6c..58be99fad 100644 --- a/extensions/ql-vscode/src/extension.ts +++ b/extensions/ql-vscode/src/extension.ts @@ -15,8 +15,6 @@ import { arch, homedir, platform } from "os"; import { ensureDir } from "fs-extra"; import { join } from "path"; import { dirSync } from "tmp-promise"; -import type { TestHub } from "vscode-test-adapter-api"; -import { testExplorerExtensionId } from "vscode-test-adapter-api"; import { lt, parse } from "semver"; import { watch } from "chokidar"; import { @@ -28,7 +26,6 @@ import { CliConfigListener, DistributionConfigListener, GitHubDatabaseConfigListener, - isCanary, joinOrderWarningThreshold, QueryHistoryConfigListener, QueryServerConfigListener, @@ -90,8 +87,6 @@ import { } from "./common/logging/vscode"; import { QueryHistoryManager } from "./query-history/query-history-manager"; import type { CompletedLocalQueryInfo } from "./query-results"; -import { QLTestAdapterFactory } from "./query-testing/test-adapter"; -import { TestUIService } from "./query-testing/test-ui"; import { CompareView } from "./compare/compare-view"; import { initializeTelemetry, @@ -130,7 +125,6 @@ import { DebuggerUI } from "./debugger/debugger-ui"; import { ModelEditorModule } from "./model-editor/model-editor-module"; import { TestManager } from "./query-testing/test-manager"; import { TestRunner } from "./query-testing/test-runner"; -import type { TestManagerBase } from "./query-testing/test-manager-base"; import { QueryRunner, QueryServerClient } from "./query-server"; import { QueriesModule } from "./queries-panel/queries-module"; import { OpenReferencedFileCodeLensProvider } from "./local-queries/open-referenced-file-code-lens-provider"; @@ -977,27 +971,8 @@ async function activateWithInstalledDistribution( const testRunner = new TestRunner(dbm, cliServer); ctx.subscriptions.push(testRunner); - let testManager: TestManagerBase | undefined = undefined; - if (isCanary()) { - testManager = new TestManager(app, testRunner, cliServer); - ctx.subscriptions.push(testManager); - } else { - const testExplorerExtension = extensions.getExtension( - testExplorerExtensionId, - ); - if (testExplorerExtension) { - const testHub = testExplorerExtension.exports; - const testAdapterFactory = new QLTestAdapterFactory( - testHub, - testRunner, - cliServer, - ); - ctx.subscriptions.push(testAdapterFactory); - - testManager = new TestUIService(app, testHub); - ctx.subscriptions.push(testManager); - } - } + const testManager = new TestManager(app, testRunner, cliServer); + ctx.subscriptions.push(testManager); const testUiCommands = testManager?.getCommands() ?? {}; diff --git a/extensions/ql-vscode/src/query-testing/test-adapter.ts b/extensions/ql-vscode/src/query-testing/test-adapter.ts index eef9a2672..afb9b47b7 100644 --- a/extensions/ql-vscode/src/query-testing/test-adapter.ts +++ b/extensions/ql-vscode/src/query-testing/test-adapter.ts @@ -1,26 +1,4 @@ import { extname } from "path"; -import type { Event, WorkspaceFolder } from "vscode"; -import { CancellationTokenSource, EventEmitter } from "vscode"; -import type { - TestAdapter, - TestEvent, - TestHub, - TestInfo, - TestLoadFinishedEvent, - TestLoadStartedEvent, - TestRunFinishedEvent, - TestRunStartedEvent, - TestSuiteEvent, - TestSuiteInfo, -} from "vscode-test-adapter-api"; -import { TestAdapterRegistrar } from "vscode-test-adapter-util"; -import { QLTestDiscovery } from "./qltest-discovery"; -import { DisposableObject } from "../common/disposable-object"; -import type { CodeQLCliServer, TestCompleted } from "../codeql-cli/cli"; -import { testLogger } from "../common/logging/vscode"; -import type { TestRunner } from "./test-runner"; -import type { FileTreeNode } from "../common/file-tree-nodes"; -import { FileTreeDirectory, FileTreeLeaf } from "../common/file-tree-nodes"; /** * Get the full path of the `.expected` file for the specified QL test. @@ -47,28 +25,6 @@ function getTestOutputFile(testPath: string, extension: string): string { return changeExtension(testPath, extension); } -/** - * A factory service that creates `QLTestAdapter` objects for workspace folders on demand. - */ -export class QLTestAdapterFactory extends DisposableObject { - constructor( - testHub: TestHub, - testRunner: TestRunner, - cliServer: CodeQLCliServer, - ) { - super(); - - // this will register a QLTestAdapter for each WorkspaceFolder - this.push( - new TestAdapterRegistrar( - testHub, - (workspaceFolder) => - new QLTestAdapter(workspaceFolder, testRunner, cliServer), - ), - ); - } -} - /** * Change the file extension of the specified path. * @param p The original file path. @@ -77,197 +33,3 @@ export class QLTestAdapterFactory extends DisposableObject { function changeExtension(p: string, ext: string): string { return p.slice(0, -extname(p).length) + ext; } - -/** - * Test adapter for QL tests. - */ -export class QLTestAdapter extends DisposableObject implements TestAdapter { - private readonly qlTestDiscovery: QLTestDiscovery; - private readonly _tests = this.push( - new EventEmitter(), - ); - private readonly _testStates = this.push( - new EventEmitter< - TestRunStartedEvent | TestRunFinishedEvent | TestSuiteEvent | TestEvent - >(), - ); - private readonly _autorun = this.push(new EventEmitter()); - private runningTask?: CancellationTokenSource = undefined; - - constructor( - public readonly workspaceFolder: WorkspaceFolder, - private readonly testRunner: TestRunner, - cliServer: CodeQLCliServer, - ) { - super(); - - this.qlTestDiscovery = this.push( - new QLTestDiscovery(workspaceFolder, cliServer), - ); - void this.qlTestDiscovery.refresh(); - - this.push(this.qlTestDiscovery.onDidChangeTests(this.discoverTests, this)); - } - - public get tests(): Event { - return this._tests.event; - } - - public get testStates(): Event< - TestRunStartedEvent | TestRunFinishedEvent | TestSuiteEvent | TestEvent - > { - return this._testStates.event; - } - - public get autorun(): Event | undefined { - return this._autorun.event; - } - - private static createTestOrSuiteInfos( - testNodes: readonly FileTreeNode[], - ): Array { - return testNodes.map((childNode) => { - return QLTestAdapter.createTestOrSuiteInfo(childNode); - }); - } - - private static createTestOrSuiteInfo( - testNode: FileTreeNode, - ): TestSuiteInfo | TestInfo { - if (testNode instanceof FileTreeLeaf) { - return QLTestAdapter.createTestInfo(testNode); - } else if (testNode instanceof FileTreeDirectory) { - return QLTestAdapter.createTestSuiteInfo(testNode, testNode.name); - } else { - throw new Error("Unexpected test type."); - } - } - - private static createTestInfo(testFile: FileTreeLeaf): TestInfo { - return { - type: "test", - id: testFile.path, - label: testFile.name, - tooltip: testFile.path, - file: testFile.path, - }; - } - - private static createTestSuiteInfo( - testDirectory: FileTreeDirectory, - label: string, - ): TestSuiteInfo { - return { - type: "suite", - id: testDirectory.path, - label, - children: QLTestAdapter.createTestOrSuiteInfos(testDirectory.children), - tooltip: testDirectory.path, - }; - } - - public async load(): Promise { - this.discoverTests(); - } - - private discoverTests(): void { - this._tests.fire({ type: "started" } as TestLoadStartedEvent); - - const testDirectory = this.qlTestDiscovery.testDirectory; - let testSuite: TestSuiteInfo | undefined; - if (testDirectory?.children.length) { - const children = QLTestAdapter.createTestOrSuiteInfos( - testDirectory.children, - ); - testSuite = { - type: "suite", - label: "CodeQL", - id: testDirectory.path, - children, - }; - } - this._tests.fire({ - type: "finished", - suite: testSuite, - } as TestLoadFinishedEvent); - } - - public async run(tests: string[]): Promise { - if (this.runningTask !== undefined) { - throw new Error("Tests already running."); - } - - testLogger.outputChannel.clear(); - testLogger.outputChannel.show(true); - - this.runningTask = this.track(new CancellationTokenSource()); - const token = this.runningTask.token; - - this._testStates.fire({ - type: "started", - tests, - } as TestRunStartedEvent); - - await this.testRunner.run(tests, testLogger, token, (event) => - this.processTestEvent(event), - ); - - this._testStates.fire({ type: "finished" } as TestRunFinishedEvent); - this.clearTask(); - } - - private clearTask(): void { - if (this.runningTask !== undefined) { - const runningTask = this.runningTask; - this.runningTask = undefined; - this.disposeAndStopTracking(runningTask); - } - } - - public cancel(): void { - if (this.runningTask !== undefined) { - void testLogger.log("Cancelling test run..."); - this.runningTask.cancel(); - this.clearTask(); - } - } - - private async processTestEvent(event: TestCompleted): Promise { - const state = event.pass - ? "passed" - : event.messages?.length - ? "errored" - : "failed"; - let message: string | undefined; - if (event.failureDescription || event.diff?.length) { - message = - event.failureStage === "RESULT" - ? [ - "", - `${state}: ${event.test}`, - event.failureDescription || event.diff?.join("\n"), - "", - ].join("\n") - : [ - "", - `${event.failureStage?.toLowerCase() ?? "unknown stage"} error: ${ - event.test - }`, - event.failureDescription || - `${event.messages[0].severity}: ${event.messages[0].message}`, - "", - ].join("\n"); - void testLogger.log(message); - } - this._testStates.fire({ - type: "test", - state, - test: event.test, - message, - decorations: event.messages?.map((msg) => ({ - line: msg.position.line, - message: msg.message, - })), - }); - } -} diff --git a/extensions/ql-vscode/src/query-testing/test-manager-base.ts b/extensions/ql-vscode/src/query-testing/test-manager-base.ts index 75d92d4f4..e7f7e18a3 100644 --- a/extensions/ql-vscode/src/query-testing/test-manager-base.ts +++ b/extensions/ql-vscode/src/query-testing/test-manager-base.ts @@ -6,9 +6,8 @@ import type { TestItem, TextDocumentShowOptions } from "vscode"; import { Uri, window } from "vscode"; import { basename } from "path"; import type { App } from "../common/app"; -import type { TestTreeNode } from "./test-tree-node"; -type TestNode = TestTreeNode | TestItem; +type TestNode = TestItem; /** * Base class for both the legacy and new test services. Implements commands that are common to diff --git a/extensions/ql-vscode/src/query-testing/test-tree-node.ts b/extensions/ql-vscode/src/query-testing/test-tree-node.ts deleted file mode 100644 index 0cd6a6d54..000000000 --- a/extensions/ql-vscode/src/query-testing/test-tree-node.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { TestSuiteInfo, TestInfo } from "vscode-test-adapter-api"; - -/** - * Tree view node for a test, suite, or collection. This object is passed as the argument to the - * command handler of a context menu item for a tree view item. - */ -export interface TestTreeNode { - readonly info: TestSuiteInfo | TestInfo; -} diff --git a/extensions/ql-vscode/src/query-testing/test-ui.ts b/extensions/ql-vscode/src/query-testing/test-ui.ts deleted file mode 100644 index c45fc01a9..000000000 --- a/extensions/ql-vscode/src/query-testing/test-ui.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { - TestHub, - TestController, - TestAdapter, - TestRunStartedEvent, - TestRunFinishedEvent, - TestEvent, - TestSuiteEvent, -} from "vscode-test-adapter-api"; -import type { TestTreeNode } from "./test-tree-node"; -import { DisposableObject } from "../common/disposable-object"; -import { QLTestAdapter } from "./test-adapter"; -import type { App } from "../common/app"; -import { TestManagerBase } from "./test-manager-base"; - -type VSCodeTestEvent = - | TestRunStartedEvent - | TestRunFinishedEvent - | TestSuiteEvent - | TestEvent; - -/** - * Test event listener. Currently unused, but left in to keep the plumbing hooked up for future use. - */ -class QLTestListener extends DisposableObject { - constructor(adapter: TestAdapter) { - super(); - - this.push(adapter.testStates(this.onTestStatesEvent, this)); - } - - private onTestStatesEvent(_e: VSCodeTestEvent): void { - /**/ - } -} - -/** - * Service that implements all UI and commands for QL tests. - */ -export class TestUIService extends TestManagerBase implements TestController { - private readonly listeners: Map = new Map(); - - public constructor( - app: App, - private readonly testHub: TestHub, - ) { - super(app); - - testHub.registerTestController(this); - } - - public dispose(): void { - this.testHub.unregisterTestController(this); - - super.dispose(); - } - - public registerTestAdapter(adapter: TestAdapter): void { - this.listeners.set(adapter, new QLTestListener(adapter)); - } - - public unregisterTestAdapter(adapter: TestAdapter): void { - if (adapter instanceof QLTestAdapter) { - this.listeners.delete(adapter); - } - } - - protected getTestPath(node: TestTreeNode): string { - return node.info.id; - } -} diff --git a/extensions/ql-vscode/test/vscode-tests/jest-runner-installed-extensions.ts b/extensions/ql-vscode/test/vscode-tests/jest-runner-installed-extensions.ts index 40bca3e6f..869ce06ba 100644 --- a/extensions/ql-vscode/test/vscode-tests/jest-runner-installed-extensions.ts +++ b/extensions/ql-vscode/test/vscode-tests/jest-runner-installed-extensions.ts @@ -50,20 +50,10 @@ export default class JestRunnerInstalledExtensions extends VSCodeTestRunner { const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); - spawnSync( - cli, - [ - ...args, - "--install-extension", - "hbenl.vscode-test-explorer", - "--install-extension", - "ms-vscode.test-adapter-converter", - ], - { - encoding: "utf-8", - stdio: "inherit", - }, - ); + spawnSync(cli, args, { + encoding: "utf-8", + stdio: "inherit", + }); installedOnVsCodeVersions.add(versionKey); }