Add quick eval count to the command palette (#2475)

* Add version constraint for quick-eval-count

* Add quick eval count context.

* Add support for running quick-eval-count from the command pallete

* Adjust name for quick-eval-count-queries

* Add changenote for quick-eval-count.

* QuickEval:Address review comments

* Fix rebase conflict in changelog
This commit is contained in:
Alexander Eyers-Taylor
2023-06-27 11:28:28 +01:00
committed by GitHub
parent 2a332f90c4
commit b0699ee524
8 changed files with 63 additions and 2 deletions

View File

@@ -2,6 +2,9 @@
## [UNRELEASED] ## [UNRELEASED]
- Add `CodeQL: Quick Evaluation Count` command to generate the count summary statistics of the results set
without speding the time to compute locations and strings.
## 1.8.6 - 14 June 2023 ## 1.8.6 - 14 June 2023
- Add repositories to a variant analysis list with GitHub Code Search. [#2439](https://github.com/github/vscode-codeql/pull/2439) and [#2476](https://github.com/github/vscode-codeql/pull/2476) - Add repositories to a variant analysis list with GitHub Code Search. [#2439](https://github.com/github/vscode-codeql/pull/2439) and [#2476](https://github.com/github/vscode-codeql/pull/2476)

View File

@@ -457,6 +457,10 @@
"command": "codeQL.quickEval", "command": "codeQL.quickEval",
"title": "CodeQL: Quick Evaluation" "title": "CodeQL: Quick Evaluation"
}, },
{
"command": "codeQL.quickEvalCount",
"title": "CodeQL: Quick Evaluation Count"
},
{ {
"command": "codeQL.quickEvalContextEditor", "command": "codeQL.quickEvalContextEditor",
"title": "CodeQL: Quick Evaluation" "title": "CodeQL: Quick Evaluation"
@@ -1245,6 +1249,10 @@
"command": "codeQL.quickEval", "command": "codeQL.quickEval",
"when": "editorLangId == ql" "when": "editorLangId == ql"
}, },
{
"command": "codeQL.quickEvalCount",
"when": "editorLangId == ql && codeql.supportsQuickEvalCount"
},
{ {
"command": "codeQL.quickEvalContextEditor", "command": "codeQL.quickEvalContextEditor",
"when": "false" "when": "false"

View File

@@ -1483,6 +1483,13 @@ export class CodeQLCliServer implements Disposable {
CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG, CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG,
) >= 0, ) >= 0,
); );
await this.app.commands.execute(
"setContext",
"codeql.supportsQuickEvalCount",
newVersion.compare(
CliVersionConstraint.CLI_VERSION_WITH_QUICK_EVAL_COUNT,
) >= 0,
);
} catch (e) { } catch (e) {
this._versionChangedListeners.forEach((listener) => this._versionChangedListeners.forEach((listener) =>
listener(undefined), listener(undefined),
@@ -1845,6 +1852,11 @@ export class CliVersionConstraint {
public static CLI_VERSION_GLOBAL_CACHE = new SemVer("2.12.4"); public static CLI_VERSION_GLOBAL_CACHE = new SemVer("2.12.4");
/**
* CLI version where the query server supports quick-eval count mode.
*/
public static CLI_VERSION_WITH_QUICK_EVAL_COUNT = new SemVer("2.13.3");
constructor(private readonly cli: CodeQLCliServer) { constructor(private readonly cli: CodeQLCliServer) {
/**/ /**/
} }
@@ -1918,4 +1930,10 @@ export class CliVersionConstraint {
async usesGlobalCompilationCache() { async usesGlobalCompilationCache() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_GLOBAL_CACHE); return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_GLOBAL_CACHE);
} }
async supportsQuickEvalCount() {
return this.isVersionAtLeast(
CliVersionConstraint.CLI_VERSION_WITH_QUICK_EVAL_COUNT,
);
}
} }

View File

