Skip to content

Commit 4c04daa

Browse files
Merge branch 'main' into elena/improvements-to-wizard
2 parents a6ffb6b + a48b1f8 commit 4c04daa

File tree

9 files changed

+230
-65
lines changed

9 files changed

+230
-65
lines changed

extensions/ql-vscode/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
## [UNRELEASED]
44

5+
## 1.8.2 - 12 April 2023
6+
7+
- Fix bug where users could end up with the managed CodeQL CLI getting uninstalled during upgrades and not reinstalled. [#2294](https://github.com/github/vscode-codeql/pull/2294)
58
- Fix bug that was causing code flows to not get updated when switching between results. [#2288](https://github.com/github/vscode-codeql/pull/2288)
69
- Restart the CodeQL language server whenever the _CodeQL: Restart Query Server_ command is invoked. This avoids bugs where the CLI version changes to support new language features, but the language server is not updated. [#2238](https://github.com/github/vscode-codeql/pull/2238)
10+
- Avoid requiring a manual restart of the query server when the [external CLI config file](https://docs.github.com/en/code-security/codeql-cli/using-the-codeql-cli/specifying-command-options-in-a-codeql-configuration-file#using-a-codeql-configuration-file) changes. [#2289](https://github.com/github/vscode-codeql/pull/2289)
711

812
## 1.8.1 - 23 March 2023
913

extensions/ql-vscode/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "CodeQL for Visual Studio Code",
55
"author": "GitHub",
66
"private": true,
7-
"version": "1.8.2",
7+
"version": "1.8.3",
88
"publisher": "GitHub",
99
"license": "MIT",
1010
"icon": "media/VS-marketplace-CodeQL-icon.png",

extensions/ql-vscode/src/common/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export type BaseCommands = {
7171
"codeQL.restartQueryServer": () => Promise<void>;
7272
"codeQL.restartQueryServerOnConfigChange": () => Promise<void>;
7373
"codeQL.restartLegacyQueryServerOnConfigChange": () => Promise<void>;
74+
"codeQL.restartQueryServerOnExternalConfigChange": () => Promise<void>;
7475
};
7576

7677
// Commands used when working with queries in the editor

extensions/ql-vscode/src/databaseFetcher.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,11 @@ export async function askForGitHubRepo(
122122
progress?: ProgressCallback,
123123
suggestedValue?: string,
124124
): Promise<string | undefined> {
125-
progress &&
126-
progress({
127-
message: "Choose repository",
128-
step: 1,
129-
maxStep: 2,
130-
});
125+
progress?.({
126+
message: "Choose repository",
127+
step: 1,
128+
maxStep: 2,
129+
});
131130

132131
const options: InputBoxOptions = {
133132
title:

extensions/ql-vscode/src/distribution.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ export class DistributionManager implements DistributionProvider {
215215
minSecondsSinceLastUpdateCheck: number,
216216
): Promise<DistributionUpdateCheckResult> {
217217
const distribution = await this.getDistributionWithoutVersionCheck();
218+
if (distribution === undefined) {
219+
minSecondsSinceLastUpdateCheck = 0;
220+
}
218221
const extensionManagedCodeQlPath =
219222
await this.extensionSpecificDistributionManager.getCodeQlPathWithoutVersionCheck();
220223
if (distribution?.codeQlPath !== extensionManagedCodeQlPath) {

extensions/ql-vscode/src/extension.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ import {
1313
workspace,
1414
} from "vscode";
1515
import { LanguageClient } from "vscode-languageclient/node";
16-
import { arch, platform } from "os";
16+
import { arch, platform, homedir } from "os";
1717
import { ensureDir } from "fs-extra";
1818
import { join } from "path";
1919
import { dirSync } from "tmp-promise";
2020
import { testExplorerExtensionId, TestHub } from "vscode-test-adapter-api";
2121
import { lt, parse } from "semver";
22+
import { watch } from "chokidar";
2223

2324
import { AstViewer } from "./astViewer";
2425
import {
@@ -194,6 +195,7 @@ function getCommands(
194195
"codeQL.restartQueryServer": restartQueryServer,
195196
"codeQL.restartQueryServerOnConfigChange": restartQueryServer,
196197
"codeQL.restartLegacyQueryServerOnConfigChange": restartQueryServer,
198+
"codeQL.restartQueryServerOnExternalConfigChange": restartQueryServer,
197199
"codeQL.copyVersion": async () => {
198200
const text = `CodeQL extension version: ${
199201
extension?.packageJSON.version
@@ -672,6 +674,7 @@ async function activateWithInstalledDistribution(
672674
extLogger,
673675
);
674676
ctx.subscriptions.push(cliServer);
677+
watchExternalConfigFile(app, ctx);
675678

676679
const statusBar = new CodeQlStatusBarHandler(
677680
cliServer,
@@ -1011,6 +1014,34 @@ async function activateWithInstalledDistribution(
10111014
};
10121015
}
10131016

1017+
/**
1018+
* Handle changes to the external config file. This is used to restart the query server
1019+
* when the user changes options.
1020+
* See https://docs.github.com/en/code-security/codeql-cli/using-the-codeql-cli/specifying-command-options-in-a-codeql-configuration-file#using-a-codeql-configuration-file
1021+
*/
1022+
function watchExternalConfigFile(app: ExtensionApp, ctx: ExtensionContext) {
1023+
const home = homedir();
1024+
if (home) {
1025+
const configPath = join(home, ".config", "codeql", "config");
1026+
const configWatcher = watch(configPath, {
1027+
// These options avoid firing the event twice.
1028+
persistent: true,
1029+
ignoreInitial: true,
1030+
awaitWriteFinish: true,
1031+
});
1032+
configWatcher.on("all", async () => {
1033+
await app.commands.execute(
1034+
"codeQL.restartQueryServerOnExternalConfigChange",
1035+
);
1036+
});
1037+
ctx.subscriptions.push({
1038+
dispose: () => {
1039+
void configWatcher.close();
1040+
},
1041+
});
1042+
}
1043+
}
1044+
10141045
async function showResultsForComparison(
10151046
compareView: CompareView,
10161047
from: CompletedLocalQueryInfo,

extensions/ql-vscode/src/view/results/__tests__/results.spec.tsx

Lines changed: 95 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from "react";
2-
import { render as reactRender, screen } from "@testing-library/react";
2+
import { act, render as reactRender, screen } from "@testing-library/react";
33
import { ResultsApp } from "../results";
44
import {
55
Interpretation,
@@ -20,18 +20,20 @@ const exampleSarif = fs.readJSONSync(
2020
describe(ResultsApp.name, () => {
2121
const render = () => reactRender(<ResultsApp />);
2222
const postMessage = async (msg: IntoResultsViewMsg) => {
23-
// window.postMessage doesn't set the origin correctly, see
24-
// https://github.com/jsdom/jsdom/issues/2745
25-
window.dispatchEvent(
26-
new MessageEvent("message", {
27-
source: window,
28-
origin: window.location.origin,
29-
data: msg,
30-
}),
31-
);
23+
await act(async () => {
24+
// window.postMessage doesn't set the origin correctly, see
25+
// https://github.com/jsdom/jsdom/issues/2745
26+
window.dispatchEvent(
27+
new MessageEvent("message", {
28+
source: window,
29+
origin: window.location.origin,
30+
data: msg,
31+
}),
32+
);
3233

33-
// The event is dispatched asynchronously, so we need to wait for it to be handled.
34-
await new Promise((resolve) => setTimeout(resolve, 0));
34+
// The event is dispatched asynchronously, so we need to wait for it to be handled.
35+
await new Promise((resolve) => setTimeout(resolve, 0));
36+
});
3537
};
3638

3739
it("renders results", async () => {
@@ -95,6 +97,7 @@ describe(ResultsApp.name, () => {
9597
},
9698
},
9799
};
100+
98101
await postMessage(message);
99102

100103
expect(
@@ -117,4 +120,84 @@ describe(ResultsApp.name, () => {
117120
screen.getByText("'x' is assigned a value but never used."),
118121
).toBeInTheDocument();
119122
});
123+
124+
it("renders results when switching between queries with different result set names", async () => {
125+
render();
126+
127+
await postMessage({
128+
t: "setState",
129+
interpretation: undefined,
130+
origResultsPaths: {
131+
resultsPath: "/a/b/c/results.bqrs",
132+
interpretedResultsPath: "/a/b/c/interpretedResults.sarif",
133+
},
134+
resultsPath: "/a/b/c/results.bqrs",
135+
parsedResultSets: {
136+
pageNumber: 0,
137+
pageSize: 200,
138+
numPages: 1,
139+
numInterpretedPages: 0,
140+
resultSet: {
141+
schema: {
142+
name: "#select",
143+
rows: 1,
144+
columns: [{ kind: "s" }],
145+
pagination: { "step-size": 200, offsets: [13] },
146+
},
147+
rows: [["foobar1"]],
148+
t: "RawResultSet",
149+
},
150+
resultSetNames: ["#select"],
151+
},
152+
sortedResultsMap: {},
153+
database: {
154+
name: "test-db",
155+
databaseUri: "test-db-uri",
156+
},
157+
shouldKeepOldResultsWhileRendering: false,
158+
metadata: {},
159+
queryName: "empty.ql",
160+
queryPath: "/a/b/c/empty.ql",
161+
});
162+
163+
expect(screen.getByText("foobar1")).toBeInTheDocument();
164+
165+
await postMessage({
166+
t: "setState",
167+
interpretation: undefined,
168+
origResultsPaths: {
169+
resultsPath: "/a/b/c/results.bqrs",
170+
interpretedResultsPath: "/a/b/c/interpretedResults.sarif",
171+
},
172+
resultsPath: "/a/b/c/results.bqrs",
173+
parsedResultSets: {
174+
pageNumber: 0,
175+
pageSize: 200,
176+
numPages: 1,
177+
numInterpretedPages: 0,
178+
resultSet: {
179+
schema: {
180+
name: "#Quick_evaluation_of_expression",
181+
rows: 1,
182+
columns: [{ name: "#expr_result", kind: "s" }],
183+
pagination: { "step-size": 200, offsets: [49] },
184+
},
185+
rows: [["foobar2"]],
186+
t: "RawResultSet",
187+
},
188+
resultSetNames: ["#Quick_evaluation_of_expression"],
189+
},
190+
sortedResultsMap: {},
191+
database: {
192+
name: "test-db",
193+
databaseUri: "test-db-uri",
194+
},
195+
shouldKeepOldResultsWhileRendering: false,
196+
metadata: {},
197+
queryName: "Quick evaluation of empty.ql:1",
198+
queryPath: "/a/b/c/empty.ql",
199+
});
200+
201+
expect(screen.getByText("foobar2")).toBeInTheDocument();
202+
});
120203
});

0 commit comments

Comments
 (0)