UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

132 lines 6.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.queryStarCommand = exports.queryCommand = void 0; const ansi_1 = require("../../../util/text/ansi"); const query_1 = require("../../../queries/query"); const retriever_1 = require("../../../r-bridge/retriever"); const query_print_1 = require("../../../queries/query-print"); const json_1 = require("../../../util/json"); const args_1 = require("../../../util/text/args"); function printHelp(output) { output.stderr(`Format: ${(0, ansi_1.italic)(':query <query> <code>', output.formatter)}`); output.stdout('Queries starting with \'@<type>\' are interpreted as a query of the given type.'); output.stdout(`With this, ${(0, ansi_1.bold)(':query @config', output.formatter)} prints the result of the config query.`); output.stdout(`If you want to run the linter on a project use:\n ${(0, ansi_1.bold)(':query @linter file://<path>', output.formatter)}.`); output.stdout((0, ansi_1.ansiInfo)('Otherwise, you can also directly pass the query json. Then, the query is an array of query objects to represent multiple queries.')); output.stdout((0, ansi_1.ansiInfo)('The example') + (0, ansi_1.italic)(String.raw `:query "[{\"type\": \"call-context\", \"callName\": \"mean\" }]" mean(1:10)`, output.formatter, { color: 7 /* Colors.White */, effect: ansi_1.ColorEffect.Foreground }) + (0, ansi_1.ansiInfo)('would return the call context of the mean function.')); output.stdout('Please have a look at the wiki for more info: https://github.com/flowr-analysis/flowr/wiki/Query-API'); } async function processQueryArgs(output, analyzer, remainingArgs) { const query = remainingArgs.shift(); if (!query) { output.stderr('No query provided, use \':query help\' to get more information.'); return; } if (query === 'help') { printHelp(output); return; } let parsedQuery; let input; if (query.startsWith('@')) { const queryName = query.slice(1); const queryObj = query_1.SupportedQueries[queryName]; if (queryObj?.fromLine) { const parseResult = queryObj.fromLine(output, remainingArgs, analyzer.flowrConfig); const q = parseResult.query; parsedQuery = q ? (Array.isArray(q) ? q : [q]) : []; input = parseResult.rCode; } else { parsedQuery = [{ type: query.slice(1) }]; input = remainingArgs.join(' ').trim(); } const validationResult = (0, query_1.QueriesSchema)().validate(parsedQuery); if (validationResult.error) { output.stderr(`Invalid query: "${output.formatter.format(JSON.stringify(parsedQuery), { style: 3 /* FontStyles.Italic */, color: 3 /* Colors.Yellow */, effect: ansi_1.ColorEffect.Foreground })}"`); for (const line of validationResult.error.details) { const value = line.context?.value ? JSON.stringify(line.context.value) : undefined; output.stderr(` - ${line.message} ${value ? '(' + (0, ansi_1.italic)(value, output.formatter) + ')' : ''}`); const ctx = line.context; for (const detail of ctx?.details?.slice(0, ctx.details.length - 1) ?? []) { if ('context' in detail && 'message' in detail.context) { const lines = detail.context.message.split('. '); for (const l of lines) { output.stderr(` - ${l.trim()}`); } } } } return; } } else if (query.startsWith('[')) { parsedQuery = JSON.parse(query); const validationResult = (0, query_1.QueriesSchema)().validate(parsedQuery); if (validationResult.error) { output.stderr(`Invalid query: ${validationResult.error.message}`); printHelp(output); return; } input = remainingArgs.join(' ').trim(); } else { parsedQuery = [{ type: 'call-context', callName: query }]; } if (input) { analyzer.reset(); analyzer.addRequest(input); } return { query: await (0, query_1.executeQueries)({ analyzer, }, parsedQuery), parsedQuery, analyzer }; } /** * Function for splitting the input line. * All input is treated as arguments, no R code is separated so that the individual queries can handle it. * @param line - The input line */ function parseArgs(line) { const args = (0, args_1.splitAtEscapeSensitive)(line); return { rCode: undefined, remaining: args }; } exports.queryCommand = { description: `Query the given R code, start with '${retriever_1.fileProtocol}' to indicate a file. The query is to be a valid query in json format (use 'help' to get more information).`, isCodeCommand: true, usageExample: ':query "<query>" <code>', aliases: [], script: false, argsParser: parseArgs, fn: async ({ output, analyzer, remainingArgs }) => { const totalStart = Date.now(); const results = await processQueryArgs(output, analyzer, remainingArgs); const totalEnd = Date.now(); if (results) { output.stdout(await (0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.ansiFormatter, totalEnd - totalStart, results.query, results.analyzer, results.parsedQuery)); } } }; exports.queryStarCommand = { description: 'Similar to query, but returns the output in json format.', isCodeCommand: true, usageExample: ':query* <query> <code>', aliases: [], script: false, argsParser: parseArgs, fn: async ({ output, analyzer, remainingArgs }) => { const results = await processQueryArgs(output, analyzer, remainingArgs); if (results) { const json = Object.fromEntries(Object.entries(results.query) .map(([query, queryResults]) => [query, query_1.SupportedQueries[query]?.jsonFormatter?.(queryResults) ?? queryResults])); output.stdout(JSON.stringify(json, json_1.jsonReplacer)); } } }; //# sourceMappingURL=repl-query.js.map