Skip to content

Commit b7dafc3

Browse files
committed
Better comments around splat and slurp functions
Also, address other small PR comments.
1 parent 2f5a306 commit b7dafc3

4 files changed

Lines changed: 45 additions & 22 deletions

File tree

extensions/ql-vscode/src/interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ export class InterfaceManager extends DisposableObject {
316316
// sortedResultsInfo doesn't have an entry for the current
317317
// result set. Use this to determine whether or not we use
318318
// the sorted bqrs file.
319-
!!this._displayedQuery?.completedQuery.sortedResultsInfo[msg.selectedTable] || false
319+
!!this._displayedQuery?.completedQuery.sortedResultsInfo[msg.selectedTable]
320320
);
321321
}
322322
break;

extensions/ql-vscode/src/query-results.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ export class CompletedQueryInfo implements QueryWithResults {
6464
*/
6565
interpretedResultsSortState: InterpretedResultsSortState | undefined;
6666

67+
/**
68+
* Note that in the {@link FullQueryInfo.slurp} method, we create a CompletedQueryInfo instance
69+
* by explicitly setting the prototype in order to avoid calling this constructor.
70+
*/
6771
constructor(
6872
evaluation: QueryWithResults,
6973
) {
@@ -191,7 +195,8 @@ export class FullQueryInfo {
191195
return queries.map((q: FullQueryInfo) => {
192196

193197
// Need to explicitly set prototype since reading in from JSON will not
194-
// do this automatically.
198+
// do this automatically. Note that we can't call the constructor here since
199+
// the constructor invokes extra logic that we don't want to do.
195200
Object.setPrototypeOf(q, FullQueryInfo.prototype);
196201

197202
// The config object is a global, se we need to set it explicitly
@@ -218,32 +223,43 @@ export class FullQueryInfo {
218223
}
219224
}
220225

226+
/**
227+
* Save the query history to disk. It is not necessary that the parent directory
228+
* exists, but if it does, it must be writable. An existing file will be overwritten.
229+
*
230+
* Any errors will be rethrown.
231+
*
232+
* @param queries the list of queries to save.
233+
* @param fsPath the path to save the queries to.
234+
*/
221235
static async splat(queries: FullQueryInfo[], fsPath: string): Promise<void> {
222236
try {
223237
const data = JSON.stringify(queries, null, 2);
224238
await fs.mkdirp(path.dirname(fsPath));
225239
await fs.writeFile(fsPath, data);
226240
} catch (e) {
227-
void showAndLogErrorMessage('Error saving query history.', {
228-
fullMessage: ['Error saving query history.', e.stack].join('\n'),
229-
});
241+
throw new Error(`Error saving query history to ${fsPath}: ${e.message}`);
230242
}
231243
}
232244

233245
public failureReason: string | undefined;
234246
public completedQuery: CompletedQueryInfo | undefined;
235247
private config: QueryHistoryConfig | undefined;
236248

249+
/**
250+
* Note that in the {@link FullQueryInfo.slurp} method, we create a FullQueryInfo instance
251+
* by explicitly setting the prototype in order to avoid calling this constructor.
252+
*/
237253
constructor(
238254
public readonly initialInfo: InitialQueryInfo,
239255
config: QueryHistoryConfig,
240-
private readonly source: CancellationTokenSource
256+
private readonly source?: CancellationTokenSource
241257
) {
242258
this.setConfig(config);
243259
}
244260

245261
cancel() {
246-
this.source.cancel();
262+
this.source?.cancel();
247263
}
248264

249265
get startTime() {

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

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ export const queriesDir = path.join(tmpDir.name, 'queries');
5959
export class QueryEvaluationInfo {
6060
readonly querySaveDir: string;
6161

62+
/**
63+
* Note that in the {@link FullQueryInfo.slurp} method, we create a QueryEvaluationInfo instance
64+
* by explicitly setting the prototype in order to avoid calling this constructor.
65+
*/
6266
constructor(
6367
public readonly id: string,
6468
public readonly dbItemPath: string,
@@ -190,16 +194,19 @@ export class QueryEvaluationInfo {
190194
canHaveInterpretedResults(): boolean {
191195
if (!this.databaseHasMetadataFile) {
192196
void logger.log('Cannot produce interpreted results since the database does not have a .dbinfo or codeql-database.yml file.');
197+
return false;
193198
}
194199

195200
const hasKind = !!this.metadata?.kind;
196201
if (!hasKind) {
197202
void logger.log('Cannot produce interpreted results since the query does not have @kind metadata.');
203+
return false;
198204
}
199205

206+
// table is the default query kind. It does not produce interpreted results.
207+
// any query kind that is not table can, in principle, produce interpreted results.
200208
const isTable = hasKind && this.metadata?.kind === 'table';
201-
202-
return this.databaseHasMetadataFile && hasKind && !isTable;
209+
return !isTable;
203210
}
204211

205212
/**
@@ -388,15 +395,13 @@ async function checkDbschemeCompatibility(
388395

389396
// At this point, we have learned about three dbschemes:
390397

391-
// query.program.dbschemePath is the dbscheme of the actual
392-
// database we're querying.
398+
// the dbscheme of the actual database we're querying.
393399
const dbschemeOfDb = await hash(dbItem.contents.dbSchemeUri.fsPath);
394400

395-
// query.queryDbScheme is the dbscheme of the query we're
396-
// running, including the library we've resolved it to use.
401+
// the dbscheme of the query we're running, including the library we've resolved it to use.
397402
const dbschemeOfLib = await hash(query.queryDbscheme);
398403

399-
// info.finalDbscheme is which database we're able to upgrade to
404+
// the database we're able to upgrade to
400405
const upgradableTo = await hash(finalDbscheme);
401406

402407
if (upgradableTo != dbschemeOfLib) {
@@ -533,14 +538,13 @@ export async function determineSelectedQuery(selectedResourceUri: Uri | undefine
533538
if (queryUri.scheme !== 'file') {
534539
throw new Error('Can only run queries that are on disk.');
535540
}
536-
const queryPath = queryUri.fsPath || '';
541+
const queryPath = queryUri.fsPath;
537542

538543
if (quickEval) {
539544
if (!(queryPath.endsWith('.ql') || queryPath.endsWith('.qll'))) {
540545
throw new Error('The selected resource is not a CodeQL file; It should have the extension ".ql" or ".qll".');
541546
}
542-
}
543-
else {
547+
} else {
544548
if (!(queryPath.endsWith('.ql'))) {
545549
throw new Error('The selected resource is not a CodeQL query file; It should have the extension ".ql".');
546550
}
@@ -645,10 +649,11 @@ export async function compileAndRunQueryAgainstDatabase(
645649
}
646650
}
647651

652+
const hasMetadataFile = (await dbItem.hasMetadataFile());
648653
const query = new QueryEvaluationInfo(
649654
initialInfo.id,
650655
dbItem.databaseUri.fsPath,
651-
(await dbItem.hasMetadataFile()),
656+
hasMetadataFile,
652657
packConfig.dbscheme,
653658
initialInfo.quickEvalPosition,
654659
metadata,

extensions/ql-vscode/src/vscode-tests/no-workspace/run-queries.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as sinon from 'sinon';
66
import * as chaiAsPromised from 'chai-as-promised';
77

88
import { QueryEvaluationInfo, queriesDir } from '../../run-queries';
9-
import { QlProgram, Severity, compileQuery } from '../../pure/messages';
9+
import { Severity, compileQuery } from '../../pure/messages';
1010
import { Uri } from 'vscode';
1111

1212
chai.use(chaiAsPromised);
@@ -21,7 +21,7 @@ describe('run-queries', () => {
2121
expect(info.dilPath).to.eq(path.join(queriesDir, queryId, 'results.dil'));
2222
expect(info.resultsPaths.resultsPath).to.eq(path.join(queriesDir, queryId, 'results.bqrs'));
2323
expect(info.resultsPaths.interpretedResultsPath).to.eq(path.join(queriesDir, queryId, 'interpretedResults.sarif'));
24-
expect(info.dbItemPath).to.eq('file:///abc');
24+
expect(info.dbItemPath).to.eq(Uri.file('/abc').fsPath);
2525
});
2626

2727
it('should check if interpreted results can be created', async () => {
@@ -47,8 +47,10 @@ describe('run-queries', () => {
4747
const mockProgress = 'progress-monitor';
4848
const mockCancel = 'cancel-token';
4949
const mockQlProgram = {
50-
mock: 'program'
51-
} as unknown as QlProgram;
50+
dbschemePath: '',
51+
libraryPath: [],
52+
queryPath: ''
53+
};
5254

5355
const results = await info.compile(
5456
qs as any,

0 commit comments

Comments
 (0)