UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

145 lines 7.76 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LinterQueryDefinition = void 0; const joi_1 = __importDefault(require("joi")); const linter_query_executor_1 = require("./linter-query-executor"); const linter_rules_1 = require("../../../linter/linter-rules"); const linter_format_1 = require("../../../linter/linter-format"); const ansi_1 = require("../../../util/text/ansi"); const time_1 = require("../../../util/text/time"); const doc_code_1 = require("../../../documentation/doc-util/doc-code"); const retriever_1 = require("../../../r-bridge/retriever"); const assert_1 = require("../../../util/assert"); function rulesFromInput(output, rulesPart) { return rulesPart .reduce((acc, ruleName) => { ruleName = ruleName.trim(); if (ruleName in linter_rules_1.LintingRules) { acc.valid.push(ruleName); } else { acc.invalid.push(ruleName); } return acc; }, { valid: [], invalid: [] }); } const rulesPrefix = 'rules:'; function linterQueryLineParser(output, line, _config) { let rules = undefined; let input = undefined; if (line.length > 0 && line[0].startsWith(rulesPrefix)) { const rulesPart = line[0].slice(rulesPrefix.length).split(','); const parseResult = rulesFromInput(output, rulesPart); if (parseResult.invalid.length > 0) { output.stderr(`Invalid linting rule name(s): ${parseResult.invalid.map(r => (0, ansi_1.bold)(r, output.formatter)).join(', ')}` + `\nValid rule names are: ${Object.keys(linter_rules_1.LintingRules).map(r => (0, ansi_1.bold)(r, output.formatter)).join(', ')}`); } rules = parseResult.valid; input = line[1]; } else if (line.length > 0) { input = line[0]; } return { query: [{ type: 'linter', rules: rules }], rCode: input }; } function linterQueryCompleter(line, startingNewArg, _config) { const rulesPrefixNotPresent = line.length == 0 || (line.length == 1 && line[0].length < rulesPrefix.length); const rulesNotFinished = line.length == 1 && line[0].startsWith(rulesPrefix) && !startingNewArg; const endOfRules = line.length == 1 && startingNewArg || line.length == 2; if (rulesPrefixNotPresent) { return { completions: [`${rulesPrefix}`] }; } else if (endOfRules) { return { completions: [retriever_1.fileProtocol] }; } else if (rulesNotFinished) { const rulesWithoutPrefix = line[0].slice(rulesPrefix.length); const usedRules = rulesWithoutPrefix.split(',').map(r => r.trim()); const allRules = Object.keys(linter_rules_1.LintingRules); const unusedRules = allRules.filter(r => !usedRules.includes(r)); const lastRule = usedRules[usedRules.length - 1]; const lastRuleIsUnfinished = !allRules.includes(lastRule); if (lastRuleIsUnfinished) { // Return all rules that have not been added yet return { completions: unusedRules, argumentPart: lastRule }; } else if (unusedRules.length > 0) { // Add a comma, if the current last rule is complete return { completions: [','], argumentPart: '' }; } else { // All rules are used, complete with a space return { completions: [' '], argumentPart: '' }; } } return { completions: [] }; } exports.LinterQueryDefinition = { executor: linter_query_executor_1.executeLinterQuery, asciiSummarizer: (formatter, analyzer, queryResults, result) => { const out = queryResults; result.push(`Query: ${(0, ansi_1.bold)('linter', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`); const allDidFail = Object.values(out.results).every(linter_format_1.LintingResults.isError); if (allDidFail) { result.push('All linting rules failed to execute.'); if (analyzer.inspectContext().files.loadingOrder.getUnorderedRequests().length === 0) { result.push(formatter.format('No requests to lint for were found in the analysis.', { color: 1 /* Colors.Red */, effect: ansi_1.ColorEffect.Foreground, style: 1 /* FontStyles.Bold */ })); result.push('If you consider this an error, please report a bug: ' + (0, assert_1.getGuardIssueUrl)('analyzer found no requests to lint for')); } else if (Object.values(out.results).length === 1) { const fst = Object.values(out.results)[0]; result.push('Error: ' + linter_format_1.LintingResults.stringifyError(fst)); if (fst.error instanceof Error) { // print stack result.push('Stack Trace:\n' + fst.error.stack); } } result.push('If you consider this an error that should be fixed, please report a bug: ' + (0, assert_1.getGuardIssueUrl)('linting rule threw an error')); return true; } for (const [ruleName, results] of Object.entries(out.results)) { addLintingRuleResult(ruleName, results, result); } return true; }, completer: linterQueryCompleter, fromLine: linterQueryLineParser, schema: joi_1.default.object({ type: joi_1.default.string().valid('linter').required().description('The type of the query.'), rules: joi_1.default.array().items(joi_1.default.string().valid(...Object.keys(linter_rules_1.LintingRules)), joi_1.default.object({ name: joi_1.default.string().valid(...Object.keys(linter_rules_1.LintingRules)).required(), config: joi_1.default.object() })).description('The rules to lint for. If unset, all rules will be included.') }).description('The linter query lints for the given set of rules and returns the result.'), flattenInvolvedNodes: (queryResults) => { const out = queryResults; return Object.values(out.results).flatMap(v => Array.from(linter_format_1.LintingResults.allInvolvedIds(v))).filter(assert_1.isNotUndefined); } }; function addLintingRuleResult(ruleName, results, result) { const rule = linter_rules_1.LintingRules[ruleName]; result.push(` ╰ **${rule.info.name}** (${ruleName}):`); if (linter_format_1.LintingResults.isError(results)) { const error = linter_format_1.LintingResults.stringifyError(results).includes('At least one request must be set') ? 'No requests to lint for were found in the analysis.' : 'Error during execution of rule: ' + linter_format_1.LintingResults.stringifyError(results); result.push(` ╰ ${error}`); return; } for (const certainty of [linter_format_1.LintingResultCertainty.Certain, linter_format_1.LintingResultCertainty.Uncertain]) { const certaintyResults = results.results.filter(r => r.certainty === certainty); if (certaintyResults.length) { result.push(` ╰ ${certainty}:`); for (const res of certaintyResults) { const pretty = rule.prettyPrint[linter_format_1.LintingPrettyPrintContext.Query](res, results['.meta']); result.push(` ╰ ${pretty}${res.quickFix ? ` (${res.quickFix.length} quick fix(es) available)` : ''}`); } } } result.push(` ╰ _Metadata_: ${(0, doc_code_1.codeInline)(renderMetaData(results['.meta']))}`); } function renderMetaData(metadata) { return Object.entries(metadata).map(r => `${r[0]}: ${JSON.stringify(r[1])}`).join(', '); } //# sourceMappingURL=linter-query-format.js.map