Skip to content

Commit bc2847a

Browse files
authored
Merge pull request #3057 from github/koesie10/contextual-no-submodule
Make contextual queries work for fresh installs
2 parents 28994b7 + 8464892 commit bc2847a

File tree

6 files changed

+159
-28
lines changed

6 files changed

+159
-28
lines changed

extensions/ql-vscode/src/language-support/contextual/location-finder.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@ import {
99
ResultSetSchema,
1010
} from "../../common/bqrs-cli-types";
1111
import { CodeQLCliServer } from "../../codeql-cli/cli";
12-
import { DatabaseManager, DatabaseItem } from "../../databases/local-databases";
12+
import { DatabaseItem, DatabaseManager } from "../../databases/local-databases";
1313
import { ProgressCallback } from "../../common/vscode/progress";
1414
import { KeyType } from "./key-type";
15-
import { resolveQueries, runContextualQuery } from "./query-resolver";
15+
import {
16+
resolveContextualQlPacksForDatabase,
17+
resolveContextualQueries,
18+
runContextualQuery,
19+
} from "./query-resolver";
1620
import { CancellationToken, LocationLink, Uri } from "vscode";
1721
import { QueryOutputDir } from "../../run-queries-shared";
1822
import { QueryRunner } from "../../query-server";
1923
import { QueryResultType } from "../../query-server/new-messages";
2024
import { fileRangeFromURI } from "./file-range-from-uri";
21-
import { qlpackOfDatabase } from "../../local-queries";
2225

2326
export const SELECT_QUERY_NAME = "#select";
2427
export const SELECTED_SOURCE_FILE = "selectedSourceFile";
@@ -63,11 +66,11 @@ export async function getLocationsForUriString(
6366
return [];
6467
}
6568

66-
const qlpack = await qlpackOfDatabase(cli, db);
69+
const qlpack = await resolveContextualQlPacksForDatabase(cli, db);
6770
const templates = createTemplates(uri.pathWithinSourceArchive);
6871

