Skip to content

Commit dd9f6bf

Browse files
author
Dave Bartolomeo
authored
Merge pull request #2244 from github/dbartol/debug-context
Refactor local query evaluation to prepare for debug adapter
2 parents 8a4f283 + 110f5f9 commit dd9f6bf

23 files changed

Lines changed: 1239 additions & 1051 deletions

extensions/ql-vscode/src/ast-cfg-commands.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,18 @@ import {
55
TemplatePrintAstProvider,
66
TemplatePrintCfgProvider,
77
} from "./contextual/templateProvider";
8-
import { compileAndRunQuery } from "./local-queries";
9-
import { QueryRunner } from "./queryRunner";
10-
import { QueryHistoryManager } from "./query-history/query-history-manager";
11-
import { DatabaseUI } from "./local-databases-ui";
12-
import { ResultsView } from "./interface";
138
import { AstCfgCommands } from "./common/commands";
9+
import { LocalQueries } from "./local-queries";
1410

1511
type AstCfgOptions = {
16-
queryRunner: QueryRunner;
17-
queryHistoryManager: QueryHistoryManager;
18-
databaseUI: DatabaseUI;
19-
localQueryResultsView: ResultsView;
20-
queryStorageDir: string;
21-
12+
localQueries: LocalQueries;
2213
astViewer: AstViewer;
2314
astTemplateProvider: TemplatePrintAstProvider;
2415
cfgTemplateProvider: TemplatePrintCfgProvider;
2516
};
2617

