UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

119 lines 5.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.asciiCallContext = asciiCallContext; exports.summarizeIdsIfTooLong = summarizeIdsIfTooLong; exports.asciiSummaryOfQueryResult = asciiSummaryOfQueryResult; const ansi_1 = require("../util/text/ansi"); const query_1 = require("./query"); const node_id_1 = require("../r-bridge/lang-4.x/ast/model/processing/node-id"); const html_hover_over_1 = require("../util/html-hover-over"); const time_1 = require("../util/text/time"); const model_1 = require("../r-bridge/lang-4.x/ast/model/model"); function nodeString(nodeId, formatter, idMap) { const isObj = typeof nodeId === 'object' && nodeId !== null && 'id' in nodeId; const id = isObj ? nodeId?.id : nodeId; const info = isObj ? nodeId?.info : undefined; if (node_id_1.NodeId.isBuiltIn(id)) { return (0, ansi_1.italic)(id, formatter) + (info ? ` (${JSON.stringify(info)})` : ''); } const node = idMap.get(id); if (node === undefined) { return `UNKNOWN: ${id} (info: ${JSON.stringify(info)})`; } return `${(0, ansi_1.italic)('`' + (model_1.RNode.lexeme(node) ?? 'UNKNOWN') + '`', formatter)} (L.${node.location?.[0]}${info ? ', ' + JSON.stringify(info) : ''})`; } function asciiCallContextSubHit(formatter, results, idMap) { const result = []; for (const { id, calls = [], linkedIds = [], aliasRoots = [] } of results.slice(0, 20)) { const node = idMap.get(id); if (node === undefined) { result.push(` ${(0, ansi_1.bold)('UNKNOWN: ' + JSON.stringify({ calls, linkedIds }))}`); continue; } let line = nodeString(id, formatter, idMap); if (calls.length > 0) { line += ` with ${calls.length} call${calls.length > 1 ? 's' : ''} (${calls.map(c => nodeString(c, formatter, idMap)).join(', ')})`; } if (linkedIds.length > 0) { line += ` with ${linkedIds.length} link${linkedIds.length > 1 ? 's' : ''} (${linkedIds.map(c => nodeString(c, formatter, idMap)).join(', ')})`; } if (aliasRoots.length > 0) { line += ` with ${aliasRoots.length} alias root${aliasRoots.length > 1 ? 's' : ''} (${aliasRoots.map(c => nodeString(c, formatter, idMap)).join(', ')})`; } result.push(line); } if (results.length > 20) { result.push(` ... and ${results.length - 20} more hits`); } return result.join(', '); } /** * Converts call context query results to an ASCII representation */ function asciiCallContext(formatter, results, idMap) { /* traverse over 'kinds' and within them 'subkinds' */ const result = []; for (const [kind, { subkinds }] of Object.entries(results['kinds'])) { const amountOfHits = Object.values(subkinds).reduce((acc, cur) => acc + cur.length, 0); result.push(` ╰ ${(0, ansi_1.bold)(kind, formatter)} (${amountOfHits} hit${amountOfHits === 1 ? '' : 's'}):`); for (const [subkind, values] of Object.entries(subkinds)) { const amountOfSubHits = values.length; result.push(` ╰ ${(0, ansi_1.bold)(subkind, formatter)} (${amountOfSubHits} hit${amountOfSubHits === 1 ? '' : 's'}): ${asciiCallContextSubHit(formatter, values, idMap)}`); } } return result.join('\n'); } /** * Summarizes a list of node IDs, shortening the output if it is too long * @example * ```ts * summarizeIdsIfTooLong(markdownFormatter, ['id1', 'id2', 'id3']); * // returns 'id1, id2, id3' * summarizeIdsIfTooLong(markdownFormatter, [<array of many ids>]); * // returns 'id1, id2, id3, ... (see JSON)' with a tooltip containing the full JSON array * ``` */ function summarizeIdsIfTooLong(formatter, ids) { const naive = ids.join(', '); if (naive.length <= 20) { return naive; } let acc = ''; let i = 0; while (acc.length <= 20) { acc += ids[i++] + ', '; } if (i < ids.length) { acc += '... (see JSON)'; } return formatter === ansi_1.markdownFormatter ? (0, html_hover_over_1.textWithTooltip)(acc, JSON.stringify(ids)) : acc; } /** * Generates an ASCII summary of the given query results */ async function asciiSummaryOfQueryResult(formatter, totalInMs, results, analyzer, queries) { const result = []; for (const [query, queryResults] of Object.entries(results)) { if (query === '.meta') { continue; } const queryType = query_1.SupportedQueries[query]; const relevantQueries = queries.filter(q => q.type === query); if (await queryType.asciiSummarizer(formatter, analyzer, queryResults, result, relevantQueries)) { continue; } result.push(`Query: ${(0, ansi_1.bold)(query, formatter)}`); let timing = -1; for (const [key, value] of Object.entries(queryResults)) { if (key === '.meta') { timing = value.timing; continue; } result.push(` ╰ ${key}: ${JSON.stringify(value)}`); } result.push(` - Took ${(0, time_1.printAsMs)(timing, 0)}`); } result.push((0, ansi_1.italic)(`All queries together required ≈${(0, time_1.printAsMs)(results['.meta'].timing, 0)} (1ms accuracy, total ${(0, time_1.printAsMs)(totalInMs, 0)})`, formatter)); return formatter.format(result.join('\n')); } //# sourceMappingURL=query-print.js.map