Merge branch 'main' into robertbrignull/use_app_commands_3

This commit is contained in:
Robert
2023-03-24 11:41:16 +00:00
29 changed files with 1149 additions and 375 deletions

View File

@@ -199,6 +199,7 @@ jobs:
run: echo "cli-versions=$(cat ./extensions/ql-vscode/supported_cli_versions.json | jq -rc)" >> $GITHUB_OUTPUT run: echo "cli-versions=$(cat ./extensions/ql-vscode/supported_cli_versions.json | jq -rc)" >> $GITHUB_OUTPUT
outputs: outputs:
cli-versions: ${{ steps.set-variables.outputs.cli-versions }} cli-versions: ${{ steps.set-variables.outputs.cli-versions }}
cli-test: cli-test:
name: CLI Test name: CLI Test
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}

File diff suppressed because it is too large Load Diff

View File

@@ -1441,12 +1441,11 @@
"classnames": "~2.2.6", "classnames": "~2.2.6",
"d3": "^7.6.1", "d3": "^7.6.1",
"d3-graphviz": "^5.0.2", "d3-graphviz": "^5.0.2",
"fs-extra": "^10.0.1", "fs-extra": "^11.1.1",
"glob-promise": "^6.0.2",
"immutable": "^4.0.0", "immutable": "^4.0.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"minimist": "~1.2.6", "minimist": "~1.2.6",
"msw": "^0.49.0", "msw": "^1.2.0",
"nanoid": "^3.2.0", "nanoid": "^3.2.0",
"node-fetch": "~2.6.7", "node-fetch": "~2.6.7",
"p-queue": "^6.0.0", "p-queue": "^6.0.0",
@@ -1492,8 +1491,7 @@
"@types/d3": "^7.4.0", "@types/d3": "^7.4.0",
"@types/d3-graphviz": "^2.6.6", "@types/d3-graphviz": "^2.6.6",
"@types/del": "^4.0.0", "@types/del": "^4.0.0",
"@types/fs-extra": "^9.0.6", "@types/fs-extra": "^11.0.1",
"@types/glob": "^7.1.1",
"@types/google-protobuf": "^3.2.7", "@types/google-protobuf": "^3.2.7",
"@types/gulp": "^4.0.9", "@types/gulp": "^4.0.9",
"@types/gulp-replace": "^1.1.0", "@types/gulp-replace": "^1.1.0",
@@ -1539,7 +1537,7 @@
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-storybook": "^0.6.4", "eslint-plugin-storybook": "^0.6.4",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"glob": "^7.1.4", "glob": "^9.3.2",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-esbuild": "^0.10.5", "gulp-esbuild": "^0.10.5",
"gulp-replace": "^1.1.3", "gulp-replace": "^1.1.3",
@@ -1573,8 +1571,5 @@
"prettier --write", "prettier --write",
"eslint --fix" "eslint --fix"
] ]
},
"resolutions": {
"glob-parent": "6.0.0"
} }
} }

View File

