UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

93 lines 4.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.R2_FILE_PATH_VALIDITY = void 0; const linter_format_1 = require("../linter-format"); const flowr_search_builder_1 = require("../../search/flowr-search-builder"); const dfg_1 = require("../../util/mermaid/dfg"); const dependencies_query_format_1 = require("../../queries/catalog/dependencies-query/dependencies-query-format"); const built_in_source_1 = require("../../dataflow/internal/process/functions/call/built-in/built-in-source"); const logic_1 = require("../../util/logic"); const config_1 = require("../../config"); const retriever_1 = require("../../r-bridge/retriever"); const read_functions_1 = require("../../queries/catalog/dependencies-query/function-info/read-functions"); const write_functions_1 = require("../../queries/catalog/dependencies-query/function-info/write-functions"); const extract_cfg_1 = require("../../control-flow/extract-cfg"); const happens_before_1 = require("../../control-flow/happens-before"); exports.R2_FILE_PATH_VALIDITY = { createSearch: (config) => flowr_search_builder_1.Q.fromQuery({ type: 'dependencies', // we only want to check read and write functions, so we explicitly clear all others ignoreDefaultFunctions: true, readFunctions: read_functions_1.ReadFunctions.concat(config.additionalReadFunctions), writeFunctions: write_functions_1.WriteFunctions.concat(config.additionalWriteFunctions) }), processSearchResult: (elements, config, data) => { const cfg = (0, extract_cfg_1.extractSimpleCfg)(data.normalize).graph; const metadata = { totalReads: 0, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0 }; return { results: elements.getElements().flatMap(element => { const results = element.queryResult; const matchingRead = results.readData.find(r => r.nodeId == element.node.info.id); if (!matchingRead) { return []; } metadata.totalReads++; const range = element.node.info.fullRange; // check if we can't parse the file path statically if (matchingRead.source === dependencies_query_format_1.Unknown) { metadata.totalUnknown++; if (config.includeUnknown) { return [{ range, filePath: dependencies_query_format_1.Unknown, certainty: linter_format_1.LintingCertainty.Maybe }]; } else { return []; } } // check if any write to the same file happens before the read, and exclude this case if so const writesToFile = results.writtenData.filter(r => samePath(r.destination, matchingRead.source)); const writesBefore = writesToFile.map(w => (0, happens_before_1.happensBefore)(cfg, w.nodeId, element.node.info.id)); if (writesBefore.some(w => w === logic_1.Ternary.Always)) { metadata.totalWritesBeforeAlways++; return []; } // check if the file exists! const paths = (0, built_in_source_1.findSource)(matchingRead.source, { referenceChain: element.node.info.file ? [(0, retriever_1.requestFromInput)(`file://${element.node.info.file}`)] : [] }); if (paths && paths.length) { metadata.totalValid++; return []; } return [{ range, filePath: matchingRead.source, certainty: writesBefore && writesBefore.length && writesBefore.every(w => w === logic_1.Ternary.Maybe) ? linter_format_1.LintingCertainty.Maybe : linter_format_1.LintingCertainty.Definitely }]; }), '.meta': metadata }; }, prettyPrint: result => `Path \`${result.filePath}\` at ${(0, dfg_1.formatRange)(result.range)}`, defaultConfig: { additionalReadFunctions: [], additionalWriteFunctions: [], includeUnknown: false } }; function samePath(a, b) { if ((0, config_1.getConfig)().solver.resolveSource?.ignoreCapitalization === true) { a = a.toLowerCase(); b = b.toLowerCase(); } return a === b; } //# sourceMappingURL=2-file-path-validity.js.map