UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

140 lines 5.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.usedPackages = exports.initialUsedPackageInfos = void 0; const xpath = __importStar(require("xpath-ts2")); const post_process_1 = require("./post-process"); const statistics_file_1 = require("../../../output/statistics-file"); exports.initialUsedPackageInfos = { library: 0, require: 0, loadNamespace: 0, requireNamespace: 0, attachNamespace: 0, withinApply: 0, '::': 0, ':::': 0, /** just contains all occurrences where it is impossible to statically determine which package is loaded */ '<loadedByVariable>': 0 }; // based on the extraction routine of lintr search for function calls which are not character-loads (we can not trace those...) const withinApply = xpath.parse(` //SYMBOL_FUNCTION_CALL[contains(.,"apply")]/../.. //SYMBOL[text()='require' or text()='library' or text()='loadNamespace' or text()='requireNamespace' or text()='attachNamespace'] /../.. `); // horrible ways I found exploratively like loading within `sapply` const libraryOrRequire = xpath.parse(` //SYMBOL_FUNCTION_CALL[text() = $variable] /parent::expr /parent::expr[ expr[2][STR_CONST] or ( expr[2][SYMBOL] and not( SYMBOL_SUB[text() = 'character.only'] /following-sibling::expr[1] /NUM_CONST[text() = 'TRUE' or text() = 'T'] ) ) ]/OP-LEFT-PAREN[1]/following-sibling::expr[1][SYMBOL | STR_CONST] `); // there is no except in xpath 1.0? const packageLoadedWithVariableLoadRequire = xpath.parse(` //SYMBOL_FUNCTION_CALL[text() = 'library' or text() = 'require'] /parent::expr /parent::expr[ expr[2][SYMBOL] and ( SYMBOL_SUB[text() = 'character.only'] /following-sibling::expr[1] /NUM_CONST[text() = 'TRUE' or text() = 'T'] ) ]/OP-LEFT-PAREN[1]/following-sibling::expr[1][SYMBOL | STR_CONST] `); const packageLoadedWithVariableNamespaces = xpath.parse(` //SYMBOL_FUNCTION_CALL[text() = 'loadNamespace' or text() = 'requireNamespace' or text() = 'attachNamespace']/../following-sibling::expr[1][SYMBOL] `); const queryForFunctionCall = xpath.parse(` //SYMBOL_FUNCTION_CALL[text() = $variable]/../following-sibling::expr[1][STR_CONST] `); // otherwise, the parser seems to fail const queryForNsAccess = xpath.parse(` //NS_GET[text() = $variable]/../SYMBOL_PACKAGE[1] | //NS_GET_INT[text() = $variable]/../SYMBOL_PACKAGE[1] `); const queries = [ { types: ['library', 'require'], query: libraryOrRequire }, { types: ['loadNamespace', 'requireNamespace', 'attachNamespace'], query: queryForFunctionCall }, { types: ['::', ':::'], query: queryForNsAccess } ]; exports.usedPackages = { name: 'Used Packages', description: 'All the packages used in the code', process(existing, input) { // we will unify in the end, so we can count, group etc. but we do not re-count multiple packages in the same file for (const q of queries) { for (const fn of q.types) { const nodes = q.query.select({ node: input.parsedRAst, variables: { variable: fn } }); existing[fn] += nodes.length; (0, statistics_file_1.appendStatisticsFile)(this.name, fn, nodes, input.filepath, true); } } const nodesForVariableLoad = [ ...packageLoadedWithVariableLoadRequire.select({ node: input.parsedRAst }), ...packageLoadedWithVariableNamespaces.select({ node: input.parsedRAst }) ]; existing['<loadedByVariable>'] += nodesForVariableLoad.length; // should not be unique as variables may be repeated, and we have no idea (0, statistics_file_1.appendStatisticsFile)(this.name, '<loadedByVariable>', nodesForVariableLoad, input.filepath); const withinApplyNodes = withinApply.select({ node: input.parsedRAst }); existing.withinApply += withinApplyNodes.length; (0, statistics_file_1.appendStatisticsFile)(this.name, 'withinApply', withinApplyNodes, input.filepath); return existing; }, initialValue: exports.initialUsedPackageInfos, postProcess: post_process_1.postProcess }; //# sourceMappingURL=used-packages.js.map