@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
220 lines • 9.16 kB
JavaScript
"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");
const search_mappers_1 = require("./search-executor/search-mappers");
/**
* 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 } });
},
/**
* Initializes a new search query based on the results of the given JSON query or queries.
* Internally, the {@link SupportedQuery#flattenInvolvedNodes} function is used to flatten the resulting nodes of the query.
* Please note that, due to the fact that not every query involves dataflow nodes, the search may not contain any elements at all for certain queries.
*/
fromQuery(...from) {
return new FlowrSearchBuilder({ type: 'generator', name: 'from-query', 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;
}
/**
* Adds the given enrichment to each element of the search.
* Added enrichments can later be retrieved using the {@link enrichmentContent} function.
*/
with(enrichment, args) {
this.search.push({ type: 'transformer', name: 'with', args: { info: enrichment, args: args } });
return this;
}
/**
* Maps the elements of the search to new values using the given mapper function.
*/
map(mapper, args) {
this.search.push({ type: 'transformer', name: 'map', args: { mapper: mapper, args: args } });
return this;
}
/**
* A convenience function that combines {@link with} and the {@link Mapper.Enrichment} mapper to immediately add an enrichment and then map to its value(s).
*/
get(enrichment, args) {
return this.with(enrichment, args).map(search_mappers_1.Mapper.Enrichment, enrichment);
}
/**
* 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