Skip to content

Commit 14b9f93

Browse files
authored
Merge pull request #2731 from github/starcke/no-submodule
Make automodel and flow queries work without submodule.
2 parents 20e5429 + f3e32ba commit 14b9f93

11 files changed

Lines changed: 83 additions & 65 deletions

File tree

extensions/ql-vscode/src/data-extensions-editor/auto-model-codeml-queries.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { CoreCompletedQuery, QueryRunner } from "../query-server";
33
import { DatabaseItem } from "../databases/local-databases";
44
import { ProgressCallback } from "../common/vscode/progress";
55
import * as Sarif from "sarif";
6-
import { qlpackOfDatabase, resolveQueries } from "../local-queries";
76
import { Mode } from "./shared/mode";
87
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
98
import { interpretResultsSarif } from "../query-results";
@@ -16,6 +15,7 @@ import { MethodSignature } from "./external-api-usage";
1615
import { runQuery } from "../local-queries/run-query";
1716
import { QueryMetadata } from "../common/interface-types";
1817
import { CancellationTokenSource } from "vscode";
18+
import { resolveQueries } from "../local-queries";
1919

2020
function modeTag(mode: Mode): string {
2121
switch (mode) {
@@ -84,6 +84,7 @@ export async function runAutoModelQueries({
8484
extensionPacks,
8585
progress,
8686
token: cancellationTokenSource.token,
87+
createLockFile: false,
8788
});
8889

8990
if (!completedQuery) {
@@ -127,15 +128,15 @@ async function resolveAutomodelQuery(
127128
queryTag: string,
128129
mode: Mode,
129130
): Promise<string> {
130-
const qlpack = await qlpackOfDatabase(cliServer, databaseItem);
131+
const packsToSearch = [`codeql/${databaseItem.language}-queries`];
131132

132133
// First, resolve the query that we want to run.
133134
// All queries are tagged like this:
134135
// internal extract automodel <mode> <queryTag>
135136
// Example: internal extract automodel framework-mode candidates
136137
const queries = await resolveQueries(
137138
cliServer,
138-
qlpack,
139+
packsToSearch,
139140
`Extract automodel ${queryTag}`,
140141
{
141142
kind: "problem",

extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-module.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,10 @@ export class DataExtensionsEditorModule extends DisposableObject {
136136

137137
// Create new temporary directory for query files and pack dependencies
138138
const queryDir = (await dir({ unsafeCleanup: true })).path;
139-
const success = await setUpPack(queryDir, language);
139+
const success = await setUpPack(this.cliServer, queryDir, language);
140140
if (!success) {
141141
return;
142142
}
143-
await this.cliServer.packInstall(queryDir);
144143

145144
const view = new DataExtensionsEditorView(
146145
this.ctx,

extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-queries.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { QueryLanguage } from "../common/query-language";
33
import { writeFile } from "fs-extra";
44
import { dump } from "js-yaml";
55
import { prepareExternalApiQuery } from "./external-api-usage-queries";
6+
import { CodeQLCliServer } from "../codeql-cli/cli";
67

78
/**
89
* setUpPack sets up a directory to use for the data extension editor queries.
@@ -11,6 +12,7 @@ import { prepareExternalApiQuery } from "./external-api-usage-queries";
1112
* @returns true if the setup was successful, false otherwise.
1213
*/
1314
export async function setUpPack(
15+
cliServer: CodeQLCliServer,
1416
queryDir: string,
1517
language: QueryLanguage,
1618
): Promise<boolean> {
@@ -23,7 +25,7 @@ export async function setUpPack(
2325
return false;
2426
}
2527

26-
// Set up a synthetic query pack to resolve dependencies.
28+
// Set up a synthetic pack so that the query can be resolved later.
2729
const syntheticQueryPack = {
2830
name: "codeql/external-api-usage",
2931
version: "0.0.0",
@@ -34,5 +36,10 @@ export async function setUpPack(
3436

3537
const qlpackFile = join(queryDir, "codeql-pack.yml");
3638
await writeFile(qlpackFile, dump(syntheticQueryPack), "utf8");
39+
await cliServer.packInstall(queryDir);
40+
41+
// Install the other needed query packs
42+
await cliServer.packDownload([`codeql/${language}-queries`]);
43+
3744
return true;
3845
}

extensions/ql-vscode/src/data-extensions-editor/external-api-usage-queries.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ export async function runExternalApiQueries(
9494
extensionPacks,
9595
progress,
9696
token,
97+
// We need to create a lock file, because the query is inside our own pack
98+
createLockFile: true,
9799
});
98100

99101
if (!completedQuery) {

extensions/ql-vscode/src/data-extensions-editor/flow-model-queries.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import { ProgressCallback } from "../common/vscode/progress";
1010
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
1111
import { ModeledMethod, ModeledMethodType } from "./modeled-method";
1212
import { redactableError } from "../common/errors";
13-
import { qlpackOfDatabase, resolveQueries } from "../local-queries";
1413
import { telemetryListener } from "../common/vscode/telemetry";
1514
import { runQuery } from "../local-queries/run-query";
15+
import { resolveQueries } from "../local-queries";
1616

1717
type FlowModelOptions = {
1818
cliServer: CodeQLCliServer;
@@ -83,11 +83,16 @@ async function resolveFlowQueries(
8383
cliServer: CodeQLCliServer,
8484
databaseItem: DatabaseItem,
8585
): Promise<string[]> {
86-
const qlpacks = await qlpackOfDatabase(cliServer, databaseItem);
86+
const packsToSearch = [`codeql/${databaseItem.language}-queries`];
8787

88-
return await resolveQueries(cliServer, qlpacks, "flow model generator", {
89-
"tags contain": ["modelgenerator"],
90-
});
88+
return await resolveQueries(
89+
cliServer,
90+
packsToSearch,
91+
"flow model generator",
92+
{
93+
"tags contain": ["modelgenerator"],
94+
},
95+
);
9196
}
9297

9398
async function runSingleFlowQuery(
@@ -129,6 +134,7 @@ async function runSingleFlowQuery(
129134
maxStep: 4000,
130135
}),
131136
token,
137+
createLockFile: false,
132138
});
133139

134140
if (!completedQuery) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from "./key-type";
99
import { CodeQLCliServer } from "../../codeql-cli/cli";
1010
import { DatabaseItem } from "../../databases/local-databases";
11-
import { resolveQueries as resolveLocalQueries } from "../../local-queries/query-resolver";
11+
import { resolveQueriesByLanguagePack as resolveLocalQueries } from "../../local-queries/query-resolver";
1212
import { extLogger } from "../../common/logging/vscode";
1313
import { TeeLogger } from "../../common/logging";
1414
import { CancellationToken } from "vscode";

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,7 @@ async function resolveQueriesFromPacks(
7272
);
7373
}
7474

75-
/**
76-
* Finds the queries with the specified kind and tags in a QLPack.
77-
*
78-
* @param cli The CLI instance to use.
79-
* @param qlpacks The list of packs to search.
80-
* @param name The name of the query to use in error messages.
81-
* @param constraints Constraints on the queries to search for.
82-
* @returns The found queries from the first pack in which any matching queries were found.
83-
*/
84-
export async function resolveQueries(
75+
export async function resolveQueriesByLanguagePack(
8576
cli: CodeQLCliServer,
8677
qlpacks: QlPacksForLanguage,
8778
name: string,
@@ -95,6 +86,24 @@ export async function resolveQueries(
9586
packsToSearch.push(qlpacks.queryPack);
9687
}
9788

89+
return resolveQueries(cli, packsToSearch, name, constraints);
90+
}
91+
92+
/**
93+
* Finds the queries with the specified kind and tags in a QLPack.
94+
*
95+
* @param cli The CLI instance to use.
96+
* @param packsToSearch The list of packs to search.
97+
* @param name The name of the query to use in error messages.
98+
* @param constraints Constraints on the queries to search for.
99+
* @returns The found queries from the first pack in which any matching queries were found.
100+
*/
101+
export async function resolveQueries(
102+
cli: CodeQLCliServer,
103+
packsToSearch: string[],
104+
name: string,
105+
constraints: QueryConstraints,
106+
): Promise<string[]> {
98107
const queries = await resolveQueriesFromPacks(
99108
cli,
100109
packsToSearch,

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type RunQueryOptions = {
2121
extensionPacks: string[] | undefined;
2222
progress: ProgressCallback;
2323
token: CancellationToken;
24+
createLockFile: boolean;
2425
};
2526

2627
export async function runQuery({
@@ -33,12 +34,17 @@ export async function runQuery({
3334
extensionPacks,
3435
progress,
3536
token,
37+
createLockFile,
3638
}: RunQueryOptions): Promise<CoreCompletedQuery | undefined> {
37-
// Create a lock file for the query. This is required to resolve dependencies and library path for the query.
38-
const { cleanup: cleanupLockFile } = await createLockFileForStandardQuery(
39-
cliServer,
40-
queryPath,
41-
);
39+
let cleanupLockFile: (() => Promise<void>) | undefined = undefined;
40+
if (createLockFile) {
41+
// Create a lock file for the query. This is required to resolve dependencies and library path for the query.
42+
const { cleanup } = await createLockFileForStandardQuery(
43+
cliServer,
44+
queryPath,
45+
);
46+
cleanupLockFile = cleanup;
47+
}
4248

4349
// Create a query run to execute
4450
const queryRun = queryRunner.createQueryRun(

extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/auto-model-codeml-queries.test.ts

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { mockedObject, mockedUri } from "../../utils/mocking.helpers";
1414
import { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
1515
import { QueryRunner } from "../../../../src/query-server";
1616
import * as queryResolver from "../../../../src/local-queries/query-resolver";
17-
import * as standardQueries from "../../../../src/local-queries/standard-queries";
1817
import { MethodSignature } from "../../../../src/data-extensions-editor/external-api-usage";
1918
import { join } from "path";
2019
import { exists, readFile } from "fs-extra";
@@ -23,40 +22,27 @@ import { CancellationTokenSource } from "vscode-jsonrpc";
2322
import { QueryOutputDir } from "../../../../src/run-queries-shared";
2423

2524
describe("runAutoModelQueries", () => {
26-
const qlpack = {
27-
dbschemePack: "dbschemePack",
28-
dbschemePackIsLibraryPack: false,
29-
};
30-
3125
let resolveQueriesSpy: jest.SpiedFunction<
3226
typeof queryResolver.resolveQueries
3327
>;
34-
let createLockFileForStandardQuerySpy: jest.SpiedFunction<
35-
typeof standardQueries.createLockFileForStandardQuery
36-
>;
37-
3828
beforeEach(() => {
39-
jest.spyOn(queryResolver, "qlpackOfDatabase").mockResolvedValue(qlpack);
40-
4129
resolveQueriesSpy = jest
4230
.spyOn(queryResolver, "resolveQueries")
43-
.mockImplementation(async (_cliServer, _qlPack, _name, constraints) => {
44-
if (constraints["tags contain all"]?.includes("candidates")) {
45-
return ["/a/b/c/ql/candidates.ql"];
46-
}
47-
if (constraints["tags contain all"]?.includes("positive")) {
48-
return ["/a/b/c/ql/positive-examples.ql"];
49-
}
50-
if (constraints["tags contain all"]?.includes("negative")) {
51-
return ["/a/b/c/ql/negative-examples.ql"];
52-
}
31+
.mockImplementation(
32+
async (_cliServer, _packsToSearch, _name, constraints) => {
33+
if (constraints["tags contain all"]?.includes("candidates")) {
34+
return ["/a/b/c/ql/candidates.ql"];
35+
}
36+
if (constraints["tags contain all"]?.includes("positive")) {
37+
return ["/a/b/c/ql/positive-examples.ql"];
38+
}
39+
if (constraints["tags contain all"]?.includes("negative")) {
40+
return ["/a/b/c/ql/negative-examples.ql"];
41+
}
5342

54-
return [];
55-
});
56-
57-
createLockFileForStandardQuerySpy = jest
58-
.spyOn(standardQueries, "createLockFileForStandardQuery")
59-
.mockResolvedValue({});
43+
return [];
44+
},
45+
);
6046
});
6147

6248
it("should run the query and return the results", async () => {
@@ -154,18 +140,13 @@ describe("runAutoModelQueries", () => {
154140
expect(resolveQueriesSpy).toHaveBeenCalledTimes(1);
155141
expect(resolveQueriesSpy).toHaveBeenCalledWith(
156142
options.cliServer,
157-
qlpack,
143+
["codeql/java-queries"],
158144
"Extract automodel candidates",
159145
{
160146
kind: "problem",
161147
"tags contain all": ["automodel", "application-mode", "candidates"],
162148
},
163149
);
164-
expect(createLockFileForStandardQuerySpy).toHaveBeenCalledTimes(1);
165-
expect(createLockFileForStandardQuerySpy).toHaveBeenCalledWith(
166-
options.cliServer,
167-
"/a/b/c/ql/candidates.ql",
168-
);
169150
expect(options.queryRunner.createQueryRun).toHaveBeenCalledTimes(1);
170151
expect(options.queryRunner.createQueryRun).toHaveBeenCalledWith(
171152
"/a/b/c/src.zip",

extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/data-extensions-editor-queries.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@ import { dirSync } from "tmp-promise";
66
import { fetchExternalApiQueries } from "../../../../src/data-extensions-editor/queries";
77
import { QueryLanguage } from "../../../../src/common/query-language";
88
import { Mode } from "../../../../src/data-extensions-editor/shared/mode";
9+
import { mockedObject } from "../../utils/mocking.helpers";
10+
import { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
911

1012
describe("setUpPack", () => {
13+
const cliServer = mockedObject<CodeQLCliServer>({
14+
packDownload: jest.fn(),
15+
packInstall: jest.fn(),
16+
});
17+
1118
const languages = Object.keys(fetchExternalApiQueries).flatMap((lang) => {
1219
const queryDir = dirSync({ unsafeCleanup: true }).name;
1320
const query = fetchExternalApiQueries[lang as QueryLanguage];
@@ -21,7 +28,7 @@ describe("setUpPack", () => {
2128
test.each(languages)(
2229
"should create files for $language",
2330
async ({ language, queryDir, query }) => {
24-
await setUpPack(queryDir, language);
31+
await setUpPack(cliServer, queryDir, language);
2532

2633
const queryFiles = await readdir(queryDir);
2734
expect(queryFiles.sort()).toEqual(

0 commit comments

Comments
 (0)