@@ -135,6 +135,7 @@ export type LocalQueryCommands = {
"codeQL.runLocalQueryFromFileTab": (uri: Uri) => Promise<void>; "codeQL.runLocalQueryFromFileTab": (uri: Uri) => Promise<void>;
"codeQL.runQueries": ExplorerSelectionCommandFunction<Uri>; "codeQL.runQueries": ExplorerSelectionCommandFunction<Uri>;
"codeQL.quickEval": (uri: Uri) => Promise<void>; "codeQL.quickEval": (uri: Uri) => Promise<void>;
"codeQL.quickEvalCount": (uri: Uri) => Promise<void>;
"codeQL.quickEvalContextEditor": (uri: Uri) => Promise<void>; "codeQL.quickEvalContextEditor": (uri: Uri) => Promise<void>;
"codeQL.codeLensQuickEval": (uri: Uri, range: Range) => Promise<void>; "codeQL.codeLensQuickEval": (uri: Uri, range: Range) => Promise<void>;
"codeQL.quickQuery": () => Promise<void>; "codeQL.quickQuery": () => Promise<void>;

View File

@@ -40,7 +40,7 @@ import {
import { CompletedLocalQueryInfo, LocalQueryInfo } from "../query-results"; import { CompletedLocalQueryInfo, LocalQueryInfo } from "../query-results";
import { WebviewReveal } from "./webview"; import { WebviewReveal } from "./webview";
import { asError, getErrorMessage } from "../common/helpers-pure"; import { asError, getErrorMessage } from "../common/helpers-pure";
import { CodeQLCliServer } from "../codeql-cli/cli"; import { CliVersionConstraint, CodeQLCliServer } from "../codeql-cli/cli";
import { LocalQueryCommands } from "../common/commands"; import { LocalQueryCommands } from "../common/commands";
import { App } from "../common/app"; import { App } from "../common/app";
import { DisposableObject } from "../common/disposable-object"; import { DisposableObject } from "../common/disposable-object";
@@ -110,6 +110,7 @@ export class LocalQueries extends DisposableObject {
this.runQueries.bind(this), this.runQueries.bind(this),
), ),
"codeQL.quickEval": this.quickEval.bind(this), "codeQL.quickEval": this.quickEval.bind(this),
"codeQL.quickEvalCount": this.quickEvalCount.bind(this),
"codeQL.quickEvalContextEditor": this.quickEval.bind(this), "codeQL.quickEvalContextEditor": this.quickEval.bind(this),
"codeQL.codeLensQuickEval": this.codeLensQuickEval.bind(this), "codeQL.codeLensQuickEval": this.codeLensQuickEval.bind(this),
"codeQL.quickQuery": this.quickQuery.bind(this), "codeQL.quickQuery": this.quickQuery.bind(this),
@@ -243,6 +244,29 @@ export class LocalQueries extends DisposableObject {
); );
} }
private async quickEvalCount(uri: Uri): Promise<void> {
await withProgress(
async (progress, token) => {
if (!(await this.cliServer.cliConstraints.supportsQuickEvalCount())) {
throw new Error(
`Quick evaluation count is only supported by CodeQL CLI v${CliVersionConstraint.CLI_VERSION_WITH_QUICK_EVAL_COUNT} or later.`,
);
}
await this.compileAndRunQuery(
QuickEvalType.QuickEvalCount,
uri,
progress,
token,
undefined,
);
},
{
title: "Running query",
cancellable: true,
},
);
}
private async codeLensQuickEval(uri: Uri, range: Range): Promise<void> { private async codeLensQuickEval(uri: Uri, range: Range): Promise<void> {
await withProgress( await withProgress(
async (progress, token) => async (progress, token) =>

View File

@@ -41,6 +41,7 @@ export interface InitialQueryInfo {
readonly queryText: string; // text of the selected file, or the selected text when doing quick eval readonly queryText: string; // text of the selected file, or the selected text when doing quick eval
readonly isQuickQuery: boolean; readonly isQuickQuery: boolean;
readonly isQuickEval: boolean; readonly isQuickEval: boolean;
readonly isQuickEvalCount?: boolean; // Missing is false for backwards compatibility
readonly quickEvalPosition?: messages.Position; readonly quickEvalPosition?: messages.Position;
readonly queryPath: string; readonly queryPath: string;
readonly databaseInfo: DatabaseInfo; readonly databaseInfo: DatabaseInfo;
@@ -270,7 +271,9 @@ export class LocalQueryInfo {
* - Otherwise, return the query file name. * - Otherwise, return the query file name.
*/ */
getQueryName() { getQueryName() {
if (this.initialInfo.quickEvalPosition) { if (this.initialInfo.isQuickEvalCount) {
return `Quick evaluation counts of ${this.getQueryFileName()}`;
} else if (this.initialInfo.isQuickEval) {
return `Quick evaluation of ${this.getQueryFileName()}`; return `Quick evaluation of ${this.getQueryFileName()}`;
} else if (this.completedQuery?.query.metadata?.name) { } else if (this.completedQuery?.query.metadata?.name) {
return this.completedQuery?.query.metadata?.name; return this.completedQuery?.query.metadata?.name;

View File

@@ -585,9 +585,12 @@ export async function createInitialQueryInfo(
databaseInfo: DatabaseInfo, databaseInfo: DatabaseInfo,
): Promise<InitialQueryInfo> { ): Promise<InitialQueryInfo> {
const isQuickEval = selectedQuery.quickEval !== undefined; const isQuickEval = selectedQuery.quickEval !== undefined;
const isQuickEvalCount =
selectedQuery.quickEval?.quickEvalCount !== undefined;
return { return {
queryPath: selectedQuery.queryPath, queryPath: selectedQuery.queryPath,
isQuickEval, isQuickEval,
isQuickEvalCount,
isQuickQuery: isQuickQueryPath(selectedQuery.queryPath), isQuickQuery: isQuickQueryPath(selectedQuery.queryPath),
databaseInfo, databaseInfo,
id: `${basename(selectedQuery.queryPath)}-${nanoid()}`, id: `${basename(selectedQuery.queryPath)}-${nanoid()}`,

View File

@@ -58,6 +58,7 @@ describe("query-results", () => {
endLine: 2, endLine: 2,
fileName: "/home/users/yz", fileName: "/home/users/yz",
}; };
(fqi.initialInfo as any).isQuickEval = true;
expect(fqi.getQueryName()).toBe("Quick evaluation of yz:1-2"); expect(fqi.getQueryName()).toBe("Quick evaluation of yz:1-2");
(fqi.initialInfo as any).quickEvalPosition.endLine = 1; (fqi.initialInfo as any).quickEvalPosition.endLine = 1;
expect(fqi.getQueryName()).toBe("Quick evaluation of yz:1"); expect(fqi.getQueryName()).toBe("Quick evaluation of yz:1");