Run eslint --fix on the extension
This commit is contained in:
Родитель
45dc2a29cf
Коммит
ff8e72a318
|
@ -1,4 +1,4 @@
|
|||
import { DecodedBqrsChunk, ResultSetSchema, ColumnKind, Column, ColumnValue } from "./bqrs-cli-types";
|
||||
import { DecodedBqrsChunk, ResultSetSchema, ColumnKind, Column, ColumnValue } from './bqrs-cli-types';
|
||||
import { LocationValue, ResultSetSchema as AdaptedSchema, ColumnSchema, ColumnType, LocationStyle } from 'semmle-bqrs';
|
||||
|
||||
// FIXME: This is a temporary bit of impedance matching to convert
|
||||
|
|
|
@ -8,12 +8,12 @@ export const PAGE_SIZE = 1000;
|
|||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace ColumnKindCode {
|
||||
export const FLOAT = "f";
|
||||
export const INTEGER = "i";
|
||||
export const STRING = "s";
|
||||
export const BOOLEAN = "b";
|
||||
export const DATE = "d";
|
||||
export const ENTITY = "e";
|
||||
export const FLOAT = 'f';
|
||||
export const INTEGER = 'i';
|
||||
export const STRING = 's';
|
||||
export const BOOLEAN = 'b';
|
||||
export const DATE = 'd';
|
||||
export const ENTITY = 'e';
|
||||
}
|
||||
|
||||
export type ColumnKind =
|
||||
|
@ -37,7 +37,7 @@ export interface ResultSetSchema {
|
|||
}
|
||||
|
||||
export function getResultSetSchema(resultSetName: string, resultSets: BQRSInfo): ResultSetSchema | undefined {
|
||||
for (const schema of resultSets["result-sets"]) {
|
||||
for (const schema of resultSets['result-sets']) {
|
||||
if (schema.name === resultSetName) {
|
||||
return schema;
|
||||
}
|
||||
|
@ -45,12 +45,12 @@ export function getResultSetSchema(resultSetName: string, resultSets: BQRSInfo):
|
|||
return undefined;
|
||||
}
|
||||
export interface PaginationInfo {
|
||||
"step-size": number;
|
||||
'step-size': number;
|
||||
offsets: number[];
|
||||
}
|
||||
|
||||
export interface BQRSInfo {
|
||||
"result-sets": ResultSetSchema[];
|
||||
'result-sets': ResultSetSchema[];
|
||||
}
|
||||
|
||||
export interface EntityValue {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as semver from "semver";
|
||||
import { runCodeQlCliCommand } from "./cli";
|
||||
import { Logger } from "./logging";
|
||||
import * as semver from 'semver';
|
||||
import { runCodeQlCliCommand } from './cli';
|
||||
import { Logger } from './logging';
|
||||
|
||||
/**
|
||||
* Get the version of a CodeQL CLI.
|
||||
|
@ -9,9 +9,9 @@ export async function getCodeQlCliVersion(codeQlPath: string, logger: Logger): P
|
|||
try {
|
||||
const output: string = await runCodeQlCliCommand(
|
||||
codeQlPath,
|
||||
["version"],
|
||||
["--format=terse"],
|
||||
"Checking CodeQL version",
|
||||
['version'],
|
||||
['--format=terse'],
|
||||
'Checking CodeQL version',
|
||||
logger
|
||||
);
|
||||
return semver.parse(output.trim()) || undefined;
|
||||
|
|
|
@ -9,16 +9,16 @@ import { StringDecoder } from 'string_decoder';
|
|||
import * as tk from 'tree-kill';
|
||||
import * as util from 'util';
|
||||
import { CancellationToken, Disposable } from 'vscode';
|
||||
import { BQRSInfo, DecodedBqrsChunk } from "./bqrs-cli-types";
|
||||
import { DistributionProvider } from "./distribution";
|
||||
import { assertNever } from "./helpers-pure";
|
||||
import { QueryMetadata, SortDirection } from "./interface-types";
|
||||
import { Logger, ProgressReporter } from "./logging";
|
||||
import { BQRSInfo, DecodedBqrsChunk } from './bqrs-cli-types';
|
||||
import { DistributionProvider } from './distribution';
|
||||
import { assertNever } from './helpers-pure';
|
||||
import { QueryMetadata, SortDirection } from './interface-types';
|
||||
import { Logger, ProgressReporter } from './logging';
|
||||
|
||||
/**
|
||||
* The version of the SARIF format that we are using.
|
||||
*/
|
||||
const SARIF_FORMAT = "sarifv2.1.0";
|
||||
const SARIF_FORMAT = 'sarifv2.1.0';
|
||||
|
||||
/**
|
||||
* Flags to pass to all cli commands.
|
||||
|
@ -131,7 +131,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
// Tell the Java CLI server process to shut down.
|
||||
this.logger.log('Sending shutdown request');
|
||||
try {
|
||||
this.process.stdin.write(JSON.stringify(["shutdown"]), "utf8");
|
||||
this.process.stdin.write(JSON.stringify(['shutdown']), 'utf8');
|
||||
this.process.stdin.write(this.nullBuffer);
|
||||
this.logger.log('Sent shutdown request');
|
||||
} catch (e) {
|
||||
|
@ -188,13 +188,13 @@ export class CodeQLCliServer implements Disposable {
|
|||
*/
|
||||
private async launchProcess(): Promise<child_process.ChildProcessWithoutNullStreams> {
|
||||
const config = await this.getCodeQlPath();
|
||||
return spawnServer(config, "CodeQL CLI Server", ["execute", "cli-server"], [], this.logger, _data => { /**/ });
|
||||
return spawnServer(config, 'CodeQL CLI Server', ['execute', 'cli-server'], [], this.logger, _data => { /**/ });
|
||||
}
|
||||
|
||||
private async runCodeQlCliInternal(command: string[], commandArgs: string[], description: string): Promise<string> {
|
||||
const stderrBuffers: Buffer[] = [];
|
||||
if (this.commandInProcess) {
|
||||
throw new Error("runCodeQlCliInternal called while cli was running");
|
||||
throw new Error('runCodeQlCliInternal called while cli was running');
|
||||
}
|
||||
this.commandInProcess = true;
|
||||
try {
|
||||
|
@ -209,7 +209,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
|
||||
// Compute the full args array
|
||||
const args = command.concat(LOGGING_FLAGS).concat(commandArgs);
|
||||
const argsString = args.join(" ");
|
||||
const argsString = args.join(' ');
|
||||
this.logger.log(`${description} using CodeQL CLI: ${argsString}...`);
|
||||
try {
|
||||
await new Promise((resolve, reject) => {
|
||||
|
@ -228,16 +228,16 @@ export class CodeQLCliServer implements Disposable {
|
|||
stderrBuffers.push(newData);
|
||||
});
|
||||
// Listen for process exit.
|
||||
process.addListener("close", (code) => reject(code));
|
||||
process.addListener('close', (code) => reject(code));
|
||||
// Write the command followed by a null terminator.
|
||||
process.stdin.write(JSON.stringify(args), "utf8");
|
||||
process.stdin.write(JSON.stringify(args), 'utf8');
|
||||
process.stdin.write(this.nullBuffer);
|
||||
});
|
||||
// Join all the data together
|
||||
const fullBuffer = Buffer.concat(stdoutBuffers);
|
||||
// Make sure we remove the terminator;
|
||||
const data = fullBuffer.toString("utf8", 0, fullBuffer.length - 1);
|
||||
this.logger.log(`CLI command succeeded.`);
|
||||
const data = fullBuffer.toString('utf8', 0, fullBuffer.length - 1);
|
||||
this.logger.log('CLI command succeeded.');
|
||||
return data;
|
||||
} catch (err) {
|
||||
// Kill the process if it isn't already dead.
|
||||
|
@ -246,15 +246,15 @@ export class CodeQLCliServer implements Disposable {
|
|||
const newError =
|
||||
stderrBuffers.length == 0
|
||||
? new Error(`${description} failed: ${err}`)
|
||||
: new Error(`${description} failed: ${Buffer.concat(stderrBuffers).toString("utf8")}`);
|
||||
: new Error(`${description} failed: ${Buffer.concat(stderrBuffers).toString('utf8')}`);
|
||||
newError.stack += (err.stack || '');
|
||||
throw newError;
|
||||
} finally {
|
||||
this.logger.log(Buffer.concat(stderrBuffers).toString("utf8"));
|
||||
this.logger.log(Buffer.concat(stderrBuffers).toString('utf8'));
|
||||
// Remove the listeners we set up.
|
||||
process.stdout.removeAllListeners('data');
|
||||
process.stderr.removeAllListeners('data');
|
||||
process.removeAllListeners("close");
|
||||
process.removeAllListeners('close');
|
||||
}
|
||||
} finally {
|
||||
this.commandInProcess = false;
|
||||
|
@ -413,10 +413,10 @@ export class CodeQLCliServer implements Disposable {
|
|||
async resolveLibraryPath(workspaces: string[], queryPath: string): Promise<QuerySetup> {
|
||||
const subcommandArgs = [
|
||||
'--query', queryPath,
|
||||
"--additional-packs",
|
||||
'--additional-packs',
|
||||
workspaces.join(path.delimiter)
|
||||
];
|
||||
return await this.runJsonCodeQlCliCommand<QuerySetup>(['resolve', 'library-path'], subcommandArgs, "Resolving library paths");
|
||||
return await this.runJsonCodeQlCliCommand<QuerySetup>(['resolve', 'library-path'], subcommandArgs, 'Resolving library paths');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -458,7 +458,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
* @param queryPath The path to the query.
|
||||
*/
|
||||
async resolveMetadata(queryPath: string): Promise<QueryMetadata> {
|
||||
return await this.runJsonCodeQlCliCommand<QueryMetadata>(['resolve', 'metadata'], [queryPath], "Resolving query metadata");
|
||||
return await this.runJsonCodeQlCliCommand<QueryMetadata>(['resolve', 'metadata'], [queryPath], 'Resolving query metadata');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -474,7 +474,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
if (queryMemoryMb !== undefined) {
|
||||
args.push('--ram', queryMemoryMb.toString());
|
||||
}
|
||||
return await this.runJsonCodeQlCliCommand<string[]>(['resolve', 'ram'], args, "Resolving RAM settings", progressReporter);
|
||||
return await this.runJsonCodeQlCliCommand<string[]>(['resolve', 'ram'], args, 'Resolving RAM settings', progressReporter);
|
||||
}
|
||||
/**
|
||||
* Gets the headers (and optionally pagination info) of a bqrs.
|
||||
|
@ -483,11 +483,11 @@ export class CodeQLCliServer implements Disposable {
|
|||
*/
|
||||
async bqrsInfo(bqrsPath: string, pageSize?: number): Promise<BQRSInfo> {
|
||||
const subcommandArgs = (
|
||||
pageSize ? ["--paginate-rows", pageSize.toString()] : []
|
||||
pageSize ? ['--paginate-rows', pageSize.toString()] : []
|
||||
).concat(
|
||||
bqrsPath
|
||||
);
|
||||
return await this.runJsonCodeQlCliCommand<BQRSInfo>(['bqrs', 'info'], subcommandArgs, "Reading bqrs header");
|
||||
return await this.runJsonCodeQlCliCommand<BQRSInfo>(['bqrs', 'info'], subcommandArgs, 'Reading bqrs header');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -499,14 +499,14 @@ export class CodeQLCliServer implements Disposable {
|
|||
*/
|
||||
async bqrsDecode(bqrsPath: string, resultSet: string, pageSize?: number, offset?: number): Promise<DecodedBqrsChunk> {
|
||||
const subcommandArgs = [
|
||||
"--entities=url,string",
|
||||
"--result-set", resultSet,
|
||||
'--entities=url,string',
|
||||
'--result-set', resultSet,
|
||||
].concat(
|
||||
pageSize ? ["--rows", pageSize.toString()] : []
|
||||
pageSize ? ['--rows', pageSize.toString()] : []
|
||||
).concat(
|
||||
offset ? ["--start-at", offset.toString()] : []
|
||||
offset ? ['--start-at', offset.toString()] : []
|
||||
).concat([bqrsPath]);
|
||||
return await this.runJsonCodeQlCliCommand<DecodedBqrsChunk>(['bqrs', 'decode'], subcommandArgs, "Reading bqrs data");
|
||||
return await this.runJsonCodeQlCliCommand<DecodedBqrsChunk>(['bqrs', 'decode'], subcommandArgs, 'Reading bqrs data');
|
||||
}
|
||||
|
||||
|
||||
|
@ -514,22 +514,22 @@ export class CodeQLCliServer implements Disposable {
|
|||
const args = [
|
||||
`-t=kind=${metadata.kind}`,
|
||||
`-t=id=${metadata.id}`,
|
||||
"--output", interpretedResultsPath,
|
||||
"--format", SARIF_FORMAT,
|
||||
'--output', interpretedResultsPath,
|
||||
'--format', SARIF_FORMAT,
|
||||
// TODO: This flag means that we don't group interpreted results
|
||||
// by primary location. We may want to revisit whether we call
|
||||
// interpretation with and without this flag, or do some
|
||||
// grouping client-side.
|
||||
"--no-group-results",
|
||||
'--no-group-results',
|
||||
];
|
||||
if (sourceInfo !== undefined) {
|
||||
args.push(
|
||||
"--source-archive", sourceInfo.sourceArchive,
|
||||
"--source-location-prefix", sourceInfo.sourceLocationPrefix
|
||||
'--source-archive', sourceInfo.sourceArchive,
|
||||
'--source-location-prefix', sourceInfo.sourceLocationPrefix
|
||||
);
|
||||
}
|
||||
args.push(resultsPath);
|
||||
await this.runCodeQlCliCommand(['bqrs', 'interpret'], args, "Interpreting query results");
|
||||
await this.runCodeQlCliCommand(['bqrs', 'interpret'], args, 'Interpreting query results');
|
||||
|
||||
let output: string;
|
||||
try {
|
||||
|
@ -549,9 +549,9 @@ export class CodeQLCliServer implements Disposable {
|
|||
const sortDirectionStrings = sortDirections.map(direction => {
|
||||
switch (direction) {
|
||||
case SortDirection.asc:
|
||||
return "asc";
|
||||
return 'asc';
|
||||
case SortDirection.desc:
|
||||
return "desc";
|
||||
return 'desc';
|
||||
default:
|
||||
return assertNever(direction);
|
||||
}
|
||||
|
@ -559,14 +559,14 @@ export class CodeQLCliServer implements Disposable {
|
|||
|
||||
await this.runCodeQlCliCommand(['bqrs', 'decode'],
|
||||
[
|
||||
"--format=bqrs",
|
||||
'--format=bqrs',
|
||||
`--result-set=${resultSet}`,
|
||||
`--output=${sortedResultsPath}`,
|
||||
`--sort-key=${sortKeys.join(",")}`,
|
||||
`--sort-direction=${sortDirectionStrings.join(",")}`,
|
||||
`--sort-key=${sortKeys.join(',')}`,
|
||||
`--sort-direction=${sortDirectionStrings.join(',')}`,
|
||||
resultsPath
|
||||
],
|
||||
"Sorting query results");
|
||||
'Sorting query results');
|
||||
}
|
||||
|
||||
|
||||
|
@ -576,7 +576,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
*/
|
||||
resolveDatabase(databasePath: string): Promise<DbInfo> {
|
||||
return this.runJsonCodeQlCliCommand(['resolve', 'database'], [databasePath],
|
||||
"Resolving database");
|
||||
'Resolving database');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -591,7 +591,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
return this.runJsonCodeQlCliCommand<UpgradesInfo>(
|
||||
['resolve', 'upgrades'],
|
||||
args,
|
||||
"Resolving database upgrade scripts",
|
||||
'Resolving database upgrade scripts',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -611,7 +611,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
return this.runJsonCodeQlCliCommand<QlpacksInfo>(
|
||||
['resolve', 'qlpacks'],
|
||||
args,
|
||||
"Resolving qlpack information",
|
||||
'Resolving qlpack information',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -632,7 +632,7 @@ export class CodeQLCliServer implements Disposable {
|
|||
return this.runJsonCodeQlCliCommand<string[]>(
|
||||
['resolve', 'queries'],
|
||||
args,
|
||||
"Resolving queries",
|
||||
'Resolving queries',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -666,7 +666,7 @@ export function spawnServer(
|
|||
|
||||
// Start the server process.
|
||||
const base = codeqlPath;
|
||||
const argsString = args.join(" ");
|
||||
const argsString = args.join(' ');
|
||||
if (progressReporter !== undefined) {
|
||||
progressReporter.report({ message: `Starting ${name}` });
|
||||
}
|
||||
|
@ -703,7 +703,7 @@ export function spawnServer(
|
|||
export async function runCodeQlCliCommand(codeQlPath: string, command: string[], commandArgs: string[], description: string, logger: Logger, progressReporter?: ProgressReporter): Promise<string> {
|
||||
// Add logging arguments first, in case commandArgs contains positional parameters.
|
||||
const args = command.concat(LOGGING_FLAGS).concat(commandArgs);
|
||||
const argsString = args.join(" ");
|
||||
const argsString = args.join(' ');
|
||||
try {
|
||||
if (progressReporter !== undefined) {
|
||||
progressReporter.report({ message: description });
|
||||
|
@ -711,7 +711,7 @@ export async function runCodeQlCliCommand(codeQlPath: string, command: string[],
|
|||
logger.log(`${description} using CodeQL CLI: ${codeQlPath} ${argsString}...`);
|
||||
const result = await util.promisify(child_process.execFile)(codeQlPath, args);
|
||||
logger.log(result.stderr);
|
||||
logger.log(`CLI command succeeded.`);
|
||||
logger.log('CLI command succeeded.');
|
||||
return result.stdout;
|
||||
} catch (err) {
|
||||
throw new Error(`${description} failed: ${err.stderr || err}`);
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
import fetch, { Response } from "node-fetch";
|
||||
import * as unzipper from "unzipper";
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import * as unzipper from 'unzipper';
|
||||
import {
|
||||
Uri,
|
||||
ProgressOptions,
|
||||
ProgressLocation,
|
||||
commands,
|
||||
window,
|
||||
} from "vscode";
|
||||
import * as fs from "fs-extra";
|
||||
import * as path from "path";
|
||||
import { DatabaseManager, DatabaseItem } from "./databases";
|
||||
} from 'vscode';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { DatabaseManager, DatabaseItem } from './databases';
|
||||
import {
|
||||
ProgressCallback,
|
||||
showAndLogErrorMessage,
|
||||
withProgress,
|
||||
showAndLogInformationMessage,
|
||||
} from "./helpers";
|
||||
import { logger } from "./logging";
|
||||
} from './helpers';
|
||||
import { logger } from './logging';
|
||||
|
||||
/**
|
||||
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
|
||||
|
@ -32,14 +32,14 @@ export async function promptImportInternetDatabase(
|
|||
|
||||
try {
|
||||
const databaseUrl = await window.showInputBox({
|
||||
prompt: "Enter URL of zipfile of database to download",
|
||||
prompt: 'Enter URL of zipfile of database to download',
|
||||
});
|
||||
if (databaseUrl) {
|
||||
validateHttpsUrl(databaseUrl);
|
||||
|
||||
const progressOptions: ProgressOptions = {
|
||||
location: ProgressLocation.Notification,
|
||||
title: "Adding database from URL",
|
||||
title: 'Adding database from URL',
|
||||
cancellable: false,
|
||||
};
|
||||
await withProgress(
|
||||
|
@ -52,10 +52,10 @@ export async function promptImportInternetDatabase(
|
|||
progress
|
||||
))
|
||||
);
|
||||
commands.executeCommand("codeQLDatabases.focus");
|
||||
commands.executeCommand('codeQLDatabases.focus');
|
||||
}
|
||||
showAndLogInformationMessage(
|
||||
"Database downloaded and imported successfully."
|
||||
'Database downloaded and imported successfully.'
|
||||
);
|
||||
} catch (e) {
|
||||
showAndLogErrorMessage(e.message);
|
||||
|
@ -81,7 +81,7 @@ export async function promptImportLgtmDatabase(
|
|||
try {
|
||||
const lgtmUrl = await window.showInputBox({
|
||||
prompt:
|
||||
"Enter the project URL on LGTM (e.g., https://lgtm.com/projects/g/github/codeql)",
|
||||
'Enter the project URL on LGTM (e.g., https://lgtm.com/projects/g/github/codeql)',
|
||||
});
|
||||
if (!lgtmUrl) {
|
||||
return;
|
||||
|
@ -91,7 +91,7 @@ export async function promptImportLgtmDatabase(
|
|||
if (databaseUrl) {
|
||||
const progressOptions: ProgressOptions = {
|
||||
location: ProgressLocation.Notification,
|
||||
title: "Adding database from LGTM",
|
||||
title: 'Adding database from LGTM',
|
||||
cancellable: false,
|
||||
};
|
||||
await withProgress(
|
||||
|
@ -104,14 +104,14 @@ export async function promptImportLgtmDatabase(
|
|||
progress
|
||||
))
|
||||
);
|
||||
commands.executeCommand("codeQLDatabases.focus");
|
||||
commands.executeCommand('codeQLDatabases.focus');
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Invalid LGTM URL: ${lgtmUrl}`);
|
||||
}
|
||||
if (item) {
|
||||
showAndLogInformationMessage(
|
||||
"Database downloaded and imported successfully."
|
||||
'Database downloaded and imported successfully.'
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -137,7 +137,7 @@ export async function importArchiveDatabase(
|
|||
try {
|
||||
const progressOptions: ProgressOptions = {
|
||||
location: ProgressLocation.Notification,
|
||||
title: "Importing database from archive",
|
||||
title: 'Importing database from archive',
|
||||
cancellable: false,
|
||||
};
|
||||
await withProgress(
|
||||
|
@ -150,16 +150,16 @@ export async function importArchiveDatabase(
|
|||
progress
|
||||
))
|
||||
);
|
||||
commands.executeCommand("codeQLDatabases.focus");
|
||||
commands.executeCommand('codeQLDatabases.focus');
|
||||
|
||||
if (item) {
|
||||
showAndLogInformationMessage(
|
||||
"Database unzipped and imported successfully."
|
||||
'Database unzipped and imported successfully.'
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.message.includes("unexpected end of file")) {
|
||||
showAndLogErrorMessage("Database is corrupt or too large. Try unzipping outside of VS Code and importing the unzipped folder instead.");
|
||||
if (e.message.includes('unexpected end of file')) {
|
||||
showAndLogErrorMessage('Database is corrupt or too large. Try unzipping outside of VS Code and importing the unzipped folder instead.');
|
||||
} else {
|
||||
showAndLogErrorMessage(e.message);
|
||||
}
|
||||
|
@ -184,11 +184,11 @@ async function databaseArchiveFetcher(
|
|||
): Promise<DatabaseItem> {
|
||||
progressCallback?.({
|
||||
maxStep: 3,
|
||||
message: "Getting database",
|
||||
message: 'Getting database',
|
||||
step: 1,
|
||||
});
|
||||
if (!storagePath) {
|
||||
throw new Error("No storage path specified.");
|
||||
throw new Error('No storage path specified.');
|
||||
}
|
||||
await fs.ensureDir(storagePath);
|
||||
const unzipPath = await getStorageFolder(storagePath, databaseUrl);
|
||||
|
@ -201,22 +201,22 @@ async function databaseArchiveFetcher(
|
|||
|
||||
progressCallback?.({
|
||||
maxStep: 3,
|
||||
message: "Opening database",
|
||||
message: 'Opening database',
|
||||
step: 3,
|
||||
});
|
||||
|
||||
// find the path to the database. The actual database might be in a sub-folder
|
||||
const dbPath = await findDirWithFile(
|
||||
unzipPath,
|
||||
".dbinfo",
|
||||
"codeql-database.yml"
|
||||
'.dbinfo',
|
||||
'codeql-database.yml'
|
||||
);
|
||||
if (dbPath) {
|
||||
const item = await databasesManager.openDatabase(Uri.file(dbPath));
|
||||
databasesManager.setCurrentDatabaseItem(item);
|
||||
return item;
|
||||
} else {
|
||||
throw new Error("Database not found in archive.");
|
||||
throw new Error('Database not found in archive.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,7 @@ async function getStorageFolder(storagePath: string, urlStr: string) {
|
|||
// MacOS has a max filename length of 255
|
||||
// and remove a few extra chars in case we need to add a counter at the end.
|
||||
let lastName = path.basename(url.path).substring(0, 250);
|
||||
if (lastName.endsWith(".zip")) {
|
||||
if (lastName.endsWith('.zip')) {
|
||||
lastName = lastName.substring(0, lastName.length - 4);
|
||||
}
|
||||
|
||||
|
@ -241,7 +241,7 @@ async function getStorageFolder(storagePath: string, urlStr: string) {
|
|||
counter++;
|
||||
folderName = path.join(realpath, `${lastName}-${counter}`);
|
||||
if (counter > 100) {
|
||||
throw new Error("Could not find a unique name for downloaded database.");
|
||||
throw new Error('Could not find a unique name for downloaded database.');
|
||||
}
|
||||
}
|
||||
return folderName;
|
||||
|
@ -255,8 +255,8 @@ function validateHttpsUrl(databaseUrl: string) {
|
|||
throw new Error(`Invalid url: ${databaseUrl}`);
|
||||
}
|
||||
|
||||
if (uri.scheme !== "https") {
|
||||
throw new Error("Must use https for downloading a database.");
|
||||
if (uri.scheme !== 'https') {
|
||||
throw new Error('Must use https for downloading a database.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,9 +269,9 @@ async function readAndUnzip(databaseUrl: string, unzipPath: string) {
|
|||
// we already know this is a file scheme
|
||||
const databaseFile = Uri.parse(databaseUrl).fsPath;
|
||||
const stream = fs.createReadStream(databaseFile);
|
||||
stream.on("error", reject);
|
||||
unzipStream.on("error", reject);
|
||||
unzipStream.on("close", resolve);
|
||||
stream.on('error', reject);
|
||||
unzipStream.on('error', reject);
|
||||
unzipStream.on('close', resolve);
|
||||
stream.pipe(unzipStream);
|
||||
});
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ async function fetchAndUnzip(
|
|||
});
|
||||
progressCallback?.({
|
||||
maxStep: 3,
|
||||
message: "Unzipping database",
|
||||
message: 'Unzipping database',
|
||||
step: 2,
|
||||
});
|
||||
await new Promise((resolve, reject) => {
|
||||
|
@ -301,9 +301,9 @@ async function fetchAndUnzip(
|
|||
reject(err);
|
||||
}
|
||||
};
|
||||
response.body.on("error", handler);
|
||||
unzipStream.on("error", handler);
|
||||
unzipStream.on("close", resolve);
|
||||
response.body.on('error', handler);
|
||||
unzipStream.on('error', handler);
|
||||
unzipStream.on('close', resolve);
|
||||
response.body.pipe(unzipStream);
|
||||
});
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ async function checkForFailingResponse(response: Response): Promise<void | never
|
|||
}
|
||||
|
||||
function isFile(databaseUrl: string) {
|
||||
return Uri.parse(databaseUrl).scheme === "file";
|
||||
return Uri.parse(databaseUrl).scheme === 'file';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -381,16 +381,16 @@ export function looksLikeLgtmUrl(lgtmUrl: string | undefined): lgtmUrl is string
|
|||
|
||||
try {
|
||||
const uri = Uri.parse(lgtmUrl, true);
|
||||
if (uri.scheme !== "https") {
|
||||
if (uri.scheme !== 'https') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uri.authority !== "lgtm.com" && uri.authority !== "www.lgtm.com") {
|
||||
if (uri.authority !== 'lgtm.com' && uri.authority !== 'www.lgtm.com') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const paths = uri.path.split("/").filter((segment) => segment);
|
||||
return paths.length >= 4 && paths[0] === "projects";
|
||||
const paths = uri.path.split('/').filter((segment) => segment);
|
||||
return paths.length >= 4 && paths[0] === 'projects';
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
@ -400,10 +400,10 @@ export function looksLikeLgtmUrl(lgtmUrl: string | undefined): lgtmUrl is string
|
|||
export async function convertToDatabaseUrl(lgtmUrl: string) {
|
||||
try {
|
||||
const uri = Uri.parse(lgtmUrl, true);
|
||||
const paths = ["api", "v1.0"].concat(
|
||||
uri.path.split("/").filter((segment) => segment)
|
||||
const paths = ['api', 'v1.0'].concat(
|
||||
uri.path.split('/').filter((segment) => segment)
|
||||
).slice(0, 6);
|
||||
const projectUrl = `https://lgtm.com/${paths.join("/")}`;
|
||||
const projectUrl = `https://lgtm.com/${paths.join('/')}`;
|
||||
const projectResponse = await fetch(projectUrl);
|
||||
const projectJson = await projectResponse.json();
|
||||
|
||||
|
@ -416,12 +416,12 @@ export async function convertToDatabaseUrl(lgtmUrl: string) {
|
|||
return;
|
||||
}
|
||||
return `https://lgtm.com/${[
|
||||
"api",
|
||||
"v1.0",
|
||||
"snapshots",
|
||||
'api',
|
||||
'v1.0',
|
||||
'snapshots',
|
||||
projectJson.id,
|
||||
language,
|
||||
].join("/")}`;
|
||||
].join('/')}`;
|
||||
} catch (e) {
|
||||
logger.log(`Error: ${e.message}`);
|
||||
throw new Error(`Invalid LGTM URL: ${lgtmUrl}`);
|
||||
|
@ -440,7 +440,7 @@ async function promptForLanguage(
|
|||
|
||||
return await window.showQuickPick(
|
||||
projectJson.languages.map((lang: { language: string }) => lang.language), {
|
||||
placeHolder: "Select the database language to download:"
|
||||
placeHolder: 'Select the database language to download:'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -670,7 +670,7 @@ export class DatabaseManager extends DisposableObject {
|
|||
|
||||
// Delete folder from file system only if it is controlled by the extension
|
||||
if (this.isExtensionControlledLocation(item.databaseUri)) {
|
||||
logger.log(`Deleting database from filesystem.`);
|
||||
logger.log('Deleting database from filesystem.');
|
||||
fs.remove(item.databaseUri.path).then(
|
||||
() => logger.log(`Deleted '${item.databaseUri.path}'`),
|
||||
e => logger.log(`Failed to delete '${item.databaseUri.path}'. Reason: ${e.message}`));
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import * as fs from 'fs-extra';
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as tmp from 'tmp';
|
||||
import * as vscode from "vscode";
|
||||
import { decodeSourceArchiveUri, zipArchiveScheme } from "./archive-filesystem-provider";
|
||||
import { ColumnKindCode, EntityValue, getResultSetSchema, LineColumnLocation, UrlValue } from "./bqrs-cli-types";
|
||||
import { CodeQLCliServer } from "./cli";
|
||||
import { DatabaseItem, DatabaseManager } from "./databases";
|
||||
import * as vscode from 'vscode';
|
||||
import { decodeSourceArchiveUri, zipArchiveScheme } from './archive-filesystem-provider';
|
||||
import { ColumnKindCode, EntityValue, getResultSetSchema, LineColumnLocation, UrlValue } from './bqrs-cli-types';
|
||||
import { CodeQLCliServer } from './cli';
|
||||
import { DatabaseItem, DatabaseManager } from './databases';
|
||||
import * as helpers from './helpers';
|
||||
import { CachedOperation } from './helpers';
|
||||
import * as messages from "./messages";
|
||||
import { QueryServerClient } from "./queryserver-client";
|
||||
import { compileAndRunQueryAgainstDatabase, QueryWithResults } from "./run-queries";
|
||||
import * as messages from './messages';
|
||||
import { QueryServerClient } from './queryserver-client';
|
||||
import { compileAndRunQueryAgainstDatabase, QueryWithResults } from './run-queries';
|
||||
|
||||
/**
|
||||
* Run templated CodeQL queries to find definitions and references in
|
||||
|
@ -19,8 +19,8 @@ import { compileAndRunQueryAgainstDatabase, QueryWithResults } from "./run-queri
|
|||
* or from a selected identifier.
|
||||
*/
|
||||
|
||||
const TEMPLATE_NAME = "selectedSourceFile";
|
||||
const SELECT_QUERY_NAME = "#select";
|
||||
const TEMPLATE_NAME = 'selectedSourceFile';
|
||||
const SELECT_QUERY_NAME = '#select';
|
||||
|
||||
enum KeyType {
|
||||
DefinitionQuery = 'DefinitionQuery',
|
||||
|
@ -29,15 +29,15 @@ enum KeyType {
|
|||
|
||||
function tagOfKeyType(keyType: KeyType): string {
|
||||
switch (keyType) {
|
||||
case KeyType.DefinitionQuery: return "ide-contextual-queries/local-definitions";
|
||||
case KeyType.ReferenceQuery: return "ide-contextual-queries/local-references";
|
||||
case KeyType.DefinitionQuery: return 'ide-contextual-queries/local-definitions';
|
||||
case KeyType.ReferenceQuery: return 'ide-contextual-queries/local-references';
|
||||
}
|
||||
}
|
||||
|
||||
function nameOfKeyType(keyType: KeyType): string {
|
||||
switch (keyType) {
|
||||
case KeyType.DefinitionQuery: return "definitions";
|
||||
case KeyType.ReferenceQuery: return "references";
|
||||
case KeyType.DefinitionQuery: return 'definitions';
|
||||
case KeyType.ReferenceQuery: return 'references';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ async function getLinksForUriString(
|
|||
if (db) {
|
||||
const qlpack = await qlpackOfDatabase(cli, db);
|
||||
if (qlpack === undefined) {
|
||||
throw new Error("Can't infer qlpack from database source archive");
|
||||
throw new Error('Can\'t infer qlpack from database source archive');
|
||||
}
|
||||
const links: FullLocationLink[] = [];
|
||||
for (const query of await resolveQueries(cli, qlpack, keyType)) {
|
||||
|
@ -191,7 +191,7 @@ async function getLinksForUriString(
|
|||
}
|
||||
|
||||
function fileRangeFromURI(uri: UrlValue, db: DatabaseItem): FileRange | undefined {
|
||||
if (typeof uri === "string") {
|
||||
if (typeof uri === 'string') {
|
||||
return undefined;
|
||||
} else if ('startOffset' in uri) {
|
||||
return undefined;
|
||||
|
@ -203,7 +203,7 @@ function fileRangeFromURI(uri: UrlValue, db: DatabaseItem): FileRange | undefine
|
|||
Math.max(0, loc.endColumn));
|
||||
try {
|
||||
const parsed = vscode.Uri.parse(uri.uri, true);
|
||||
if (parsed.scheme === "file") {
|
||||
if (parsed.scheme === 'file') {
|
||||
return { file: db.resolveSourceFile(parsed.fsPath), range };
|
||||
}
|
||||
return undefined;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import * as fetch from "node-fetch";
|
||||
import * as fs from "fs-extra";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as semver from "semver";
|
||||
import * as unzipper from "unzipper";
|
||||
import * as url from "url";
|
||||
import { ExtensionContext, Event } from "vscode";
|
||||
import { DistributionConfig } from "./config";
|
||||
import { InvocationRateLimiter, InvocationRateLimiterResultKind, showAndLogErrorMessage } from "./helpers";
|
||||
import { logger } from "./logging";
|
||||
import * as helpers from "./helpers";
|
||||
import { getCodeQlCliVersion } from "./cli-version";
|
||||
import * as fetch from 'node-fetch';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as unzipper from 'unzipper';
|
||||
import * as url from 'url';
|
||||
import { ExtensionContext, Event } from 'vscode';
|
||||
import { DistributionConfig } from './config';
|
||||
import { InvocationRateLimiter, InvocationRateLimiterResultKind, showAndLogErrorMessage } from './helpers';
|
||||
import { logger } from './logging';
|
||||
import * as helpers from './helpers';
|
||||
import { getCodeQlCliVersion } from './cli-version';
|
||||
|
||||
/**
|
||||
* distribution.ts
|
||||
|
@ -25,7 +25,7 @@ import { getCodeQlCliVersion } from "./cli-version";
|
|||
* We set the default here rather than as a default config value so that this default is invoked
|
||||
* upon blanking the setting.
|
||||
*/
|
||||
const DEFAULT_DISTRIBUTION_OWNER_NAME = "github";
|
||||
const DEFAULT_DISTRIBUTION_OWNER_NAME = 'github';
|
||||
|
||||
/**
|
||||
* Default value for the repository name of the extension-managed distribution on GitHub.
|
||||
|
@ -33,14 +33,14 @@ const DEFAULT_DISTRIBUTION_OWNER_NAME = "github";
|
|||
* We set the default here rather than as a default config value so that this default is invoked
|
||||
* upon blanking the setting.
|
||||
*/
|
||||
const DEFAULT_DISTRIBUTION_REPOSITORY_NAME = "codeql-cli-binaries";
|
||||
const DEFAULT_DISTRIBUTION_REPOSITORY_NAME = 'codeql-cli-binaries';
|
||||
|
||||
/**
|
||||
* Range of versions of the CLI that are compatible with the extension.
|
||||
*
|
||||
* This applies to both extension-managed and CLI distributions.
|
||||
*/
|
||||
export const DEFAULT_DISTRIBUTION_VERSION_RANGE: semver.Range = new semver.Range("2.x");
|
||||
export const DEFAULT_DISTRIBUTION_VERSION_RANGE: semver.Range = new semver.Range('2.x');
|
||||
|
||||
export interface DistributionProvider {
|
||||
getCodeQlPathWithoutVersionCheck(): Promise<string | undefined>;
|
||||
|
@ -54,7 +54,7 @@ export class DistributionManager implements DistributionProvider {
|
|||
this._onDidChangeDistribution = config.onDidChangeDistributionConfiguration;
|
||||
this._updateCheckRateLimiter = new InvocationRateLimiter(
|
||||
extensionContext,
|
||||
"extensionSpecificDistributionUpdateCheck",
|
||||
'extensionSpecificDistributionUpdateCheck',
|
||||
() => this._extensionSpecificDistributionManager.checkForUpdatesToDistribution()
|
||||
);
|
||||
this._versionRange = versionRange;
|
||||
|
@ -128,8 +128,8 @@ export class DistributionManager implements DistributionProvider {
|
|||
if (this._config.customCodeQlPath) {
|
||||
if (!await fs.pathExists(this._config.customCodeQlPath)) {
|
||||
showAndLogErrorMessage(`The CodeQL executable path is specified as "${this._config.customCodeQlPath}" ` +
|
||||
"by a configuration setting, but a CodeQL executable could not be found at that path. Please check " +
|
||||
"that a CodeQL executable exists at the specified path or remove the setting.");
|
||||
'by a configuration setting, but a CodeQL executable could not be found at that path. Please check ' +
|
||||
'that a CodeQL executable exists at the specified path or remove the setting.');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ export class DistributionManager implements DistributionProvider {
|
|||
};
|
||||
}
|
||||
}
|
||||
logger.log("INFO: Could not find CodeQL on path.");
|
||||
logger.log('INFO: Could not find CodeQL on path.');
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
@ -248,7 +248,7 @@ class ExtensionSpecificDistributionManager {
|
|||
try {
|
||||
await this.removeDistribution();
|
||||
} catch (e) {
|
||||
logger.log("WARNING: Tried to remove corrupted CodeQL CLI at " +
|
||||
logger.log('WARNING: Tried to remove corrupted CodeQL CLI at ' +
|
||||
`${this.getDistributionStoragePath()} but encountered an error: ${e}.`);
|
||||
}
|
||||
}
|
||||
|
@ -309,13 +309,13 @@ class ExtensionSpecificDistributionManager {
|
|||
}
|
||||
|
||||
const assetStream = await this.createReleasesApiConsumer().streamBinaryContentOfAsset(assets[0]);
|
||||
const tmpDirectory = await fs.mkdtemp(path.join(os.tmpdir(), "vscode-codeql"));
|
||||
const tmpDirectory = await fs.mkdtemp(path.join(os.tmpdir(), 'vscode-codeql'));
|
||||
|
||||
try {
|
||||
const archivePath = path.join(tmpDirectory, "distributionDownload.zip");
|
||||
const archivePath = path.join(tmpDirectory, 'distributionDownload.zip');
|
||||
const archiveFile = fs.createWriteStream(archivePath);
|
||||
|
||||
const contentLength = assetStream.headers.get("content-length");
|
||||
const contentLength = assetStream.headers.get('content-length');
|
||||
let numBytesDownloaded = 0;
|
||||
|
||||
if (progressCallback && contentLength !== null) {
|
||||
|
@ -332,7 +332,7 @@ class ExtensionSpecificDistributionManager {
|
|||
// Display the progress straight away rather than waiting for the first chunk.
|
||||
updateProgress();
|
||||
|
||||
assetStream.body.on("data", data => {
|
||||
assetStream.body.on('data', data => {
|
||||
numBytesDownloaded += data.length;
|
||||
updateProgress();
|
||||
});
|
||||
|
@ -340,8 +340,8 @@ class ExtensionSpecificDistributionManager {
|
|||
|
||||
await new Promise((resolve, reject) =>
|
||||
assetStream.body.pipe(archiveFile)
|
||||
.on("finish", resolve)
|
||||
.on("error", reject)
|
||||
.on('finish', resolve)
|
||||
.on('error', reject)
|
||||
);
|
||||
|
||||
await this.bumpDistributionFolderIndex();
|
||||
|
@ -413,7 +413,7 @@ class ExtensionSpecificDistributionManager {
|
|||
private getDistributionStoragePath(): string {
|
||||
// Use an empty string for the initial distribution for backwards compatibility.
|
||||
const distributionFolderIndex = this._extensionContext.globalState.get(
|
||||
ExtensionSpecificDistributionManager._currentDistributionFolderIndexStateKey, 0) || "";
|
||||
ExtensionSpecificDistributionManager._currentDistributionFolderIndexStateKey, 0) || '';
|
||||
return path.join(this._extensionContext.globalStoragePath,
|
||||
ExtensionSpecificDistributionManager._currentDistributionFolderBaseName + distributionFolderIndex);
|
||||
}
|
||||
|
@ -435,19 +435,19 @@ class ExtensionSpecificDistributionManager {
|
|||
private readonly _extensionContext: ExtensionContext;
|
||||
private readonly _versionRange: semver.Range;
|
||||
|
||||
private static readonly _currentDistributionFolderBaseName = "distribution";
|
||||
private static readonly _currentDistributionFolderIndexStateKey = "distributionFolderIndex";
|
||||
private static readonly _installedReleaseStateKey = "distributionRelease";
|
||||
private static readonly _codeQlExtractedFolderName = "codeql";
|
||||
private static readonly _currentDistributionFolderBaseName = 'distribution';
|
||||
private static readonly _currentDistributionFolderIndexStateKey = 'distributionFolderIndex';
|
||||
private static readonly _installedReleaseStateKey = 'distributionRelease';
|
||||
private static readonly _codeQlExtractedFolderName = 'codeql';
|
||||
}
|
||||
|
||||
export class ReleasesApiConsumer {
|
||||
constructor(ownerName: string, repoName: string, personalAccessToken?: string) {
|
||||
// Specify version of the GitHub API
|
||||
this._defaultHeaders["accept"] = "application/vnd.github.v3+json";
|
||||
this._defaultHeaders['accept'] = 'application/vnd.github.v3+json';
|
||||
|
||||
if (personalAccessToken) {
|
||||
this._defaultHeaders["authorization"] = `token ${personalAccessToken}`;
|
||||
this._defaultHeaders['authorization'] = `token ${personalAccessToken}`;
|
||||
}
|
||||
|
||||
this._ownerName = ownerName;
|
||||
|
@ -475,11 +475,11 @@ export class ReleasesApiConsumer {
|
|||
if (versionComparison !== 0) {
|
||||
return versionComparison;
|
||||
}
|
||||
return b.created_at.localeCompare(a.created_at, "en-US");
|
||||
return b.created_at.localeCompare(a.created_at, 'en-US');
|
||||
})[0];
|
||||
if (latestRelease === undefined) {
|
||||
throw new Error("No compatible CodeQL CLI releases were found. " +
|
||||
"Please check that the CodeQL extension is up to date.");
|
||||
throw new Error('No compatible CodeQL CLI releases were found. ' +
|
||||
'Please check that the CodeQL extension is up to date.');
|
||||
}
|
||||
const assets: ReleaseAsset[] = latestRelease.assets.map(asset => {
|
||||
return {
|
||||
|
@ -501,7 +501,7 @@ export class ReleasesApiConsumer {
|
|||
const apiPath = `/repos/${this._ownerName}/${this._repoName}/releases/assets/${asset.id}`;
|
||||
|
||||
return await this.makeApiCall(apiPath, {
|
||||
"accept": "application/octet-stream"
|
||||
'accept': 'application/octet-stream'
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -511,7 +511,7 @@ export class ReleasesApiConsumer {
|
|||
|
||||
if (!response.ok) {
|
||||
// Check for rate limiting
|
||||
const rateLimitResetValue = response.headers.get("X-RateLimit-Reset");
|
||||
const rateLimitResetValue = response.headers.get('X-RateLimit-Reset');
|
||||
if (response.status === 403 && rateLimitResetValue) {
|
||||
const secondsToMillisecondsFactor = 1000;
|
||||
const rateLimitResetDate = new Date(parseInt(rateLimitResetValue, 10) * secondsToMillisecondsFactor);
|
||||
|
@ -528,21 +528,21 @@ export class ReleasesApiConsumer {
|
|||
redirectCount = 0): Promise<fetch.Response> {
|
||||
const response = await fetch.default(requestUrl, {
|
||||
headers,
|
||||
redirect: "manual"
|
||||
redirect: 'manual'
|
||||
});
|
||||
|
||||
const redirectUrl = response.headers.get("location");
|
||||
const redirectUrl = response.headers.get('location');
|
||||
if (isRedirectStatusCode(response.status) && redirectUrl && redirectCount < ReleasesApiConsumer._maxRedirects) {
|
||||
const parsedRedirectUrl = url.parse(redirectUrl);
|
||||
if (parsedRedirectUrl.protocol != "https:") {
|
||||
throw new Error("Encountered a non-https redirect, rejecting");
|
||||
if (parsedRedirectUrl.protocol != 'https:') {
|
||||
throw new Error('Encountered a non-https redirect, rejecting');
|
||||
}
|
||||
if (parsedRedirectUrl.host != "api.github.com") {
|
||||
if (parsedRedirectUrl.host != 'api.github.com') {
|
||||
// Remove authorization header if we are redirected outside of the GitHub API.
|
||||
//
|
||||
// This is necessary to stream release assets since AWS fails if more than one auth
|
||||
// mechanism is provided.
|
||||
delete headers["authorization"];
|
||||
delete headers['authorization'];
|
||||
}
|
||||
return await this.makeRawRequest(redirectUrl, headers, redirectCount + 1);
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ export class ReleasesApiConsumer {
|
|||
private readonly _ownerName: string;
|
||||
private readonly _repoName: string;
|
||||
|
||||
private static readonly _apiBase = "https://api.github.com";
|
||||
private static readonly _apiBase = 'https://api.github.com';
|
||||
private static readonly _maxRedirects = 20;
|
||||
}
|
||||
|
||||
|
@ -576,11 +576,11 @@ export async function extractZipArchive(archivePath: string, outPath: string): P
|
|||
}
|
||||
|
||||
function codeQlLauncherName(): string {
|
||||
return (os.platform() === "win32") ? "codeql.exe" : "codeql";
|
||||
return (os.platform() === 'win32') ? 'codeql.exe' : 'codeql';
|
||||
}
|
||||
|
||||
function deprecatedCodeQlLauncherName(): string | undefined {
|
||||
return (os.platform() === "win32") ? "codeql.cmd" : undefined;
|
||||
return (os.platform() === 'win32') ? 'codeql.cmd' : undefined;
|
||||
}
|
||||
|
||||
function isRedirectStatusCode(statusCode: number): boolean {
|
||||
|
@ -713,7 +713,7 @@ export async function getExecutableFromDirectory(directory: string, warnWhenNotF
|
|||
}
|
||||
if (warnWhenNotFound) {
|
||||
logger.log(`WARNING: Expected to find a CodeQL CLI executable at ${expectedLauncherPath} but one was not found. ` +
|
||||
"Will try PATH.");
|
||||
'Will try PATH.');
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
const codeQlVersionRange = DEFAULT_DISTRIBUTION_VERSION_RANGE;
|
||||
const distributionManager = new DistributionManager(ctx, distributionConfigListener, codeQlVersionRange);
|
||||
|
||||
const shouldUpdateOnNextActivationKey = "shouldUpdateOnNextActivation";
|
||||
const shouldUpdateOnNextActivationKey = 'shouldUpdateOnNextActivation';
|
||||
|
||||
registerErrorStubs([checkForUpdatesCommand], command => () => {
|
||||
helpers.showAndLogErrorMessage(`Can't execute ${command}: waiting to finish loading CodeQL CLI.`);
|
||||
|
@ -118,7 +118,7 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
|
||||
switch (result.kind) {
|
||||
case DistributionUpdateCheckResultKind.AlreadyCheckedRecentlyResult:
|
||||
logger.log("Didn't perform CodeQL CLI update check since a check was already performed within the previous " +
|
||||
logger.log('Didn\'t perform CodeQL CLI update check since a check was already performed within the previous ' +
|
||||
`${minSecondsSinceLastUpdateCheck} seconds.`);
|
||||
break;
|
||||
case DistributionUpdateCheckResultKind.AlreadyUpToDate:
|
||||
|
@ -155,16 +155,16 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
|
||||
async function installOrUpdateDistribution(config: DistributionUpdateConfig): Promise<void> {
|
||||
if (isInstallingOrUpdatingDistribution) {
|
||||
throw new Error("Already installing or updating CodeQL CLI");
|
||||
throw new Error('Already installing or updating CodeQL CLI');
|
||||
}
|
||||
isInstallingOrUpdatingDistribution = true;
|
||||
const codeQlInstalled = await distributionManager.getCodeQlPathWithoutVersionCheck() !== undefined;
|
||||
const willUpdateCodeQl = ctx.globalState.get(shouldUpdateOnNextActivationKey);
|
||||
const messageText = willUpdateCodeQl
|
||||
? "Updating CodeQL CLI"
|
||||
? 'Updating CodeQL CLI'
|
||||
: codeQlInstalled
|
||||
? "Checking for updates to CodeQL CLI"
|
||||
: "Installing CodeQL CLI";
|
||||
? 'Checking for updates to CodeQL CLI'
|
||||
: 'Installing CodeQL CLI';
|
||||
|
||||
try {
|
||||
await installOrUpdateDistributionWithProgressTitle(messageText, config);
|
||||
|
@ -173,8 +173,8 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
// or updating the distribution.
|
||||
const alertFunction = (codeQlInstalled && !config.isUserInitiated) ?
|
||||
helpers.showAndLogWarningMessage : helpers.showAndLogErrorMessage;
|
||||
const taskDescription = (willUpdateCodeQl ? "update" :
|
||||
codeQlInstalled ? "check for updates to" : "install") + " CodeQL CLI";
|
||||
const taskDescription = (willUpdateCodeQl ? 'update' :
|
||||
codeQlInstalled ? 'check for updates to' : 'install') + ' CodeQL CLI';
|
||||
|
||||
if (e instanceof GithubRateLimitedError) {
|
||||
alertFunction(`Rate limited while trying to ${taskDescription}. Please try again after ` +
|
||||
|
@ -198,7 +198,7 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
const fixGuidanceMessage = (() => {
|
||||
switch (result.distribution.kind) {
|
||||
case DistributionKind.ExtensionManaged:
|
||||
return "Please update the CodeQL CLI by running the \"CodeQL: Check for CLI Updates\" command.";
|
||||
return 'Please update the CodeQL CLI by running the "CodeQL: Check for CLI Updates" command.';
|
||||
case DistributionKind.CustomPathConfig:
|
||||
return `Please update the \"CodeQL CLI Executable Path\" setting to point to a CLI in the version range ${codeQlVersionRange}.`;
|
||||
case DistributionKind.PathEnvironmentVariable:
|
||||
|
@ -208,15 +208,15 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
})();
|
||||
|
||||
helpers.showAndLogWarningMessage(`The current version of the CodeQL CLI (${result.version.raw}) ` +
|
||||
"is incompatible with this extension. " + fixGuidanceMessage);
|
||||
'is incompatible with this extension. ' + fixGuidanceMessage);
|
||||
break;
|
||||
}
|
||||
case FindDistributionResultKind.UnknownCompatibilityDistribution:
|
||||
helpers.showAndLogWarningMessage("Compatibility with the configured CodeQL CLI could not be determined. " +
|
||||
"You may experience problems using the extension.");
|
||||
helpers.showAndLogWarningMessage('Compatibility with the configured CodeQL CLI could not be determined. ' +
|
||||
'You may experience problems using the extension.');
|
||||
break;
|
||||
case FindDistributionResultKind.NoDistribution:
|
||||
helpers.showAndLogErrorMessage("The CodeQL CLI could not be found.");
|
||||
helpers.showAndLogErrorMessage('The CodeQL CLI could not be found.');
|
||||
break;
|
||||
default:
|
||||
assertNever(result);
|
||||
|
@ -234,7 +234,7 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
await activateWithInstalledDistribution(ctx, distributionManager);
|
||||
} else if (distributionResult.kind === FindDistributionResultKind.NoDistribution) {
|
||||
registerErrorStubs([checkForUpdatesCommand], command => async () => {
|
||||
const installActionName = "Install CodeQL CLI";
|
||||
const installActionName = 'Install CodeQL CLI';
|
||||
const chosenAction = await helpers.showAndLogErrorMessage(`Can't execute ${command}: missing CodeQL CLI.`, {
|
||||
items: [installActionName]
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
class ExhaustivityCheckingError extends Error {
|
||||
constructor(public expectedExhaustiveValue: never) {
|
||||
super("Internal error: exhaustivity checking failure");
|
||||
super('Internal error: exhaustivity checking failure');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ export function getOnDiskWorkspaceFolders() {
|
|||
const workspaceFolders = workspace.workspaceFolders || [];
|
||||
const diskWorkspaceFolders: string[] = [];
|
||||
for (const workspaceFolder of workspaceFolders) {
|
||||
if (workspaceFolder.uri.scheme === "file")
|
||||
if (workspaceFolder.uri.scheme === 'file')
|
||||
diskWorkspaceFolders.push(workspaceFolder.uri.fsPath);
|
||||
}
|
||||
return diskWorkspaceFolders;
|
||||
|
@ -213,7 +213,7 @@ export class InvocationRateLimiter<T> {
|
|||
private readonly _func: () => Promise<T>;
|
||||
private readonly _funcIdentifier: string;
|
||||
|
||||
private static readonly _invocationRateLimiterPrefix = "invocationRateLimiter_lastInvocationDate_";
|
||||
private static readonly _invocationRateLimiterPrefix = 'invocationRateLimiter_lastInvocationDate_';
|
||||
}
|
||||
|
||||
export enum InvocationRateLimiterResultKind {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { RawResultSet } from "./adapt";
|
||||
import { ResultSetSchema } from "semmle-bqrs";
|
||||
import { Interpretation } from "./interface-types";
|
||||
import { RawResultSet } from './adapt';
|
||||
import { ResultSetSchema } from 'semmle-bqrs';
|
||||
import { Interpretation } from './interface-types';
|
||||
|
||||
export const SELECT_TABLE_NAME = '#select';
|
||||
export const ALERTS_TABLE_NAME = 'alerts';
|
||||
|
|
|
@ -129,7 +129,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
private _panelLoadedCallBacks: (() => void)[] = [];
|
||||
|
||||
private readonly _diagnosticCollection = languages.createDiagnosticCollection(
|
||||
`codeql-query-results`
|
||||
'codeql-query-results'
|
||||
);
|
||||
|
||||
constructor(
|
||||
|
@ -148,20 +148,20 @@ export class InterfaceManager extends DisposableObject {
|
|||
logger.log('Registering path-step navigation commands.');
|
||||
this.push(
|
||||
vscode.commands.registerCommand(
|
||||
"codeQLQueryResults.nextPathStep",
|
||||
'codeQLQueryResults.nextPathStep',
|
||||
this.navigatePathStep.bind(this, 1)
|
||||
)
|
||||
);
|
||||
this.push(
|
||||
vscode.commands.registerCommand(
|
||||
"codeQLQueryResults.previousPathStep",
|
||||
'codeQLQueryResults.previousPathStep',
|
||||
this.navigatePathStep.bind(this, -1)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
navigatePathStep(direction: number): void {
|
||||
this.postMessage({ t: "navigatePath", direction });
|
||||
this.postMessage({ t: 'navigatePath', direction });
|
||||
}
|
||||
|
||||
// Returns the webview panel, creating it if it doesn't already
|
||||
|
@ -170,8 +170,8 @@ export class InterfaceManager extends DisposableObject {
|
|||
if (this._panel == undefined) {
|
||||
const { ctx } = this;
|
||||
const panel = (this._panel = Window.createWebviewPanel(
|
||||
"resultsView", // internal name
|
||||
"CodeQL Query Results", // user-visible name
|
||||
'resultsView', // internal name
|
||||
'CodeQL Query Results', // user-visible name
|
||||
{ viewColumn: vscode.ViewColumn.Beside, preserveFocus: true },
|
||||
{
|
||||
enableScripts: true,
|
||||
|
@ -179,7 +179,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
retainContextWhenHidden: true,
|
||||
localResourceRoots: [
|
||||
vscode.Uri.file(tmpDir.name),
|
||||
vscode.Uri.file(path.join(this.ctx.extensionPath, "out"))
|
||||
vscode.Uri.file(path.join(this.ctx.extensionPath, 'out'))
|
||||
]
|
||||
}
|
||||
));
|
||||
|
@ -191,10 +191,10 @@ export class InterfaceManager extends DisposableObject {
|
|||
ctx.subscriptions
|
||||
);
|
||||
const scriptPathOnDisk = vscode.Uri.file(
|
||||
ctx.asAbsolutePath("out/resultsView.js")
|
||||
ctx.asAbsolutePath('out/resultsView.js')
|
||||
);
|
||||
const stylesheetPathOnDisk = vscode.Uri.file(
|
||||
ctx.asAbsolutePath("out/resultsView.css")
|
||||
ctx.asAbsolutePath('out/resultsView.css')
|
||||
);
|
||||
getHtmlForWebview(
|
||||
panel.webview,
|
||||
|
@ -215,12 +215,12 @@ export class InterfaceManager extends DisposableObject {
|
|||
): Promise<void> {
|
||||
if (this._displayedQuery === undefined) {
|
||||
showAndLogErrorMessage(
|
||||
"Failed to sort results since evaluation info was unknown."
|
||||
'Failed to sort results since evaluation info was unknown.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Notify the webview that it should expect new results.
|
||||
await this.postMessage({ t: "resultsUpdating" });
|
||||
await this.postMessage({ t: 'resultsUpdating' });
|
||||
await update(this._displayedQuery);
|
||||
await this.showResults(
|
||||
this._displayedQuery,
|
||||
|
@ -233,7 +233,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
msg: FromResultsViewMsg
|
||||
): Promise<void> {
|
||||
switch (msg.t) {
|
||||
case "viewSourceFile": {
|
||||
case 'viewSourceFile': {
|
||||
const databaseItem = this.databaseManager.findDatabaseItem(
|
||||
Uri.parse(msg.databaseUri)
|
||||
);
|
||||
|
@ -244,7 +244,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
if (e instanceof Error) {
|
||||
if (e.message.match(/File not found/)) {
|
||||
vscode.window.showErrorMessage(
|
||||
`Original file of this result is not in the database's source archive.`
|
||||
'Original file of this result is not in the database\'s source archive.'
|
||||
);
|
||||
} else {
|
||||
this.logger.log(
|
||||
|
@ -258,7 +258,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case "toggleDiagnostics": {
|
||||
case 'toggleDiagnostics': {
|
||||
if (msg.visible) {
|
||||
const databaseItem = this.databaseManager.findDatabaseItem(
|
||||
Uri.parse(msg.databaseUri)
|
||||
|
@ -276,12 +276,12 @@ export class InterfaceManager extends DisposableObject {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case "resultViewLoaded":
|
||||
case 'resultViewLoaded':
|
||||
this._panelLoaded = true;
|
||||
this._panelLoadedCallBacks.forEach(cb => cb());
|
||||
this._panelLoadedCallBacks = [];
|
||||
break;
|
||||
case "changeSort":
|
||||
case 'changeSort':
|
||||
await this.changeSortState(query =>
|
||||
query.updateSortState(
|
||||
this.cliServer,
|
||||
|
@ -290,12 +290,12 @@ export class InterfaceManager extends DisposableObject {
|
|||
)
|
||||
);
|
||||
break;
|
||||
case "changeInterpretedSort":
|
||||
case 'changeInterpretedSort':
|
||||
await this.changeSortState(query =>
|
||||
query.updateInterpretedSortState(this.cliServer, msg.sortState)
|
||||
);
|
||||
break;
|
||||
case "changePage":
|
||||
case 'changePage':
|
||||
await this.showPageOfResults(msg.selectedTable, msg.pageNumber);
|
||||
break;
|
||||
default:
|
||||
|
@ -360,10 +360,10 @@ export class InterfaceManager extends DisposableObject {
|
|||
// is not visible; it's in a not-currently-viewed tab. Show a
|
||||
// more asynchronous message to not so abruptly interrupt
|
||||
// user's workflow by immediately revealing the panel.
|
||||
const showButton = "View Results";
|
||||
const showButton = 'View Results';
|
||||
const queryName = results.queryName;
|
||||
const resultPromise = vscode.window.showInformationMessage(
|
||||
`Finished running query ${queryName.length > 0 ? ` "${queryName}"` : ""}.`,
|
||||
`Finished running query ${queryName.length > 0 ? ` "${queryName}"` : ''}.`,
|
||||
showButton
|
||||
);
|
||||
// Address this click asynchronously so we still update the
|
||||
|
@ -379,12 +379,12 @@ export class InterfaceManager extends DisposableObject {
|
|||
if (EXPERIMENTAL_BQRS_SETTING.getValue()) {
|
||||
const schemas = await this.cliServer.bqrsInfo(results.query.resultsPaths.resultsPath, RAW_RESULTS_PAGE_SIZE);
|
||||
|
||||
const resultSetNames = schemas["result-sets"].map(resultSet => resultSet.name);
|
||||
const resultSetNames = schemas['result-sets'].map(resultSet => resultSet.name);
|
||||
|
||||
// This may not wind up being the page we actually show, if there are interpreted results,
|
||||
// but speculatively send it anyway.
|
||||
const selectedTable = getDefaultResultSetName(resultSetNames);
|
||||
const schema = schemas["result-sets"].find(resultSet => resultSet.name == selectedTable)!;
|
||||
const schema = schemas['result-sets'].find(resultSet => resultSet.name == selectedTable)!;
|
||||
if (schema === undefined) {
|
||||
return { t: 'WebviewParsed' };
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
};
|
||||
|
||||
await this.postMessage({
|
||||
t: "setState",
|
||||
t: 'setState',
|
||||
interpretation,
|
||||
origResultsPaths: results.query.resultsPaths,
|
||||
resultsPath: this.convertPathToWebviewUri(
|
||||
|
@ -441,9 +441,9 @@ export class InterfaceManager extends DisposableObject {
|
|||
|
||||
const schemas = await this.cliServer.bqrsInfo(results.query.resultsPaths.resultsPath, RAW_RESULTS_PAGE_SIZE);
|
||||
|
||||
const resultSetNames = schemas["result-sets"].map(resultSet => resultSet.name);
|
||||
const resultSetNames = schemas['result-sets'].map(resultSet => resultSet.name);
|
||||
|
||||
const schema = schemas["result-sets"].find(resultSet => resultSet.name == selectedTable)!;
|
||||
const schema = schemas['result-sets'].find(resultSet => resultSet.name == selectedTable)!;
|
||||
if (schema === undefined)
|
||||
throw new Error(`Query result set '${selectedTable}' not found.`);
|
||||
|
||||
|
@ -461,7 +461,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
};
|
||||
|
||||
await this.postMessage({
|
||||
t: "setState",
|
||||
t: 'setState',
|
||||
interpretation: this._interpretation,
|
||||
origResultsPaths: results.query.resultsPaths,
|
||||
resultsPath: this.convertPathToWebviewUri(
|
||||
|
@ -602,7 +602,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
|
||||
if (!sarif.runs || !sarif.runs[0].results) {
|
||||
this.logger.log(
|
||||
"Didn't find a run in the sarif results. Error processing sarif?"
|
||||
'Didn\'t find a run in the sarif results. Error processing sarif?'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -612,11 +612,11 @@ export class InterfaceManager extends DisposableObject {
|
|||
for (const result of sarif.runs[0].results) {
|
||||
const message = result.message.text;
|
||||
if (message === undefined) {
|
||||
this.logger.log("Sarif had result without plaintext message");
|
||||
this.logger.log('Sarif had result without plaintext message');
|
||||
continue;
|
||||
}
|
||||
if (!result.locations) {
|
||||
this.logger.log("Sarif had result without location");
|
||||
this.logger.log('Sarif had result without location');
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -624,12 +624,12 @@ export class InterfaceManager extends DisposableObject {
|
|||
result.locations[0],
|
||||
sourceLocationPrefix
|
||||
);
|
||||
if (sarifLoc.t == "NoLocation") {
|
||||
if (sarifLoc.t == 'NoLocation') {
|
||||
continue;
|
||||
}
|
||||
const resultLocation = tryResolveLocation(sarifLoc, databaseItem);
|
||||
if (!resultLocation) {
|
||||
this.logger.log("Sarif location was not resolvable " + sarifLoc);
|
||||
this.logger.log('Sarif location was not resolvable ' + sarifLoc);
|
||||
continue;
|
||||
}
|
||||
const parsedMessage = parseSarifPlainTextMessage(message);
|
||||
|
@ -641,7 +641,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
}
|
||||
const resultMessageChunks: string[] = [];
|
||||
for (const section of parsedMessage) {
|
||||
if (typeof section === "string") {
|
||||
if (typeof section === 'string') {
|
||||
resultMessageChunks.push(section);
|
||||
} else {
|
||||
resultMessageChunks.push(section.text);
|
||||
|
@ -649,7 +649,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
relatedLocationsById[section.dest],
|
||||
sourceLocationPrefix
|
||||
);
|
||||
if (sarifChunkLoc.t == "NoLocation") {
|
||||
if (sarifChunkLoc.t == 'NoLocation') {
|
||||
continue;
|
||||
}
|
||||
const referenceLocation = tryResolveLocation(
|
||||
|
@ -668,7 +668,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
}
|
||||
const diagnostic = new Diagnostic(
|
||||
resultLocation.range,
|
||||
resultMessageChunks.join(""),
|
||||
resultMessageChunks.join(''),
|
||||
DiagnosticSeverity.Warning
|
||||
);
|
||||
diagnostic.relatedInformation = relatedInformation;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IndentAction, languages } from "vscode";
|
||||
import { IndentAction, languages } from 'vscode';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -18,9 +18,9 @@ export function install() {
|
|||
langConfig.wordPattern = new RegExp(langConfig.wordPattern);
|
||||
langConfig.onEnterRules = onEnterRules;
|
||||
langConfig.indentationRules = {
|
||||
decreaseIndentPattern: /^((?!.*?\/\*).*\*\/)?\s*[\}\]].*$/,
|
||||
increaseIndentPattern: /^((?!\/\/).)*(\{[^}"'`]*|\([^)"'`]*|\[[^\]"'`]*)$/
|
||||
};
|
||||
decreaseIndentPattern: /^((?!.*?\/\*).*\*\/)?\s*[\}\]].*$/,
|
||||
increaseIndentPattern: /^((?!\/\/).)*(\{[^}"'`]*|\([^)"'`]*|\[[^\]"'`]*)$/
|
||||
};
|
||||
|
||||
languages.setLanguageConfiguration('ql', langConfig);
|
||||
languages.setLanguageConfiguration('qll', langConfig);
|
||||
|
|
|
@ -352,9 +352,9 @@ export class QueryHistoryManager {
|
|||
} catch (e) {
|
||||
if (
|
||||
e.message.includes(
|
||||
"Files above 50MB cannot be synchronized with extensions"
|
||||
'Files above 50MB cannot be synchronized with extensions'
|
||||
) ||
|
||||
e.message.includes("too large to open")
|
||||
e.message.includes('too large to open')
|
||||
) {
|
||||
const res = await helpers.showBinaryChoiceDialog(
|
||||
`VS Code does not allow extensions to open files >50MB. This file
|
||||
|
@ -365,7 +365,7 @@ the file in the file explorer and dragging it into the workspace.`
|
|||
);
|
||||
if (res) {
|
||||
try {
|
||||
await vscode.commands.executeCommand("revealFileInOS", uri);
|
||||
await vscode.commands.executeCommand('revealFileInOS', uri);
|
||||
} catch (e) {
|
||||
helpers.showAndLogErrorMessage(e.message);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { env } from 'vscode';
|
||||
|
||||
import { QueryWithResults, tmpDir, QueryInfo } from "./run-queries";
|
||||
import { QueryWithResults, tmpDir, QueryInfo } from './run-queries';
|
||||
import * as messages from './messages';
|
||||
import * as helpers from './helpers';
|
||||
import * as cli from './cli';
|
||||
import * as sarif from 'sarif';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { RawResultsSortState, SortedResultSetInfo, DatabaseInfo, QueryMetadata, InterpretedResultsSortState, ResultsPaths } from "./interface-types";
|
||||
import { QueryHistoryConfig } from "./config";
|
||||
import { QueryHistoryItemOptions } from "./query-history";
|
||||
import { RawResultsSortState, SortedResultSetInfo, DatabaseInfo, QueryMetadata, InterpretedResultsSortState, ResultsPaths } from './interface-types';
|
||||
import { QueryHistoryConfig } from './config';
|
||||
import { QueryHistoryItemOptions } from './query-history';
|
||||
|
||||
export class CompletedQuery implements QueryWithResults {
|
||||
readonly time: string;
|
||||
|
@ -61,7 +61,7 @@ export class CompletedQuery implements QueryWithResults {
|
|||
case messages.QueryResultType.CANCELLATION:
|
||||
return `cancelled after ${this.result.evaluationTime / 1000} seconds`;
|
||||
case messages.QueryResultType.OOM:
|
||||
return `out of memory`;
|
||||
return 'out of memory';
|
||||
case messages.QueryResultType.SUCCESS:
|
||||
return `finished in ${this.result.evaluationTime / 1000} seconds`;
|
||||
case messages.QueryResultType.TIMEOUT:
|
||||
|
@ -140,7 +140,7 @@ export async function interpretResults(server: cli.CodeQLCliServer, metadata: Qu
|
|||
if (id === undefined) {
|
||||
// Interpretation per se doesn't really require an id, but the
|
||||
// SARIF format does, so in the absence of one, we use a dummy id.
|
||||
id = "dummy-id";
|
||||
id = 'dummy-id';
|
||||
}
|
||||
return await server.interpretBqrs({ kind, id }, resultsPath, interpretedResultsPath, sourceInfo);
|
||||
}
|
||||
|
|
|
@ -102,8 +102,8 @@ export async function displayQuickQuery(ctx: ExtensionContext, cliServer: CodeQL
|
|||
const datasetFolder = await dbItem.getDatasetFolder(cliServer);
|
||||
const { qlpack, dbscheme } = await helpers.resolveDatasetFolder(cliServer, datasetFolder);
|
||||
const quickQueryQlpackYaml: any = {
|
||||
name: "quick-query",
|
||||
version: "1.0.0",
|
||||
name: 'quick-query',
|
||||
version: '1.0.0',
|
||||
libraryPathDependencies: [qlpack]
|
||||
};
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ export class QueryInfo {
|
|||
try {
|
||||
await helpers.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: "Running Query",
|
||||
title: 'Running Query',
|
||||
cancellable: true,
|
||||
}, (progress, token) => {
|
||||
return qs.sendRequest(messages.runQueries, params, token, progress);
|
||||
|
@ -110,7 +110,7 @@ export class QueryInfo {
|
|||
}
|
||||
return result || {
|
||||
evaluationTime: 0,
|
||||
message: "No result from server",
|
||||
message: 'No result from server',
|
||||
queryId: -1,
|
||||
runId: callbackId,
|
||||
resultType: messages.QueryResultType.OTHER_ERROR
|
||||
|
@ -145,13 +145,13 @@ export class QueryInfo {
|
|||
|
||||
compiled = await helpers.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: "Compiling Query",
|
||||
title: 'Compiling Query',
|
||||
cancellable: true,
|
||||
}, (progress, token) => {
|
||||
return qs.sendRequest(messages.compileQuery, params, token, progress);
|
||||
});
|
||||
} finally {
|
||||
qs.logger.log(" - - - COMPILATION DONE - - - ");
|
||||
qs.logger.log(' - - - COMPILATION DONE - - - ');
|
||||
}
|
||||
return (compiled?.messages || []).filter(msg => msg.severity === messages.Severity.ERROR);
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ export class QueryInfo {
|
|||
async canHaveInterpretedResults(): Promise<boolean> {
|
||||
const hasMetadataFile = await this.dbItem.hasMetadataFile();
|
||||
if (!hasMetadataFile) {
|
||||
logger.log("Cannot produce interpreted results since the database does not have a .dbinfo or codeql-database.yml file.");
|
||||
logger.log('Cannot produce interpreted results since the database does not have a .dbinfo or codeql-database.yml file.');
|
||||
}
|
||||
return hasMetadataFile;
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ export async function clearCacheInDatabase(
|
|||
|
||||
return helpers.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: "Clearing Cache",
|
||||
title: 'Clearing Cache',
|
||||
cancellable: false,
|
||||
}, (progress, token) =>
|
||||
qs.sendRequest(messages.clearCache, params, token, progress)
|
||||
|
@ -216,7 +216,7 @@ export async function clearCacheInDatabase(
|
|||
*
|
||||
*/
|
||||
async function convertToQlPath(filePath: string): Promise<string> {
|
||||
if (process.platform === "win32") {
|
||||
if (process.platform === 'win32') {
|
||||
|
||||
if (path.parse(filePath).root === filePath) {
|
||||
// Java assumes uppercase drive letters are canonical.
|
||||
|
@ -234,7 +234,7 @@ async function convertToQlPath(filePath: string): Promise<string> {
|
|||
}
|
||||
}
|
||||
}
|
||||
throw new Error("Can't convert path to form suitable for QL:" + filePath);
|
||||
throw new Error('Can\'t convert path to form suitable for QL:' + filePath);
|
||||
} else {
|
||||
return filePath;
|
||||
}
|
||||
|
@ -517,18 +517,18 @@ export async function compileAndRunQueryAgainstDatabase(
|
|||
const formattedMessages: string[] = [];
|
||||
|
||||
for (const error of errors) {
|
||||
const message = error.message || "[no error message available]";
|
||||
const message = error.message || '[no error message available]';
|
||||
const formatted = `ERROR: ${message} (${error.position.fileName}:${error.position.line}:${error.position.column}:${error.position.endLine}:${error.position.endColumn})`;
|
||||
formattedMessages.push(formatted);
|
||||
qs.logger.log(formatted);
|
||||
}
|
||||
if (quickEval && formattedMessages.length <= 3) {
|
||||
helpers.showAndLogErrorMessage("Quick evaluation compilation failed: \n" + formattedMessages.join("\n"));
|
||||
helpers.showAndLogErrorMessage('Quick evaluation compilation failed: \n' + formattedMessages.join('\n'));
|
||||
} else {
|
||||
helpers.showAndLogErrorMessage((quickEval ? "Quick evaluation" : "Query") +
|
||||
" compilation failed. Please make sure there are no errors in the query, the database is up to date," +
|
||||
" and the query and database use the same target language. For more details on the error, go to View > Output," +
|
||||
" and choose CodeQL Query Server from the dropdown.");
|
||||
helpers.showAndLogErrorMessage((quickEval ? 'Quick evaluation' : 'Query') +
|
||||
' compilation failed. Please make sure there are no errors in the query, the database is up to date,' +
|
||||
' and the query and database use the same target language. For more details on the error, go to View > Output,' +
|
||||
' and choose CodeQL Query Server from the dropdown.');
|
||||
}
|
||||
|
||||
return createSyntheticResult(query, db, historyItemOptions, 'Query had compilation errors', messages.QueryResultType.OTHER_ERROR);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as Sarif from "sarif";
|
||||
import * as path from "path";
|
||||
import { LocationStyle, ResolvableLocationValue } from "semmle-bqrs";
|
||||
import * as Sarif from 'sarif';
|
||||
import * as path from 'path';
|
||||
import { LocationStyle, ResolvableLocationValue } from 'semmle-bqrs';
|
||||
|
||||
export interface SarifLink {
|
||||
dest: number;
|
||||
|
@ -23,7 +23,7 @@ export type SarifMessageComponent = string | SarifLink
|
|||
* Unescape "[", "]" and "\\" like in sarif plain text messages
|
||||
*/
|
||||
export function unescapeSarifText(message: string): string {
|
||||
return message.replace(/\\\[/g, "[").replace(/\\\]/g, "]").replace(/\\\\/, "\\");
|
||||
return message.replace(/\\\[/g, '[').replace(/\\\]/g, ']').replace(/\\\\/, '\\');
|
||||
}
|
||||
|
||||
export function parseSarifPlainTextMessage(message: string): SarifMessageComponent[] {
|
||||
|
@ -38,8 +38,8 @@ export function parseSarifPlainTextMessage(message: string): SarifMessageCompone
|
|||
let curIndex = 0;
|
||||
while ((result = linkRegex.exec(message)) !== null) {
|
||||
results.push(unescapeSarifText(message.substring(curIndex, result.index)));
|
||||
const linkText = result.groups!["linkText"];
|
||||
const linkTarget = +result.groups!["linkTarget"];
|
||||
const linkText = result.groups!['linkText'];
|
||||
const linkTarget = +result.groups!['linkTarget'];
|
||||
results.push({ dest: linkTarget, text: unescapeSarifText(linkText) });
|
||||
curIndex = result.index + result[0].length;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ async function checkAndConfirmDatabaseUpgrade(
|
|||
qs: qsClient.QueryServerClient, db: DatabaseItem, targetDbScheme: vscode.Uri, upgradesDirectories: vscode.Uri[]
|
||||
): Promise<messages.UpgradeParams | undefined> {
|
||||
if (db.contents === undefined || db.contents.dbSchemeUri === undefined) {
|
||||
helpers.showAndLogErrorMessage("Database is invalid, and cannot be upgraded.");
|
||||
helpers.showAndLogErrorMessage('Database is invalid, and cannot be upgraded.');
|
||||
return;
|
||||
}
|
||||
const params: messages.UpgradeParams = {
|
||||
|
@ -86,11 +86,11 @@ async function checkAndConfirmDatabaseUpgrade(
|
|||
let messageLines = descriptionMessage.split('\n');
|
||||
if (messageLines.length > MAX_UPGRADE_MESSAGE_LINES) {
|
||||
messageLines = messageLines.slice(0, MAX_UPGRADE_MESSAGE_LINES);
|
||||
messageLines.push(`The list of upgrades was truncated, click "No, Show Changes" to see the full list.`);
|
||||
messageLines.push('The list of upgrades was truncated, click "No, Show Changes" to see the full list.');
|
||||
dialogOptions.push(showLogItem);
|
||||
}
|
||||
|
||||
const message = `Should the database ${db.databaseUri.fsPath} be upgraded?\n\n${messageLines.join("\n")}`;
|
||||
const message = `Should the database ${db.databaseUri.fsPath} be upgraded?\n\n${messageLines.join('\n')}`;
|
||||
const chosenItem = await vscode.window.showInformationMessage(message, { modal: true }, ...dialogOptions);
|
||||
|
||||
if (chosenItem === showLogItem) {
|
||||
|
@ -157,7 +157,7 @@ async function checkDatabaseUpgrade(
|
|||
): Promise<messages.CheckUpgradeResult> {
|
||||
return helpers.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: "Checking for database upgrades",
|
||||
title: 'Checking for database upgrades',
|
||||
cancellable: true,
|
||||
}, (progress, token) => qs.sendRequest(messages.checkUpgrade, upgradeParams, token, progress));
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ async function compileDatabaseUpgrade(
|
|||
|
||||
return helpers.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: "Compiling database upgrades",
|
||||
title: 'Compiling database upgrades',
|
||||
cancellable: true,
|
||||
}, (progress, token) => qs.sendRequest(messages.compileUpgrade, params, token, progress));
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ async function runDatabaseUpgrade(
|
|||
|
||||
return helpers.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: "Running database upgrades",
|
||||
title: 'Running database upgrades',
|
||||
cancellable: true,
|
||||
}, (progress, token) => qs.sendRequest(messages.runUpgrade, params, token, progress));
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
|
|||
|
||||
|
||||
for (const part of parts) {
|
||||
if (typeof part === "string") {
|
||||
if (typeof part === 'string') {
|
||||
result.push(<span>{part} </span>);
|
||||
} else {
|
||||
const renderedLocation = renderSarifLocationWithText(part.text, relatedLocationsById[part.dest],
|
||||
|
@ -149,7 +149,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
|
|||
let shortLocation, longLocation: string;
|
||||
switch (parsedLoc.t) {
|
||||
case 'NoLocation':
|
||||
return renderNonLocation("[no location]", parsedLoc.hint);
|
||||
return renderNonLocation('[no location]', parsedLoc.hint);
|
||||
case LocationStyle.WholeFile:
|
||||
shortLocation = `${path.basename(parsedLoc.userVisibleFile)}`;
|
||||
longLocation = `${parsedLoc.userVisibleFile}`;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as React from "react";
|
||||
import * as React from 'react';
|
||||
|
||||
/**
|
||||
* These icons come from https://github.com/microsoft/vscode-icons
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as React from "react";
|
||||
import { renderLocation, ResultTableProps, zebraStripe, className, nextSortDirection } from "./result-table-utils";
|
||||
import { vscode } from "./results";
|
||||
import { ResultValue } from "../adapt";
|
||||
import { SortDirection, RAW_RESULTS_LIMIT, RawResultsSortState } from "../interface-types";
|
||||
import { RawTableResultSet } from "../interface-utils";
|
||||
import * as React from 'react';
|
||||
import { renderLocation, ResultTableProps, zebraStripe, className, nextSortDirection } from './result-table-utils';
|
||||
import { vscode } from './results';
|
||||
import { ResultValue } from '../adapt';
|
||||
import { SortDirection, RAW_RESULTS_LIMIT, RawResultsSortState } from '../interface-types';
|
||||
import { RawTableResultSet } from '../interface-utils';
|
||||
|
||||
export type RawTableProps = ResultTableProps & {
|
||||
resultSet: RawTableResultSet;
|
||||
|
@ -58,7 +58,7 @@ export class RawTable extends React.Component<RawTableProps, {}> {
|
|||
...resultSet.schema.columns.map((col, index) => {
|
||||
const displayName = col.name || `[${index}]`;
|
||||
const sortDirection = this.props.sortState && index === this.props.sortState.columnIndex ? this.props.sortState.sortDirection : undefined;
|
||||
return <th className={"sort-" + (sortDirection !== undefined ? SortDirection[sortDirection] : "none")} key={index} onClick={() => this.toggleSortStateForColumn(index)}><b>{displayName}</b></th>;
|
||||
return <th className={'sort-' + (sortDirection !== undefined ? SortDirection[sortDirection] : 'none')} key={index} onClick={() => this.toggleSortStateForColumn(index)}><b>{displayName}</b></th>;
|
||||
})
|
||||
]
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ interface ResultTablesState {
|
|||
selectedPage: string; // stringified selected page
|
||||
}
|
||||
|
||||
const UPDATING_RESULTS_TEXT_CLASS_NAME = "vscode-codeql__result-tables-updating-text";
|
||||
const UPDATING_RESULTS_TEXT_CLASS_NAME = 'vscode-codeql__result-tables-updating-text';
|
||||
|
||||
function getResultCount(resultSet: ResultSet): number {
|
||||
switch (resultSet.t) {
|
||||
|
|
|
@ -336,4 +336,4 @@ Rdom.render(
|
|||
document.getElementById('root')
|
||||
);
|
||||
|
||||
vscode.postMessage({ t: "resultViewLoaded" });
|
||||
vscode.postMessage({ t: 'resultViewLoaded' });
|
||||
|
|
|
@ -5,31 +5,31 @@ import { encodeSourceArchiveUri, ArchiveFileSystemProvider, decodeSourceArchiveU
|
|||
import { FileType, FileSystemError } from 'vscode';
|
||||
|
||||
describe('archive-filesystem-provider', () => {
|
||||
it("reads empty file correctly", async () => {
|
||||
it('reads empty file correctly', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/single_file.zip"),
|
||||
pathWithinSourceArchive: "/aFileName.txt"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/single_file.zip'),
|
||||
pathWithinSourceArchive: '/aFileName.txt'
|
||||
});
|
||||
const data = await archiveProvider.readFile(uri);
|
||||
expect(data.length).to.equal(0);
|
||||
});
|
||||
|
||||
it("read non-empty file correctly", async () => {
|
||||
it('read non-empty file correctly', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/zip_with_folder.zip"),
|
||||
pathWithinSourceArchive: "folder1/textFile.txt"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/zip_with_folder.zip'),
|
||||
pathWithinSourceArchive: 'folder1/textFile.txt'
|
||||
});
|
||||
const data = await archiveProvider.readFile(uri);
|
||||
expect(Buffer.from(data).toString('utf8')).to.be.equal('I am a text\n');
|
||||
});
|
||||
|
||||
it("read a directory", async () => {
|
||||
it('read a directory', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/zip_with_folder.zip"),
|
||||
pathWithinSourceArchive: "folder1"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/zip_with_folder.zip'),
|
||||
pathWithinSourceArchive: 'folder1'
|
||||
});
|
||||
const files = await archiveProvider.readDirectory(uri);
|
||||
expect(files).to.be.deep.equal([
|
||||
|
@ -42,8 +42,8 @@ describe('archive-filesystem-provider', () => {
|
|||
it('should handle a missing directory', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/zip_with_folder.zip"),
|
||||
pathWithinSourceArchive: "folder1/not-here"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/zip_with_folder.zip'),
|
||||
pathWithinSourceArchive: 'folder1/not-here'
|
||||
});
|
||||
try {
|
||||
await archiveProvider.readDirectory(uri);
|
||||
|
@ -56,8 +56,8 @@ describe('archive-filesystem-provider', () => {
|
|||
it('should handle a missing file', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/zip_with_folder.zip"),
|
||||
pathWithinSourceArchive: "folder1/not-here"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/zip_with_folder.zip'),
|
||||
pathWithinSourceArchive: 'folder1/not-here'
|
||||
});
|
||||
try {
|
||||
await archiveProvider.readFile(uri);
|
||||
|
@ -70,8 +70,8 @@ describe('archive-filesystem-provider', () => {
|
|||
it('should handle reading a file as a directory', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/zip_with_folder.zip"),
|
||||
pathWithinSourceArchive: "folder1/textFile.txt"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/zip_with_folder.zip'),
|
||||
pathWithinSourceArchive: 'folder1/textFile.txt'
|
||||
});
|
||||
try {
|
||||
await archiveProvider.readDirectory(uri);
|
||||
|
@ -84,8 +84,8 @@ describe('archive-filesystem-provider', () => {
|
|||
it('should handle reading a directory as a file', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/zip_with_folder.zip"),
|
||||
pathWithinSourceArchive: "folder1/folder2"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/zip_with_folder.zip'),
|
||||
pathWithinSourceArchive: 'folder1/folder2'
|
||||
});
|
||||
try {
|
||||
await archiveProvider.readFile(uri);
|
||||
|
@ -95,11 +95,11 @@ describe('archive-filesystem-provider', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it("read a nested directory", async () => {
|
||||
it('read a nested directory', async () => {
|
||||
const archiveProvider = new ArchiveFileSystemProvider();
|
||||
const uri = encodeSourceArchiveUri({
|
||||
sourceArchiveZipPath: path.resolve(__dirname, "data/archive-filesystem-provider-test/zip_with_folder.zip"),
|
||||
pathWithinSourceArchive: "folder1/folder2"
|
||||
sourceArchiveZipPath: path.resolve(__dirname, 'data/archive-filesystem-provider-test/zip_with_folder.zip'),
|
||||
pathWithinSourceArchive: 'folder1/folder2'
|
||||
});
|
||||
const files = await archiveProvider.readDirectory(uri);
|
||||
expect(files).to.be.deep.equal([
|
||||
|
@ -112,15 +112,15 @@ describe('source archive uri encoding', function() {
|
|||
const testCases: { name: string; input: ZipFileReference }[] = [
|
||||
{
|
||||
name: 'mixed case and unicode',
|
||||
input: { sourceArchiveZipPath: "/I-\u2665-codeql.zip", pathWithinSourceArchive: "/foo/bar" }
|
||||
input: { sourceArchiveZipPath: '/I-\u2665-codeql.zip', pathWithinSourceArchive: '/foo/bar' }
|
||||
},
|
||||
{
|
||||
name: 'Windows path',
|
||||
input: { sourceArchiveZipPath: "C:/Users/My Name/folder/src.zip", pathWithinSourceArchive: "/foo/bar.ext" }
|
||||
input: { sourceArchiveZipPath: 'C:/Users/My Name/folder/src.zip', pathWithinSourceArchive: '/foo/bar.ext' }
|
||||
},
|
||||
{
|
||||
name: 'Unix path',
|
||||
input: { sourceArchiveZipPath: "/home/folder/src.zip", pathWithinSourceArchive: "/foo/bar.ext" }
|
||||
input: { sourceArchiveZipPath: '/home/folder/src.zip', pathWithinSourceArchive: '/foo/bar.ext' }
|
||||
}
|
||||
];
|
||||
for (const testCase of testCases) {
|
||||
|
|
|
@ -1,131 +1,131 @@
|
|||
import "vscode-test";
|
||||
import "mocha";
|
||||
import * as chaiAsPromised from "chai-as-promised";
|
||||
import * as sinon from "sinon";
|
||||
import 'vscode-test';
|
||||
import 'mocha';
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import * as sinon from 'sinon';
|
||||
// import * as sinonChai from 'sinon-chai';
|
||||
import * as path from "path";
|
||||
import * as fs from "fs-extra";
|
||||
import * as tmp from "tmp";
|
||||
import * as chai from "chai";
|
||||
import { window } from "vscode";
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as tmp from 'tmp';
|
||||
import * as chai from 'chai';
|
||||
import { window } from 'vscode';
|
||||
|
||||
import {
|
||||
convertToDatabaseUrl,
|
||||
looksLikeLgtmUrl,
|
||||
findDirWithFile,
|
||||
} from "../../databaseFetcher";
|
||||
} from '../../databaseFetcher';
|
||||
chai.use(chaiAsPromised);
|
||||
const expect = chai.expect;
|
||||
|
||||
describe("databaseFetcher", () => {
|
||||
describe("convertToDatabaseUrl", () => {
|
||||
describe('databaseFetcher', () => {
|
||||
describe('convertToDatabaseUrl', () => {
|
||||
let quickPickSpy: sinon.SinonStub;
|
||||
beforeEach(() => {
|
||||
quickPickSpy = sinon.stub(window, "showQuickPick");
|
||||
quickPickSpy = sinon.stub(window, 'showQuickPick');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
(window.showQuickPick as sinon.SinonStub).restore();
|
||||
});
|
||||
|
||||
it("should convert a project url to a database url", async () => {
|
||||
quickPickSpy.returns("javascript" as any);
|
||||
const lgtmUrl = "https://lgtm.com/projects/g/github/codeql";
|
||||
it('should convert a project url to a database url', async () => {
|
||||
quickPickSpy.returns('javascript' as any);
|
||||
const lgtmUrl = 'https://lgtm.com/projects/g/github/codeql';
|
||||
const dbUrl = await convertToDatabaseUrl(lgtmUrl);
|
||||
|
||||
expect(dbUrl).to.equal(
|
||||
"https://lgtm.com/api/v1.0/snapshots/1506465042581/javascript"
|
||||
'https://lgtm.com/api/v1.0/snapshots/1506465042581/javascript'
|
||||
);
|
||||
expect(quickPickSpy.firstCall.args[0]).to.contain("javascript");
|
||||
expect(quickPickSpy.firstCall.args[0]).to.contain("python");
|
||||
expect(quickPickSpy.firstCall.args[0]).to.contain('javascript');
|
||||
expect(quickPickSpy.firstCall.args[0]).to.contain('python');
|
||||
});
|
||||
|
||||
it("should convert a project url to a database url with extra path segments", async () => {
|
||||
quickPickSpy.returns("python" as any);
|
||||
it('should convert a project url to a database url with extra path segments', async () => {
|
||||
quickPickSpy.returns('python' as any);
|
||||
const lgtmUrl =
|
||||
"https://lgtm.com/projects/g/github/codeql/subpage/subpage2?query=xxx";
|
||||
'https://lgtm.com/projects/g/github/codeql/subpage/subpage2?query=xxx';
|
||||
const dbUrl = await convertToDatabaseUrl(lgtmUrl);
|
||||
|
||||
expect(dbUrl).to.equal(
|
||||
"https://lgtm.com/api/v1.0/snapshots/1506465042581/python"
|
||||
'https://lgtm.com/api/v1.0/snapshots/1506465042581/python'
|
||||
);
|
||||
});
|
||||
|
||||
it("should fail on a nonexistant prohect", async () => {
|
||||
quickPickSpy.returns("javascript" as any);
|
||||
const lgtmUrl = "https://lgtm.com/projects/g/github/hucairz";
|
||||
it('should fail on a nonexistant prohect', async () => {
|
||||
quickPickSpy.returns('javascript' as any);
|
||||
const lgtmUrl = 'https://lgtm.com/projects/g/github/hucairz';
|
||||
expect(convertToDatabaseUrl(lgtmUrl)).to.rejectedWith(/Invalid LGTM URL/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("looksLikeLgtmUrl", () => {
|
||||
it("should handle invalid urls", () => {
|
||||
expect(looksLikeLgtmUrl("")).to.be.false;
|
||||
expect(looksLikeLgtmUrl("http://lgtm.com/projects/g/github/codeql")).to.be
|
||||
describe('looksLikeLgtmUrl', () => {
|
||||
it('should handle invalid urls', () => {
|
||||
expect(looksLikeLgtmUrl('')).to.be.false;
|
||||
expect(looksLikeLgtmUrl('http://lgtm.com/projects/g/github/codeql')).to.be
|
||||
.false;
|
||||
expect(looksLikeLgtmUrl("https://ww.lgtm.com/projects/g/github/codeql"))
|
||||
expect(looksLikeLgtmUrl('https://ww.lgtm.com/projects/g/github/codeql'))
|
||||
.to.be.false;
|
||||
expect(looksLikeLgtmUrl("https://ww.lgtm.com/projects/g/github")).to.be
|
||||
expect(looksLikeLgtmUrl('https://ww.lgtm.com/projects/g/github')).to.be
|
||||
.false;
|
||||
});
|
||||
|
||||
it("should handle valid urls", () => {
|
||||
expect(looksLikeLgtmUrl("https://lgtm.com/projects/g/github/codeql")).to
|
||||
it('should handle valid urls', () => {
|
||||
expect(looksLikeLgtmUrl('https://lgtm.com/projects/g/github/codeql')).to
|
||||
.be.true;
|
||||
expect(looksLikeLgtmUrl("https://www.lgtm.com/projects/g/github/codeql"))
|
||||
expect(looksLikeLgtmUrl('https://www.lgtm.com/projects/g/github/codeql'))
|
||||
.to.be.true;
|
||||
expect(
|
||||
looksLikeLgtmUrl("https://lgtm.com/projects/g/github/codeql/sub/pages")
|
||||
looksLikeLgtmUrl('https://lgtm.com/projects/g/github/codeql/sub/pages')
|
||||
).to.be.true;
|
||||
expect(
|
||||
looksLikeLgtmUrl(
|
||||
"https://lgtm.com/projects/g/github/codeql/sub/pages?query=string"
|
||||
'https://lgtm.com/projects/g/github/codeql/sub/pages?query=string'
|
||||
)
|
||||
).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe("findDirWithFile", () => {
|
||||
describe('findDirWithFile', () => {
|
||||
let dir: tmp.DirResult;
|
||||
beforeEach(() => {
|
||||
dir = tmp.dirSync({ unsafeCleanup: true });
|
||||
createFile("a");
|
||||
createFile("b");
|
||||
createFile("c");
|
||||
createFile('a');
|
||||
createFile('b');
|
||||
createFile('c');
|
||||
|
||||
createDir("dir1");
|
||||
createFile("dir1", "d");
|
||||
createFile("dir1", "e");
|
||||
createFile("dir1", "f");
|
||||
createDir('dir1');
|
||||
createFile('dir1', 'd');
|
||||
createFile('dir1', 'e');
|
||||
createFile('dir1', 'f');
|
||||
|
||||
createDir("dir2");
|
||||
createFile("dir2", "g");
|
||||
createFile("dir2", "h");
|
||||
createFile("dir2", "i");
|
||||
createDir('dir2');
|
||||
createFile('dir2', 'g');
|
||||
createFile('dir2', 'h');
|
||||
createFile('dir2', 'i');
|
||||
|
||||
createDir("dir2", "dir3");
|
||||
createFile("dir2", "dir3", "j");
|
||||
createFile("dir2", "dir3", "k");
|
||||
createFile("dir2", "dir3", "l");
|
||||
createDir('dir2', 'dir3');
|
||||
createFile('dir2', 'dir3', 'j');
|
||||
createFile('dir2', 'dir3', 'k');
|
||||
createFile('dir2', 'dir3', 'l');
|
||||
});
|
||||
|
||||
it("should find files", async () => {
|
||||
expect(await findDirWithFile(dir.name, "k")).to.equal(
|
||||
path.join(dir.name, "dir2", "dir3")
|
||||
it('should find files', async () => {
|
||||
expect(await findDirWithFile(dir.name, 'k')).to.equal(
|
||||
path.join(dir.name, 'dir2', 'dir3')
|
||||
);
|
||||
expect(await findDirWithFile(dir.name, "h")).to.equal(
|
||||
path.join(dir.name, "dir2")
|
||||
expect(await findDirWithFile(dir.name, 'h')).to.equal(
|
||||
path.join(dir.name, 'dir2')
|
||||
);
|
||||
expect(await findDirWithFile(dir.name, "z", "a")).to.equal(dir.name);
|
||||
expect(await findDirWithFile(dir.name, 'z', 'a')).to.equal(dir.name);
|
||||
// there's some slight indeterminism when more than one name exists
|
||||
// but in general, this will find files in the current directory before
|
||||
// finding files in sub-dirs
|
||||
expect(await findDirWithFile(dir.name, "k", "a")).to.equal(dir.name);
|
||||
expect(await findDirWithFile(dir.name, 'k', 'a')).to.equal(dir.name);
|
||||
});
|
||||
|
||||
|
||||
it("should not find files", async () => {
|
||||
expect(await findDirWithFile(dir.name, "x", "y", "z")).to.be.undefined;
|
||||
it('should not find files', async () => {
|
||||
expect(await findDirWithFile(dir.name, 'x', 'y', 'z')).to.be.undefined;
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -1,71 +1,71 @@
|
|||
import * as chai from "chai";
|
||||
import * as path from "path";
|
||||
import * as fetch from "node-fetch";
|
||||
import "chai/register-should";
|
||||
import * as semver from "semver";
|
||||
import * as sinonChai from "sinon-chai";
|
||||
import * as sinon from "sinon";
|
||||
import * as pq from "proxyquire";
|
||||
import "mocha";
|
||||
import * as chai from 'chai';
|
||||
import * as path from 'path';
|
||||
import * as fetch from 'node-fetch';
|
||||
import 'chai/register-should';
|
||||
import * as semver from 'semver';
|
||||
import * as sinonChai from 'sinon-chai';
|
||||
import * as sinon from 'sinon';
|
||||
import * as pq from 'proxyquire';
|
||||
import 'mocha';
|
||||
|
||||
import { GithubRelease, GithubReleaseAsset, ReleasesApiConsumer } from "../../distribution";
|
||||
import { GithubRelease, GithubReleaseAsset, ReleasesApiConsumer } from '../../distribution';
|
||||
|
||||
const proxyquire = pq.noPreserveCache();
|
||||
chai.use(sinonChai);
|
||||
const expect = chai.expect;
|
||||
|
||||
describe("Releases API consumer", () => {
|
||||
const owner = "someowner";
|
||||
const repo = "somerepo";
|
||||
const unconstrainedVersionRange = new semver.Range("*");
|
||||
describe('Releases API consumer', () => {
|
||||
const owner = 'someowner';
|
||||
const repo = 'somerepo';
|
||||
const unconstrainedVersionRange = new semver.Range('*');
|
||||
|
||||
describe("picking the latest release", () => {
|
||||
describe('picking the latest release', () => {
|
||||
const sampleReleaseResponse: GithubRelease[] = [
|
||||
{
|
||||
"assets": [],
|
||||
"created_at": "2019-09-01T00:00:00Z",
|
||||
"id": 1,
|
||||
"name": "",
|
||||
"prerelease": false,
|
||||
"tag_name": "v2.1.0"
|
||||
'assets': [],
|
||||
'created_at': '2019-09-01T00:00:00Z',
|
||||
'id': 1,
|
||||
'name': '',
|
||||
'prerelease': false,
|
||||
'tag_name': 'v2.1.0'
|
||||
},
|
||||
{
|
||||
"assets": [],
|
||||
"created_at": "2019-08-10T00:00:00Z",
|
||||
"id": 2,
|
||||
"name": "",
|
||||
"prerelease": false,
|
||||
"tag_name": "v3.1.1"
|
||||
'assets': [],
|
||||
'created_at': '2019-08-10T00:00:00Z',
|
||||
'id': 2,
|
||||
'name': '',
|
||||
'prerelease': false,
|
||||
'tag_name': 'v3.1.1'
|
||||
},
|
||||
{
|
||||
"assets": [{
|
||||
'assets': [{
|
||||
id: 1,
|
||||
name: "exampleAsset.txt",
|
||||
name: 'exampleAsset.txt',
|
||||
size: 1
|
||||
}],
|
||||
"created_at": "2019-09-05T00:00:00Z",
|
||||
"id": 3,
|
||||
"name": "",
|
||||
"prerelease": false,
|
||||
"tag_name": "v2.0.0"
|
||||
'created_at': '2019-09-05T00:00:00Z',
|
||||
'id': 3,
|
||||
'name': '',
|
||||
'prerelease': false,
|
||||
'tag_name': 'v2.0.0'
|
||||
},
|
||||
{
|
||||
"assets": [],
|
||||
"created_at": "2019-08-11T00:00:00Z",
|
||||
"id": 4,
|
||||
"name": "",
|
||||
"prerelease": true,
|
||||
"tag_name": "v3.1.2-pre-1.1"
|
||||
'assets': [],
|
||||
'created_at': '2019-08-11T00:00:00Z',
|
||||
'id': 4,
|
||||
'name': '',
|
||||
'prerelease': true,
|
||||
'tag_name': 'v3.1.2-pre-1.1'
|
||||
},
|
||||
// Release ID 5 is older than release ID 4 but its version has a higher precedence, so release
|
||||
// ID 5 should be picked over release ID 4.
|
||||
{
|
||||
"assets": [],
|
||||
"created_at": "2019-08-09T00:00:00Z",
|
||||
"id": 5,
|
||||
"name": "",
|
||||
"prerelease": true,
|
||||
"tag_name": "v3.1.2-pre-2.0"
|
||||
'assets': [],
|
||||
'created_at': '2019-08-09T00:00:00Z',
|
||||
'id': 5,
|
||||
'name': '',
|
||||
'prerelease': true,
|
||||
'tag_name': 'v3.1.2-pre-2.0'
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -78,50 +78,50 @@ describe("Releases API consumer", () => {
|
|||
}
|
||||
}
|
||||
|
||||
it("picked release has version with the highest precedence", async () => {
|
||||
it('picked release has version with the highest precedence', async () => {
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const latestRelease = await consumer.getLatestRelease(unconstrainedVersionRange);
|
||||
expect(latestRelease.id).to.equal(2);
|
||||
});
|
||||
|
||||
it("version of picked release is within the version range", async () => {
|
||||
it('version of picked release is within the version range', async () => {
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const latestRelease = await consumer.getLatestRelease(new semver.Range("2.*.*"));
|
||||
const latestRelease = await consumer.getLatestRelease(new semver.Range('2.*.*'));
|
||||
expect(latestRelease.id).to.equal(1);
|
||||
});
|
||||
|
||||
it("fails if none of the releases are within the version range", async () => {
|
||||
it('fails if none of the releases are within the version range', async () => {
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
await chai.expect(
|
||||
consumer.getLatestRelease(new semver.Range("5.*.*"))
|
||||
consumer.getLatestRelease(new semver.Range('5.*.*'))
|
||||
).to.be.rejectedWith(Error);
|
||||
});
|
||||
|
||||
it("picked release passes additional compatibility test if an additional compatibility test is specified", async () => {
|
||||
it('picked release passes additional compatibility test if an additional compatibility test is specified', async () => {
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const latestRelease = await consumer.getLatestRelease(
|
||||
new semver.Range("2.*.*"),
|
||||
new semver.Range('2.*.*'),
|
||||
true,
|
||||
release => release.assets.some(asset => asset.name === "exampleAsset.txt")
|
||||
release => release.assets.some(asset => asset.name === 'exampleAsset.txt')
|
||||
);
|
||||
expect(latestRelease.id).to.equal(3);
|
||||
});
|
||||
|
||||
it("fails if none of the releases pass the additional compatibility test", async () => {
|
||||
it('fails if none of the releases pass the additional compatibility test', async () => {
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
await chai.expect(consumer.getLatestRelease(
|
||||
new semver.Range("2.*.*"),
|
||||
new semver.Range('2.*.*'),
|
||||
true,
|
||||
release => release.assets.some(asset => asset.name === "otherExampleAsset.txt")
|
||||
release => release.assets.some(asset => asset.name === 'otherExampleAsset.txt')
|
||||
)).to.be.rejectedWith(Error);
|
||||
});
|
||||
|
||||
it("picked release is the most recent prerelease when includePrereleases is set", async () => {
|
||||
it('picked release is the most recent prerelease when includePrereleases is set', async () => {
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const latestRelease = await consumer.getLatestRelease(unconstrainedVersionRange, true);
|
||||
|
@ -129,17 +129,17 @@ describe("Releases API consumer", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("gets correct assets for a release", async () => {
|
||||
it('gets correct assets for a release', async () => {
|
||||
const expectedAssets: GithubReleaseAsset[] = [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "firstAsset",
|
||||
"size": 11
|
||||
'id': 1,
|
||||
'name': 'firstAsset',
|
||||
'size': 11
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "secondAsset",
|
||||
"size": 12
|
||||
'id': 2,
|
||||
'name': 'secondAsset',
|
||||
'size': 12
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -147,12 +147,12 @@ describe("Releases API consumer", () => {
|
|||
protected async makeApiCall(apiPath: string): Promise<fetch.Response> {
|
||||
if (apiPath === `/repos/${owner}/${repo}/releases`) {
|
||||
const responseBody: GithubRelease[] = [{
|
||||
"assets": expectedAssets,
|
||||
"created_at": "2019-09-01T00:00:00Z",
|
||||
"id": 1,
|
||||
"name": "Release 1",
|
||||
"prerelease": false,
|
||||
"tag_name": "v2.0.0"
|
||||
'assets': expectedAssets,
|
||||
'created_at': '2019-09-01T00:00:00Z',
|
||||
'id': 1,
|
||||
'name': 'Release 1',
|
||||
'prerelease': false,
|
||||
'tag_name': 'v2.0.0'
|
||||
}];
|
||||
|
||||
return Promise.resolve(new fetch.Response(JSON.stringify(responseBody)));
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { expect } from "chai";
|
||||
import "mocha";
|
||||
import { ExtensionContext, Memento } from "vscode";
|
||||
import { InvocationRateLimiter } from "../../helpers";
|
||||
import { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import { ExtensionContext, Memento } from 'vscode';
|
||||
import { InvocationRateLimiter } from '../../helpers';
|
||||
|
||||
describe("Invocation rate limiter", () => {
|
||||
describe('Invocation rate limiter', () => {
|
||||
// 1 January 2020
|
||||
let currentUnixTime = 1577836800;
|
||||
|
||||
|
@ -19,18 +19,18 @@ describe("Invocation rate limiter", () => {
|
|||
return new InvocationRateLimiter(new MockExtensionContext(), funcIdentifier, func, s => createDate(s));
|
||||
}
|
||||
|
||||
it("initially invokes function", async () => {
|
||||
it('initially invokes function', async () => {
|
||||
let numTimesFuncCalled = 0;
|
||||
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
|
||||
const invocationRateLimiter = createInvocationRateLimiter('funcid', async () => {
|
||||
numTimesFuncCalled++;
|
||||
});
|
||||
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(100);
|
||||
expect(numTimesFuncCalled).to.equal(1);
|
||||
});
|
||||
|
||||
it("doesn't invoke function again if no time has passed", async () => {
|
||||
it('doesn\'t invoke function again if no time has passed', async () => {
|
||||
let numTimesFuncCalled = 0;
|
||||
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
|
||||
const invocationRateLimiter = createInvocationRateLimiter('funcid', async () => {
|
||||
numTimesFuncCalled++;
|
||||
});
|
||||
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(100);
|
||||
|
@ -38,9 +38,9 @@ describe("Invocation rate limiter", () => {
|
|||
expect(numTimesFuncCalled).to.equal(1);
|
||||
});
|
||||
|
||||
it("doesn't invoke function again if requested time since last invocation hasn't passed", async () => {
|
||||
it('doesn\'t invoke function again if requested time since last invocation hasn\'t passed', async () => {
|
||||
let numTimesFuncCalled = 0;
|
||||
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
|
||||
const invocationRateLimiter = createInvocationRateLimiter('funcid', async () => {
|
||||
numTimesFuncCalled++;
|
||||
});
|
||||
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(100);
|
||||
|
@ -49,9 +49,9 @@ describe("Invocation rate limiter", () => {
|
|||
expect(numTimesFuncCalled).to.equal(1);
|
||||
});
|
||||
|
||||
it("invokes function again immediately if requested time since last invocation is 0 seconds", async () => {
|
||||
it('invokes function again immediately if requested time since last invocation is 0 seconds', async () => {
|
||||
let numTimesFuncCalled = 0;
|
||||
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
|
||||
const invocationRateLimiter = createInvocationRateLimiter('funcid', async () => {
|
||||
numTimesFuncCalled++;
|
||||
});
|
||||
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(0);
|
||||
|
@ -59,9 +59,9 @@ describe("Invocation rate limiter", () => {
|
|||
expect(numTimesFuncCalled).to.equal(2);
|
||||
});
|
||||
|
||||
it("invokes function again after requested time since last invocation has elapsed", async () => {
|
||||
it('invokes function again after requested time since last invocation has elapsed', async () => {
|
||||
let numTimesFuncCalled = 0;
|
||||
const invocationRateLimiter = createInvocationRateLimiter("funcid", async () => {
|
||||
const invocationRateLimiter = createInvocationRateLimiter('funcid', async () => {
|
||||
numTimesFuncCalled++;
|
||||
});
|
||||
await invocationRateLimiter.invokeFunctionIfIntervalElapsed(1);
|
||||
|
@ -70,13 +70,13 @@ describe("Invocation rate limiter", () => {
|
|||
expect(numTimesFuncCalled).to.equal(2);
|
||||
});
|
||||
|
||||
it("invokes functions with different rate limiters", async () => {
|
||||
it('invokes functions with different rate limiters', async () => {
|
||||
let numTimesFuncACalled = 0;
|
||||
const invocationRateLimiterA = createInvocationRateLimiter("funcid", async () => {
|
||||
const invocationRateLimiterA = createInvocationRateLimiter('funcid', async () => {
|
||||
numTimesFuncACalled++;
|
||||
});
|
||||
let numTimesFuncBCalled = 0;
|
||||
const invocationRateLimiterB = createInvocationRateLimiter("funcid", async () => {
|
||||
const invocationRateLimiterB = createInvocationRateLimiter('funcid', async () => {
|
||||
numTimesFuncBCalled++;
|
||||
});
|
||||
await invocationRateLimiterA.invokeFunctionIfIntervalElapsed(100);
|
||||
|
@ -90,13 +90,13 @@ class MockExtensionContext implements ExtensionContext {
|
|||
subscriptions: { dispose(): unknown }[] = [];
|
||||
workspaceState: Memento = new MockMemento();
|
||||
globalState: Memento = new MockMemento();
|
||||
extensionPath = "";
|
||||
extensionPath = '';
|
||||
asAbsolutePath(_relativePath: string): string {
|
||||
throw new Error("Method not implemented.");
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
storagePath = "";
|
||||
globalStoragePath = "";
|
||||
logPath = "";
|
||||
storagePath = '';
|
||||
globalStoragePath = '';
|
||||
logPath = '';
|
||||
}
|
||||
|
||||
class MockMemento implements Memento {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import * as chai from "chai";
|
||||
import "mocha";
|
||||
import * as vscode from "vscode";
|
||||
import * as sinon from "sinon";
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
import * as vscode from 'vscode';
|
||||
import * as sinon from 'sinon';
|
||||
// import * as sinonChai from 'sinon-chai';
|
||||
import * as chaiAsPromised from "chai-as-promised";
|
||||
import { logger } from "../../logging";
|
||||
import { QueryHistoryManager } from "../../query-history";
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import { logger } from '../../logging';
|
||||
import { QueryHistoryManager } from '../../query-history';
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
const expect = chai.expect;
|
||||
|
@ -14,7 +14,7 @@ const expect = chai.expect;
|
|||
|
||||
describe('query-history', () => {
|
||||
|
||||
describe("tryOpenExternalFile", () => {
|
||||
describe('tryOpenExternalFile', () => {
|
||||
let showTextDocumentSpy: sinon.SinonStub;
|
||||
let showInformationMessageSpy: sinon.SinonStub;
|
||||
let executeCommandSpy: sinon.SinonStub;
|
||||
|
@ -23,13 +23,13 @@ describe('query-history', () => {
|
|||
let tryOpenExternalFile: Function;
|
||||
|
||||
beforeEach(() => {
|
||||
showTextDocumentSpy = sinon.stub(vscode.window, "showTextDocument");
|
||||
showTextDocumentSpy = sinon.stub(vscode.window, 'showTextDocument');
|
||||
showInformationMessageSpy = sinon.stub(
|
||||
vscode.window,
|
||||
"showInformationMessage"
|
||||
'showInformationMessage'
|
||||
);
|
||||
executeCommandSpy = sinon.stub(vscode.commands, "executeCommand");
|
||||
logSpy = sinon.stub(logger, "log");
|
||||
executeCommandSpy = sinon.stub(vscode.commands, 'executeCommand');
|
||||
logSpy = sinon.stub(logger, 'log');
|
||||
tryOpenExternalFile = (QueryHistoryManager.prototype as any).tryOpenExternalFile;
|
||||
logSpy;
|
||||
executeCommandSpy;
|
||||
|
@ -42,7 +42,7 @@ describe('query-history', () => {
|
|||
(vscode.window.showInformationMessage as sinon.SinonStub).restore();
|
||||
});
|
||||
|
||||
it("should open an external file", async () => {
|
||||
it('should open an external file', async () => {
|
||||
await tryOpenExternalFile('xxx');
|
||||
expect(showTextDocumentSpy).to.have.been.calledOnceWith(
|
||||
vscode.Uri.file('xxx')
|
||||
|
@ -51,30 +51,30 @@ describe('query-history', () => {
|
|||
});
|
||||
|
||||
[
|
||||
"too large to open",
|
||||
"Files above 50MB cannot be synchronized with extensions",
|
||||
'too large to open',
|
||||
'Files above 50MB cannot be synchronized with extensions',
|
||||
].forEach(msg => {
|
||||
it(`should fail to open a file because "${msg}" and open externally`, async () => {
|
||||
showTextDocumentSpy.throws(new Error(msg));
|
||||
showInformationMessageSpy.returns({ title: "Yes" });
|
||||
showInformationMessageSpy.returns({ title: 'Yes' });
|
||||
|
||||
await tryOpenExternalFile("xxx");
|
||||
const uri = vscode.Uri.file("xxx");
|
||||
await tryOpenExternalFile('xxx');
|
||||
const uri = vscode.Uri.file('xxx');
|
||||
expect(showTextDocumentSpy).to.have.been.calledOnceWith(
|
||||
uri
|
||||
);
|
||||
expect(executeCommandSpy).to.have.been.calledOnceWith(
|
||||
"revealFileInOS",
|
||||
'revealFileInOS',
|
||||
uri
|
||||
);
|
||||
});
|
||||
|
||||
it(`should fail to open a file because "${msg}" and NOT open externally`, async () => {
|
||||
showTextDocumentSpy.throws(new Error(msg));
|
||||
showInformationMessageSpy.returns({ title: "No" });
|
||||
showInformationMessageSpy.returns({ title: 'No' });
|
||||
|
||||
await tryOpenExternalFile("xxx");
|
||||
const uri = vscode.Uri.file("xxx");
|
||||
await tryOpenExternalFile('xxx');
|
||||
const uri = vscode.Uri.file('xxx');
|
||||
expect(showTextDocumentSpy).to.have.been.calledOnceWith(uri);
|
||||
expect(showInformationMessageSpy).to.have.been.called;
|
||||
expect(executeCommandSpy).not.to.have.been.called;
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
import 'mocha';
|
||||
import { expect } from "chai";
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { parseSarifPlainTextMessage } from '../../sarif-utils';
|
||||
|
||||
|
||||
describe('parsing sarif', () => {
|
||||
it('should be able to parse a simple message from the spec', async function() {
|
||||
const message = "Tainted data was used. The data came from [here](3).";
|
||||
const message = 'Tainted data was used. The data came from [here](3).';
|
||||
const results = parseSarifPlainTextMessage(message);
|
||||
expect(results).to.deep.equal([
|
||||
"Tainted data was used. The data came from ",
|
||||
{ dest: 3, text: "here" }, "."
|
||||
'Tainted data was used. The data came from ',
|
||||
{ dest: 3, text: 'here' }, '.'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should be able to parse a complex message from the spec', async function() {
|
||||
const message = "Prohibited term used in [para\\[0\\]\\\\spans\\[2\\]](1).";
|
||||
const message = 'Prohibited term used in [para\\[0\\]\\\\spans\\[2\\]](1).';
|
||||
const results = parseSarifPlainTextMessage(message);
|
||||
expect(results).to.deep.equal([
|
||||
"Prohibited term used in ",
|
||||
{ dest: 1, text: "para[0]\\spans[2]" }, "."
|
||||
'Prohibited term used in ',
|
||||
{ dest: 1, text: 'para[0]\\spans[2]' }, '.'
|
||||
]);
|
||||
});
|
||||
it('should be able to parse a broken complex message from the spec', async function() {
|
||||
const message = "Prohibited term used in [para\\[0\\]\\\\spans\\[2\\](1).";
|
||||
const message = 'Prohibited term used in [para\\[0\\]\\\\spans\\[2\\](1).';
|
||||
const results = parseSarifPlainTextMessage(message);
|
||||
expect(results).to.deep.equal([
|
||||
"Prohibited term used in [para[0]\\spans[2](1)."
|
||||
'Prohibited term used in [para[0]\\spans[2](1).'
|
||||
]);
|
||||
});
|
||||
it('should be able to parse a message with extra escaping the spec', async function() {
|
||||
const message = "Tainted data was used. The data came from \\[here](3).";
|
||||
const message = 'Tainted data was used. The data came from \\[here](3).';
|
||||
const results = parseSarifPlainTextMessage(message);
|
||||
expect(results).to.deep.equal([
|
||||
"Tainted data was used. The data came from [here](3)."
|
||||
'Tainted data was used. The data came from [here](3).'
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { expect } from "chai";
|
||||
import * as path from "path";
|
||||
import * as tmp from "tmp";
|
||||
import { window, ViewColumn, Uri } from "vscode";
|
||||
import { expect } from 'chai';
|
||||
import * as path from 'path';
|
||||
import * as tmp from 'tmp';
|
||||
import { window, ViewColumn, Uri } from 'vscode';
|
||||
import { fileUriToWebviewUri, webviewUriToFileUri } from '../../interface';
|
||||
|
||||
describe('webview uri conversion', function() {
|
||||
|
@ -27,7 +27,7 @@ describe('webview uri conversion', function() {
|
|||
});
|
||||
|
||||
// CSP allowing nothing, to prevent warnings.
|
||||
const html = `<html><head><meta http-equiv="Content-Security-Policy" content="default-src 'none';"></head></html>`;
|
||||
const html = '<html><head><meta http-equiv="Content-Security-Policy" content="default-src \'none\';"></head></html>';
|
||||
panel.webview.html = html;
|
||||
return {
|
||||
fileUriOnDisk,
|
||||
|
@ -42,7 +42,7 @@ describe('webview uri conversion', function() {
|
|||
expect(reconstructedFileUri.toString(true)).to.equal(fileUriOnDisk.toString(true));
|
||||
});
|
||||
|
||||
it("does not double-encode # in URIs", function() {
|
||||
it('does not double-encode # in URIs', function() {
|
||||
const { fileUriOnDisk, panel } = setupWebview('#');
|
||||
const webviewUri = fileUriToWebviewUri(panel, fileUriOnDisk);
|
||||
const parsedUri = Uri.parse(webviewUri);
|
||||
|
|
|
@ -13,7 +13,7 @@ import * as cli from '../../src/cli';
|
|||
import { ProgressReporter, Logger } from '../../src/logging';
|
||||
|
||||
|
||||
declare module "url" {
|
||||
declare module 'url' {
|
||||
export function pathToFileURL(urlStr: string): Url;
|
||||
}
|
||||
|
||||
|
@ -63,21 +63,21 @@ const queryTestCases: QueryTestCase[] = [
|
|||
{
|
||||
queryPath: path.join(__dirname, '../data/query.ql'),
|
||||
expectedResultSets: {
|
||||
'#select': [[42, 3.14159, "hello world", true]]
|
||||
'#select': [[42, 3.14159, 'hello world', true]]
|
||||
}
|
||||
},
|
||||
{
|
||||
queryPath: path.join(__dirname, '../data/multiple-result-sets.ql'),
|
||||
expectedResultSets: {
|
||||
'edges': [[1, 2], [2, 3]],
|
||||
'#select': [["s"]]
|
||||
'#select': [['s']]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
describe('using the query server', function() {
|
||||
before(function() {
|
||||
if (process.env["CODEQL_PATH"] === undefined) {
|
||||
if (process.env['CODEQL_PATH'] === undefined) {
|
||||
console.log('The environment variable CODEQL_PATH is not set. The query server tests, which require the CodeQL CLI, will be skipped.');
|
||||
this.skip();
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ describe('using the query server', function() {
|
|||
// ensure they are all written with standard anonymous functions.
|
||||
this.timeout(10000);
|
||||
|
||||
const codeQlPath = process.env["CODEQL_PATH"]!;
|
||||
const codeQlPath = process.env['CODEQL_PATH']!;
|
||||
let qs: qsClient.QueryServerClient;
|
||||
let cliServer: cli.CodeQLCliServer;
|
||||
const queryServerStarted = new Checkpoint<void>();
|
||||
|
|
Загрузка…
Ссылка в новой задаче