@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
123 lines • 6.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowrAnalyzerContext = void 0;
exports.contextFromInput = contextFromInput;
exports.contextFromSources = contextFromSources;
const flowr_analyzer_files_context_1 = require("./flowr-analyzer-files-context");
const flowr_analyzer_dependencies_context_1 = require("./flowr-analyzer-dependencies-context");
const flowr_analyzer_plugin_1 = require("../plugins/flowr-analyzer-plugin");
const flowr_analyzer_loading_order_context_1 = require("./flowr-analyzer-loading-order-context");
const flowr_analyzer_functions_context_1 = require("./flowr-analyzer-functions-context");
const arrays_1 = require("../../util/collections/arrays");
const retriever_1 = require("../../r-bridge/retriever");
const config_1 = require("../../config");
const flowr_file_1 = require("./flowr-file");
const flowr_analyzer_environment_context_1 = require("./flowr-analyzer-environment-context");
const flowr_analyzer_meta_context_1 = require("./flowr-analyzer-meta-context");
/**
* This summarizes the other context layers used by the {@link FlowrAnalyzer}.
* Have a look at the attributes and layers listed below (e.g., {@link files} and {@link deps})
* to get an idea of the capabilities provided by this context.
* Besides these, this layer only orchestrates the different steps and layers, providing a collection of convenience methods alongside the
* {@link resolvePreAnalysis} method that conducts all the steps that can be done before the main analysis run.
* In general, you do not have to worry about these details, as the {@link FlowrAnalyzerBuilder} and {@link FlowrAnalyzer} take care of them.
*
* To inspect, e.g., the loading order, you can do so via {@link files.loadingOrder.getLoadingOrder}. To get information on a specific library, use
* {@link deps.getDependency}.
* If you are just interested in inspecting the context, you can use {@link ReadOnlyFlowrAnalyzerContext} instead (e.g., via {@link inspect}).
*/
class FlowrAnalyzerContext {
meta;
files;
deps;
env;
_analyzer;
config;
constructor(config, plugins) {
this.config = config;
const loadingOrder = new flowr_analyzer_loading_order_context_1.FlowrAnalyzerLoadingOrderContext(this, plugins.get(flowr_analyzer_plugin_1.PluginType.LoadingOrder));
this.files = new flowr_analyzer_files_context_1.FlowrAnalyzerFilesContext(loadingOrder, (plugins.get(flowr_analyzer_plugin_1.PluginType.ProjectDiscovery) ?? []), (plugins.get(flowr_analyzer_plugin_1.PluginType.FileLoad) ?? []));
this.env = new flowr_analyzer_environment_context_1.FlowrAnalyzerEnvironmentContext(this);
const functions = new flowr_analyzer_functions_context_1.FlowrAnalyzerFunctionsContext(this);
this.deps = new flowr_analyzer_dependencies_context_1.FlowrAnalyzerDependenciesContext(functions, (plugins.get(flowr_analyzer_plugin_1.PluginType.DependencyIdentification) ?? []));
this.meta = new flowr_analyzer_meta_context_1.FlowrAnalyzerMetaContext();
}
/**
* Provides the analyzer associated with this context, if any.
* This is usually set when the context is used within an analyzer instance.
* Please note, that this may be `undefined` if the context is used standalone (e.g., during setup or in plugins that do not have access to the analyzer).
*/
get analyzer() {
return this._analyzer;
}
setAnalyzer(analyzer) {
this._analyzer = analyzer;
}
/** delegate request addition */
addRequests(requests) {
this.files.addRequests(requests);
}
addFile(f) {
this.files.addFile(f);
}
addFiles(f) {
this.files.addFiles(f);
}
/** this conducts all the step that can be done before the main analysis run */
resolvePreAnalysis() {
this.files.computeLoadingOrder();
this.deps.resolveStaticDependencies();
}
/**
* Get a read-only version of this context.
* This is useful if you want to pass the context to a place where you do not want it to be modified or just to reduce
* the available methods.
*/
inspect() {
return this;
}
/**
* Reset the context to its initial state, e.g., removing all files, dependencies, and loading orders.
*/
reset() {
this.files.reset();
this.deps.reset();
this.meta.reset();
}
}
exports.FlowrAnalyzerContext = FlowrAnalyzerContext;
/**
* Lifting {@link requestFromInput} to create a full {@link FlowrAnalyzerContext} from input requests.
* Please use this only for a "quick" setup, or to have compatibility with the pre-project flowR era.
* Otherwise, refer to a {@link FlowrAnalyzerBuilder} to create a fully customized {@link FlowrAnalyzer} instance.
* @see {@link requestFromInput} - for details on how inputs are processed into requests.
* @see {@link contextFromSources} - to create a context from source code strings directly.
*/
function contextFromInput(input, config = config_1.FlowrConfig.default(), plugins) {
const context = new FlowrAnalyzerContext(config, (0, arrays_1.arraysGroupBy)(plugins ?? [], (p) => p.type));
if (typeof input === 'string' || Array.isArray(input) && input.every(i => typeof i === 'string')) {
const requests = (0, retriever_1.requestFromInput)(input);
context.addRequests(Array.isArray(requests) ? requests : [requests]);
}
else {
const requests = Array.isArray(input) ? input : [input];
context.addRequests(requests);
}
return context;
}
/**
* Create a {@link FlowrAnalyzerContext} from a set of source code strings.
* @param sources - A record mapping file paths to their source code content.
* @param config - Configuration options for the analyzer.
* @param plugins - Optional plugins to extend the analyzer's functionality.
* @see {@link contextFromInput} - to create a context from input requests.
* @see {@link FlowrInlineTextFile} - to create inline text files for the sources.
*/
function contextFromSources(sources, config = config_1.FlowrConfig.default(), plugins) {
const context = new FlowrAnalyzerContext(config, (0, arrays_1.arraysGroupBy)(plugins ?? [], (p) => p.type));
for (const [p, c] of Object.entries(sources)) {
context.addFile(new flowr_file_1.FlowrInlineTextFile(p, c));
}
return context;
}
//# sourceMappingURL=flowr-analyzer-context.js.map