@@ -289,7 +289,7 @@ const MIN_VERSION = "1.67.0";
*/ */
export async function activate( export async function activate(
ctx: ExtensionContext, ctx: ExtensionContext,
): Promise<CodeQLExtensionInterface | Record<string, never>> { ): Promise<CodeQLExtensionInterface | undefined> {
void extLogger.log(`Starting ${extensionId} extension`); void extLogger.log(`Starting ${extensionId} extension`);
if (extension === undefined) { if (extension === undefined) {
throw new Error(`Can't find extension ${extensionId}`); throw new Error(`Can't find extension ${extensionId}`);
@@ -379,9 +379,11 @@ export async function activate(
}, },
); );
variantAnalysisViewSerializer.onExtensionLoaded( if (codeQlExtension !== undefined) {
codeQlExtension.variantAnalysisManager, variantAnalysisViewSerializer.onExtensionLoaded(
); codeQlExtension.variantAnalysisManager,
);
}
return codeQlExtension; return codeQlExtension;
} }
@@ -571,7 +573,7 @@ async function installOrUpdateThenTryActivate(
distributionManager: DistributionManager, distributionManager: DistributionManager,
distributionConfigListener: DistributionConfigListener, distributionConfigListener: DistributionConfigListener,
config: DistributionUpdateConfig, config: DistributionUpdateConfig,
): Promise<CodeQLExtensionInterface | Record<string, never>> { ): Promise<CodeQLExtensionInterface | undefined> {
await installOrUpdateDistribution(ctx, app, distributionManager, config); await installOrUpdateDistribution(ctx, app, distributionManager, config);
try { try {
@@ -585,20 +587,19 @@ async function installOrUpdateThenTryActivate(
// Display the warnings even if the extension has already activated. // Display the warnings even if the extension has already activated.
const distributionResult = const distributionResult =
await getDistributionDisplayingDistributionWarnings(distributionManager); await getDistributionDisplayingDistributionWarnings(distributionManager);
let extensionInterface: CodeQLExtensionInterface | Record<string, never> = {};
if ( if (
!beganMainExtensionActivation && !beganMainExtensionActivation &&
distributionResult.kind !== FindDistributionResultKind.NoDistribution distributionResult.kind !== FindDistributionResultKind.NoDistribution
) { ) {
extensionInterface = await activateWithInstalledDistribution( return await activateWithInstalledDistribution(
ctx, ctx,
app, app,
distributionManager, distributionManager,
distributionConfigListener, distributionConfigListener,
); );
} else if ( }
distributionResult.kind === FindDistributionResultKind.NoDistribution
) { if (distributionResult.kind === FindDistributionResultKind.NoDistribution) {
registerErrorStubs([checkForUpdatesCommand], (command) => async () => { registerErrorStubs([checkForUpdatesCommand], (command) => async () => {
const installActionName = "Install CodeQL CLI"; const installActionName = "Install CodeQL CLI";
const chosenAction = await showAndLogErrorMessage( const chosenAction = await showAndLogErrorMessage(
@@ -622,7 +623,7 @@ async function installOrUpdateThenTryActivate(
} }
}); });
} }
return extensionInterface; return undefined;
} }
const PACK_GLOBS = [ const PACK_GLOBS = [

View File

@@ -6,7 +6,7 @@ import {
writeFile, writeFile,
opendir, opendir,
} from "fs-extra"; } from "fs-extra";
import { promise as glob } from "glob-promise"; import { glob } from "glob";
import { load } from "js-yaml"; import { load } from "js-yaml";
import { join, basename } from "path"; import { join, basename } from "path";
import { dirSync } from "tmp-promise"; import { dirSync } from "tmp-promise";
@@ -515,7 +515,9 @@ export async function getQlPackForDbscheme(
export async function getPrimaryDbscheme( export async function getPrimaryDbscheme(
datasetFolder: string, datasetFolder: string,
): Promise<string> { ): Promise<string> {
const dbschemes = await glob(join(datasetFolder, "*.dbscheme")); const dbschemes = await glob("*.dbscheme", {
cwd: datasetFolder,
});
if (dbschemes.length < 1) { if (dbschemes.length < 1) {
throw new Error( throw new Error(

View File

@@ -33,7 +33,7 @@ import { redactableError } from "../pure/errors";
export class QueryInProgress { export class QueryInProgress {
public queryEvalInfo: QueryEvaluationInfo; public queryEvalInfo: QueryEvaluationInfo;
/** /**
* Note that in the {@link deserializeQueryHistory} method, we create a QueryEvaluationInfo instance * Note that in the {@link readQueryHistoryFromFile} method, we create a QueryEvaluationInfo instance
* by explicitly setting the prototype in order to avoid calling this constructor. * by explicitly setting the prototype in order to avoid calling this constructor.
*/ */
constructor( constructor(

View File

@@ -1,5 +1,5 @@
import { pathExists, stat, remove } from "fs-extra"; import { pathExists, stat, remove } from "fs-extra";
import { promise as glob } from "glob-promise"; import { glob } from "glob";
import { join, basename, resolve, relative, dirname, extname } from "path"; import { join, basename, resolve, relative, dirname, extname } from "path";
import * as vscode from "vscode"; import * as vscode from "vscode";
import * as cli from "./cli"; import * as cli from "./cli";

View File

@@ -1,6 +1,6 @@
import { join, resolve } from "path"; import { join, resolve } from "path";
import { pathExists } from "fs-extra"; import { pathExists } from "fs-extra";
import { setupServer, SetupServerApi } from "msw/node"; import { setupServer, SetupServer } from "msw/node";
import { DisposableObject } from "../pure/disposable-object"; import { DisposableObject } from "../pure/disposable-object";
@@ -14,7 +14,7 @@ import { getDirectoryNamesInsidePath } from "../pure/files";
export class MockGitHubApiServer extends DisposableObject { export class MockGitHubApiServer extends DisposableObject {
private _isListening: boolean; private _isListening: boolean;
private readonly server: SetupServerApi; private readonly server: SetupServer;
private readonly recorder: Recorder; private readonly recorder: Recorder;
constructor() { constructor() {

View File

@@ -2,7 +2,7 @@ import { ensureDir, writeFile } from "fs-extra";
import { join } from "path"; import { join } from "path";
import { MockedRequest } from "msw"; import { MockedRequest } from "msw";
import { SetupServerApi } from "msw/node"; import { SetupServer } from "msw/node";
import { IsomorphicResponse } from "@mswjs/interceptors"; import { IsomorphicResponse } from "@mswjs/interceptors";
import { Headers } from "headers-polyfill"; import { Headers } from "headers-polyfill";
@@ -22,7 +22,7 @@ export class Recorder extends DisposableObject {
private _isRecording = false; private _isRecording = false;
constructor(private readonly server: SetupServerApi) { constructor(private readonly server: SetupServer) {
super(); super();
this.onRequestStart = this.onRequestStart.bind(this); this.onRequestStart = this.onRequestStart.bind(this);
this.onResponseBypass = this.onResponseBypass.bind(this); this.onResponseBypass = this.onResponseBypass.bind(this);
@@ -88,13 +88,18 @@ export class Recorder extends DisposableObject {
const bodyFileName = `${i}-${writtenRequest.request.kind}.body.${extension}`; const bodyFileName = `${i}-${writtenRequest.request.kind}.body.${extension}`;
const bodyFilePath = join(scenarioDirectory, bodyFileName); const bodyFilePath = join(scenarioDirectory, bodyFileName);
await writeFile(bodyFilePath, writtenRequest.response.body);
let bodyFileLink = undefined;
if (writtenRequest.response.body) {
await writeFile(bodyFilePath, writtenRequest.response.body || "");
bodyFileLink = `file:${bodyFileName}`;
}
writtenRequest = { writtenRequest = {
...writtenRequest, ...writtenRequest,
response: { response: {
...writtenRequest.response, ...writtenRequest.response,
body: `file:${bodyFileName}`, body: bodyFileLink,
}, },
}; };
} }

View File

@@ -40,8 +40,8 @@ import {
variantAnalysisStatusToQueryStatus, variantAnalysisStatusToQueryStatus,
} from "../query-status"; } from "../query-status";
import { import {
deserializeQueryHistory, readQueryHistoryFromFile,
serializeQueryHistory, writeQueryHistoryToFile,
} from "./store/query-history-store"; } from "./store/query-history-store";
import { pathExists } from "fs-extra"; import { pathExists } from "fs-extra";
import { CliVersionConstraint } from "../cli"; import { CliVersionConstraint } from "../cli";
@@ -379,7 +379,7 @@ export class QueryHistoryManager extends DisposableObject {
void extLogger.log( void extLogger.log(
`Reading cached query history from '${this.queryMetadataStorageLocation}'.`, `Reading cached query history from '${this.queryMetadataStorageLocation}'.`,
); );
const history = await deserializeQueryHistory( const history = await readQueryHistoryFromFile(
this.queryMetadataStorageLocation, this.queryMetadataStorageLocation,
); );
this.treeDataProvider.allHistory = history; this.treeDataProvider.allHistory = history;
@@ -395,7 +395,7 @@ export class QueryHistoryManager extends DisposableObject {
} }
async writeQueryHistory(): Promise<void> { async writeQueryHistory(): Promise<void> {
await serializeQueryHistory( await writeQueryHistoryToFile(
this.treeDataProvider.allHistory, this.treeDataProvider.allHistory,
this.queryMetadataStorageLocation, this.queryMetadataStorageLocation,
); );

View File

@@ -14,7 +14,7 @@ import { QueryEvaluationInfo } from "../../run-queries-shared";
import { QueryResultType } from "../../pure/legacy-messages"; import { QueryResultType } from "../../pure/legacy-messages";
import { redactableError } from "../../pure/errors"; import { redactableError } from "../../pure/errors";
export async function deserializeQueryHistory( export async function readQueryHistoryFromFile(
fsPath: string, fsPath: string,
): Promise<QueryHistoryInfo[]> { ): Promise<QueryHistoryInfo[]> {
try { try {
@@ -109,7 +109,7 @@ export async function deserializeQueryHistory(
* @param queries the list of queries to save. * @param queries the list of queries to save.
* @param fsPath the path to save the queries to. * @param fsPath the path to save the queries to.
*/ */
export async function serializeQueryHistory( export async function writeQueryHistoryToFile(
queries: QueryHistoryInfo[], queries: QueryHistoryInfo[],
fsPath: string, fsPath: string,
): Promise<void> { ): Promise<void> {

View File

@@ -70,7 +70,7 @@ export class CompletedQueryInfo implements QueryWithResults {
interpretedResultsSortState: InterpretedResultsSortState | undefined; interpretedResultsSortState: InterpretedResultsSortState | undefined;
/** /**
* Note that in the {@link deserializeQueryHistory} method, we create a CompletedQueryInfo instance * Note that in the {@link readQueryHistoryFromFile} method, we create a CompletedQueryInfo instance
* by explicitly setting the prototype in order to avoid calling this constructor. * by explicitly setting the prototype in order to avoid calling this constructor.
*/ */
constructor(evaluation: QueryWithResults) { constructor(evaluation: QueryWithResults) {
@@ -224,7 +224,7 @@ export class LocalQueryInfo {
public evalLogSummarySymbolsLocation: string | undefined; public evalLogSummarySymbolsLocation: string | undefined;
/** /**
* Note that in the {@link deserializeQueryHistory} method, we create a FullQueryInfo instance * Note that in the {@link readQueryHistoryFromFile} method, we create a FullQueryInfo instance
* by explicitly setting the prototype in order to avoid calling this constructor. * by explicitly setting the prototype in order to avoid calling this constructor.
*/ */
constructor( constructor(

View File

@@ -68,7 +68,7 @@ function findQueryEvalLogEndSummaryFile(resultPath: string): string {
export class QueryEvaluationInfo { export class QueryEvaluationInfo {
/** /**
* Note that in the {@link deserializeQueryHistory} method, we create a QueryEvaluationInfo instance * Note that in the {@link readQueryHistoryFromFile} method, we create a QueryEvaluationInfo instance
* by explicitly setting the prototype in order to avoid calling this constructor. * by explicitly setting the prototype in order to avoid calling this constructor.
*/ */
constructor( constructor(

View File

@@ -1,6 +1,5 @@
import { commands, extensions, window } from "vscode"; import { commands, window } from "vscode";
import { CodeQLExtensionInterface } from "../../../../src/extension";
import { readJson } from "fs-extra"; import { readJson } from "fs-extra";
import * as path from "path"; import * as path from "path";
import { import {
@@ -15,19 +14,15 @@ import { DbListKind } from "../../../../src/databases/db-item";
import { createDbTreeViewItemSystemDefinedList } from "../../../../src/databases/ui/db-tree-view-item"; import { createDbTreeViewItemSystemDefinedList } from "../../../../src/databases/ui/db-tree-view-item";
import { createRemoteSystemDefinedListDbItem } from "../../../factories/db-item-factories"; import { createRemoteSystemDefinedListDbItem } from "../../../factories/db-item-factories";
import { DbConfigStore } from "../../../../src/databases/config/db-config-store"; import { DbConfigStore } from "../../../../src/databases/config/db-config-store";
import { getActivatedExtension } from "../../global.helper";
jest.setTimeout(60_000); jest.setTimeout(60_000);
describe("Db panel UI commands", () => { describe("Db panel UI commands", () => {
let extension: CodeQLExtensionInterface | Record<string, never>;
let storagePath: string; let storagePath: string;
beforeEach(async () => { beforeEach(async () => {
extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>(
"GitHub.vscode-codeql",
)!
.activate();
storagePath = storagePath =
extension.ctx.storageUri?.fsPath || extension.ctx.globalStorageUri.fsPath; extension.ctx.storageUri?.fsPath || extension.ctx.globalStorageUri.fsPath;

View File

@@ -1,14 +1,12 @@
import { import {
commands, commands,
env, env,
extensions,
TextDocument, TextDocument,
TextEditor, TextEditor,
Uri, Uri,
window, window,
workspace, workspace,
} from "vscode"; } from "vscode";
import { CodeQLExtensionInterface } from "../../../../src/extension";
import { extLogger } from "../../../../src/common"; import { extLogger } from "../../../../src/common";
import * as ghApiClient from "../../../../src/variant-analysis/gh-api/gh-api-client"; import * as ghApiClient from "../../../../src/variant-analysis/gh-api/gh-api-client";
import * as ghActionsApiClient from "../../../../src/variant-analysis/gh-api/gh-actions-api-client"; import * as ghActionsApiClient from "../../../../src/variant-analysis/gh-api/gh-actions-api-client";
@@ -20,7 +18,7 @@ import { Response } from "node-fetch";
import { VariantAnalysisManager } from "../../../../src/variant-analysis/variant-analysis-manager"; import { VariantAnalysisManager } from "../../../../src/variant-analysis/variant-analysis-manager";
import { CodeQLCliServer } from "../../../../src/cli"; import { CodeQLCliServer } from "../../../../src/cli";
import { storagePath } from "../../global.helper"; import { getActivatedExtension, storagePath } from "../../global.helper";
import { VariantAnalysisResultsManager } from "../../../../src/variant-analysis/variant-analysis-results-manager"; import { VariantAnalysisResultsManager } from "../../../../src/variant-analysis/variant-analysis-results-manager";
import { createMockVariantAnalysis } from "../../../factories/variant-analysis/shared/variant-analysis"; import { createMockVariantAnalysis } from "../../../factories/variant-analysis/shared/variant-analysis";
import * as VariantAnalysisModule from "../../../../src/variant-analysis/shared/variant-analysis"; import * as VariantAnalysisModule from "../../../../src/variant-analysis/shared/variant-analysis";
@@ -67,11 +65,7 @@ describe("Variant Analysis Manager", () => {
scannedRepos, scannedRepos,
}); });
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>(
"GitHub.vscode-codeql",
)!
.activate();
const cli = mockedObject<CodeQLCliServer>({}); const cli = mockedObject<CodeQLCliServer>({});
app = new ExtensionApp(extension.ctx); app = new ExtensionApp(extension.ctx);
const dbManager = new DbManager(app, new DbConfigStore(app)); const dbManager = new DbManager(app, new DbConfigStore(app));

View File

@@ -1,14 +1,19 @@
import { join } from "path"; import { join } from "path";
import { extensions, CancellationToken, Uri, window } from "vscode"; import { CancellationToken, Uri, window } from "vscode";
import { CodeQLExtensionInterface } from "../../../src/extension";
import { CodeQLCliServer } from "../../../src/cli"; import { CodeQLCliServer } from "../../../src/cli";
import { DatabaseManager } from "../../../src/local-databases"; import { DatabaseManager } from "../../../src/local-databases";
import { import {
importArchiveDatabase, importArchiveDatabase,
promptImportInternetDatabase, promptImportInternetDatabase,
} from "../../../src/databaseFetcher"; } from "../../../src/databaseFetcher";
import { cleanDatabases, dbLoc, DB_URL, storagePath } from "../global.helper"; import {
cleanDatabases,
dbLoc,
DB_URL,
getActivatedExtension,
storagePath,
} from "../global.helper";
import { createMockCommandManager } from "../../__mocks__/commandsMock"; import { createMockCommandManager } from "../../__mocks__/commandsMock";
jest.setTimeout(60_000); jest.setTimeout(60_000);
@@ -30,18 +35,8 @@ describe("DatabaseFetcher", () => {
jest.spyOn(window, "showErrorMessage").mockResolvedValue(undefined); jest.spyOn(window, "showErrorMessage").mockResolvedValue(undefined);
jest.spyOn(window, "showInformationMessage").mockResolvedValue(undefined); jest.spyOn(window, "showInformationMessage").mockResolvedValue(undefined);
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>( databaseManager = extension.databaseManager;
"GitHub.vscode-codeql",
)!
.activate();
if ("databaseManager" in extension) {
databaseManager = extension.databaseManager;
} else {
throw new Error(
"Extension not initialized. Make sure cli is downloaded and installed properly.",
);
}
await cleanDatabases(databaseManager); await cleanDatabases(databaseManager);
}); });

View File

@@ -1,9 +1,8 @@
import { join } from "path"; import { join } from "path";
import { extensions } from "vscode";
import { CodeQLCliServer } from "../../../src/cli"; import { CodeQLCliServer } from "../../../src/cli";
import { CodeQLExtensionInterface } from "../../../src/extension";
import { tryGetQueryMetadata } from "../../../src/helpers"; import { tryGetQueryMetadata } from "../../../src/helpers";
import { getActivatedExtension } from "../global.helper";
// up to 3 minutes per test // up to 3 minutes per test
jest.setTimeout(3 * 60 * 1000); jest.setTimeout(3 * 60 * 1000);
@@ -14,18 +13,8 @@ describe("helpers (with CLI)", () => {
let cli: CodeQLCliServer; let cli: CodeQLCliServer;
beforeEach(async () => { beforeEach(async () => {
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>( cli = extension.cliServer;
"GitHub.vscode-codeql",
)!
.activate();
if ("cliServer" in extension) {
cli = extension.cliServer;
} else {
throw new Error(
"Extension not initialized. Make sure cli is downloaded and installed properly.",
);
}
}); });
it("should get query metadata when available", async () => { it("should get query metadata when available", async () => {

View File

@@ -7,12 +7,11 @@ import * as messages from "../../../src/pure/legacy-messages";
import * as qsClient from "../../../src/legacy-query-server/queryserver-client"; import * as qsClient from "../../../src/legacy-query-server/queryserver-client";
import * as cli from "../../../src/cli"; import * as cli from "../../../src/cli";
import { CellValue } from "../../../src/pure/bqrs-cli-types"; import { CellValue } from "../../../src/pure/bqrs-cli-types";
import { extensions } from "vscode";
import { CodeQLExtensionInterface } from "../../../src/extension";
import { describeWithCodeQL } from "../cli"; import { describeWithCodeQL } from "../cli";
import { QueryServerClient } from "../../../src/legacy-query-server/queryserver-client"; import { QueryServerClient } from "../../../src/legacy-query-server/queryserver-client";
import { extLogger, ProgressReporter } from "../../../src/common"; import { extLogger, ProgressReporter } from "../../../src/common";
import { createMockApp } from "../../__mocks__/appMock"; import { createMockApp } from "../../__mocks__/appMock";
import { getActivatedExtension } from "../global.helper";
const baseDir = join(__dirname, "../../../test/data"); const baseDir = join(__dirname, "../../../test/data");
@@ -112,41 +111,30 @@ describeWithCodeQL()("using the legacy query server", () => {
let cliServer: cli.CodeQLCliServer; let cliServer: cli.CodeQLCliServer;
beforeAll(async () => { beforeAll(async () => {
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>( cliServer = extension.cliServer;
"GitHub.vscode-codeql", cliServer.quiet = true;
)!
.activate();
if ("cliServer" in extension) {
cliServer = extension.cliServer;
cliServer.quiet = true;
qs = new QueryServerClient( qs = new QueryServerClient(
createMockApp({}), createMockApp({}),
{ {
codeQlPath: codeQlPath:
(await extension.distributionManager.getCodeQlPathWithoutVersionCheck()) || (await extension.distributionManager.getCodeQlPathWithoutVersionCheck()) ||
"", "",
debug: false, debug: false,
cacheSize: 0, cacheSize: 0,
numThreads: 1, numThreads: 1,
saveCache: false, saveCache: false,
timeoutSecs: 0, timeoutSecs: 0,
}, },
cliServer, cliServer,
{ {
contextStoragePath: tmpDir.name, contextStoragePath: tmpDir.name,
logger: extLogger, logger: extLogger,
}, },
(task) => (task) => task(nullProgressReporter, new CancellationTokenSource().token),
task(nullProgressReporter, new CancellationTokenSource().token), );
); await qs.startQueryServer();
await qs.startQueryServer();
} else {
throw new Error(
"Extension not initialized. Make sure cli is downloaded and installed properly.",
);
}
}); });
for (const queryTestCase of queryTestCases) { for (const queryTestCase of queryTestCases) {

View File

@@ -5,13 +5,17 @@ import * as messages from "../../../src/pure/new-messages";
import * as qsClient from "../../../src/query-server/queryserver-client"; import * as qsClient from "../../../src/query-server/queryserver-client";
import * as cli from "../../../src/cli"; import * as cli from "../../../src/cli";
import { CellValue } from "../../../src/pure/bqrs-cli-types"; import { CellValue } from "../../../src/pure/bqrs-cli-types";
import { extensions, Uri } from "vscode"; import { Uri } from "vscode";
import { CodeQLExtensionInterface } from "../../../src/extension";
import { describeWithCodeQL } from "../cli"; import { describeWithCodeQL } from "../cli";
import { QueryServerClient } from "../../../src/query-server/queryserver-client"; import { QueryServerClient } from "../../../src/query-server/queryserver-client";
import { extLogger, ProgressReporter } from "../../../src/common"; import { extLogger, ProgressReporter } from "../../../src/common";
import { QueryResultType } from "../../../src/pure/new-messages"; import { QueryResultType } from "../../../src/pure/new-messages";
import { cleanDatabases, dbLoc, storagePath } from "../global.helper"; import {
cleanDatabases,
dbLoc,
getActivatedExtension,
storagePath,
} from "../global.helper";
import { importArchiveDatabase } from "../../../src/databaseFetcher"; import { importArchiveDatabase } from "../../../src/databaseFetcher";
import { createMockApp } from "../../__mocks__/appMock"; import { createMockApp } from "../../__mocks__/appMock";
@@ -111,64 +115,53 @@ describeWithCodeQL()("using the new query server", () => {
beforeAll(async () => { beforeAll(async () => {
const app = createMockApp({}); const app = createMockApp({});
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>( cliServer = extension.cliServer;
"GitHub.vscode-codeql",
)!
.activate();
if ("cliServer" in extension && "databaseManager" in extension) {
cliServer = extension.cliServer;
cliServer.quiet = true; cliServer.quiet = true;
if (!(await cliServer.cliConstraints.supportsNewQueryServerForTests())) { if (!(await cliServer.cliConstraints.supportsNewQueryServerForTests())) {
supportNewQueryServer = false; supportNewQueryServer = false;
}
qs = new QueryServerClient(
app,
{
codeQlPath:
(await extension.distributionManager.getCodeQlPathWithoutVersionCheck()) ||
"",
debug: false,
cacheSize: 0,
numThreads: 1,
saveCache: false,
timeoutSecs: 0,
},
cliServer,
{
contextStoragePath: tmpDir.name,
logger: extLogger,
},
(task) =>
task(nullProgressReporter, new CancellationTokenSource().token),
);
await qs.startQueryServer();
// Unlike the old query sevre the new one wants a database and the empty direcrtory is not valid.
// Add a database, but make sure the database manager is empty first
await cleanDatabases(extension.databaseManager);
const uri = Uri.file(dbLoc);
const maybeDbItem = await importArchiveDatabase(
app.commands,
uri.toString(true),
extension.databaseManager,
storagePath,
() => {
/**ignore progress */
},
token,
);
if (!maybeDbItem) {
throw new Error("Could not import database");
}
db = maybeDbItem.databaseUri.fsPath;
} else {
throw new Error(
"Extension not initialized. Make sure cli is downloaded and installed properly.",
);
} }
qs = new QueryServerClient(
app,
{
codeQlPath:
(await extension.distributionManager.getCodeQlPathWithoutVersionCheck()) ||
"",
debug: false,
cacheSize: 0,
numThreads: 1,
saveCache: false,
timeoutSecs: 0,
},
cliServer,
{
contextStoragePath: tmpDir.name,
logger: extLogger,
},
(task) => task(nullProgressReporter, new CancellationTokenSource().token),
);
await qs.startQueryServer();
// Unlike the old query sevre the new one wants a database and the empty direcrtory is not valid.
// Add a database, but make sure the database manager is empty first
await cleanDatabases(extension.databaseManager);
const uri = Uri.file(dbLoc);
const maybeDbItem = await importArchiveDatabase(
app.commands,
uri.toString(true),
extension.databaseManager,
storagePath,
() => {
/**ignore progress */
},
token,
);
if (!maybeDbItem) {
throw new Error("Could not import database");
}
db = maybeDbItem.databaseUri.fsPath;
}); });
for (const queryTestCase of queryTestCases) { for (const queryTestCase of queryTestCases) {

View File

@@ -1,8 +1,7 @@
import { extensions, window } from "vscode"; import { window } from "vscode";
import { join } from "path"; import { join } from "path";
import { CodeQLCliServer } from "../../../src/cli"; import { CodeQLCliServer } from "../../../src/cli";
import { CodeQLExtensionInterface } from "../../../src/extension";
import { getErrorMessage } from "../../../src/pure/helpers-pure"; import { getErrorMessage } from "../../../src/pure/helpers-pure";
import * as helpers from "../../../src/helpers"; import * as helpers from "../../../src/helpers";
@@ -11,6 +10,7 @@ import {
handleInstallPackDependencies, handleInstallPackDependencies,
} from "../../../src/packaging"; } from "../../../src/packaging";
import { mockedQuickPickItem } from "../utils/mocking.helpers"; import { mockedQuickPickItem } from "../utils/mocking.helpers";
import { getActivatedExtension } from "../global.helper";
// up to 3 minutes per test // up to 3 minutes per test
jest.setTimeout(3 * 60 * 1000); jest.setTimeout(3 * 60 * 1000);
@@ -41,18 +41,8 @@ describe("Packaging commands", () => {
.spyOn(helpers, "showAndLogInformationMessage") .spyOn(helpers, "showAndLogInformationMessage")
.mockResolvedValue(undefined); .mockResolvedValue(undefined);
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>( cli = extension.cliServer;
"GitHub.vscode-codeql",
)!
.activate();
if ("cliServer" in extension) {
cli = extension.cliServer;
} else {
throw new Error(
"Extension not initialized. Make sure cli is downloaded and installed properly.",
);
}
}); });
it("should download all core query packs", async () => { it("should download all core query packs", async () => {

View File

@@ -1,10 +1,4 @@
import { import { CancellationToken, commands, ExtensionContext, Uri } from "vscode";
CancellationToken,
commands,
ExtensionContext,
extensions,
Uri,
} from "vscode";
import { join, dirname } from "path"; import { join, dirname } from "path";
import { import {
pathExistsSync, pathExistsSync,
@@ -16,8 +10,12 @@ import {
import { load, dump } from "js-yaml"; import { load, dump } from "js-yaml";
import { DatabaseItem, DatabaseManager } from "../../../src/local-databases"; import { DatabaseItem, DatabaseManager } from "../../../src/local-databases";
import { CodeQLExtensionInterface } from "../../../src/extension"; import {
import { cleanDatabases, dbLoc, storagePath } from "../global.helper"; cleanDatabases,
dbLoc,
getActivatedExtension,
storagePath,
} from "../global.helper";
import { importArchiveDatabase } from "../../../src/databaseFetcher"; import { importArchiveDatabase } from "../../../src/databaseFetcher";
import { CliVersionConstraint, CodeQLCliServer } from "../../../src/cli"; import { CliVersionConstraint, CodeQLCliServer } from "../../../src/cli";
import { describeWithCodeQL } from "../cli"; import { describeWithCodeQL } from "../cli";
@@ -48,26 +46,16 @@ describeWithCodeQL()("Queries", () => {
let qlFile: string; let qlFile: string;
beforeEach(async () => { beforeEach(async () => {
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>( databaseManager = extension.databaseManager;
"GitHub.vscode-codeql", cli = extension.cliServer;
)! qs = extension.qs;
.activate(); cli.quiet = true;
if ("databaseManager" in extension) { ctx = extension.ctx;
databaseManager = extension.databaseManager; qlpackFile = `${ctx.storageUri?.fsPath}/quick-queries/qlpack.yml`;
cli = extension.cliServer; qlpackLockFile = `${ctx.storageUri?.fsPath}/quick-queries/codeql-pack.lock.yml`;
qs = extension.qs; oldQlpackLockFile = `${ctx.storageUri?.fsPath}/quick-queries/qlpack.lock.yml`;
cli.quiet = true; qlFile = `${ctx.storageUri?.fsPath}/quick-queries/quick-query.ql`;
ctx = extension.ctx;
qlpackFile = `${ctx.storageUri?.fsPath}/quick-queries/qlpack.yml`;
qlpackLockFile = `${ctx.storageUri?.fsPath}/quick-queries/codeql-pack.lock.yml`;
oldQlpackLockFile = `${ctx.storageUri?.fsPath}/quick-queries/qlpack.lock.yml`;
qlFile = `${ctx.storageUri?.fsPath}/quick-queries/quick-query.ql`;
} else {
throw new Error(
"Extension not initialized. Make sure cli is downloaded and installed properly.",
);
}
// Ensure we are starting from a clean slate. // Ensure we are starting from a clean slate.
safeDel(qlFile); safeDel(qlFile);

View File

@@ -1,9 +1,8 @@
import { authentication, extensions, Uri } from "vscode"; import { authentication, Uri } from "vscode";
import { join } from "path"; import { join } from "path";
import { SemVer } from "semver"; import { SemVer } from "semver";
import { CodeQLCliServer, QueryInfoByLanguage } from "../../../src/cli"; import { CodeQLCliServer, QueryInfoByLanguage } from "../../../src/cli";
import { CodeQLExtensionInterface } from "../../../src/extension";
import { itWithCodeQL } from "../cli"; import { itWithCodeQL } from "../cli";
import { import {
getOnDiskWorkspaceFolders, getOnDiskWorkspaceFolders,
@@ -13,6 +12,7 @@ import {
import { resolveQueries } from "../../../src/contextual/queryResolver"; import { resolveQueries } from "../../../src/contextual/queryResolver";
import { KeyType } from "../../../src/contextual/keyType"; import { KeyType } from "../../../src/contextual/keyType";
import { faker } from "@faker-js/faker"; import { faker } from "@faker-js/faker";
import { getActivatedExtension } from "../global.helper";
jest.setTimeout(60_000); jest.setTimeout(60_000);
@@ -24,19 +24,9 @@ describe("Use cli", () => {
let supportedLanguages: string[]; let supportedLanguages: string[];
beforeEach(async () => { beforeEach(async () => {
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>( cli = extension.cliServer;
"GitHub.vscode-codeql", supportedLanguages = await cli.getSupportedLanguages();
)!
.activate();
if ("cliServer" in extension) {
cli = extension.cliServer;
supportedLanguages = await cli.getSupportedLanguages();
} else {
throw new Error(
"Extension not initialized. Make sure cli is downloaded and installed properly.",
);
}
}); });
if (process.env.CLI_VERSION && process.env.CLI_VERSION !== "nightly") { if (process.env.CLI_VERSION && process.env.CLI_VERSION !== "nightly") {

View File

@@ -1,11 +1,4 @@
import { import { CancellationTokenSource, commands, Uri, window } from "vscode";
CancellationTokenSource,
commands,
extensions,
Uri,
window,
} from "vscode";
import { CodeQLExtensionInterface } from "../../../../src/extension";
import { extLogger } from "../../../../src/common"; import { extLogger } from "../../../../src/common";
import { setRemoteControllerRepo } from "../../../../src/config"; import { setRemoteControllerRepo } from "../../../../src/config";
import * as ghApiClient from "../../../../src/variant-analysis/gh-api/gh-api-client"; import * as ghApiClient from "../../../../src/variant-analysis/gh-api/gh-api-client";
@@ -15,6 +8,7 @@ import { VariantAnalysisManager } from "../../../../src/variant-analysis/variant
import { CliVersionConstraint, CodeQLCliServer } from "../../../../src/cli"; import { CliVersionConstraint, CodeQLCliServer } from "../../../../src/cli";
import { import {
fixWorkspaceReferences, fixWorkspaceReferences,
getActivatedExtension,
restoreWorkspaceReferences, restoreWorkspaceReferences,
storagePath, storagePath,
} from "../../global.helper"; } from "../../global.helper";
@@ -48,11 +42,7 @@ describe("Variant Analysis Manager", () => {
cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource = new CancellationTokenSource();
const extension = await extensions const extension = await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>(
"GitHub.vscode-codeql",
)!
.activate();
cli = extension.cliServer; cli = extension.cliServer;
const app = new ExtensionApp(extension.ctx); const app = new ExtensionApp(extension.ctx);
const dbManager = new DbManager(app, new DbConfigStore(app)); const dbManager = new DbManager(app, new DbConfigStore(app));

View File

@@ -3,16 +3,15 @@ import { resolve } from "path";
import { import {
authentication, authentication,
commands, commands,
extensions,
TextDocument, TextDocument,
window, window,
workspace, workspace,
} from "vscode"; } from "vscode";
import { CodeQLExtensionInterface } from "../../../../src/extension";
import { MockGitHubApiServer } from "../../../../src/mocks/mock-gh-api-server"; import { MockGitHubApiServer } from "../../../../src/mocks/mock-gh-api-server";
import { mockedQuickPickItem } from "../../utils/mocking.helpers"; import { mockedQuickPickItem } from "../../utils/mocking.helpers";
import { setRemoteControllerRepo } from "../../../../src/config"; import { setRemoteControllerRepo } from "../../../../src/config";
import { getActivatedExtension } from "../../global.helper";
jest.setTimeout(30_000); jest.setTimeout(30_000);
@@ -55,11 +54,7 @@ describe("Variant Analysis Submission Integration", () => {
.spyOn(window, "showErrorMessage") .spyOn(window, "showErrorMessage")
.mockResolvedValue(undefined); .mockResolvedValue(undefined);
await extensions await getActivatedExtension();
.getExtension<CodeQLExtensionInterface | Record<string, never>>(
"GitHub.vscode-codeql",
)!
.activate();
}); });
describe("Successful scenario", () => { describe("Successful scenario", () => {

View File

@@ -1,10 +1,11 @@
import { join } from "path"; import { join } from "path";
import { load, dump } from "js-yaml"; import { load, dump } from "js-yaml";
import { realpathSync, readFileSync, writeFileSync } from "fs-extra"; import { realpathSync, readFileSync, writeFileSync } from "fs-extra";
import { commands } from "vscode"; import { commands, extensions } from "vscode";
import { DatabaseManager } from "../../src/local-databases"; import { DatabaseManager } from "../../src/local-databases";
import { CodeQLCliServer } from "../../src/cli"; import { CodeQLCliServer } from "../../src/cli";
import { removeWorkspaceRefs } from "../../src/variant-analysis/run-remote-query"; import { removeWorkspaceRefs } from "../../src/variant-analysis/run-remote-query";
import { CodeQLExtensionInterface } from "../../src/extension";
// This file contains helpers shared between tests that work with an activated extension. // This file contains helpers shared between tests that work with an activated extension.
@@ -23,6 +24,18 @@ export function setStoragePath(path: string) {
storagePath = path; storagePath = path;
} }
export async function getActivatedExtension(): Promise<CodeQLExtensionInterface> {
const extension = await extensions
.getExtension<CodeQLExtensionInterface | undefined>("GitHub.vscode-codeql")
?.activate();
if (extension === undefined) {
throw new Error(
"Unable to active CodeQL extension. Make sure cli is downloaded and installed properly.",
);
}
return extension;
}
export async function cleanDatabases(databaseManager: DatabaseManager) { export async function cleanDatabases(databaseManager: DatabaseManager) {
for (const item of databaseManager.databaseItems) { for (const item of databaseManager.databaseItems) {
await commands.executeCommand("codeQLDatabases.removeDatabase", item); await commands.executeCommand("codeQLDatabases.removeDatabase", item);

View File

@@ -1,13 +1,19 @@
import { CUSTOM_CODEQL_PATH_SETTING } from "../../src/config"; import { CUSTOM_CODEQL_PATH_SETTING } from "../../src/config";
import { ConfigurationTarget, env, extensions } from "vscode"; import { ConfigurationTarget, env } from "vscode";
import { beforeEachAction as testConfigBeforeEachAction } from "./test-config"; import { beforeEachAction as testConfigBeforeEachAction } from "./test-config";
import * as tmp from "tmp"; import * as tmp from "tmp";
import { realpathSync } from "fs-extra"; import { realpathSync } from "fs-extra";
import { setStoragePath, storagePath } from "./global.helper"; import {
getActivatedExtension,
setStoragePath,
storagePath,
} from "./global.helper";
jest.retryTimes(3, { if (process.env.CI) {
logErrorsBeforeRetry: true, jest.retryTimes(3, {
}); logErrorsBeforeRetry: true,
});
}
// create an extension storage location // create an extension storage location
let removeStorage: tmp.DirResult["removeCallback"] | undefined; let removeStorage: tmp.DirResult["removeCallback"] | undefined;
@@ -33,7 +39,7 @@ export async function beforeAllAction() {
removeStorage = dir.removeCallback; removeStorage = dir.removeCallback;
// Activate the extension // Activate the extension
await extensions.getExtension("GitHub.vscode-codeql")?.activate(); await getActivatedExtension();
} }
export async function beforeEachAction() { export async function beforeEachAction() {

View File

@@ -1,9 +1,11 @@
import { env } from "vscode"; import { env } from "vscode";
import { beforeEachAction } from "./test-config"; import { beforeEachAction } from "./test-config";
jest.retryTimes(3, { if (process.env.CI) {
logErrorsBeforeRetry: true, jest.retryTimes(3, {
}); logErrorsBeforeRetry: true,
});
}
beforeEach(async () => { beforeEach(async () => {
jest.spyOn(env, "openExternal").mockResolvedValue(false); jest.spyOn(env, "openExternal").mockResolvedValue(false);

View File

@@ -1,6 +1,6 @@
import { import {
deserializeQueryHistory, readQueryHistoryFromFile,
serializeQueryHistory, writeQueryHistoryToFile,
} from "../../../../../src/query-history/store/query-history-store"; } from "../../../../../src/query-history/store/query-history-store";
import { join } from "path"; import { join } from "path";
import { writeFileSync, mkdirpSync, writeFile } from "fs-extra"; import { writeFileSync, mkdirpSync, writeFile } from "fs-extra";
@@ -19,7 +19,7 @@ import { QueryHistoryInfo } from "../../../../../src/query-history/query-history
import { createMockVariantAnalysisHistoryItem } from "../../../../factories/query-history/variant-analysis-history-item"; import { createMockVariantAnalysisHistoryItem } from "../../../../factories/query-history/variant-analysis-history-item";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
describe("serialize and deserialize", () => { describe("write and read", () => {
let infoSuccessRaw: LocalQueryInfo; let infoSuccessRaw: LocalQueryInfo;
let infoSuccessInterpreted: LocalQueryInfo; let infoSuccessInterpreted: LocalQueryInfo;
let infoEarlyFailure: LocalQueryInfo; let infoEarlyFailure: LocalQueryInfo;
@@ -93,12 +93,12 @@ describe("serialize and deserialize", () => {
]; ];
}); });
it("should serialize and deserialize query history", async () => { it("should write and read query history", async () => {
const allHistoryPath = join(tmpDir.name, "workspace-query-history.json"); const allHistoryPath = join(tmpDir.name, "workspace-query-history.json");
// serialize and deserialize // write and read
await serializeQueryHistory(allHistory, allHistoryPath); await writeQueryHistoryToFile(allHistory, allHistoryPath);
const allHistoryActual = await deserializeQueryHistory(allHistoryPath); const allHistoryActual = await readQueryHistoryFromFile(allHistoryPath);
// the dispose methods will be different. Ignore them. // the dispose methods will be different. Ignore them.
allHistoryActual.forEach((info) => { allHistoryActual.forEach((info) => {
@@ -106,7 +106,7 @@ describe("serialize and deserialize", () => {
const completedQuery = info.completedQuery; const completedQuery = info.completedQuery;
(completedQuery as any).dispose = undefined; (completedQuery as any).dispose = undefined;
// these fields should be missing on the deserialized value // these fields should be missing on the read value
// but they are undefined on the original value // but they are undefined on the original value
if (!("logFileLocation" in completedQuery)) { if (!("logFileLocation" in completedQuery)) {
(completedQuery as any).logFileLocation = undefined; (completedQuery as any).logFileLocation = undefined;
@@ -181,7 +181,7 @@ describe("serialize and deserialize", () => {
"utf8", "utf8",
); );
const actual = await deserializeQueryHistory(path); const actual = await readQueryHistoryFromFile(path);
expect(actual.length).toEqual(expectedHistory.length); expect(actual.length).toEqual(expectedHistory.length);
}); });
@@ -196,7 +196,7 @@ describe("serialize and deserialize", () => {
"utf8", "utf8",
); );
const allHistoryActual = await deserializeQueryHistory(badPath); const allHistoryActual = await readQueryHistoryFromFile(badPath);
// version number is invalid. Should return an empty array. // version number is invalid. Should return an empty array.
expect(allHistoryActual).toEqual([]); expect(allHistoryActual).toEqual([]);
}); });

View File

@@ -1,4 +1,3 @@
import * as fs from "fs-extra";
import { Uri, WorkspaceFolder } from "vscode"; import { Uri, WorkspaceFolder } from "vscode";
import { QLTestAdapter } from "../../../src/test-adapter"; import { QLTestAdapter } from "../../../src/test-adapter";
@@ -19,8 +18,6 @@ jest.mock("fs-extra", () => {
}; };
}); });
const mockedFsExtra = jest.mocked(fs);
describe("test-adapter", () => { describe("test-adapter", () => {
let adapter: QLTestAdapter; let adapter: QLTestAdapter;
let fakeDatabaseManager: DatabaseManager; let fakeDatabaseManager: DatabaseManager;
@@ -131,8 +128,6 @@ describe("test-adapter", () => {
}); });
it("should reregister testproj databases around test run", async () => { it("should reregister testproj databases around test run", async () => {
mockedFsExtra.access.mockResolvedValue(undefined);
currentDatabaseItem = preTestDatabaseItem; currentDatabaseItem = preTestDatabaseItem;
databaseItems = [preTestDatabaseItem]; databaseItems = [preTestDatabaseItem];
await adapter.run(["/path/to/test/dir"]); await adapter.run(["/path/to/test/dir"]);