Skip to content

Commit a228dba

Browse files
Merge branch 'main' into robertbrignull/move_language_pack
2 parents e70b083 + 5367bde commit a228dba

File tree

17 files changed

+699
-169
lines changed

17 files changed

+699
-169
lines changed

extensions/ql-vscode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- Enable collection of telemetry for the `codeQL.addingDatabases.addDatabaseSourceToWorkspace` setting. [#3238](https://github.com/github/vscode-codeql/pull/3238)
66
- In the CodeQL model editor, you can now select individual method rows and save changes to only the selected rows, instead of having to save the entire library model. [#3156](https://github.com/github/vscode-codeql/pull/3156)
77
- If you run a query without having selected a database, we show a more intuitive prompt to help you select a database. [#3214](https://github.com/github/vscode-codeql/pull/3214)
8+
- Error messages returned from the CodeQL CLI are now less verbose and more user-friendly. [#3259](https://github.com/github/vscode-codeql/pull/3259)
89
- The UI for browsing and running CodeQL tests has moved to use VS Code's built-in test UI. This makes the CodeQL test UI more consistent with the test UIs for other languages.
910
This change means that this extension no longer depends on the "Test Explorer UI" and "Test Adapter Converter" extensions. You can uninstall those two extensions if they are
1011
not being used by any other extensions you may have installed.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { asError, getErrorMessage } from "../common/helpers-pure";
2+
3+
// https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/exit-codes
4+
const EXIT_CODE_USER_ERROR = 2;
5+
const EXIT_CODE_CANCELLED = 98;
6+
7+
export class ExitCodeError extends Error {
8+
constructor(public readonly exitCode: number | null) {
9+
super(`Process exited with code ${exitCode}`);
10+
}
11+
}
12+
13+
export class CliError extends Error {
14+
constructor(
15+
message: string,
16+
public readonly stderr: string | undefined,
17+
public readonly cause: Error,
18+
public readonly commandDescription: string,
19+
public readonly commandArgs: string[],
20+
) {
21+
super(message);
22+
}
23+
}
24+
25+
export function getCliError(
26+
e: unknown,
27+
stderr: string | undefined,
28+
commandDescription: string,
29+
commandArgs: string[],
30+
): CliError {
31+
const error = asError(e);
32+
33+
if (!(error instanceof ExitCodeError) || !stderr) {
34+
return formatCliErrorFallback(
35+
error,
36+
stderr,
37+
commandDescription,
38+
commandArgs,
39+
);
40+
}
41+
42+
switch (error.exitCode) {
43+
case EXIT_CODE_USER_ERROR: {
44+
// This is an error that we should try to format nicely
45+
const fatalErrorIndex = stderr.lastIndexOf("A fatal error occurred: ");
46+
if (fatalErrorIndex !== -1) {
47+
return new CliError(
48+
stderr.slice(fatalErrorIndex),
49+
stderr,
50+
error,
51+
commandDescription,
52+
commandArgs,
53+
);
54+
}
55+
56+
break;
57+
}
58+
case EXIT_CODE_CANCELLED: {
59+
const cancellationIndex = stderr.lastIndexOf(
60+
"Computation was cancelled: ",
61+
);
62+
if (cancellationIndex !== -1) {
63+
return new CliError(
64+
stderr.slice(cancellationIndex),
65+
stderr,
66+
error,
67+
commandDescription,
68+
commandArgs,
69+
);
70+
}
71+
72+
break;
73+
}
74+
}
75+
76+
return formatCliErrorFallback(error, stderr, commandDescription, commandArgs);
77+
}
78+
79+
function formatCliErrorFallback(
80+
error: Error,
81+
stderr: string | undefined,
82+
commandDescription: string,
83+
commandArgs: string[],
84+
): CliError {
85+
if (stderr) {
86+
return new CliError(
87+
stderr,
88+
undefined,
89+
error,
90+
commandDescription,
91+
commandArgs,
92+
);
93+
}
94+
95+
return new CliError(
96+
getErrorMessage(error),
97+
undefined,
98+
error,
99+
commandDescription,
100+
commandArgs,
101+
);
102+
}

extensions/ql-vscode/src/codeql-cli/cli.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { LINE_ENDINGS, splitStreamAtSeparators } from "../common/split-stream";
3535
import type { Position } from "../query-server/messages";
3636
import { LOGGING_FLAGS } from "./cli-command";
3737
import type { CliFeatures, VersionAndFeatures } from "./cli-version";
38+
import { ExitCodeError, getCliError } from "./cli-errors";
3839

3940
/**
4041
* The version of the SARIF format that we are using.
@@ -420,7 +421,9 @@ export class CodeQLCliServer implements Disposable {
420421
stderrBuffers.push(newData);
421422
});
422423
// Listen for process exit.
423-
process.addListener("close", (code) => reject(code));
424+
process.addListener("close", (code) =>
425+
reject(new ExitCodeError(code)),
426+
);
424427
// Write the command followed by a null terminator.
425428
process.stdin.write(JSON.stringify(args), "utf8");
426429
process.stdin.write(this.nullBuffer);
@@ -436,19 +439,18 @@ export class CodeQLCliServer implements Disposable {
436439
} catch (err) {
437440
// Kill the process if it isn't already dead.
438441
this.killProcessIfRunning();
442+
439443
// Report the error (if there is a stderr then use that otherwise just report the error code or nodejs error)
440-
const newError =
441-
stderrBuffers.length === 0
442-
? new Error(
443-
`${description} failed with args:${EOL} ${argsString}${EOL}${err}`,
444-
)
445-
: new Error(
446-
`${description} failed with args:${EOL} ${argsString}${EOL}${Buffer.concat(
447-
stderrBuffers,
448-
).toString("utf8")}`,
449-
);
450-
newError.stack += getErrorStack(err);
451-
throw newError;
444+
const cliError = getCliError(
445+
err,
446+
stderrBuffers.length > 0
447+
? Buffer.concat(stderrBuffers).toString("utf8")
448+
: undefined,
449+
description,
450+
args,
451+
);
452+
cliError.stack += getErrorStack(err);
453+
throw cliError;
452454
} finally {
453455
if (!silent) {
454456
void this.logger.log(Buffer.concat(stderrBuffers).toString("utf8"));

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { redactableError } from "../../common/errors";
1313
import { UserCancellationException } from "./progress";
1414
import { telemetryListener } from "./telemetry";
1515
import type { AppTelemetry } from "../telemetry";
16+
import { CliError } from "../../codeql-cli/cli-errors";
17+
import { EOL } from "os";
1618

1719
/**
1820
* Create a command manager for VSCode, wrapping registerCommandWithErrorHandling
@@ -62,6 +64,16 @@ export function registerCommandWithErrorHandling(
6264
} else {
6365
void showAndLogWarningMessage(logger, errorMessage.fullMessage);
6466
}
67+
} else if (e instanceof CliError) {
68+
const fullMessage = `${e.commandDescription} failed with args:${EOL} ${e.commandArgs.join(" ")}${EOL}${
69+
e.stderr ?? e.cause
70+
}`;
71+
void showAndLogExceptionWithTelemetry(logger, telemetry, errorMessage, {
72+
fullMessage,
73+
extraTelemetryProperties: {
74+
command: commandId,
75+
},
76+
});
6577
} else {
6678
// Include the full stack in the error log only.
6779
const fullMessage = errorMessage.fullMessageWithStack;

extensions/ql-vscode/src/variant-analysis/shared/variant-analysis.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export interface VariantAnalysisSubmission {
158158
// unclear what it will look like in the future.
159159
export interface VariantAnalysisQueries {
160160
language: QueryLanguage;
161+
count: number;
161162
}
162163

163164
export async function isVariantAnalysisComplete(

extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ export class VariantAnalysisManager
405405
? undefined
406406
: {
407407
language: qlPackDetails.language,
408+
count: qlPackDetails.queryFiles.length,
408409
};
409410

410411
const variantAnalysisSubmission: VariantAnalysisSubmission = {

extensions/ql-vscode/src/variant-analysis/variant-analysis-view.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,15 @@ export class VariantAnalysisView
218218
}
219219

220220
private getTitle(variantAnalysis: VariantAnalysis | undefined): string {
221-
return variantAnalysis
222-
? `${variantAnalysis.query.name} - Variant Analysis Results`
223-
: `Variant Analysis ${this.variantAnalysisId} - Results`;
221+
if (!variantAnalysis) {
222+
return `Variant Analysis ${this.variantAnalysisId} - Results`;
223+
}
224+
225+
if (variantAnalysis.queries) {
226+
return `Variant Analysis using multiple queries - Results`;
227+
} else {
228+
return `${variantAnalysis.query.name} - Variant Analysis Results`;
229+
}
224230
}
225231

226232
private async showDataFlows(dataFlows: DataFlowPaths): Promise<void> {

extensions/ql-vscode/src/view/common/SuggestBox/SuggestBox.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { findMatchingOptions } from "./options";
2020
import { SuggestBoxItem } from "./SuggestBoxItem";
2121
import { LabelText } from "./LabelText";
2222
import type { Diagnostic } from "./diagnostics";
23+
import { useOpenKey } from "./useOpenKey";
2324

2425
const Input = styled(VSCodeTextField)<{ $error: boolean }>`
2526
width: 430px;
@@ -152,6 +153,7 @@ export const SuggestBox = <
152153
const focus = useFocus(context);
153154
const role = useRole(context, { role: "listbox" });
154155
const dismiss = useDismiss(context);
156+
const openKey = useOpenKey(context);
155157
const listNav = useListNavigation(context, {
156158
listRef,
157159
activeIndex,
@@ -161,7 +163,7 @@ export const SuggestBox = <
161163
});
162164

163165
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(
164-
[focus, role, dismiss, listNav],
166+
[focus, role, dismiss, openKey, listNav],
165167
);
166168

167169
const handleInput = useCallback(
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { renderHook } from "@testing-library/react";
2+
import { useEffectEvent } from "../useEffectEvent";
3+
4+
describe("useEffectEvent", () => {
5+
it("does not change reference when changing the callback function", () => {
6+
const callback1 = jest.fn();
7+
const callback2 = jest.fn();
8+
9+
const { result, rerender } = renderHook(
10+
(callback) => useEffectEvent(callback),
11+
{
12+
initialProps: callback1,
13+
},
14+
);
15+
16+
const callbackResult = result.current;
17+
18+
rerender();
19+
20+
expect(result.current).toBe(callbackResult);
21+
22+
rerender(callback2);
23+
24+
expect(result.current).toBe(callbackResult);
25+
});
26+
});

0 commit comments

Comments
 (0)