UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

156 lines 5.49 kB
"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