@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
135 lines (113 loc) • 5.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegisteredQueries = void 0;
exports.showQuery = showQuery;
exports.registerQueryDocumentation = registerQueryDocumentation;
exports.linkToQueryOfName = linkToQueryOfName;
exports.tocForQueryType = tocForQueryType;
exports.explainQueries = explainQueries;
const query_1 = require("../../queries/query");
const pipeline_executor_1 = require("../../core/pipeline-executor");
const default_pipelines_1 = require("../../core/steps/pipeline/default-pipelines");
const retriever_1 = require("../../r-bridge/retriever");
const json_1 = require("../../util/json");
const ansi_1 = require("../../util/text/ansi");
const doc_files_1 = require("./doc-files");
const doc_dfg_1 = require("./doc-dfg");
const doc_code_1 = require("./doc-code");
const time_1 = require("../../util/text/time");
const query_print_1 = require("../../queries/query-print");
const doc_cli_option_1 = require("./doc-cli-option");
const config_1 = require("../../config");
async function showQuery(shell, code, queries, { showCode, collapseResult, collapseQuery, addOutput = () => '' } = {}) {
const now = performance.now();
const analysis = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
parser: shell,
request: (0, retriever_1.requestFromInput)(code)
}, config_1.defaultConfigOptions).allRemainingSteps();
const results = await Promise.resolve((0, query_1.executeQueries)({
dataflow: analysis.dataflow,
ast: analysis.normalize,
config: (0, config_1.cloneConfig)(config_1.defaultConfigOptions)
}, queries));
const duration = performance.now() - now;
const metaInfo = `
The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
`.trim();
const str = JSON.stringify(queries, json_1.jsonReplacer, collapseQuery ? ' ' : 2);
return `
${(0, doc_code_1.codeBlock)('json', collapseQuery ? str.split('\n').join(' ').replace(/([{[])\s{2,}/g, '$1 ').replace(/\s{2,}([\]}])/g, ' $1') : str)}
${(function () {
if (queries.length === 1 && Object.keys(queries[0]).length === 1) {
return `(This query can be shortened to \`@${queries[0].type}\` when used within the REPL command ${(0, doc_cli_option_1.getReplCommand)('query')}).`;
}
else {
return '';
}
})()}
${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
_Results (prettified and summarized):_
${(0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.markdownFormatter, duration, results, analysis, queries)}
<details> <summary style="color:gray">Show Detailed Results as Json</summary>
${metaInfo}
In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR.
Please consult the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on how to get those.
${(0, doc_code_1.jsonWithLimit)(results)}
</details>
${showCode ? `
<details> <summary style="color:gray">Original Code</summary>
${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { switchCodeAndGraph: true })}
</details>
` : ''}
${collapseResult ? '</details>' : ''}
${addOutput(results, analysis)}
`;
}
exports.RegisteredQueries = {
'active': new Map(),
'virtual': new Map()
};
function registerQueryDocumentation(query, doc) {
const map = exports.RegisteredQueries[doc.type];
if (map.has(query)) {
throw new Error(`Query ${query} already registered`);
}
map.set(query, doc);
}
function linkify(name) {
return name.toLowerCase().replace(/ /g, '-');
}
function linkToQueryOfName(id) {
const query = exports.RegisteredQueries.active.get(id) ?? exports.RegisteredQueries.virtual.get(id);
if (!query) {
throw new Error(`Query ${id} not found`);
}
return `[${query.name}](#${linkify(query.name)})`;
}
function tocForQueryType(type) {
const queries = [...exports.RegisteredQueries[type].entries()].sort(([, { name: a }], [, { name: b }]) => a.localeCompare(b));
const result = [];
for (const [id, { name, shortDescription }] of queries) {
result.push(`1. [${name}](#${linkify(name)}) (\`${id}\`):\\\n ${shortDescription}`);
}
return result.join('\n');
}
async function explainQuery(shell, { name, functionName, functionFile, buildExplanation }) {
return `
### ${name}
${await buildExplanation(shell)}
<details>
<summary style="color:gray">Implementation Details</summary>
Responsible for the execution of the ${name} query is \`${functionName}\` in ${(0, doc_files_1.getFilePathMd)(functionFile)}.
</details>
`;
}
async function explainQueries(shell, type) {
const queries = [...exports.RegisteredQueries[type].entries()].sort(([, { name: a }], [, { name: b }]) => a.localeCompare(b));
const result = [];
for (const [, doc] of queries) {
result.push(await explainQuery(shell, doc));
}
return result.join(`\n${'-'.repeat(5)}\n\n`);
}
//# sourceMappingURL=doc-query.js.map