6972
const links: FullLocationLink[] = [];
70-
for (const query of await resolveQueries(cli, qlpack, keyType)) {
73+
for (const query of await resolveContextualQueries(cli, qlpack, keyType)) {
7174
const results = await runContextualQuery(
7275
query,
7376
db,

extensions/ql-vscode/src/language-support/contextual/query-resolver.ts

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,67 @@ import {
88
} from "./key-type";
99
import { CodeQLCliServer } from "../../codeql-cli/cli";
1010
import { DatabaseItem } from "../../databases/local-databases";
11-
import { resolveQueriesByLanguagePack as resolveLocalQueries } from "../../local-queries/query-resolver";
11+
import {
12+
qlpackOfDatabase,
13+
resolveQueriesByLanguagePack as resolveLocalQueriesByLanguagePack,
14+
} from "../../local-queries/query-resolver";
1215
import { extLogger } from "../../common/logging/vscode";
1316
import { TeeLogger } from "../../common/logging";
1417
import { CancellationToken } from "vscode";
1518
import { ProgressCallback } from "../../common/vscode/progress";
1619
import { CoreCompletedQuery, QueryRunner } from "../../query-server";
1720
import { createLockFileForStandardQuery } from "../../local-queries/standard-queries";
1821

19-
export async function resolveQueries(
22+
/**
23+
* This wil try to determine the qlpacks for a given database. If it can't find a matching
24+
* dbscheme with downloaded packs, it will download the default packs instead.
25+
*
26+
* @param cli The CLI server to use
27+
* @param databaseItem The database item to find the qlpacks for
28+
*/
29+
export async function resolveContextualQlPacksForDatabase(
30+
cli: CodeQLCliServer,
31+
databaseItem: DatabaseItem,
32+
): Promise<QlPacksForLanguage> {
33+
try {
34+
return await qlpackOfDatabase(cli, databaseItem);
35+
} catch (e) {
36+
// If we can't find the qlpacks for the database, use the defaults instead
37+
}
38+
39+
const dbInfo = await cli.resolveDatabase(databaseItem.databaseUri.fsPath);
40+
const primaryLanguage = dbInfo.languages?.[0];
41+
if (!primaryLanguage) {
42+
throw new Error("Unable to determine primary language of database");
43+
}
44+
45+
const libraryPack = `codeql/${primaryLanguage}-all`;
46+
const queryPack = `codeql/${primaryLanguage}-queries`;
47+
48+
await cli.packDownload([libraryPack, queryPack]);
49+
50+
// Return the default packs. If these weren't valid packs, the download would have failed.
51+
return {
52+
dbschemePack: libraryPack,
53+
dbschemePackIsLibraryPack: true,
54+
queryPack,
55+
};
56+
}
57+
58+
export async function resolveContextualQueries(
2059
cli: CodeQLCliServer,
2160
qlpacks: QlPacksForLanguage,
2261
keyType: KeyType,
2362
): Promise<string[]> {
24-
return resolveLocalQueries(cli, qlpacks, nameOfKeyType(keyType), {
25-
kind: kindOfKeyType(keyType),
26-
"tags contain": [tagOfKeyType(keyType)],
27-
});
63+
return resolveLocalQueriesByLanguagePack(
64+
cli,
65+
qlpacks,
66+
nameOfKeyType(keyType),
67+
{
68+
kind: kindOfKeyType(keyType),
69+
"tags contain": [tagOfKeyType(keyType)],
70+
},
71+
);
2872
}
2973

3074
export async function runContextualQuery(

extensions/ql-vscode/src/language-support/contextual/template-provider.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,22 @@ import { KeyType } from "./key-type";
2323
import {
2424
FullLocationLink,
2525
getLocationsForUriString,
26+
SELECTED_SOURCE_COLUMN,
2627
SELECTED_SOURCE_FILE,
2728
SELECTED_SOURCE_LINE,
28-
SELECTED_SOURCE_COLUMN,
2929
} from "./location-finder";
30-
import { resolveQueries, runContextualQuery } from "./query-resolver";
30+
import {
31+
resolveContextualQlPacksForDatabase,
32+
resolveContextualQueries,
33+
runContextualQuery,
34+
} from "./query-resolver";
3135
import {
3236
isCanary,
3337
NO_CACHE_AST_VIEWER,
3438
NO_CACHE_CONTEXTUAL_QUERIES,
3539
} from "../../config";
3640
import { CoreCompletedQuery, QueryRunner } from "../../query-server";
3741
import { AstBuilder } from "../ast-viewer/ast-builder";
38-
import { qlpackOfDatabase } from "../../local-queries";
3942
import { MultiCancellationToken } from "../../common/vscode/multi-cancellation-token";
4043

4144
/**
@@ -248,8 +251,8 @@ export class TemplatePrintAstProvider {
248251
throw new Error("Can't infer database from the provided source.");
249252
}
250253

251-
const qlpacks = await qlpackOfDatabase(this.cli, db);
252-
const queries = await resolveQueries(
254+
const qlpacks = await resolveContextualQlPacksForDatabase(this.cli, db);
255+
const queries = await resolveContextualQueries(
253256
this.cli,
254257
qlpacks,
255258
KeyType.PrintAstQuery,
@@ -336,11 +339,11 @@ export class TemplatePrintCfgProvider {
336339
throw new Error("Can't infer database from the provided source.");
337340
}
338341

339-
const qlpack = await qlpackOfDatabase(this.cli, db);
342+
const qlpack = await resolveContextualQlPacksForDatabase(this.cli, db);
340343
if (!qlpack) {
341344
throw new Error("Can't infer qlpack from database source archive.");
342345
}
343-
const queries = await resolveQueries(
346+
const queries = await resolveContextualQueries(
344347
this.cli,
345348
qlpack,
346349
KeyType.PrintCfgQuery,

extensions/ql-vscode/src/local-queries/query-resolver.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import { telemetryListener } from "../common/vscode/telemetry";
1616
import { SuiteInstruction } from "../packaging/suite-instruction";
1717
import { QueryConstraints } from "./query-constraints";
1818

19+
/**
20+
* Consider using `resolveContextualQlPacksForDatabase` instead.
21+
* @param cli The CLI server instance to use.
22+
* @param db The database to find the QLPack for.
23+
*/
1924
export async function qlpackOfDatabase(
2025
cli: Pick<CodeQLCliServer, "resolveQlpacks">,
2126
db: Pick<DatabaseItem, "contents">,

extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import {
88
} from "../../../src/codeql-cli/cli";
99
import { itWithCodeQL } from "../cli";
1010
import { getOnDiskWorkspaceFolders } from "../../../src/common/vscode/workspace-folders";
11-
import { KeyType, resolveQueries } from "../../../src/language-support";
11+
import {
12+
KeyType,
13+
resolveContextualQueries,
14+
} from "../../../src/language-support";
1215
import { faker } from "@faker-js/faker";
1316
import { getActivatedExtension } from "../global.helper";
1417
import { BaseLogger } from "../../../src/common/logging";
@@ -117,7 +120,11 @@ describe("Use cli", () => {
117120
expect(pack.queryPack).toContain(lang);
118121
}
119122

120-
const result = await resolveQueries(cli, pack, KeyType.PrintAstQuery);
123+
const result = await resolveContextualQueries(
124+
cli,
125+
pack,
126+
KeyType.PrintAstQuery,
127+
);
121128

122129
// It doesn't matter what the name or path of the query is, only
123130
// that we have found exactly one query.

extensions/ql-vscode/test/vscode-tests/no-workspace/language-support/contextual/query-resolver.test.ts

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,97 @@ import { getErrorMessage } from "../../../../../src/common/helpers-pure";
55

66
import * as log from "../../../../../src/common/logging/notifications";
77
import * as workspaceFolders from "../../../../../src/common/vscode/workspace-folders";
8-
import { KeyType, resolveQueries } from "../../../../../src/language-support";
9-
import { CodeQLCliServer } from "../../../../../src/codeql-cli/cli";
8+
import {
9+
KeyType,
10+
resolveContextualQlPacksForDatabase,
11+
resolveContextualQueries,
12+
} from "../../../../../src/language-support";
13+
import { CodeQLCliServer, DbInfo } from "../../../../../src/codeql-cli/cli";
1014
import { mockedObject } from "../../../utils/mocking.helpers";
15+
import * as queryResolver from "../../../../../src/local-queries/query-resolver";
16+
import { DatabaseItem } from "../../../../../src/databases/local-databases";
17+
import { Uri } from "vscode";
1118

1219
describe("queryResolver", () => {
13-
const resolveQueriesInSuite = jest.fn();
20+
let qlpackOfDatabase: jest.SpiedFunction<
21+
typeof queryResolver.qlpackOfDatabase
22+
>;
23+
24+
const resolveQueriesInSuite: jest.MockedFunction<
25+
typeof CodeQLCliServer.prototype.resolveQueriesInSuite
26+
> = jest.fn();
27+
const resolveDatabase: jest.MockedFunction<
28+
typeof CodeQLCliServer.prototype.resolveDatabase
29+
> = jest.fn();
30+
const packDownload: jest.MockedFunction<
31+
typeof CodeQLCliServer.prototype.packDownload
32+
> = jest.fn();
1433

1534
const mockCli = mockedObject<CodeQLCliServer>({
1635
resolveQueriesInSuite,
36+
resolveDatabase,
37+
packDownload,
1738
});
1839

1940
beforeEach(() => {
41+
qlpackOfDatabase = jest.spyOn(queryResolver, "qlpackOfDatabase");
42+
2043
jest
2144
.spyOn(workspaceFolders, "getOnDiskWorkspaceFolders")
2245
.mockReturnValue([]);
2346
jest.spyOn(log, "showAndLogErrorMessage").mockResolvedValue(undefined);
2447
});
2548

26-
describe("resolveQueries", () => {
49+
describe("resolveContextualQlPacksForDatabase", () => {
50+
let databaseItem: DatabaseItem;
51+
52+
beforeEach(() => {
53+
databaseItem = {
54+
name: "my-db",
55+
language: "csharp",
56+
databaseUri: Uri.file("/a/b/c/db"),
57+
} as DatabaseItem;
58+
});
59+
60+
it("should resolve a qlpack when CLI returns qlpack", async () => {
61+
qlpackOfDatabase.mockResolvedValue({
62+
dbschemePack: "dbschemePack",
63+
dbschemePackIsLibraryPack: false,
64+
});
65+
66+
expect(
67+
await resolveContextualQlPacksForDatabase(mockCli, databaseItem),
68+
).toEqual({
69+
dbschemePack: "dbschemePack",
70+
dbschemePackIsLibraryPack: false,
71+
});
72+
});
73+
74+
it("should return qlpack when downloading packs", async () => {
75+
qlpackOfDatabase.mockRejectedValue(new Error("error"));
76+
resolveDatabase.mockResolvedValue({
77+
languages: ["csharp"],
78+
} as DbInfo);
79+
80+
expect(
81+
await resolveContextualQlPacksForDatabase(mockCli, databaseItem),
82+
).toEqual({
83+
dbschemePack: "codeql/csharp-all",
84+
dbschemePackIsLibraryPack: true,
85+
queryPack: "codeql/csharp-queries",
86+
});
87+
expect(packDownload).toHaveBeenCalledTimes(1);
88+
expect(packDownload).toHaveBeenCalledWith([
89+
"codeql/csharp-all",
90+
"codeql/csharp-queries",
91+
]);
92+
});
93+
});
94+
95+
describe("resolveContextualQueries", () => {
2796
it("should resolve a query", async () => {
28-
resolveQueriesInSuite.mockReturnValue(["a", "b"]);
29-
const result = await resolveQueries(
97+
resolveQueriesInSuite.mockResolvedValue(["a", "b"]);
98+
const result = await resolveContextualQueries(
3099
mockCli,
31100
{ dbschemePack: "my-qlpack", dbschemePackIsLibraryPack: false },
32101
KeyType.DefinitionQuery,
@@ -53,10 +122,10 @@ describe("queryResolver", () => {
53122
});
54123

55124
it("should throw an error when there are no queries found", async () => {
56-
resolveQueriesInSuite.mockReturnValue([]);
125+
resolveQueriesInSuite.mockResolvedValue([]);
57126

58127
try {
59-
await resolveQueries(
128+
await resolveContextualQueries(
60129
mockCli,
61130
{ dbschemePack: "my-qlpack", dbschemePackIsLibraryPack: false },
62131
KeyType.DefinitionQuery,

0 commit comments

Comments
 (0)