@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
156 lines • 5.49 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowrAnalyzer = void 0;
const query_1 = require("../queries/query");
const decorate_1 = require("../r-bridge/lang-4.x/ast/model/processing/decorate");
const flowr_search_executor_1 = require("../search/flowr-search-executor");
const cfg_kind_1 = require("./cfg-kind");
const retriever_1 = require("../r-bridge/retriever");
const files_1 = require("../util/files");
const tree_sitter_normalize_1 = require("../r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize");
const tree_sitter_executor_1 = require("../r-bridge/lang-4.x/tree-sitter/tree-sitter-executor");
/**
* Central class for conducting analyses with FlowR.
* Use the {@link FlowrAnalyzerBuilder} to create a new instance.
*
* If you want the original pattern of creating a pipeline and running all steps, you can still do this with {@link FlowrAnalyzer#runFull}.
*
* To inspect the context of the analyzer, use {@link FlowrAnalyzer#inspectContext} (if you are a plugin and need to modify it, use {@link FlowrAnalyzer#context} instead).
* @see https://github.com/flowr-analysis/flowr/wiki/Analyzer
*/
class FlowrAnalyzer {
/** The parser and engine backend */
parser;
/** The cache used for storing analysis results */
cache;
ctx;
parserInfo;
/**
* Create a new analyzer instance.
* **Prefer the use of the {@link FlowrAnalyzerBuilder} instead of calling this constructor directly.**
* @param parser - The parser to use for parsing the given request.
* @param ctx - The context to use for the analyses.
* @param cache - The caching layer to use for storing analysis results.
*/
constructor(parser, ctx, cache) {
this.parser = parser;
this.ctx = ctx;
ctx.setAnalyzer(this);
this.cache = cache;
}
get flowrConfig() {
return this.ctx.config;
}
context() {
return this.ctx;
}
parserInformation() {
this.parserInfo ??= this.parser.information(this);
return this.parserInfo;
}
inspectContext() {
return this.ctx.inspect();
}
reset() {
this.ctx.reset();
this.cache.reset();
}
parseStandalone(data) {
const request = (0, retriever_1.isParseRequest)(data) ? data : (0, retriever_1.requestFromInput)(data);
if (this.parser.name === 'tree-sitter') {
return this.parser.parse(request);
}
else {
const ts = new tree_sitter_executor_1.TreeSitterExecutor();
return ts.parse(request);
}
}
normalizeStandalone(data) {
const parse = this.parseStandalone(data);
return (0, decorate_1.decorateAst)((0, tree_sitter_normalize_1.normalizeTreeSitterTreeToAst)([{ parsed: parse, filePath: undefined }], true), {});
}
addRequest(...request) {
for (const r of request) {
if (typeof r === 'string') {
const trimmed = r.substring(retriever_1.fileProtocol.length);
if (r.startsWith(retriever_1.fileProtocol) && !(0, files_1.isFilePath)(trimmed)) {
this.addAnalysisRequest({ request: 'project', content: trimmed });
}
else {
this.addRequestFromInput(r);
}
}
else {
this.addAnalysisRequest(r);
}
}
return this;
}
addFile(...f) {
this.ctx.addFiles(f);
return this;
}
/**
* Add a request created from the given input.
* This is a convenience method that uses {@link requestFromInput} internally.
*/
addRequestFromInput(input) {
this.addAnalysisRequest((0, retriever_1.requestFromInput)(input));
return this;
}
/**
* Add one or multiple requests to analyze the builder.
*/
addAnalysisRequest(request) {
this.ctx.addRequests((Array.isArray(request) ? request : [request]));
return this;
}
async parse(force) {
return this.cache.parse(force);
}
peekParse() {
return this.cache.peekParse();
}
async normalize(force) {
return this.cache.normalize(force);
}
peekNormalize() {
return this.cache.peekNormalize();
}
async dataflow(force) {
return this.cache.dataflow(force);
}
peekDataflow() {
return this.cache.peekDataflow();
}
async runFull(force) {
await this.dataflow(force);
return;
}
async controlflow(simplifications, kind, force) {
return this.cache.controlflow(force, kind ?? cfg_kind_1.CfgKind.NoDataflow, simplifications);
}
peekControlflow(simplifications, kind) {
return this.cache.peekControlflow(kind ?? cfg_kind_1.CfgKind.NoDataflow, simplifications);
}
async callGraph(force) {
return this.cache.callGraph(force);
}
peekCallGraph() {
return this.cache.peekCallGraph();
}
async query(query) {
return (0, query_1.executeQueries)({ analyzer: this }, query);
}
async runSearch(search) {
return (0, flowr_search_executor_1.runSearch)(search, this);
}
/**
* Close the parser if it was created by this builder. This is only required if you rely on an RShell/remote engine.
*/
close() {
return this.parser?.close();
}
}
exports.FlowrAnalyzer = FlowrAnalyzer;
//# sourceMappingURL=flowr-analyzer.js.map