Skip to content

Commit 288f49e

Browse files
committed
use ExtraOptions in codeql commands
1 parent c2b7b7f commit 288f49e

2 files changed

Lines changed: 98 additions & 2 deletions

File tree

src/codeql.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,35 @@ test('parse codeql bundle url version', t => {
6363
}
6464
}
6565
});
66+
67+
test('getExtraOptions works for explicit paths', t => {
68+
t.deepEqual(codeql.getExtraOptions({}, ['foo'], []), []);
69+
70+
t.deepEqual(codeql.getExtraOptions({foo: [42]}, ['foo'], []), ['42']);
71+
72+
t.deepEqual(codeql.getExtraOptions({foo: {bar: [42]}}, ['foo', 'bar'], []), ['42']);
73+
});
74+
75+
test('getExtraOptions works for wildcards', t => {
76+
t.deepEqual(codeql.getExtraOptions({'*': [42]}, ['foo'], []), ['42']);
77+
});
78+
79+
test('getExtraOptions works for wildcards and explicit paths', t => {
80+
let o1 = {'*': [42], foo: [87]};
81+
t.deepEqual(codeql.getExtraOptions(o1, ['foo'], []), ['42', '87']);
82+
83+
let o2 = {'*': [42], foo: [87]};
84+
t.deepEqual(codeql.getExtraOptions(o2, ['foo', 'bar'], []), ['42']);
85+
86+
let o3 = {'*': [42], foo: { '*': [87], bar: [99]}};
87+
let p = ['foo', 'bar'];
88+
t.deepEqual(codeql.getExtraOptions(o3, p, []), ['42', '87', '99']);
89+
});
90+
91+
test('getExtraOptions throws for bad content', t => {
92+
t.throws(() => codeql.getExtraOptions({'*': 42}, ['foo'], []));
93+
94+
t.throws(() => codeql.getExtraOptions({foo: 87}, ['foo'], []));
95+
96+
t.throws(() => codeql.getExtraOptions({'*': [42], foo: { '*': 87, bar: [99]}}, ['foo', 'bar'], []));
97+
});

src/codeql.ts

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ function getCodeQLForCmd(cmd: string): CodeQL {
307307
'trace-command',
308308
databasePath,
309309
...compilerSpecArg,
310+
...getExtraOptionsFromEnv(['database', 'trace-command']),
310311
process.execPath,
311312
path.resolve(__dirname, 'tracer-env.js'),
312313
envFile
@@ -320,6 +321,7 @@ function getCodeQLForCmd(cmd: string): CodeQL {
320321
databasePath,
321322
'--language=' + language,
322323
'--source-root=' + sourceRoot,
324+
...getExtraOptionsFromEnv(['database', 'init']),
323325
]);
324326
},
325327
runAutobuild: async function(language: string) {
@@ -345,7 +347,8 @@ function getCodeQLForCmd(cmd: string): CodeQL {
345347
'resolve',
346348
'extractor',
347349
'--format=json',
348-
'--language=' + language
350+
'--language=' + language,
351+
...getExtraOptionsFromEnv(['resolve', 'extractor']),
349352
],
350353
{
351354
silent: true,
@@ -363,6 +366,7 @@ function getCodeQLForCmd(cmd: string): CodeQL {
363366
await exec.exec(cmd, [
364367
'database',
365368
'trace-command',
369+
...getExtraOptionsFromEnv(['database', 'trace-command']),
366370
databasePath,
367371
'--',
368372
traceCommand
@@ -372,6 +376,7 @@ function getCodeQLForCmd(cmd: string): CodeQL {
372376
await exec.exec(cmd, [
373377
'database',
374378
'finalize',
379+
...getExtraOptionsFromEnv(['database', 'finalize']),
375380
databasePath
376381
]);
377382
},
@@ -380,7 +385,8 @@ function getCodeQLForCmd(cmd: string): CodeQL {
380385
'resolve',
381386
'queries',
382387
...queries,
383-
'--format=bylanguage'
388+
'--format=bylanguage',
389+
...getExtraOptionsFromEnv(['resolve', 'queries'])
384390
];
385391
if (extraSearchPath !== undefined) {
386392
codeqlArgs.push('--search-path', extraSearchPath);
@@ -406,6 +412,7 @@ function getCodeQLForCmd(cmd: string): CodeQL {
406412
'--format=sarif-latest',
407413
'--output=' + sarifFile,
408414
'--no-sarif-add-snippets',
415+
...getExtraOptionsFromEnv(['database', 'analyze']),
409416
querySuite
410417
]);
411418
}
@@ -419,3 +426,60 @@ export function isTracedLanguage(language: string): boolean {
419426
export function isScannedLanguage(language: string): boolean {
420427
return !isTracedLanguage(language);
421428
}
429+
430+
/**
431+
* Gets the options for `path` of `options` as an array of extra option strings.
432+
*/
433+
function getExtraOptionsFromEnv(path: string[]) {
434+
let options: ExtraOptions = util.getExtraOptionsEnvParam();
435+
return getExtraOptions(options, path, []);
436+
}
437+
438+
/**
439+
* Gets the options for `path` of `options` as an array of extra option strings.
440+
*
441+
* - the special terminal step name '*' in `options` matches all path steps
442+
* - throws an exception if this conversion is impossible.
443+
*/
444+
export /* exported for testing */ function getExtraOptions(
445+
options: any,
446+
path: string[],
447+
pathInfo: string[]): string[] {
448+
/**
449+
* Gets `options` as an array of extra option strings.
450+
*
451+
* - throws an exception mentioning `pathInfo` if this conversion is impossible.
452+
*/
453+
function asExtraOptions(options: any, pathInfo: string[]): string[] {
454+
if (options === undefined) {
455+
return [];
456+
}
457+
if (!Array.isArray(options)) {
458+
const msg =
459+
'The extra options for `' +
460+
pathInfo.join('.') +
461+
'` (`' +
462+
JSON.stringify(options) +
463+
'`) are not in an array.';
464+
throw new Error(msg);
465+
}
466+
return options.map(o => {
467+
const t = typeof o;
468+
if (t !== 'string' && t !== 'number' && t !== 'boolean') {
469+
const msg =
470+
'The extra option for `' +
471+
pathInfo.join('.') +
472+
'` (`' +
473+
JSON.stringify(o) +
474+
'`) is not a primitive value.';
475+
throw new Error(msg);
476+
}
477+
return o + '';
478+
});
479+
}
480+
let all = asExtraOptions(options?.['*'], pathInfo.concat('*'));
481+
let specific = path.length === 0 ?
482+
asExtraOptions(options, pathInfo) :
483+
getExtraOptions(options?.[path[0]], path?.slice(1), pathInfo.concat(path[0]));
484+
return all.concat(specific);
485+
}

0 commit comments

Comments
 (0)