UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

190 lines 7.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FlowrSearchBuilder = exports.Q = exports.FlowrSearchGenerator = void 0; exports.getFlowrSearch = getFlowrSearch; const search_optimizer_1 = require("./search-optimizer/search-optimizer"); const assert_1 = require("../util/assert"); /** * This object holds all the methods to generate search queries. * For compatibility, please use the {@link Q} identifier object to access these methods. */ exports.FlowrSearchGenerator = { /** * Initialize a search query with the given elements. * <b>This is not intended to serialize well</b> wrt. the nodes, * see {@link FlowrSearchGenerator.criterion} for a serializable alternative (passing the ids with `$id`). */ from(from) { return new FlowrSearchBuilder({ type: 'generator', name: 'from', args: { from } }); }, /** * Returns all elements (nodes/dataflow vertices) from the given data. */ all() { return new FlowrSearchBuilder({ type: 'generator', name: 'all', args: undefined }); }, /** * Returns all elements that match the given {@link FlowrSearchGetFilters|filters}. * You may pass a negative line number to count from the back. * Please note that this is currently only working for single files, it approximates over the nodes, and it is not to be used for "production". */ get(filter) { (0, assert_1.guard)(!filter.nameIsRegex || filter.name, 'If nameIsRegex is set, a name should be provided'); (0, assert_1.guard)(!filter.line || filter.line != 0, 'If line is set, it must be different from 0 as there is no 0 line'); (0, assert_1.guard)(!filter.column || filter.column > 0, 'If column is set, it must be greater than 0, but was ' + filter.column); return new FlowrSearchBuilder({ type: 'generator', name: 'get', args: { filter } }); }, /** * Returns all elements that match the given {@link SlicingCriteria|criteria} * (e.g., `criterion('2@x', '3@<-')`, * to retrieve the first use of `x` in the second line and the first `<-` assignment in the third line). * This will throw an error, if any criteria cannot be resolved to an id. */ criterion(...criterion) { (0, assert_1.guard)(criterion.length > 0, 'At least one criterion must be provided'); return new FlowrSearchBuilder({ type: 'generator', name: 'criterion', args: { criterion } }); }, /** * Short form of {@link get} with only the * {@link FlowrSearchGetFilters#line|line} and {@link FlowrSearchGetFilters#column|column} filters: * `get({line, column})`. */ loc(line, column) { return exports.FlowrSearchGenerator.get({ line, column }); }, /** * Short form of {@link get} with only the {@link FlowrSearchGetFilters#name|name} and {@link FlowrSearchGetFilters#line|line} filters: * `get({name, line})`. */ varInLine(name, line) { return exports.FlowrSearchGenerator.get({ name, line }); }, /** * Short form of {@link get} with only the {@link FlowrSearchGetFilters#name|name} filter: * `get({name})`. */ var(name) { return exports.FlowrSearchGenerator.get({ name }); }, /** * Short form of {@link get} with only the {@link FlowrSearchGetFilters#id|id} filter: * `get({id})`. */ id(id) { return exports.FlowrSearchGenerator.get({ id }); } }; /** * This is the root object to use for creating searches. * See the {@link FlowrSearchGenerator} for the available methods. * After the query is generated, * you can use what is provided by the {@link FlowrSearchBuilder} to further refine the search. */ exports.Q = exports.FlowrSearchGenerator; /** * Allows you to construct a search query from a {@link FlowrSearchGeneratorNode}. * Please use the {@link Q} object to create an object of this class! * In the end, you _can_ freeze the search by calling {@link FlowrSearchBuilder#build}, * however, the search executors may do that for you. * * @see {@link FlowrSearchGenerator} * @see {@link FlowrSearch} * @see {@link FlowrSearchLike} */ class FlowrSearchBuilder { generator; search = []; constructor(generator) { this.generator = generator; } /** * only returns the elements that match the given filter. */ filter(filter) { this.search.push({ type: 'transformer', name: 'filter', args: { filter: filter } }); return this; } /** * first either returns the first element of the search or nothing, if no elements are present. */ first() { this.search.push({ type: 'transformer', name: 'first', args: undefined }); return this; } /** * last either returns the last element of the search or nothing, if no elements are present. */ last() { this.search.push({ type: 'transformer', name: 'last', args: undefined }); return this; } /** * index returns the element at the given index if it exists */ index(index) { (0, assert_1.guard)(index >= 0, 'Index must be greater or equal to 0, but was ' + index); this.search.push({ type: 'transformer', name: 'index', args: { index } }); return this; } /** * tail returns all elements of the search except the first one. */ tail() { this.search.push({ type: 'transformer', name: 'tail', args: undefined }); return this; } /** * take returns the first `count` elements of the search. */ take(count) { (0, assert_1.guard)(count >= 0, 'Count must be greater or equal to 0, but was ' + count); this.search.push({ type: 'transformer', name: 'take', args: { count } }); return this; } /** * skip returns all elements of the search except the first `count` ones. */ skip(count) { (0, assert_1.guard)(count >= 0, 'Count must be greater or equal to 0, but was ' + count); this.search.push({ type: 'transformer', name: 'skip', args: { count } }); return this; } /** * select returns only the elements at the given indices. */ select(...select) { (0, assert_1.guard)(select.length > 0, 'At least one index must be provided'); (0, assert_1.guard)(select.every(i => i >= 0), () => 'All indices must be greater or equal to 0, but were ' + JSON.stringify(select)); this.search.push({ type: 'transformer', name: 'select', args: { select } }); return this; } /** * merge combines the search results with those of another search. */ merge(other /* | FlowrSearch<Info, Generator2, Transformers2, OtherElementType> */) { this.search.push({ type: 'transformer', name: 'merge', args: { generator: other.generator, search: other.search } }); return this; } /** * Construct the final search (this may happen automatically with most search handlers). * * @param shouldOptimize - This may optimize the search. */ build(shouldOptimize = true) { return shouldOptimize ? (0, search_optimizer_1.optimize)(this.generator, this.search) : { generator: this.generator, search: this.search }; } } exports.FlowrSearchBuilder = FlowrSearchBuilder; /** * Freezes any accepted {@link FlowrSearchLike} into a {@link FlowrSearch}. */ function getFlowrSearch(search, optimizeIfBuild = true) { if (search instanceof FlowrSearchBuilder) { return search.build(optimizeIfBuild); } return search; } //# sourceMappingURL=flowr-search-builder.js.map