2718
export function getAstCfgCommands({
28-
queryRunner,
29-
queryHistoryManager,
30-
databaseUI,
31-
localQueryResultsView,
32-
queryStorageDir,
19+
localQueries,
3320
astViewer,
3421
astTemplateProvider,
3522
cfgTemplateProvider,
@@ -59,12 +46,7 @@ export function getAstCfgCommands({
5946
window.activeTextEditor?.document,
6047
);
6148
if (res) {
62-
await compileAndRunQuery(
63-
queryRunner,
64-
queryHistoryManager,
65-
databaseUI,
66-
localQueryResultsView,
67-
queryStorageDir,
49+
await localQueries.compileAndRunQuery(
6850
false,
6951
res[0],
7052
progress,

extensions/ql-vscode/src/common/logging/logger.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ export interface LogOptions {
33
trailingNewline?: boolean;
44
}
55

6-
export interface Logger {
6+
/** Minimal logger interface. */
7+
export interface BaseLogger {
78
/**
89
* Writes the given log message, optionally followed by a newline.
910
* This function is asynchronous and will only resolve once the message is written
@@ -15,7 +16,10 @@ export interface Logger {
1516
* @param options Optional settings.
1617
*/
1718
log(message: string, options?: LogOptions): Promise<void>;
19+
}
1820

21+
/** Full logger interface, including a function to show the log in the UI. */
22+
export interface Logger extends BaseLogger {
1923
/**
2024
* Reveal the logger channel in the UI.
2125
*

extensions/ql-vscode/src/contextual/astBuilder.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { DatabaseItem } from "../local-databases";
44
import { ChildAstItem, AstItem } from "../astViewer";
55
import fileRangeFromURI from "./fileRangeFromURI";
66
import { Uri } from "vscode";
7-
import { QueryWithResults } from "../run-queries-shared";
7+
import { QueryOutputDir } from "../run-queries-shared";
88

99
/**
1010
* A class that wraps a tree of QL results from a query that
@@ -14,12 +14,12 @@ export default class AstBuilder {
1414
private roots: AstItem[] | undefined;
1515
private bqrsPath: string;
1616
constructor(
17-
queryResults: QueryWithResults,
17+
outputDir: QueryOutputDir,
1818
private cli: CodeQLCliServer,
1919
public db: DatabaseItem,
2020
public fileName: Uri,
2121
) {
22-
this.bqrsPath = queryResults.query.resultsPaths.resultsPath;
22+
this.bqrsPath = outputDir.bqrsPath;
2323
}
2424

2525
async getRoots(): Promise<AstItem[]> {

extensions/ql-vscode/src/contextual/locationFinder.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import {
1919
runContextualQuery,
2020
} from "./queryResolver";
2121
import { CancellationToken, LocationLink, Uri } from "vscode";
22-
import { QueryWithResults } from "../run-queries-shared";
22+
import { QueryOutputDir } from "../run-queries-shared";
2323
import { QueryRunner } from "../queryRunner";
24+
import { QueryResultType } from "../pure/new-messages";
2425

2526
export const SELECT_QUERY_NAME = "#select";
2627
export const TEMPLATE_NAME = "selectedSourceFile";
@@ -78,21 +79,23 @@ export async function getLocationsForUriString(
7879
token,
7980
templates,
8081
);
81-
if (results.successful) {
82-
links.push(...(await getLinksFromResults(results, cli, db, filter)));
82+
if (results.resultType === QueryResultType.SUCCESS) {
83+
links.push(
84+
...(await getLinksFromResults(results.outputDir, cli, db, filter)),
85+
);
8386
}
8487
}
8588
return links;
8689
}
8790

8891
async function getLinksFromResults(
89-
results: QueryWithResults,
92+
outputDir: QueryOutputDir,
9093
cli: CodeQLCliServer,
9194
db: DatabaseItem,
9295
filter: (srcFile: string, destFile: string) => boolean,
9396
): Promise<FullLocationLink[]> {
9497
const localLinks: FullLocationLink[] = [];
95-
const bqrsPath = results.query.resultsPaths.resultsPath;
98+
const bqrsPath = outputDir.bqrsPath;
9699
const info = await cli.bqrsInfo(bqrsPath);
97100
const selectInfo = getResultSetSchema(SELECT_QUERY_NAME, info);
98101
if (isValidSelect(selectInfo)) {

extensions/ql-vscode/src/contextual/queryResolver.ts

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@ import {
1313
import { KeyType, kindOfKeyType, nameOfKeyType, tagOfKeyType } from "./keyType";
1414
import { CodeQLCliServer } from "../cli";
1515
import { DatabaseItem } from "../local-databases";
16-
import { extLogger } from "../common";
17-
import { createInitialQueryInfo } from "../run-queries-shared";
18-
import { CancellationToken, Uri } from "vscode";
16+
import { extLogger, TeeLogger } from "../common";
17+
import { CancellationToken } from "vscode";
1918
import { ProgressCallback } from "../progress";
20-
import { QueryRunner } from "../queryRunner";
19+
import { CoreCompletedQuery, QueryRunner } from "../queryRunner";
2120
import { redactableError } from "../pure/errors";
2221
import { QLPACK_FILENAMES } from "../pure/ql";
2322

@@ -169,32 +168,30 @@ export async function runContextualQuery(
169168
progress: ProgressCallback,
170169
token: CancellationToken,
171170
templates: Record<string, string>,
172-
) {
171+
): Promise<CoreCompletedQuery> {
173172
const { packPath, createdTempLockFile } = await resolveContextualQuery(
174173
cli,
175174
query,
176175
);
177-
const initialInfo = await createInitialQueryInfo(
178-
Uri.file(query),
179-
{
180-
name: db.name,
181-
databaseUri: db.databaseUri.toString(),
182-
},
176+
const queryRun = qs.createQueryRun(
177+
db.databaseUri.fsPath,
178+
{ queryPath: query, quickEvalPosition: undefined },
183179
false,
180+
getOnDiskWorkspaceFolders(),
181+
queryStorageDir,
182+
undefined,
183+
templates,
184184
);
185185
void extLogger.log(
186-
`Running contextual query ${query}; results will be stored in ${queryStorageDir}`,
186+
`Running contextual query ${query}; results will be stored in ${queryRun.outputDir.querySaveDir}`,
187187
);
188-
const queryResult = await qs.compileAndRunQueryAgainstDatabase(
189-
db,
190-
initialInfo,
191-
queryStorageDir,
188+
const results = await queryRun.evaluate(
192189
progress,
193190
token,
194-
templates,
191+
new TeeLogger(qs.logger, queryRun.outputDir.logPath),
195192
);
196193
if (createdTempLockFile) {
197194
await removeTemporaryLockFile(packPath);
198195
}
199-
return queryResult;
196+
return results;
200197
}

extensions/ql-vscode/src/contextual/templateProvider.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ import {
3232
runContextualQuery,
3333
} from "./queryResolver";
3434
import { isCanary, NO_CACHE_AST_VIEWER } from "../config";
35-
import { QueryWithResults } from "../run-queries-shared";
36-
import { QueryRunner } from "../queryRunner";
35+
import { CoreCompletedQuery, QueryRunner } from "../queryRunner";
3736

3837
/**
3938
* Runs templated CodeQL queries to find definitions in
@@ -155,25 +154,22 @@ export class TemplateQueryReferenceProvider implements ReferenceProvider {
155154
}
156155
}
157156

158-
type QueryWithDb = {
159-
query: QueryWithResults;
160-
dbUri: Uri;
161-
};
162-
163157
/**
164158
* Run templated CodeQL queries to produce AST information for
165159
* source-language files.
166160
*/
167161
export class TemplatePrintAstProvider {
168-
private cache: CachedOperation<QueryWithDb>;
162+
private cache: CachedOperation<CoreCompletedQuery>;
169163

170164
constructor(
171165
private cli: CodeQLCliServer,
172166
private qs: QueryRunner,
173167
private dbm: DatabaseManager,
174168
private queryStorageDir: string,
175169
) {
176-
this.cache = new CachedOperation<QueryWithDb>(this.getAst.bind(this));
170+
this.cache = new CachedOperation<CoreCompletedQuery>(
171+
this.getAst.bind(this),
172+
);
177173
}
178174

179175
async provideAst(
@@ -186,14 +182,14 @@ export class TemplatePrintAstProvider {
186182
"Cannot view the AST. Please select a valid source file inside a CodeQL database.",
187183
);
188184
}
189-
const { query, dbUri } = this.shouldCache()
185+
const completedQuery = this.shouldCache()
190186
? await this.cache.get(fileUri.toString(), progress, token)
191187
: await this.getAst(fileUri.toString(), progress, token);
192188

193189
return new AstBuilder(
194-
query,
190+
completedQuery.outputDir,
195191
this.cli,
196-
this.dbm.findDatabaseItem(dbUri)!,
192+
this.dbm.findDatabaseItem(Uri.file(completedQuery.dbPath))!,
197193
fileUri,
198194
);
199195
}
@@ -206,7 +202,7 @@ export class TemplatePrintAstProvider {
206202
uriString: string,
207203
progress: ProgressCallback,
208204
token: CancellationToken,
209-
): Promise<QueryWithDb> {
205+
): Promise<CoreCompletedQuery> {
210206
const uri = Uri.parse(uriString, true);
211207
if (uri.scheme !== zipArchiveScheme) {
212208
throw new Error(
@@ -242,7 +238,7 @@ export class TemplatePrintAstProvider {
242238
[TEMPLATE_NAME]: zippedArchive.pathWithinSourceArchive,
243239
};
244240

245-
const queryResult = await runContextualQuery(
241+
const results = await runContextualQuery(
246242
query,
247243
db,
248244
this.queryStorageDir,
@@ -252,10 +248,7 @@ export class TemplatePrintAstProvider {
252248
token,
253249
templates,
254250
);
255-
return {
256-
query: queryResult,
257-
dbUri: db.databaseUri,
258-
};
251+
return results;
259252
}
260253
}
261254

extensions/ql-vscode/src/extension.ts

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,7 @@ import {
115115
QueryServerCommands,
116116
TestUICommands,
117117
} from "./common/commands";
118-
import {
119-
getLocalQueryCommands,
120-
showResultsForCompletedQuery,
121-
} from "./local-queries";
118+
import { LocalQueries } from "./local-queries";
122119
import { getAstCfgCommands } from "./ast-cfg-commands";
123120
import { getQueryEditorCommands } from "./query-editor";
124121
import { App } from "./common/app";
@@ -260,6 +257,7 @@ export interface CodeQLExtensionInterface {
260257
readonly distributionManager: DistributionManager;
261258
readonly databaseManager: DatabaseManager;
262259
readonly databaseUI: DatabaseUI;
260+
readonly localQueries: LocalQueries;
263261
readonly variantAnalysisManager: VariantAnalysisManager;
264262
readonly dispose: () => void;
265263
}
@@ -716,12 +714,6 @@ async function activateWithInstalledDistribution(
716714
void extLogger.log("Initializing query history manager.");
717715
const queryHistoryConfigurationListener = new QueryHistoryConfigListener();
718716
ctx.subscriptions.push(queryHistoryConfigurationListener);
719-
const showResults = async (item: CompletedLocalQueryInfo) =>
720-
showResultsForCompletedQuery(
721-
localQueryResultsView,
722-
item,
723-
WebviewReveal.Forced,
724-
);
725717
const queryStorageDir = join(ctx.globalStorageUri.fsPath, "queries");
726718
await ensureDir(queryStorageDir);
727719

@@ -795,8 +787,10 @@ async function activateWithInstalledDistribution(
795787
ctx,
796788
queryHistoryConfigurationListener,
797789
labelProvider,
798-
async (from: CompletedLocalQueryInfo, to: CompletedLocalQueryInfo) =>
799-
showResultsForComparison(compareView, from, to),
790+
async (
791+
from: CompletedLocalQueryInfo,
792+
to: CompletedLocalQueryInfo,
793+
): Promise<void> => showResultsForComparison(compareView, from, to),
800794
);
801795

802796
ctx.subscriptions.push(qhm);
@@ -817,7 +811,8 @@ async function activateWithInstalledDistribution(
817811
cliServer,
818812
queryServerLogger,
819813
labelProvider,
820-
showResults,
814+
async (item: CompletedLocalQueryInfo) =>
815+
localQueries.showResultsForCompletedQuery(item, WebviewReveal.Forced),
821816
);
822817
ctx.subscriptions.push(compareView);
823818

@@ -853,6 +848,18 @@ async function activateWithInstalledDistribution(
853848
true,
854849
);
855850

851+
const localQueries = new LocalQueries(
852+
app,
853+
qs,
854+
qhm,
855+
dbm,
856+
cliServer,
857+
databaseUI,
858+
localQueryResultsView,
859+
queryStorageDir,
860+
);
861+
ctx.subscriptions.push(localQueries);
862+
856863
void extLogger.log("Initializing QLTest interface.");
857864
const testExplorerExtension = extensions.getExtension<TestHub>(
858865
testExplorerExtensionId,
@@ -906,11 +913,7 @@ async function activateWithInstalledDistribution(
906913
...databaseUI.getCommands(),
907914
...dbModule.getCommands(),
908915
...getAstCfgCommands({
909-
queryRunner: qs,
910-
queryHistoryManager: qhm,
911-
databaseUI,
912-
localQueryResultsView,
913-
queryStorageDir,
916+
localQueries,
914917
astViewer,
915918
astTemplateProvider,
916919
cfgTemplateProvider,
@@ -930,16 +933,7 @@ async function activateWithInstalledDistribution(
930933
}
931934

932935
const queryServerCommands: QueryServerCommands = {
933-
...getLocalQueryCommands({
934-
app,
935-
queryRunner: qs,
936-
queryHistoryManager: qhm,
937-
databaseManager: dbm,
938-
cliServer,
939-
databaseUI,
940-
localQueryResultsView,
941-
queryStorageDir,
942-
}),
936+
...localQueries.getCommands(),
943937
};
944938

945939
for (const [commandName, command] of Object.entries(queryServerCommands)) {
@@ -989,6 +983,7 @@ async function activateWithInstalledDistribution(
989983
return {
990984
ctx,
991985
cliServer,
986+
localQueries,
992987
qs,
993988
distributionManager,
994989
databaseManager: dbm,

0 commit comments

Comments
 (0)