@eagleoutice/flowr 2.7.5 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -65
- package/cli/wiki.js +1 -1
- package/control-flow/extract-cfg.js +3 -3
- package/control-flow/useless-loop.d.ts +1 -1
- package/control-flow/useless-loop.js +2 -2
- package/dataflow/cluster.js +3 -3
- package/dataflow/environments/built-in-config.d.ts +8 -4
- package/dataflow/environments/built-in.d.ts +27 -14
- package/dataflow/environments/built-in.js +27 -12
- package/dataflow/environments/default-builtin-config.d.ts +614 -3
- package/dataflow/environments/default-builtin-config.js +50 -15
- package/dataflow/environments/environment.js +3 -2
- package/dataflow/environments/identifier.d.ts +5 -1
- package/dataflow/environments/reference-to-maybe.d.ts +2 -2
- package/dataflow/environments/reference-to-maybe.js +23 -14
- package/dataflow/environments/resolve-by-name.d.ts +6 -2
- package/dataflow/environments/resolve-by-name.js +5 -1
- package/dataflow/environments/scoping.js +1 -3
- package/dataflow/eval/resolve/alias-tracking.js +5 -1
- package/dataflow/extractor.js +3 -3
- package/dataflow/fn/exceptions-of-function.d.ts +13 -0
- package/dataflow/fn/exceptions-of-function.js +47 -0
- package/dataflow/fn/higher-order-function.d.ts +1 -1
- package/dataflow/fn/higher-order-function.js +3 -3
- package/dataflow/fn/recursive-function.d.ts +6 -0
- package/dataflow/fn/recursive-function.js +32 -0
- package/dataflow/graph/call-graph.d.ts +10 -0
- package/dataflow/graph/call-graph.js +209 -0
- package/dataflow/graph/dataflowgraph-builder.d.ts +7 -2
- package/dataflow/graph/dataflowgraph-builder.js +14 -9
- package/dataflow/graph/diff-dataflow-graph.js +96 -2
- package/dataflow/graph/graph.d.ts +10 -7
- package/dataflow/graph/graph.js +7 -8
- package/dataflow/graph/vertex.d.ts +6 -3
- package/dataflow/hooks.d.ts +30 -0
- package/dataflow/hooks.js +38 -0
- package/dataflow/info.d.ts +28 -5
- package/dataflow/info.js +66 -31
- package/dataflow/internal/linker.d.ts +13 -3
- package/dataflow/internal/linker.js +155 -53
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +4 -0
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +7 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +19 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +14 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +30 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +24 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +5 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +59 -21
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.d.ts +34 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.js +92 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.d.ts +21 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.js +129 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.d.ts +16 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.js +127 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +5 -3
- package/dataflow/internal/process/functions/call/common.d.ts +13 -1
- package/dataflow/internal/process/functions/call/common.js +33 -2
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +13 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +29 -3
- package/dataflow/internal/process/functions/call/named-call-handling.js +2 -1
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -4
- package/dataflow/internal/process/functions/process-argument.js +7 -6
- package/dataflow/internal/process/functions/process-parameter.js +2 -1
- package/dataflow/internal/process/process-named-call.d.ts +2 -2
- package/dataflow/internal/process/process-symbol.js +3 -2
- package/dataflow/internal/process/process-value.d.ts +3 -2
- package/dataflow/internal/process/process-value.js +8 -6
- package/dataflow/origin/dfg-get-origin.js +2 -1
- package/dataflow/origin/dfg-get-symbol-refs.js +1 -1
- package/documentation/doc-readme.d.ts +1 -1
- package/documentation/doc-readme.js +6 -6
- package/documentation/doc-util/doc-code.js +1 -1
- package/documentation/doc-util/doc-dfg.d.ts +1 -0
- package/documentation/doc-util/doc-dfg.js +7 -4
- package/documentation/doc-util/doc-query.d.ts +1 -0
- package/documentation/doc-util/doc-query.js +1 -1
- package/documentation/doc-util/doc-repl.d.ts +2 -1
- package/documentation/doc-util/doc-repl.js +11 -3
- package/documentation/wiki-analyzer.js +2 -0
- package/documentation/wiki-dataflow-graph.js +59 -16
- package/documentation/wiki-interface.js +33 -5
- package/documentation/wiki-mk/doc-context.d.ts +2 -1
- package/documentation/wiki-mk/doc-context.js +2 -2
- package/documentation/wiki-mk/doc-maker.js +4 -3
- package/documentation/wiki-normalized-ast.js +6 -0
- package/documentation/wiki-query.js +109 -1
- package/linter/linter-rules.d.ts +1 -1
- package/linter/rules/seeded-randomness.js +17 -12
- package/linter/rules/useless-loop.d.ts +1 -1
- package/package.json +9 -11
- package/project/cache/flowr-analyzer-cache.d.ts +11 -0
- package/project/cache/flowr-analyzer-cache.js +19 -0
- package/project/context/flowr-analyzer-dependencies-context.d.ts +6 -1
- package/project/context/flowr-analyzer-dependencies-context.js +6 -0
- package/project/context/flowr-analyzer-files-context.d.ts +5 -2
- package/project/context/flowr-analyzer-files-context.js +24 -17
- package/project/context/flowr-file.d.ts +9 -4
- package/project/context/flowr-file.js +20 -6
- package/project/flowr-analyzer.d.ts +11 -0
- package/project/flowr-analyzer.js +6 -0
- package/project/plugins/file-plugins/files/flowr-description-file.d.ts +11 -3
- package/project/plugins/file-plugins/files/flowr-description-file.js +38 -28
- package/project/plugins/file-plugins/files/flowr-jupyter-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-namespace-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-news-file.js +1 -1
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +1 -1
- package/project/plugins/file-plugins/flowr-analyzer-description-file-plugin.js +1 -1
- package/project/plugins/file-plugins/flowr-analyzer-file-plugin.d.ts +4 -1
- package/project/plugins/file-plugins/flowr-analyzer-file-plugin.js +3 -0
- package/project/plugins/file-plugins/{flowr-analyzer-namespace-file-plugin.d.ts → flowr-analyzer-namespace-files-plugin.d.ts} +1 -1
- package/project/plugins/file-plugins/{flowr-analyzer-namespace-file-plugin.js → flowr-analyzer-namespace-files-plugin.js} +4 -4
- package/project/plugins/file-plugins/flowr-analyzer-test-file-plugin.d.ts +26 -0
- package/project/plugins/file-plugins/flowr-analyzer-test-file-plugin.js +39 -0
- package/project/plugins/file-plugins/flowr-analyzer-vignette-file-plugin.d.ts +26 -0
- package/project/plugins/file-plugins/flowr-analyzer-vignette-file-plugin.js +39 -0
- package/project/plugins/flowr-analyzer-plugin-defaults.js +6 -2
- package/project/plugins/package-version-plugins/flowr-analyzer-package-versions-description-file-plugin.js +3 -13
- package/project/plugins/package-version-plugins/package.d.ts +1 -1
- package/project/plugins/package-version-plugins/package.js +3 -3
- package/project/plugins/plugin-registry.d.ts +4 -2
- package/project/plugins/plugin-registry.js +6 -2
- package/project/plugins/project-discovery/flowr-analyzer-project-discovery-plugin.d.ts +11 -0
- package/project/plugins/project-discovery/flowr-analyzer-project-discovery-plugin.js +5 -2
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +4 -12
- package/queries/catalog/call-graph-query/call-graph-query-executor.d.ts +6 -0
- package/queries/catalog/call-graph-query/call-graph-query-executor.js +21 -0
- package/queries/catalog/call-graph-query/call-graph-query-format.d.ts +21 -0
- package/queries/catalog/call-graph-query/call-graph-query-format.js +32 -0
- package/queries/catalog/dataflow-query/dataflow-query-executor.js +4 -3
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +29 -3
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -0
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +8 -1
- package/queries/catalog/dependencies-query/function-info/write-functions.js +13 -0
- package/queries/catalog/does-call-query/does-call-query-executor.d.ts +6 -0
- package/queries/catalog/does-call-query/does-call-query-executor.js +100 -0
- package/queries/catalog/does-call-query/does-call-query-format.d.ts +51 -0
- package/queries/catalog/does-call-query/does-call-query-format.js +102 -0
- package/queries/catalog/files-query/files-query-executor.js +4 -4
- package/queries/catalog/files-query/files-query-format.d.ts +2 -1
- package/queries/catalog/files-query/files-query-format.js +18 -2
- package/queries/catalog/id-map-query/id-map-query-executor.js +4 -3
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.d.ts +18 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.js +56 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.d.ts +34 -0
- package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.js +54 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +3 -28
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +6 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.js +12 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-executor.d.ts +6 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-executor.js +23 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.d.ts +28 -0
- package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.js +44 -0
- package/queries/catalog/linter-query/linter-query-format.js +4 -1
- package/queries/catalog/location-map-query/location-map-query-executor.js +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.js +4 -3
- package/queries/catalog/project-query/project-query-executor.js +9 -3
- package/queries/catalog/project-query/project-query-format.d.ts +8 -3
- package/queries/catalog/project-query/project-query-format.js +35 -9
- package/queries/query.d.ts +34 -2
- package/queries/query.js +9 -0
- package/r-bridge/data/data.d.ts +10 -5
- package/r-bridge/data/data.js +11 -5
- package/r-bridge/lang-4.x/ast/model/model.d.ts +7 -7
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +5 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.js +8 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +2 -2
- package/r-bridge/lang-4.x/ast/parser/main/internal/other/normalize-comment.js +0 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +0 -2
- package/r-bridge/roxygen2/roxygen-ast.d.ts +218 -0
- package/r-bridge/roxygen2/roxygen-ast.js +82 -0
- package/r-bridge/roxygen2/roxygen-parse.d.ts +24 -0
- package/r-bridge/roxygen2/roxygen-parse.js +214 -0
- package/reconstruct/auto-select/magic-comments.js +4 -4
- package/slicing/static/slice-call.js +3 -4
- package/slicing/static/static-slicer.js +2 -2
- package/statistics/features/supported/defined-functions/defined-functions.js +1 -1
- package/util/collections/defaultmap.d.ts +3 -3
- package/util/mermaid/dfg.js +5 -5
- package/util/objects.js +1 -1
- package/util/r-author.d.ts +5 -0
- package/util/r-author.js +110 -0
- package/util/r-license.d.ts +32 -0
- package/util/r-license.js +217 -0
- package/util/r-version.d.ts +19 -0
- package/util/r-version.js +106 -0
- package/util/range.d.ts +6 -0
- package/util/range.js +7 -0
- package/util/simple-df/dfg-ascii.js +2 -2
- package/util/text/args.d.ts +9 -0
- package/util/text/args.js +65 -0
- package/util/version.js +1 -1
|
@@ -23,9 +23,7 @@ export interface DefaultCallContextQueryFormat<RegexType extends CallNameTypes>
|
|
|
23
23
|
readonly type: 'call-context';
|
|
24
24
|
/** Regex regarding the function name, please note that strings will be interpreted as regular expressions too! */
|
|
25
25
|
readonly callName: RegexType;
|
|
26
|
-
/**
|
|
27
|
-
* Should we automatically add the `^` and `$` anchors to the regex to make it an exact match?
|
|
28
|
-
*/
|
|
26
|
+
/** Should we automatically add the `^` and `$` anchors to the regex to make it an exact match? */
|
|
29
27
|
readonly callNameExact?: boolean;
|
|
30
28
|
/** kind may be a step or anything that you attach to the call, this can be used to group calls together (e.g., linking `ggplot` to `visualize`). Defaults to `.` */
|
|
31
29
|
readonly kind?: string;
|
|
@@ -36,17 +34,11 @@ export interface DefaultCallContextQueryFormat<RegexType extends CallNameTypes>
|
|
|
36
34
|
* Request this specifically to gain all call targets we can resolve.
|
|
37
35
|
*/
|
|
38
36
|
readonly callTargets?: CallTargets;
|
|
39
|
-
/**
|
|
40
|
-
* Consider a case like `f <- function_of_interest`, do you want uses of `f` to be included in the results?
|
|
41
|
-
*/
|
|
37
|
+
/** Consider a case like `f <- function_of_interest`, do you want uses of `f` to be included in the results? */
|
|
42
38
|
readonly includeAliases?: boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Should we ignore default values for parameters in the results?
|
|
45
|
-
*/
|
|
39
|
+
/** Should we ignore default values for parameters in the results? */
|
|
46
40
|
readonly ignoreParameterValues?: boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Filter that, when set, a node's file attribute must match to be considered
|
|
49
|
-
*/
|
|
41
|
+
/** Filter that, when set, a node's file attribute must match to be considered */
|
|
50
42
|
readonly fileFilter?: FileFilter<RegexType>;
|
|
51
43
|
}
|
|
52
44
|
export type CallNameTypes = RegExp | string | string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CallGraphQuery, CallGraphQueryResult } from './call-graph-query-format';
|
|
2
|
+
import type { BasicQueryData } from '../../base-query-format';
|
|
3
|
+
/**
|
|
4
|
+
* Executes the given call graph queries.
|
|
5
|
+
*/
|
|
6
|
+
export declare function executeCallGraphQuery({ analyzer }: BasicQueryData, queries: readonly CallGraphQuery[]): Promise<CallGraphQueryResult>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeCallGraphQuery = executeCallGraphQuery;
|
|
4
|
+
const log_1 = require("../../../util/log");
|
|
5
|
+
/**
|
|
6
|
+
* Executes the given call graph queries.
|
|
7
|
+
*/
|
|
8
|
+
async function executeCallGraphQuery({ analyzer }, queries) {
|
|
9
|
+
if (queries.length !== 1) {
|
|
10
|
+
log_1.log.warn('Call Graph query expects only up to one query, but got', queries.length);
|
|
11
|
+
}
|
|
12
|
+
const startTime = Date.now();
|
|
13
|
+
const graph = await analyzer.callGraph();
|
|
14
|
+
return {
|
|
15
|
+
'.meta': {
|
|
16
|
+
timing: Date.now() - startTime
|
|
17
|
+
},
|
|
18
|
+
graph
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=call-graph-query-executor.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
|
|
2
|
+
import { executeCallGraphQuery } from './call-graph-query-executor';
|
|
3
|
+
import Joi from 'joi';
|
|
4
|
+
import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
5
|
+
import type { CallGraph } from '../../../dataflow/graph/call-graph';
|
|
6
|
+
/**
|
|
7
|
+
* Computes the Call Graph of the analyzed project.
|
|
8
|
+
*/
|
|
9
|
+
export interface CallGraphQuery extends BaseQueryFormat {
|
|
10
|
+
readonly type: 'call-graph';
|
|
11
|
+
}
|
|
12
|
+
export interface CallGraphQueryResult extends BaseQueryResult {
|
|
13
|
+
/** Please be aware that this is the graph in its JSON representation, use {@link DataflowGraph#fromJson} if the result is serialized */
|
|
14
|
+
readonly graph: CallGraph;
|
|
15
|
+
}
|
|
16
|
+
export declare const CallGraphQueryDefinition: {
|
|
17
|
+
readonly executor: typeof executeCallGraphQuery;
|
|
18
|
+
readonly asciiSummarizer: (formatter: import("../../../util/text/ansi").OutputFormatter, _analyzer: import("../../../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider<import("../../../r-bridge/parser").KnownParser>, queryResults: BaseQueryResult, result: string[]) => true;
|
|
19
|
+
readonly schema: Joi.ObjectSchema<any>;
|
|
20
|
+
readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
|
|
21
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CallGraphQueryDefinition = void 0;
|
|
7
|
+
const call_graph_query_executor_1 = require("./call-graph-query-executor");
|
|
8
|
+
const ansi_1 = require("../../../util/text/ansi");
|
|
9
|
+
const time_1 = require("../../../util/text/time");
|
|
10
|
+
const dfg_1 = require("../../../util/mermaid/dfg");
|
|
11
|
+
const joi_1 = __importDefault(require("joi"));
|
|
12
|
+
exports.CallGraphQueryDefinition = {
|
|
13
|
+
executor: call_graph_query_executor_1.executeCallGraphQuery,
|
|
14
|
+
asciiSummarizer: (formatter, _analyzer, queryResults, result) => {
|
|
15
|
+
const out = queryResults;
|
|
16
|
+
result.push(`Query: ${(0, ansi_1.bold)('call-graph', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
|
|
17
|
+
result.push(` ╰ [Call Graph](${(0, dfg_1.graphToMermaidUrl)(out.graph)})`);
|
|
18
|
+
return true;
|
|
19
|
+
},
|
|
20
|
+
schema: joi_1.default.object({
|
|
21
|
+
type: joi_1.default.string().valid('call-graph').required().description('The type of the query.'),
|
|
22
|
+
}).description('A query to compute the Call Graph of the analyzed project.'),
|
|
23
|
+
flattenInvolvedNodes: queryResults => {
|
|
24
|
+
const flattened = [];
|
|
25
|
+
const out = queryResults;
|
|
26
|
+
for (const id of out.graph.idMap?.keys() ?? []) {
|
|
27
|
+
flattened.push(id);
|
|
28
|
+
}
|
|
29
|
+
return flattened;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=call-graph-query-format.js.map
|
|
@@ -9,12 +9,13 @@ async function executeDataflowQuery({ analyzer }, queries) {
|
|
|
9
9
|
if (queries.length !== 1) {
|
|
10
10
|
log_1.log.warn('Dataflow query expects only up to one query, but got', queries.length);
|
|
11
11
|
}
|
|
12
|
+
const startTime = Date.now();
|
|
13
|
+
const graph = (await analyzer.dataflow()).graph;
|
|
12
14
|
return {
|
|
13
15
|
'.meta': {
|
|
14
|
-
|
|
15
|
-
timing: 0
|
|
16
|
+
timing: Date.now() - startTime
|
|
16
17
|
},
|
|
17
|
-
graph
|
|
18
|
+
graph
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
//# sourceMappingURL=dataflow-query-executor.js.map
|
|
@@ -79,17 +79,40 @@ function getResults(queries, { dataflow, config, normalize }, results, kind, fun
|
|
|
79
79
|
const args = (0, resolve_argument_1.getArgumentStringValue)(config.solver.variables, dataflow.graph, vertex, info.argIdx, info.argName, info.resolveValue, data.analyzer.inspectContext());
|
|
80
80
|
const linkedArgs = collectValuesFromLinks(args, { dataflow, config, ctx: data.analyzer.inspectContext() }, linkedIds);
|
|
81
81
|
const linked = dropInfoOnLinkedIds(linkedIds);
|
|
82
|
+
function ignoreOnArgVal() {
|
|
83
|
+
if (info.ignoreIf === 'arg-true' || info.ignoreIf === 'arg-false') {
|
|
84
|
+
const margs = info.additionalArgs?.val;
|
|
85
|
+
(0, assert_1.guard)(margs, 'Need additional argument val when checking for arg-true');
|
|
86
|
+
const valArgs = (0, resolve_argument_1.getArgumentStringValue)(config.solver.variables, dataflow.graph, vertex, margs.argIdx, margs.argName, margs.resolveValue, data?.analyzer.inspectContext());
|
|
87
|
+
const valValues = valArgs?.values().flatMap(v => Array.from(v)).toArray() ?? [];
|
|
88
|
+
if (valValues.length === 0) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
if (info.ignoreIf === 'arg-true' && valValues.every(v => v === 'TRUE')) {
|
|
92
|
+
// all values are TRUE, so we can ignore this
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
else if (info.ignoreIf === 'arg-false' && valValues.every(v => v === 'FALSE')) {
|
|
96
|
+
// all values are FALSE, so we can ignore this
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
82
102
|
const foundValues = linkedArgs ?? args;
|
|
83
103
|
if (!foundValues) {
|
|
84
104
|
if (info.ignoreIf === 'arg-missing') {
|
|
85
105
|
return [];
|
|
86
106
|
}
|
|
107
|
+
else if (ignoreOnArgVal()) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
87
110
|
const record = (0, objects_1.compactRecord)({
|
|
88
111
|
nodeId: id,
|
|
89
112
|
functionName: vertex.name,
|
|
90
113
|
lexemeOfArgument: undefined,
|
|
91
114
|
linkedIds: linked?.length ? linked : undefined,
|
|
92
|
-
value: defaultValue
|
|
115
|
+
value: info.defaultValue ?? defaultValue
|
|
93
116
|
});
|
|
94
117
|
return record ? [record] : [];
|
|
95
118
|
}
|
|
@@ -98,7 +121,7 @@ function getResults(queries, { dataflow, config, normalize }, results, kind, fun
|
|
|
98
121
|
const margs = info.additionalArgs?.mode;
|
|
99
122
|
(0, assert_1.guard)(margs, 'Need additional argument mode when checking for mode');
|
|
100
123
|
const modeArgs = (0, resolve_argument_1.getArgumentStringValue)(config.solver.variables, dataflow.graph, vertex, margs.argIdx, margs.argName, margs.resolveValue, data?.analyzer.inspectContext());
|
|
101
|
-
const modeValues = modeArgs?.values().flatMap(v =>
|
|
124
|
+
const modeValues = modeArgs?.values().flatMap(v => Array.from(v)) ?? [];
|
|
102
125
|
if (info.ignoreIf === 'mode-only-read' && modeValues.every(m => m && readOnlyModes.has(m))) {
|
|
103
126
|
// all modes are read-only, so we can ignore this
|
|
104
127
|
return [];
|
|
@@ -108,6 +131,9 @@ function getResults(queries, { dataflow, config, normalize }, results, kind, fun
|
|
|
108
131
|
return [];
|
|
109
132
|
}
|
|
110
133
|
}
|
|
134
|
+
else if (ignoreOnArgVal()) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
111
137
|
const results = [];
|
|
112
138
|
for (const [arg, values] of foundValues.entries()) {
|
|
113
139
|
for (const value of values) {
|
|
@@ -117,7 +143,7 @@ function getResults(queries, { dataflow, config, normalize }, results, kind, fun
|
|
|
117
143
|
functionName: vertex.name,
|
|
118
144
|
lexemeOfArgument: getLexeme(value, arg),
|
|
119
145
|
linkedIds: linked?.length ? linked : undefined,
|
|
120
|
-
value: value ?? defaultValue,
|
|
146
|
+
value: value ?? info.defaultValue ?? defaultValue,
|
|
121
147
|
versionConstraints: dep?.versionConstraints,
|
|
122
148
|
derivedVersion: dep?.derivedVersion,
|
|
123
149
|
namespaceInfo: dep?.namespaceInfo
|
|
@@ -11,6 +11,7 @@ export declare const Unknown = "unknown";
|
|
|
11
11
|
export interface DependencyCategorySettings {
|
|
12
12
|
queryDisplayName?: string;
|
|
13
13
|
functions: FunctionInfo[];
|
|
14
|
+
/** this describes the global default value for this category, e.g., 'stdout' for write operations, please be aware, that this can be overwritten by a by-function default value */
|
|
14
15
|
defaultValue?: string;
|
|
15
16
|
additionalAnalysis?: (data: BasicQueryData, ignoreDefault: boolean, functions: FunctionInfo[], queryResults: CallContextQueryResult, result: DependencyInfo[]) => AsyncOrSync<void>;
|
|
16
17
|
}
|
|
@@ -18,11 +18,18 @@ export interface FunctionArgInfo {
|
|
|
18
18
|
argName?: string;
|
|
19
19
|
resolveValue?: boolean | 'library';
|
|
20
20
|
}
|
|
21
|
+
/** Describes a function that may create a dependency */
|
|
21
22
|
export interface FunctionInfo extends FunctionArgInfo {
|
|
23
|
+
/** Which package does the function belong to */
|
|
22
24
|
package?: string;
|
|
25
|
+
/** The name of the function */
|
|
23
26
|
name: string;
|
|
27
|
+
/** links to other function calls to get the dependency from there (e.g., with `sink` for `print`) */
|
|
24
28
|
linkTo?: DependencyInfoLink[];
|
|
25
|
-
|
|
29
|
+
/** default value for the argument if no binding value is found, please be aware, that categories can define global defaults, these are overwritten by the per-function defaults */
|
|
30
|
+
defaultValue?: string;
|
|
31
|
+
/** the function is not to be counted as a dependency if the argument is missing */
|
|
32
|
+
ignoreIf?: 'arg-missing' | 'mode-only-read' | 'mode-only-write' | 'arg-true' | 'arg-false';
|
|
26
33
|
/** additional info on arguments - e.g. for the mode flag */
|
|
27
34
|
additionalArgs?: Record<string, FunctionArgInfo>;
|
|
28
35
|
}
|
|
@@ -14,6 +14,19 @@ exports.WriteFunctions = [
|
|
|
14
14
|
{ package: 'utils', name: 'write.table', argIdx: 1, argName: 'file', resolveValue: true },
|
|
15
15
|
{ package: 'utils', name: 'write.csv', argIdx: 1, argName: 'file', resolveValue: true },
|
|
16
16
|
{ package: 'base', name: 'saveRDS', argIdx: 1, argName: 'file', resolveValue: true },
|
|
17
|
+
{
|
|
18
|
+
package: 'base',
|
|
19
|
+
name: 'try',
|
|
20
|
+
linkTo: OutputRedirects,
|
|
21
|
+
argIdx: 2,
|
|
22
|
+
argName: 'outFile',
|
|
23
|
+
resolveValue: true,
|
|
24
|
+
defaultValue: 'stderr',
|
|
25
|
+
ignoreIf: 'arg-true',
|
|
26
|
+
additionalArgs: {
|
|
27
|
+
val: { argIdx: 1, argName: 'silent' }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
17
30
|
// write functions that don't have argIndex are assumed to write to stdout
|
|
18
31
|
{ package: 'base', name: 'print', linkTo: OutputRedirects, resolveValue: true },
|
|
19
32
|
{ package: 'base', name: 'cat', linkTo: OutputRedirects, argName: 'file', resolveValue: true },
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DoesCallQuery, DoesCallQueryResult } from './does-call-query-format';
|
|
2
|
+
import type { BasicQueryData } from '../../base-query-format';
|
|
3
|
+
/**
|
|
4
|
+
* Execute does call queries on the given analyzer.
|
|
5
|
+
*/
|
|
6
|
+
export declare function executeDoesCallQuery({ analyzer }: BasicQueryData, queries: readonly DoesCallQuery[]): Promise<DoesCallQueryResult>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeDoesCallQuery = executeDoesCallQuery;
|
|
4
|
+
const log_1 = require("../../../util/log");
|
|
5
|
+
const parse_1 = require("../../../slicing/criterion/parse");
|
|
6
|
+
const built_in_1 = require("../../../dataflow/environments/built-in");
|
|
7
|
+
/**
|
|
8
|
+
* Execute does call queries on the given analyzer.
|
|
9
|
+
*/
|
|
10
|
+
async function executeDoesCallQuery({ analyzer }, queries) {
|
|
11
|
+
const start = Date.now();
|
|
12
|
+
const cg = await analyzer.callGraph();
|
|
13
|
+
const idMap = (await analyzer.normalize()).idMap;
|
|
14
|
+
const results = {};
|
|
15
|
+
for (const query of queries) {
|
|
16
|
+
const id = query.queryId ?? JSON.stringify(query);
|
|
17
|
+
if (id in results) {
|
|
18
|
+
log_1.log.warn(`Duplicate query id '${id}' in does-call queries, SKIP.`);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const nodeId = (0, parse_1.tryResolveSliceCriterionToId)(query.call, idMap);
|
|
22
|
+
if (!nodeId) {
|
|
23
|
+
results[id] = false;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const c = makeCallMatcher(query.calls);
|
|
27
|
+
results[id] = findCallersMatchingConstraints(cg, nodeId, c);
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
'.meta': {
|
|
31
|
+
timing: Date.now() - start
|
|
32
|
+
},
|
|
33
|
+
results
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function makeCallMatcher(constraint) {
|
|
37
|
+
switch (constraint.type) {
|
|
38
|
+
case 'calls-id':
|
|
39
|
+
return (vtx) => vtx.id === constraint.id;
|
|
40
|
+
case 'name':
|
|
41
|
+
if (constraint.nameExact) {
|
|
42
|
+
return (vtx) => vtx.name === constraint.name;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const regex = new RegExp(constraint.name);
|
|
46
|
+
return (vtx) => 'name' in vtx && vtx.name ? regex.test(vtx.name) : false;
|
|
47
|
+
}
|
|
48
|
+
case 'and': {
|
|
49
|
+
let matchersAndRemain = constraint.calls.map(makeCallMatcher);
|
|
50
|
+
return (vtx, cg) => {
|
|
51
|
+
const matchersToRemove = [];
|
|
52
|
+
for (const matcher of matchersAndRemain) {
|
|
53
|
+
if (matcher(vtx, cg)) {
|
|
54
|
+
matchersToRemove.push(matcher);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
matchersAndRemain = matchersAndRemain.filter(m => !matchersToRemove.includes(m));
|
|
58
|
+
return matchersAndRemain.length === 0;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
case 'or': {
|
|
62
|
+
const matchersOr = constraint.calls.map(makeCallMatcher);
|
|
63
|
+
return (vtx, cg) => matchersOr.some(m => m(vtx, cg));
|
|
64
|
+
}
|
|
65
|
+
default: {
|
|
66
|
+
throw new Error(`Unhandled constraint type ${JSON.stringify(constraint)}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function findCallersMatchingConstraints(cg, start, constraints) {
|
|
71
|
+
const visited = new Set();
|
|
72
|
+
const toVisit = [start];
|
|
73
|
+
while (toVisit.length > 0) {
|
|
74
|
+
const cur = toVisit.pop();
|
|
75
|
+
if (visited.has(cur)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
visited.add(cur);
|
|
79
|
+
if ((0, built_in_1.isBuiltIn)(cur)) {
|
|
80
|
+
const name = (0, built_in_1.dropBuiltInPrefix)(cur);
|
|
81
|
+
if (constraints({ id: cur, name }, cg)) {
|
|
82
|
+
return { call: start };
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const vtx = cg.getVertex(cur);
|
|
87
|
+
if (!vtx) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
// check if matches
|
|
91
|
+
if (constraints(vtx, cg)) {
|
|
92
|
+
return { call: start };
|
|
93
|
+
}
|
|
94
|
+
for (const out of cg.outgoingEdges(cur) ?? []) {
|
|
95
|
+
toVisit.push(out[0]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=does-call-query-executor.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
|
|
2
|
+
import Joi from 'joi';
|
|
3
|
+
import type { ParsedQueryLine } from '../../query';
|
|
4
|
+
import { executeDoesCallQuery } from './does-call-query-executor';
|
|
5
|
+
import { type NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
6
|
+
import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
|
|
7
|
+
import type { ReplOutput } from '../../../cli/repl/commands/repl-main';
|
|
8
|
+
import type { FlowrConfigOptions } from '../../../config';
|
|
9
|
+
interface CallsIdConstraint {
|
|
10
|
+
readonly type: 'calls-id';
|
|
11
|
+
/** The id of the function being called. */
|
|
12
|
+
readonly id: NodeId;
|
|
13
|
+
}
|
|
14
|
+
interface CallsWithNameConstraint {
|
|
15
|
+
readonly type: 'name';
|
|
16
|
+
/** The name of the function being called. */
|
|
17
|
+
readonly name: string;
|
|
18
|
+
/** Should we match the name exactly, or as a regex? */
|
|
19
|
+
readonly nameExact?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface CallsConstraints {
|
|
22
|
+
readonly type: 'and' | 'or' | 'one-of';
|
|
23
|
+
readonly calls: readonly CallsConstraint[];
|
|
24
|
+
}
|
|
25
|
+
export type CallsConstraint = CallsIdConstraint | CallsWithNameConstraint | CallsConstraints;
|
|
26
|
+
/**
|
|
27
|
+
* Either checks whether a given function calls another function matching the given constraints,
|
|
28
|
+
* or returns all functions that call any function matching the given constraints.
|
|
29
|
+
*/
|
|
30
|
+
export interface DoesCallQuery extends BaseQueryFormat {
|
|
31
|
+
readonly type: 'does-call';
|
|
32
|
+
readonly queryId?: string;
|
|
33
|
+
readonly call: SingleSlicingCriterion;
|
|
34
|
+
readonly calls: CallsConstraint;
|
|
35
|
+
}
|
|
36
|
+
export interface FindAllCallsResult {
|
|
37
|
+
readonly call: NodeId;
|
|
38
|
+
}
|
|
39
|
+
export interface DoesCallQueryResult extends BaseQueryResult {
|
|
40
|
+
/** Results are either false (does not call) or an object with details on the calls made */
|
|
41
|
+
readonly results: Record<string, FindAllCallsResult | false>;
|
|
42
|
+
}
|
|
43
|
+
declare function doesCallQueryLineParser(output: ReplOutput, line: readonly string[], _config: FlowrConfigOptions): ParsedQueryLine<'does-call'>;
|
|
44
|
+
export declare const DoesCallQueryDefinition: {
|
|
45
|
+
readonly executor: typeof executeDoesCallQuery;
|
|
46
|
+
readonly asciiSummarizer: (formatter: import("../../../util/text/ansi").OutputFormatter, processed: import("../../../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider<import("../../../r-bridge/parser").KnownParser>, queryResults: BaseQueryResult, result: string[]) => Promise<boolean>;
|
|
47
|
+
readonly fromLine: typeof doesCallQueryLineParser;
|
|
48
|
+
readonly schema: Joi.ObjectSchema<any>;
|
|
49
|
+
readonly flattenInvolvedNodes: (queryResults: BaseQueryResult) => NodeId[];
|
|
50
|
+
};
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DoesCallQueryDefinition = void 0;
|
|
7
|
+
const ansi_1 = require("../../../util/text/ansi");
|
|
8
|
+
const joi_1 = __importDefault(require("joi"));
|
|
9
|
+
const does_call_query_executor_1 = require("./does-call-query-executor");
|
|
10
|
+
const dfg_1 = require("../../../util/mermaid/dfg");
|
|
11
|
+
const args_1 = require("../../../util/text/args");
|
|
12
|
+
const strings_1 = require("../../../util/text/strings");
|
|
13
|
+
const FormatError = 'Invalid constraint format, expected format "(left:$id/"regex")"';
|
|
14
|
+
/**
|
|
15
|
+
* Parses a constraint from a string argument.
|
|
16
|
+
* Returns the constraint or an error message.
|
|
17
|
+
*/
|
|
18
|
+
function constraintParser(argument) {
|
|
19
|
+
if (!argument?.startsWith('(') || !argument.includes(')')) {
|
|
20
|
+
return FormatError + ` (got: "${argument}")`;
|
|
21
|
+
}
|
|
22
|
+
const endBracket = argument.indexOf(')');
|
|
23
|
+
const constrPart = argument.slice(1, endBracket);
|
|
24
|
+
const args = (0, args_1.splitAtEscapeSensitive)(constrPart, true, ':');
|
|
25
|
+
if (args.length !== 2) {
|
|
26
|
+
return FormatError + ` (got ${args.length} parts: ${args.join(', ')})`;
|
|
27
|
+
}
|
|
28
|
+
const [criteria, ...rhs] = args;
|
|
29
|
+
const rhsStr = rhs.join(' ');
|
|
30
|
+
if (rhsStr.startsWith('$')) {
|
|
31
|
+
return {
|
|
32
|
+
call: criteria,
|
|
33
|
+
constraint: {
|
|
34
|
+
type: 'calls-id',
|
|
35
|
+
id: rhsStr.slice(1),
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const isExact = (0, strings_1.startAndEndsWith)(rhsStr, '"');
|
|
41
|
+
const name = isExact ? rhsStr.slice(1, -1) : rhsStr;
|
|
42
|
+
return {
|
|
43
|
+
call: criteria,
|
|
44
|
+
constraint: {
|
|
45
|
+
type: 'name',
|
|
46
|
+
name: name,
|
|
47
|
+
nameExact: isExact ? true : undefined,
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function doesCallQueryLineParser(output, line, _config) {
|
|
53
|
+
const constraint = constraintParser(line[0]);
|
|
54
|
+
if (!constraint || typeof constraint === 'string') {
|
|
55
|
+
output.stderr(output.formatter.format(`Invalid does-call query format:\n ${constraint}`, { color: 1 /* Colors.Red */, effect: ansi_1.ColorEffect.Foreground, style: 1 /* FontStyles.Bold */ }));
|
|
56
|
+
return { query: [] };
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
query: [
|
|
60
|
+
{
|
|
61
|
+
type: 'does-call',
|
|
62
|
+
queryId: constraint.call + ' (shorthand)',
|
|
63
|
+
call: constraint.call,
|
|
64
|
+
calls: constraint.constraint,
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
rCode: line[1]
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
exports.DoesCallQueryDefinition = {
|
|
71
|
+
executor: does_call_query_executor_1.executeDoesCallQuery,
|
|
72
|
+
asciiSummarizer: async (formatter, processed, queryResults, result) => {
|
|
73
|
+
const out = queryResults;
|
|
74
|
+
result.push(`Query: ${(0, ansi_1.bold)('does-call', formatter)} (${out['.meta'].timing.toFixed(0)}ms)`);
|
|
75
|
+
for (const [r, v] of Object.entries(out.results)) {
|
|
76
|
+
const idMap = (await processed.normalize()).idMap;
|
|
77
|
+
result.push(` - ${(0, ansi_1.bold)(r, formatter)} found:`);
|
|
78
|
+
if (v === false) {
|
|
79
|
+
result.push(' - Does not call any matching functions.');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const loc = idMap.get(v.call)?.location ?? undefined;
|
|
83
|
+
result.push(` - Call with id ${(0, ansi_1.bold)(String(v.call), formatter)} (${(0, dfg_1.formatRange)(loc)})`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
},
|
|
88
|
+
fromLine: doesCallQueryLineParser,
|
|
89
|
+
schema: joi_1.default.object({
|
|
90
|
+
type: joi_1.default.string().valid('does-call').required().description('The type of the query.'),
|
|
91
|
+
queryId: joi_1.default.string().optional().description('An optional unique identifier for this query, to identify it in the output.'),
|
|
92
|
+
call: joi_1.default.string().description('The function from which calls are being made. This is a slicing criterion that resolves to a function definition node.'),
|
|
93
|
+
calls: joi_1.default.object().required().description('The constraints on which functions are being called. This can be a combination of name-based or id-based constraints, combined with logical operators (and, or, one-of).')
|
|
94
|
+
}).description('Either returns all function definitions alongside whether they are recursive, or just those matching the filters.'),
|
|
95
|
+
flattenInvolvedNodes: (queryResults) => {
|
|
96
|
+
const out = queryResults;
|
|
97
|
+
return Object.entries(out.results).flatMap(([, v]) => {
|
|
98
|
+
return v !== false ? v.call : [];
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=does-call-query-format.js.map
|
|
@@ -13,7 +13,7 @@ function executeFileQuery({ analyzer }, queries) {
|
|
|
13
13
|
for (const query of queries) {
|
|
14
14
|
if (query.matchesPathRegex === undefined && query.roles === undefined) {
|
|
15
15
|
files = base.map(l => ({
|
|
16
|
-
|
|
16
|
+
roles: l.roles,
|
|
17
17
|
content: l.content(),
|
|
18
18
|
path: l.path()
|
|
19
19
|
}));
|
|
@@ -21,19 +21,19 @@ function executeFileQuery({ analyzer }, queries) {
|
|
|
21
21
|
}
|
|
22
22
|
const pathRegex = query.matchesPathRegex ? new RegExp(query.matchesPathRegex) : undefined;
|
|
23
23
|
for (const file of base) {
|
|
24
|
-
const fingerprint = `${file.
|
|
24
|
+
const fingerprint = `${file.roles?.join(':')}:::${file.path()}`;
|
|
25
25
|
if (foundFingerprints.has(fingerprint)) {
|
|
26
26
|
continue;
|
|
27
27
|
}
|
|
28
28
|
if (pathRegex && !pathRegex.test(file.path())) {
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
|
-
if (query.roles && !query.roles.includes(
|
|
31
|
+
if ((query.roles?.length ?? 0) > 0 && !query.roles?.every(r => file.roles?.includes(r))) {
|
|
32
32
|
continue;
|
|
33
33
|
}
|
|
34
34
|
foundFingerprints.add(fingerprint);
|
|
35
35
|
files.push({
|
|
36
|
-
|
|
36
|
+
roles: file.roles,
|
|
37
37
|
content: file.content(),
|
|
38
38
|
path: file.path()
|
|
39
39
|
});
|
|
@@ -12,11 +12,12 @@ import type { CommandCompletions } from '../../../cli/repl/core';
|
|
|
12
12
|
*/
|
|
13
13
|
export interface FilesQuery extends BaseQueryFormat {
|
|
14
14
|
readonly type: 'files';
|
|
15
|
+
/** If you provide roles, only files with all the given roles are returned. Supply multiple queries if you want a union! */
|
|
15
16
|
readonly roles?: FileRole[];
|
|
16
17
|
readonly matchesPathRegex?: string;
|
|
17
18
|
}
|
|
18
19
|
export interface FileQueryInfo<T = object> {
|
|
19
|
-
|
|
20
|
+
roles?: readonly FileRole[];
|
|
20
21
|
path: string;
|
|
21
22
|
content: T;
|
|
22
23
|
}
|
|
@@ -85,6 +85,21 @@ function filesQueryCompleter(line, startingNewArg, _config) {
|
|
|
85
85
|
}
|
|
86
86
|
return { completions: [] };
|
|
87
87
|
}
|
|
88
|
+
function guessProto(obj) {
|
|
89
|
+
if (obj === null || obj === undefined) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
else if (typeof obj !== 'object') {
|
|
93
|
+
return typeof obj;
|
|
94
|
+
}
|
|
95
|
+
else if ('prototype' in obj && obj.prototype && typeof obj.prototype === 'object') {
|
|
96
|
+
const proto = obj.prototype;
|
|
97
|
+
if (proto.constructor && typeof proto.constructor.name === 'string') {
|
|
98
|
+
return proto.constructor.name;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
88
103
|
exports.FilesQueryDefinition = {
|
|
89
104
|
executor: files_query_executor_1.executeFileQuery,
|
|
90
105
|
asciiSummarizer: (formatter, _analyzer, queryResults, result) => {
|
|
@@ -92,8 +107,9 @@ exports.FilesQueryDefinition = {
|
|
|
92
107
|
result.push(`Query: ${(0, ansi_1.bold)('files', formatter)} (${out['.meta'].timing.toFixed(0)}ms)`);
|
|
93
108
|
result.push(` ╰ Found ${out.files.length} file${out.files.length === 1 ? '' : 's'}`);
|
|
94
109
|
for (const f of out.files) {
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
const nam = guessProto(f.content);
|
|
111
|
+
result.push(` ╰ ${(0, ansi_1.bold)(f.path, formatter)}${nam ? ' ' + formatter.format(nam, { effect: ansi_1.ColorEffect.Foreground, color: 7 /* Colors.White */ }) : ''}${f.roles ? ` [role: ${f.roles.join(', ')}]` : ''}:`);
|
|
112
|
+
const summary = summarizeObjectWithLimit(f.content, 250);
|
|
97
113
|
for (const line of summary.split('\n')) {
|
|
98
114
|
result.push(` ${line}`);
|
|
99
115
|
}
|
|
@@ -9,12 +9,13 @@ async function executeIdMapQuery({ analyzer }, queries) {
|
|
|
9
9
|
if (queries.length !== 1) {
|
|
10
10
|
log_1.log.warn('Id-Map query expects only up to one query, but got', queries.length);
|
|
11
11
|
}
|
|
12
|
+
const startTime = Date.now();
|
|
13
|
+
const idMap = (await analyzer.normalize()).idMap;
|
|
12
14
|
return {
|
|
13
15
|
'.meta': {
|
|
14
|
-
|
|
15
|
-
timing: 0
|
|
16
|
+
timing: Date.now() - startTime
|
|
16
17
|
},
|
|
17
|
-
idMap
|
|
18
|
+
idMap
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
//# sourceMappingURL=id-map-query-executor.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { InspectExceptionQuery, InspectExceptionQueryResult } from './inspect-exception-query-format';
|
|
2
|
+
import type { BasicQueryData } from '../../base-query-format';
|
|
3
|
+
import { type SingleSlicingCriterion } from '../../../slicing/criterion/parse';
|
|
4
|
+
import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
5
|
+
import type { ReadonlyFlowrAnalysisProvider } from '../../../project/flowr-analyzer';
|
|
6
|
+
/**
|
|
7
|
+
* Get the functions to consider in the call graph based on the given queries.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getFunctionsToConsiderInCallGraph(queries: readonly {
|
|
10
|
+
filter?: readonly SingleSlicingCriterion[];
|
|
11
|
+
}[], analyzer: ReadonlyFlowrAnalysisProvider, onlyDefinitions?: boolean): Promise<{
|
|
12
|
+
cg: import("../../../dataflow/graph/call-graph").CallGraph;
|
|
13
|
+
fns: IteratorObject<[NodeId, Required<import("../../../dataflow/graph/vertex").DataflowGraphVertexFunctionCall | import("../../../dataflow/graph/vertex").DataflowGraphVertexFunctionDefinition>], undefined, unknown>;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Execute exception function inspection queries on the given analyzer.
|
|
17
|
+
*/
|
|
18
|
+
export declare function executeExceptionQuery({ analyzer }: BasicQueryData, queries: readonly InspectExceptionQuery[]): Promise<InspectExceptionQueryResult>;
|