@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
125 lines • 7.09 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.signatureCommand = exports.signatureSubcommandNames = void 0;
exports.replSignatureCompleter = replSignatureCompleter;
const ansi_1 = require("../../../util/text/ansi");
const args_1 = require("../../../util/text/args");
const query_1 = require("../../../queries/query");
const signature_query_format_1 = require("../../../queries/catalog/signature-query/signature-query-format");
const query_print_1 = require("../../../queries/query-print");
const sigdb_download_1 = require("../../../project/sigdb/sigdb-download");
const config_1 = require("../../../config");
const retriever_1 = require("../../../r-bridge/retriever");
const signature_query_executor_1 = require("../../../queries/catalog/signature-query/signature-query-executor");
/** treat the whole line as arguments, no R code to separate */
function parseArgs(line) {
return { rCode: undefined, remaining: (0, args_1.splitAtEscapeSensitive)(line) };
}
/** the (possibly space-containing) path/argument remainder passed to a subcommand */
function joinArgs(args) {
return args.filter(a => a.length > 0).join(' ').trim();
}
function printHelp(output) {
const f = output.formatter;
output.stdout((0, ansi_1.bold)('Signature Database', f) + (0, ansi_1.italic)(' (inspect and extend the databases that resolve library()/`::` calls)', f));
output.stdout('');
output.stdout(` ${(0, ansi_1.bold)(':signature query', f)} ${(0, ansi_1.italic)('[<package>[@<version>][::<function>] [<function>]] [--param <name>] [--required <n>]', f)}`);
output.stdout(` ${(0, ansi_1.italic)('inspect the database -- identical to :query @signature; with no package it summarizes the loaded databases and per-shard load state (run :signature query help for the full syntax)', f)}`);
output.stdout(` ${(0, ansi_1.bold)(':signature add', f)} ${(0, ansi_1.italic)('<path-to-.sigs.ndjson|.br|.manifest.json>', f)}`);
output.stdout(` ${(0, ansi_1.italic)('mount an additional signature database/source (dictionaries + shards); takes precedence over the bundle', f)}`);
output.stdout(` ${(0, ansi_1.bold)(':signature download', f)} ${(0, ansi_1.italic)('[<version>]', f)}`);
output.stdout(` ${(0, ansi_1.italic)('download the full-history database (all CRAN versions) from the release and mount it', f)}`);
}
/** `:signature query ...` -- inspect the database (identical to the signature query run via `:query`) */
async function runQuery(output, analyzer, args) {
const parsed = signature_query_format_1.SignatureQueryDefinition.fromLine(output, args, analyzer.flowrConfig).query;
const queries = parsed ? (Array.isArray(parsed) ? parsed : [parsed]) : [];
if (queries.length === 0) {
return; // e.g. `:signature query help` already printed the usage guide
}
const start = Date.now();
const results = await (0, query_1.executeQueries)({ analyzer }, queries);
output.stdout(await (0, query_print_1.asciiSummaryOfQueryResult)(output.formatter, Date.now() - start, results, analyzer, queries));
}
/** `:signature add <path>` -- mount an additional signature database/source (takes precedence over the bundle) */
async function runAdd(output, analyzer, rest) {
const f = output.formatter;
const source = joinArgs(rest);
if (!source) {
output.stderr(`Usage: ${(0, ansi_1.italic)(':signature add <path-to-.sigs.ndjson|.br|.manifest.json>', f)}`);
return;
}
await analyzer.context().deps.addDatabaseSource(source);
analyzer.reset();
output.stdout(`Mounted signature source ${(0, ansi_1.bold)(source, f)} (takes precedence over the bundled default).`);
output.stdout((0, ansi_1.italic)('Inspect it with :signature query.', f));
}
/** `:signature download [<version>]` -- fetch the full-history database from the release and mount it */
async function runDownload(output, analyzer, rest) {
const f = output.formatter;
const sigdb = analyzer.flowrConfig.solver.sigdb;
try {
const { dir, manifest, files } = await (0, sigdb_download_1.downloadFullSigDb)({
version: rest.find(a => a.length > 0),
repo: sigdb.downloadRepo,
onProgress: msg => output.stdout((0, ansi_1.italic)(` ${msg}`, f))
});
output.stdout(`Downloaded ${(0, ansi_1.bold)(String(files.length), f)} file(s) to ${(0, ansi_1.bold)(dir, f)}.`);
if (manifest) {
await analyzer.context().deps.addDatabaseSource(manifest);
analyzer.reset();
output.stdout(`Mounted ${(0, ansi_1.bold)(manifest, f)}.`);
}
try {
output.stdout(`Recorded in ${(0, ansi_1.bold)((0, config_1.persistSigDbPathToGlobalConfig)(dir), f)}; loads automatically on the next startup.`);
}
catch (e) {
output.stderr((0, ansi_1.italic)(`Could not update global config (${e.message}); add ${dir} to solver.sigdb.additionalPaths manually.`, f));
}
}
catch (e) {
output.stderr(`Download failed: ${e.message}`);
}
}
/** every `:signature` subcommand keyed by name -- the single source driving both dispatch and completion */
const signatureSubcommands = {
query: runQuery,
add: runAdd,
download: runDownload,
help: output => printHelp(output),
};
/** the `:signature` subcommand names, offered as completions for its first argument */
exports.signatureSubcommandNames = Object.keys(signatureSubcommands);
/** completes `:signature`: its subcommands, then a file path for `add` (query args are freeform names) */
function replSignatureCompleter(splitLine, startingNewArg) {
const subArgs = splitLine.slice(1).map(s => s.trim()).filter(s => s.length > 0);
const inSubArgs = subArgs.length >= 2 || (subArgs.length === 1 && startingNewArg);
if (!inSubArgs) {
return { completions: exports.signatureSubcommandNames.map(s => s + ' ') };
}
if (subArgs[0] === 'add') {
return { completions: [retriever_1.fileProtocol] };
}
if (subArgs[0] === 'query') {
return (0, signature_query_executor_1.signatureQueryCompleter)(subArgs.slice(1), startingNewArg);
}
return { completions: [] };
}
exports.signatureCommand = {
description: 'Inspect and extend the signature database: `query` (identical to :query @signature), `add <path>` to mount another database/source, `download` to fetch the full-history database.',
isCodeCommand: true,
usageExample: ':signature <query|add|download> ...',
aliases: ['sig'],
script: false,
argsParser: parseArgs,
fn: async ({ output, analyzer, remainingArgs }) => {
const [sub = 'help', ...rest] = remainingArgs.filter(a => a.length > 0);
const handler = signatureSubcommands[sub];
if (!handler) {
output.stderr(`Unknown subcommand ${(0, ansi_1.bold)(sub, output.formatter)}. Use ${(0, ansi_1.italic)(':signature help', output.formatter)}.`);
return;
}
await handler(output, analyzer, rest);
}
};
//# sourceMappingURL=repl-signature.js.map