@eagleoutice/flowr 2.8.12 → 2.8.13

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.
Files changed (38) hide show
  1. package/README.md +23 -22
  2. package/control-flow/simple-visitor.js +3 -1
  3. package/dataflow/environments/default-builtin-config.d.ts +1 -1
  4. package/dataflow/environments/default-builtin-config.js +1 -1
  5. package/dataflow/extractor.js +1 -1
  6. package/dataflow/graph/graph.d.ts +1 -14
  7. package/dataflow/graph/graph.js +1 -10
  8. package/dataflow/internal/linker.d.ts +12 -0
  9. package/dataflow/internal/linker.js +24 -11
  10. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +5 -4
  11. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +3 -2
  12. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +7 -4
  13. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +16 -10
  14. package/dataflow/internal/process/functions/call/built-in/built-in-get.js +1 -1
  15. package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.js +3 -2
  16. package/dataflow/internal/process/functions/process-argument.js +2 -1
  17. package/dataflow/internal/process/functions/process-parameter.js +4 -3
  18. package/documentation/wiki-query.js +2 -3
  19. package/package.json +1 -1
  20. package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
  21. package/queries/catalog/call-context-query/call-context-query-executor.js +4 -3
  22. package/queries/catalog/call-context-query/call-context-query-format.d.ts +21 -1
  23. package/queries/catalog/call-context-query/call-context-query-format.js +15 -7
  24. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +11 -3
  25. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +14 -1
  26. package/queries/catalog/call-context-query/identify-link-to-nested-call-relation.d.ts +12 -0
  27. package/queries/catalog/call-context-query/identify-link-to-nested-call-relation.js +30 -0
  28. package/queries/catalog/call-context-query/identify-link-to-relation.d.ts +10 -0
  29. package/queries/catalog/call-context-query/identify-link-to-relation.js +21 -0
  30. package/queries/catalog/dependencies-query/dependencies-query-format.js +1 -1
  31. package/queries/catalog/dependencies-query/function-info/test-functions.js +146 -12
  32. package/queries/query.js +1 -1
  33. package/search/search-executor/search-enrichers.d.ts +8 -40
  34. package/search/search-executor/search-enrichers.js +17 -13
  35. package/search/search-executor/search-generators.js +5 -7
  36. package/search/search-executor/search-transformer.js +1 -7
  37. package/util/schema.js +6 -8
  38. package/util/version.js +1 -1
@@ -47,6 +47,7 @@ export type CallNameTypes = RegExp | string | string[];
47
47
  * This way, you can link a call like `points` to the latest graphics plot etc.
48
48
  * For now, this uses the static Control-Flow-Graph produced by flowR as the FD over-approximation is still not stable (see #1005).
49
49
  * In short, this means that we are unable to detect origins over function call boundaries but plan on being more precise in the future.
50
+ * @see LinkToNestedCall
50
51
  */
51
52
  export interface LinkToLastCall<CallName extends CallNameTypes = CallNameTypes> extends BaseQueryFormat {
52
53
  readonly type: 'link-to-last-call';
@@ -63,7 +64,26 @@ export interface LinkToLastCall<CallName extends CallNameTypes = CallNameTypes>
63
64
  */
64
65
  readonly cascadeIf?: (target: DataflowGraphVertexInfo, from: NodeId, graph: DataflowGraph) => CascadeAction;
65
66
  }
66
- export type LinkTo<CallName extends CallNameTypes = CallNameTypes, AttachLinkInfo = NoInfo> = (LinkToLastCall<CallName>) & {
67
+ /**
68
+ * Allows to link nested calls to their parent calls.
69
+ * This way, you can link an `assert_equal` call to the parent `test_that` call etc:
70
+ * ```r
71
+ * test_that("my test", {
72
+ * assert_equal(1 + 1, 2)
73
+ * })
74
+ * ```
75
+ */
76
+ export interface LinkToNestedCall<CallName extends CallNameTypes = CallNameTypes> extends BaseQueryFormat {
77
+ readonly type: 'link-to-nested-call';
78
+ /** Regex regarding the function name of the last call. Similar to {@link DefaultCallContextQueryFormat#callName}, strings are interpreted as a `RegExp`. */
79
+ readonly callName: CallName;
80
+ /**
81
+ * Should we ignore this (source) call?
82
+ * Currently, there is no well working serialization for this.
83
+ */
84
+ readonly ignoreIf?: (id: NodeId, graph: DataflowGraph) => boolean;
85
+ }
86
+ export type LinkTo<CallName extends CallNameTypes = CallNameTypes, AttachLinkInfo = NoInfo> = (LinkToLastCall<CallName> | LinkToNestedCall<CallName>) & {
67
87
  attachLinkInfo?: AttachLinkInfo;
68
88
  };
69
89
  export interface SubCallContextQueryFormat<CallName extends CallNameTypes = CallNameTypes, AttachLinkInfo = NoInfo> extends DefaultCallContextQueryFormat<CallName> {
@@ -10,13 +10,21 @@ const time_1 = require("../../../util/text/time");
10
10
  const joi_1 = __importDefault(require("joi"));
11
11
  const query_print_1 = require("../../query-print");
12
12
  const identify_link_to_last_call_relation_1 = require("./identify-link-to-last-call-relation");
13
- const CallContextQueryLinkTo = joi_1.default.object({
14
- type: joi_1.default.string().valid('link-to-last-call').required().description('The type of the linkTo sub-query.'),
15
- callName: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().items(joi_1.default.string())).required().description('Test regarding the function name of the last call. Similar to `callName`, strings are interpreted as a regular expression, and string arrays are checked for containment.'),
16
- ignoreIf: joi_1.default.function().optional().description('Should we ignore this (source) call? Currently, there is no well working serialization for this.'),
17
- cascadeIf: joi_1.default.function().optional().description('Should we continue searching after the link was created? Currently, there is no well working serialization for this.'),
18
- attachLinkInfo: joi_1.default.object().optional().description('Additional information to attach to the link.')
19
- });
13
+ const CallContextQueryLinkTo = joi_1.default.alternatives([
14
+ joi_1.default.object({
15
+ type: joi_1.default.string().valid('link-to-last-call').required().description('The type of the linkTo sub-query.'),
16
+ callName: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().items(joi_1.default.string())).required().description('Test regarding the function name of the last call. Similar to `callName`, strings are interpreted as a regular expression, and string arrays are checked for containment.'),
17
+ ignoreIf: joi_1.default.function().optional().description('Should we ignore this (source) call? Currently, there is no well working serialization for this.'),
18
+ cascadeIf: joi_1.default.function().optional().description('Should we continue searching after the link was created? Currently, there is no well working serialization for this.'),
19
+ attachLinkInfo: joi_1.default.object().optional().description('Additional information to attach to the link.')
20
+ }).description('Links the current call to the last call of the given kind. This way, you can link a call like `points` to the latest graphics plot etc.'),
21
+ joi_1.default.object({
22
+ type: joi_1.default.string().valid('link-to-nested-call').required().description('The type of the linkTo sub-query.'),
23
+ callName: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().items(joi_1.default.string())).required().description('Test regarding the function name of the last call. Similar to `callName`, strings are interpreted as a regular expression, and string arrays are checked for containment.'),
24
+ ignoreIf: joi_1.default.function().optional().description('Should we ignore this (source) call? Currently, there is no well working serialization for this.'),
25
+ attachLinkInfo: joi_1.default.object().optional().description('Additional information to attach to the link.')
26
+ }).description('Allows to link nested calls to their parent calls. This way, you can link an `assert_equal` call to the parent `test_that` call etc.')
27
+ ]);
20
28
  exports.CallContextQueryDefinition = {
21
29
  executor: call_context_query_executor_1.executeCallContextQueries,
22
30
  asciiSummarizer: async (formatter, analyzer, queryResults, result) => {
@@ -3,9 +3,10 @@ import { type DataflowGraph } from '../../../dataflow/graph/graph';
3
3
  import { type DataflowGraphVertexFunctionCall } from '../../../dataflow/graph/vertex';
4
4
  import { RType } from '../../../r-bridge/lang-4.x/ast/model/type';
5
5
  import type { RNodeWithParent } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
6
- import type { LinkTo } from './call-context-query-format';
7
- import type { ControlFlowGraph } from '../../../control-flow/control-flow-graph';
6
+ import type { LinkToLastCall } from './call-context-query-format';
8
7
  import type { PromotedLinkTo } from './call-context-query-executor';
8
+ import type { ReadonlyFlowrAnalysisProvider } from '../../../project/flowr-analyzer';
9
+ import type { ControlFlowGraph } from '../../../control-flow/control-flow-graph';
9
10
  export declare enum CallTargets {
10
11
  /** call targets a function that is not defined locally in the script (e.g., the call targets a library function) */
11
12
  OnlyGlobal = "global",
@@ -32,9 +33,16 @@ export declare function getValueOfArgument<Types extends readonly RType[] = read
32
33
  type: Types[number];
33
34
  }) | undefined;
34
35
  /**
36
+ * **Please refer to {@link identifyLinkToRelation}.**
37
+ *
35
38
  * Identifies nodes that link to the last call of a specified function from a given starting node in the control flow graph.
36
39
  * If you pass on `knownCalls` (e.g., produced by {@link getCallsInCfg}), this will only respect the functions
37
40
  * listed there and ignore any other calls. This can be also used to speed up the process if you already have
38
41
  * the known calls available.
42
+ * @see {@link identifyLinkToLastCallRelationSync} for the synchronous version.
43
+ */
44
+ export declare function identifyLinkToLastCallRelation(from: NodeId, analyzer: ReadonlyFlowrAnalysisProvider, l: LinkToLastCall<RegExp> | PromotedLinkTo<LinkToLastCall<RegExp>>, knownCalls?: Map<NodeId, Required<DataflowGraphVertexFunctionCall>>): Promise<NodeId[]>;
45
+ /**
46
+ * Synchronous version of {@link identifyLinkToLastCallRelation}.
39
47
  */
40
- export declare function identifyLinkToLastCallRelation(from: NodeId, cfg: ControlFlowGraph, graph: DataflowGraph, { callName, ignoreIf, cascadeIf }: LinkTo<RegExp> | PromotedLinkTo, knownCalls?: Map<NodeId, Required<DataflowGraphVertexFunctionCall>>): NodeId[];
48
+ export declare function identifyLinkToLastCallRelationSync(from: NodeId, cfg: ControlFlowGraph, graph: DataflowGraph, { callName, cascadeIf, ignoreIf }: LinkToLastCall<RegExp> | PromotedLinkTo<LinkToLastCall<RegExp>>, knownCalls?: Map<NodeId, Required<DataflowGraphVertexFunctionCall>>): NodeId[];
@@ -4,6 +4,7 @@ exports.CallTargets = void 0;
4
4
  exports.satisfiesCallTargets = satisfiesCallTargets;
5
5
  exports.getValueOfArgument = getValueOfArgument;
6
6
  exports.identifyLinkToLastCallRelation = identifyLinkToLastCallRelation;
7
+ exports.identifyLinkToLastCallRelationSync = identifyLinkToLastCallRelationSync;
7
8
  const graph_1 = require("../../../dataflow/graph/graph");
8
9
  const simple_visitor_1 = require("../../../control-flow/simple-visitor");
9
10
  const vertex_1 = require("../../../dataflow/graph/vertex");
@@ -15,6 +16,7 @@ const assert_1 = require("../../../util/assert");
15
16
  const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
16
17
  const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
17
18
  const cascade_action_1 = require("./cascade-action");
19
+ const cfg_kind_1 = require("../../../project/cfg-kind");
18
20
  var CallTargets;
19
21
  (function (CallTargets) {
20
22
  /** call targets a function that is not defined locally in the script (e.g., the call targets a library function) */
@@ -111,12 +113,23 @@ function getValueOfArgument(graph, call, argument, additionalAllowedTypes) {
111
113
  }
112
114
  }
113
115
  /**
116
+ * **Please refer to {@link identifyLinkToRelation}.**
117
+ *
114
118
  * Identifies nodes that link to the last call of a specified function from a given starting node in the control flow graph.
115
119
  * If you pass on `knownCalls` (e.g., produced by {@link getCallsInCfg}), this will only respect the functions
116
120
  * listed there and ignore any other calls. This can be also used to speed up the process if you already have
117
121
  * the known calls available.
122
+ * @see {@link identifyLinkToLastCallRelationSync} for the synchronous version.
118
123
  */
119
- function identifyLinkToLastCallRelation(from, cfg, graph, { callName, ignoreIf, cascadeIf }, knownCalls) {
124
+ async function identifyLinkToLastCallRelation(from, analyzer, l, knownCalls) {
125
+ const graph = (await analyzer.dataflow()).graph;
126
+ const cfg = (await analyzer.controlflow([], cfg_kind_1.CfgKind.WithDataflow)).graph;
127
+ return identifyLinkToLastCallRelationSync(from, cfg, graph, l, knownCalls);
128
+ }
129
+ /**
130
+ * Synchronous version of {@link identifyLinkToLastCallRelation}.
131
+ */
132
+ function identifyLinkToLastCallRelationSync(from, cfg, graph, { callName, cascadeIf, ignoreIf }, knownCalls) {
120
133
  if (ignoreIf?.(from, graph)) {
121
134
  return [];
122
135
  }
@@ -0,0 +1,12 @@
1
+ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
2
+ import type { LinkToNestedCall } from './call-context-query-format';
3
+ import type { PromotedLinkTo } from './call-context-query-executor';
4
+ import type { ReadonlyFlowrAnalysisProvider } from '../../../project/flowr-analyzer';
5
+ /**
6
+ * **Please refer to {@link identifyLinkToRelation}.**
7
+ *
8
+ * Links to the nested call context of the current function call.
9
+ * This is useful for identifying calls made within nested functions
10
+ * that should be associated with their parent function's call context.
11
+ */
12
+ export declare function identifyLinkToNestedRelation(from: NodeId, analyzer: ReadonlyFlowrAnalysisProvider, { callName, ignoreIf }: LinkToNestedCall<RegExp> | PromotedLinkTo<LinkToNestedCall<RegExp>>): Promise<NodeId[]>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.identifyLinkToNestedRelation = identifyLinkToNestedRelation;
4
+ const call_graph_1 = require("../../../dataflow/graph/call-graph");
5
+ /**
6
+ * **Please refer to {@link identifyLinkToRelation}.**
7
+ *
8
+ * Links to the nested call context of the current function call.
9
+ * This is useful for identifying calls made within nested functions
10
+ * that should be associated with their parent function's call context.
11
+ */
12
+ async function identifyLinkToNestedRelation(from, analyzer, { callName, ignoreIf }) {
13
+ const df = await analyzer.dataflow();
14
+ if (ignoreIf?.(from, df.graph)) {
15
+ return [];
16
+ }
17
+ const found = [];
18
+ const cg = await analyzer.callGraph();
19
+ const subCg = (0, call_graph_1.getSubCallGraph)(cg, new Set([from]));
20
+ for (const [, { id, name }] of subCg.vertices(true)) {
21
+ if (typeof name !== 'string') {
22
+ continue;
23
+ }
24
+ if (callName instanceof RegExp ? callName.test(name) : callName.has(name)) {
25
+ found.push(id);
26
+ }
27
+ }
28
+ return found;
29
+ }
30
+ //# sourceMappingURL=identify-link-to-nested-call-relation.js.map
@@ -0,0 +1,10 @@
1
+ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
2
+ import type { LinkTo } from './call-context-query-format';
3
+ import type { PromotedLinkTo } from './call-context-query-executor';
4
+ import type { DataflowGraphVertexFunctionCall } from '../../../dataflow/graph/vertex';
5
+ import type { ReadonlyFlowrAnalysisProvider } from '../../../project/flowr-analyzer';
6
+ /**
7
+ * This facade selects the appropriate link-to relation identification function
8
+ * based on the type of link-to relation specified.
9
+ */
10
+ export declare function identifyLinkToRelation(from: NodeId, analyzer: ReadonlyFlowrAnalysisProvider, l: LinkTo | PromotedLinkTo, knownCalls?: Map<NodeId, Required<DataflowGraphVertexFunctionCall>>): Promise<NodeId[]>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.identifyLinkToRelation = identifyLinkToRelation;
4
+ const identify_link_to_last_call_relation_1 = require("./identify-link-to-last-call-relation");
5
+ const identify_link_to_nested_call_relation_1 = require("./identify-link-to-nested-call-relation");
6
+ const assert_1 = require("../../../util/assert");
7
+ /**
8
+ * This facade selects the appropriate link-to relation identification function
9
+ * based on the type of link-to relation specified.
10
+ */
11
+ async function identifyLinkToRelation(from, analyzer, l, knownCalls) {
12
+ switch (l.type) {
13
+ case 'link-to-last-call':
14
+ return (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(from, analyzer, l, knownCalls);
15
+ case 'link-to-nested-call':
16
+ return (0, identify_link_to_nested_call_relation_1.identifyLinkToNestedRelation)(from, analyzer, l);
17
+ default:
18
+ (0, assert_1.assertUnreachable)(l);
19
+ }
20
+ }
21
+ //# sourceMappingURL=identify-link-to-relation.js.map
@@ -84,7 +84,7 @@ function printResultSection(title, infos, result) {
84
84
  }, new Map());
85
85
  for (const [functionName, infos] of grouped) {
86
86
  result.push(` ╰ \`${functionName}\``);
87
- result.push(infos.map(i => ` ╰ Node Id: ${i.nodeId}${i.value !== undefined ? `, \`${i.value}\`` : ''}${i.derivedVersion !== undefined ? `, Version: \`${i.derivedVersion.format()}\`` : ''}`).join('\n'));
87
+ result.push(infos.map(i => ` ╰ Node Id: ${i.nodeId}${i.value !== undefined ? `, \`${i.value}\`` : ''}${i.derivedVersion !== undefined ? `, Version: \`${i.derivedVersion.format()}\`` : ''}${i.linkedIds ? `, linked: [${i.linkedIds.join(', ')}]` : ''}`).join('\n'));
88
88
  }
89
89
  }
90
90
  /**
@@ -1,19 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TestFunctions = void 0;
4
+ const ExpectFunctions = {
5
+ type: 'link-to-nested-call',
6
+ callName: new RegExp(/* testthat */ '^(expect_equal|expect_identical|expect_error|expect_warning|expect_message|expect_condition|' +
7
+ 'expect_true|expect_false|expect_all_equal|expect_all_true|expect_all_false|expect_lt|expect_lte|expect_gt|expect_gte|' +
8
+ 'expect_length|expect_shape|expect_match|expect_no_match|expect_named|expect_null|expect_setequal|expect_mapequal|' +
9
+ 'expect_contains|expect_in|expect_disjoint|expect_type|expect_s3_class|expect_s4_class|expect_r6_class|expect_s7_class|' +
10
+ 'expect_vector|expect_no_error|expect_no_warning|expect_no_message|expect_no_condition|expect_invisible|expect_visible|' +
11
+ 'expect_output|expect_silent|expect_snapshot|expect_snapshot_value|expect_snapshot_file|announce_snapshot_file|' +
12
+ 'compare_file_binary|compare_file_text|snapshot_accept|snapshot_reject|snapshot_review|' +
13
+ 'fail|pass|expect_success|expect_failure|expect_snapshot_failure|show_failure|' +
14
+ /* tinytest */
15
+ 'exit_file|exit_if_not|expect_equal|expect_identical|expect_equivalent|expect_true|expect_false|expect_silent|expect_null|' +
16
+ 'expect_inherits|expect_error|expect_warning|expect_message|expect_stdout|expect_equal_to_reference|' +
17
+ 'expect_equivalent_to_reference|expect_length|expect_match|ignore|report_side_effects|' +
18
+ /* RUnit */
19
+ 'checkEquals|checkEqualsNumeric|checkIdentical|checkTrue|checkException|' +
20
+ /* checkmate */
21
+ 'assertAccess|assert_access|assertArray|assert_array|assert_atomic|assertAtomic|assert_atomic_vector|assertAtomicVector|' +
22
+ 'assert_character|assertCharacter|assert_choice|assertChoice|assert_class|assertClass|assert_complex|assertComplex|' +
23
+ 'assert_count|assertCount|assert_data_frame|assertDataFrame|assert_data_table|assertDataTable|assert_date|assertDate|' +
24
+ 'assert_directory|assertDirectory|assert_directory_exists|assertDirectoryExists|assert_disjunct|assertDisjunct|assert_double|' +
25
+ 'assertDouble|assert_environment|assertEnvironment|assert_factor|assertFactor|assert_false|assertFalse|assert_file|assertFile|' +
26
+ 'assert_file_exists|assertFileExists|assert_flag|assertFlag|assert_formula|assertFormula|assert_function|assertFunction|' +
27
+ 'assert_int|assertInt|assert_integer|assertInteger|assert_list|assertList|assert_logical|assertLogical|assert_matrix|' +
28
+ 'assertMatrix|assert_multi_class|assertMultiClass|assert_named|assertNamed|assert_names|assertNames|assert_null|assertNull|' +
29
+ 'assert_number|assertNumber|assert_numeric|assertNumeric|assert_os|assertOs|assert_path_for_output|assertPathForOutput|' +
30
+ 'assert_permutation|assertPermutation|assert_posixct|assertPOSIXct|assert_r6|assertR6|assert_raw|assertRaw|assert_scalar|' +
31
+ 'assertScalar|assert_scalar_na|assertScalarNA|assert_set_equal|assertSetEqual|assert_string|assertString|assert_subset|' +
32
+ 'assertSubset|assert_tibble|assertTibble|assert_true|assertTrue|assert_vector|assertVector' +
33
+ ')$')
34
+ };
35
+ const ContextFunctions = {
36
+ type: 'link-to-last-call',
37
+ callName: new RegExp('^(context)$')
38
+ };
4
39
  exports.TestFunctions = [
5
- { package: 'testthat', name: 'test_that' },
6
- { package: 'testthat', name: 'expect_equal' },
7
- { package: 'testthat', name: 'expect_identical' },
8
- { package: 'testthat', name: 'expect_error' },
9
- { package: 'testthat', name: 'expect_warning' },
10
- { package: 'testthat', name: 'expect_message' },
11
- { package: 'testthat', name: 'expect_condition' },
12
- { package: 'testthat', name: 'expect_true' },
13
- { package: 'testthat', name: 'expect_false' },
14
- { package: 'testthat', name: 'expect_all_equal' },
15
- { package: 'testthat', name: 'expect_all_true' },
16
- { package: 'testthat', name: 'expect_all_false' },
40
+ { package: 'testthat', name: 'test_that', argName: 'desc', argIdx: 0, resolveValue: true, linkTo: [ExpectFunctions, ContextFunctions] },
41
+ { package: 'testthat', name: 'describe', argName: 'description', argIdx: 0, resolveValue: true, linkTo: [ExpectFunctions, ContextFunctions] },
42
+ { package: 'testthat', name: 'it', argName: 'description', argIdx: 0, resolveValue: true, linkTo: [ExpectFunctions, ContextFunctions] },
43
+ /* for now we do not want to list them extra:
17
44
  { package: 'testthat', name: 'expect_lt' },
18
45
  { package: 'testthat', name: 'expect_lte' },
19
46
  { package: 'testthat', name: 'expect_gt' },
@@ -58,6 +85,7 @@ exports.TestFunctions = [
58
85
  { package: 'testthat', name: 'expect_failure' },
59
86
  { package: 'testthat', name: 'expect_snapshot_failure' },
60
87
  { package: 'testthat', name: 'show_failure' },
88
+
61
89
  { package: 'tinytest', name: 'exit_file', argName: 'msg', resolveValue: true },
62
90
  { package: 'tinytest', name: 'exit_if_not' },
63
91
  { package: 'tinytest', name: 'expect_equal', argName: 'info', resolveValue: true },
@@ -78,5 +106,111 @@ exports.TestFunctions = [
78
106
  { package: 'tinytest', name: 'expect_match', argName: 'info', resolveValue: true },
79
107
  { package: 'tinytest', name: 'ignore' },
80
108
  { package: 'tinytest', name: 'report_side_effects' },
109
+
110
+ { package: 'RUnit', name: 'checkEquals', argName: 'msg', argIdx: 2, resolveValue: true },
111
+ { package: 'RUnit', name: 'checkEqualsNumeric', argName: 'msg', argIdx: 2, resolveValue: true },
112
+ { package: 'RUnit', name: 'checkIdentical', argName: 'msg', argIdx: 2, resolveValue: true },
113
+ { package: 'RUnit', name: 'checkTrue', argName: 'msg', argIdx: 1, resolveValue: true },
114
+ { package: 'RUnit', name: 'checkException', argName: 'msg', argIdx: 1, resolveValue: true },
115
+
116
+ { package: 'checkmate', name: 'assertAccess' },
117
+ { package: 'checkmate', name: 'assert_access' },
118
+ { package: 'checkmate', name: 'assertArray' },
119
+ { package: 'checkmate', name: 'assert_array' },
120
+ { package: 'checkmate', name: 'assert_atomic' },
121
+ { package: 'checkmate', name: 'assertAtomic' },
122
+ { package: 'checkmate', name: 'assert_atomic_vector' },
123
+ { package: 'checkmate', name: 'assertAtomicVector' },
124
+ { package: 'checkmate', name: 'assert_character' },
125
+ { package: 'checkmate', name: 'assertCharacter' },
126
+ { package: 'checkmate', name: 'assert_choice' },
127
+ { package: 'checkmate', name: 'assertChoice' },
128
+ { package: 'checkmate', name: 'assert_class' },
129
+ { package: 'checkmate', name: 'assertClass' },
130
+ { package: 'checkmate', name: 'assert_complex' },
131
+ { package: 'checkmate', name: 'assertComplex' },
132
+ { package: 'checkmate', name: 'assert_count' },
133
+ { package: 'checkmate', name: 'assertCount' },
134
+ { package: 'checkmate', name: 'assert_data_frame' },
135
+ { package: 'checkmate', name: 'assertDataFrame' },
136
+ { package: 'checkmate', name: 'assert_data_table' },
137
+ { package: 'checkmate', name: 'assertDataTable' },
138
+ { package: 'checkmate', name: 'assert_date' },
139
+ { package: 'checkmate', name: 'assertDate' },
140
+ { package: 'checkmate', name: 'assert_directory' },
141
+ { package: 'checkmate', name: 'assertDirectory' },
142
+ { package: 'checkmate', name: 'assert_directory_exists' },
143
+ { package: 'checkmate', name: 'assertDirectoryExists' },
144
+ { package: 'checkmate', name: 'assert_disjunct' },
145
+ { package: 'checkmate', name: 'assertDisjunct' },
146
+ { package: 'checkmate', name: 'assert_double' },
147
+ { package: 'checkmate', name: 'assertDouble' },
148
+ { package: 'checkmate', name: 'assert_environment' },
149
+ { package: 'checkmate', name: 'assertEnvironment' },
150
+ { package: 'checkmate', name: 'assert_factor' },
151
+ { package: 'checkmate', name: 'assertFactor' },
152
+ { package: 'checkmate', name: 'assert_false' },
153
+ { package: 'checkmate', name: 'assertFalse' },
154
+ { package: 'checkmate', name: 'assert_file' },
155
+ { package: 'checkmate', name: 'assertFile' },
156
+ { package: 'checkmate', name: 'assert_file_exists' },
157
+ { package: 'checkmate', name: 'assertFileExists' },
158
+ { package: 'checkmate', name: 'assert_flag' },
159
+ { package: 'checkmate', name: 'assertFlag' },
160
+ { package: 'checkmate', name: 'assert_formula' },
161
+ { package: 'checkmate', name: 'assertFormula' },
162
+ { package: 'checkmate', name: 'assert_function' },
163
+ { package: 'checkmate', name: 'assertFunction' },
164
+ { package: 'checkmate', name: 'assert_int' },
165
+ { package: 'checkmate', name: 'assertInt' },
166
+ { package: 'checkmate', name: 'assert_integer' },
167
+ { package: 'checkmate', name: 'assertInteger' },
168
+ { package: 'checkmate', name: 'assert_list' },
169
+ { package: 'checkmate', name: 'assertList' },
170
+ { package: 'checkmate', name: 'assert_logical' },
171
+ { package: 'checkmate', name: 'assertLogical' },
172
+ { package: 'checkmate', name: 'assert_matrix' },
173
+ { package: 'checkmate', name: 'assertMatrix' },
174
+ { package: 'checkmate', name: 'assert_multi_class' },
175
+ { package: 'checkmate', name: 'assertMultiClass' },
176
+ { package: 'checkmate', name: 'assert_named' },
177
+ { package: 'checkmate', name: 'assertNamed' },
178
+ { package: 'checkmate', name: 'assert_names' },
179
+ { package: 'checkmate', name: 'assertNames' },
180
+ { package: 'checkmate', name: 'assert_null' },
181
+ { package: 'checkmate', name: 'assertNull' },
182
+ { package: 'checkmate', name: 'assert_number' },
183
+ { package: 'checkmate', name: 'assertNumber' },
184
+ { package: 'checkmate', name: 'assert_numeric' },
185
+ { package: 'checkmate', name: 'assertNumeric' },
186
+ { package: 'checkmate', name: 'assert_os' },
187
+ { package: 'checkmate', name: 'assertOs' },
188
+ { package: 'checkmate', name: 'assert_path_for_output' },
189
+ { package: 'checkmate', name: 'assertPathForOutput' },
190
+ { package: 'checkmate', name: 'assert_permutation' },
191
+ { package: 'checkmate', name: 'assertPermutation' },
192
+ { package: 'checkmate', name: 'assert_posixct' },
193
+ { package: 'checkmate', name: 'assertPOSIXct' },
194
+ { package: 'checkmate', name: 'assert_r6' },
195
+ { package: 'checkmate', name: 'assertR6' },
196
+ { package: 'checkmate', name: 'assert_raw' },
197
+ { package: 'checkmate', name: 'assertRaw' },
198
+ { package: 'checkmate', name: 'assert_scalar' },
199
+ { package: 'checkmate', name: 'assertScalar' },
200
+ { package: 'checkmate', name: 'assert_scalar_na' },
201
+ { package: 'checkmate', name: 'assertScalarNA' },
202
+ { package: 'checkmate', name: 'assert_set_equal' },
203
+ { package: 'checkmate', name: 'assertSetEqual' },
204
+ { package: 'checkmate', name: 'assert_string' },
205
+ { package: 'checkmate', name: 'assertString' },
206
+ { package: 'checkmate', name: 'assert_subset' },
207
+ { package: 'checkmate', name: 'assertSubset' },
208
+ { package: 'checkmate', name: 'assert_tibble' },
209
+ { package: 'checkmate', name: 'assertTibble' },
210
+ { package: 'checkmate', name: 'assert_true' },
211
+ { package: 'checkmate', name: 'assertTrue' },
212
+ { package: 'checkmate', name: 'assert_vector' },
213
+ { package: 'checkmate', name: 'assertVector' }
214
+ */
81
215
  ];
82
216
  //# sourceMappingURL=test-functions.js.map
package/queries/query.js CHANGED
@@ -149,7 +149,7 @@ function VirtualQuerySchema() {
149
149
  * Produces a Joi schema representing any supported query (including virtual queries).
150
150
  */
151
151
  function AnyQuerySchema() {
152
- return joi_1.default.alternatives(SupportedQueriesSchema(), VirtualQuerySchema()).description('Any query');
152
+ return joi_1.default.alternatives(SupportedQueriesSchema(), VirtualQuerySchema()).description('A virtual or an active query!');
153
153
  }
154
154
  /**
155
155
  * Produces a Joi schema representing an array of supported queries.
@@ -1,5 +1,5 @@
1
1
  import type { FlowrSearchElement, FlowrSearchElements } from '../flowr-search';
2
- import type { NormalizedAst, ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
2
+ import type { ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
3
3
  import { type MergeableRecord } from '../../util/objects';
4
4
  import type { Identifier } from '../../dataflow/environments/identifier';
5
5
  import type { LinkToLastCall } from '../../queries/catalog/call-context-query/call-context-query-format';
@@ -9,18 +9,11 @@ import type { Query, QueryResult } from '../../queries/query';
9
9
  import { type CfgSimplificationPassName } from '../../control-flow/cfg-simplification';
10
10
  import type { AsyncOrSync } from 'ts-essentials';
11
11
  import type { ReadonlyFlowrAnalysisProvider } from '../../project/flowr-analyzer';
12
- import type { DataflowInformation } from '../../dataflow/info';
13
- import type { FlowrConfigOptions } from '../../config';
14
12
  export interface EnrichmentData<ElementContent extends MergeableRecord, ElementArguments = undefined, SearchContent extends MergeableRecord = never, SearchArguments = ElementArguments> {
15
13
  /**
16
14
  * A function that is applied to each element of the search to enrich it with additional data.
17
15
  */
18
- readonly enrichElement?: (element: FlowrSearchElement<ParentInformation>, search: FlowrSearchElements<ParentInformation>, data: {
19
- dataflow: DataflowInformation;
20
- normalize: NormalizedAst;
21
- cfg: ControlFlowInformation;
22
- config: FlowrConfigOptions;
23
- }, args: ElementArguments | undefined, previousValue: ElementContent | undefined) => AsyncOrSync<ElementContent>;
16
+ readonly enrichElement?: (element: FlowrSearchElement<ParentInformation>, search: FlowrSearchElements<ParentInformation>, analyzer: ReadonlyFlowrAnalysisProvider, args: ElementArguments | undefined, previousValue: ElementContent | undefined) => AsyncOrSync<ElementContent>;
24
17
  readonly enrichSearch?: (search: FlowrSearchElements<ParentInformation>, data: ReadonlyFlowrAnalysisProvider, args: SearchArguments | undefined, previousValue: SearchContent | undefined) => AsyncOrSync<SearchContent>;
25
18
  /**
26
19
  * The mapping function used by the {@link Mapper.Enrichment} mapper.
@@ -96,44 +89,24 @@ export interface QueryDataSearchContent extends MergeableRecord {
96
89
  */
97
90
  export declare const Enrichments: {
98
91
  readonly "call-targets": {
99
- enrichElement: (e: FlowrSearchElement<ParentInformation>, _s: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, data: {
100
- dataflow: DataflowInformation;
101
- normalize: NormalizedAst;
102
- cfg: ControlFlowInformation;
103
- config: FlowrConfigOptions;
104
- }, args: {
92
+ enrichElement: (e: FlowrSearchElement<ParentInformation>, _s: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, analyzer: ReadonlyFlowrAnalysisProvider<import("../../r-bridge/parser").KnownParser>, args: {
105
93
  onlyBuiltin?: boolean;
106
- } | undefined, prev: CallTargetsContent | undefined) => CallTargetsContent;
94
+ } | undefined, prev: CallTargetsContent | undefined) => Promise<CallTargetsContent>;
107
95
  mapper: ({ targets }: CallTargetsContent) => FlowrSearchElement<ParentInformation>[];
108
96
  };
109
97
  readonly "last-call": {
110
- enrichElement: (e: FlowrSearchElement<ParentInformation>, _s: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, data: {
111
- dataflow: DataflowInformation;
112
- normalize: NormalizedAst;
113
- cfg: ControlFlowInformation;
114
- config: FlowrConfigOptions;
115
- }, args: Omit<LinkToLastCall<import("../../queries/catalog/call-context-query/call-context-query-format").CallNameTypes>, "type">[] | undefined, prev: LastCallContent | undefined) => LastCallContent;
98
+ enrichElement: (e: FlowrSearchElement<ParentInformation>, _s: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, analyzer: ReadonlyFlowrAnalysisProvider<import("../../r-bridge/parser").KnownParser>, args: Omit<LinkToLastCall<import("../../queries/catalog/call-context-query/call-context-query-format").CallNameTypes>, "type">[] | undefined, prev: LastCallContent | undefined) => Promise<LastCallContent>;
116
99
  mapper: ({ linkedIds }: LastCallContent) => FlowrSearchElement<ParentInformation>[];
117
100
  };
118
101
  readonly "cfg-information": {
119
- enrichElement: (e: FlowrSearchElement<ParentInformation>, search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: {
120
- dataflow: DataflowInformation;
121
- normalize: NormalizedAst;
122
- cfg: ControlFlowInformation;
123
- config: FlowrConfigOptions;
124
- }, _args: CfgInformationArguments | undefined, prev: CfgInformationElementContent | undefined) => {
102
+ enrichElement: (e: FlowrSearchElement<ParentInformation>, search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: ReadonlyFlowrAnalysisProvider<import("../../r-bridge/parser").KnownParser>, _args: CfgInformationArguments | undefined, prev: CfgInformationElementContent | undefined) => {
125
103
  isRoot: boolean;
126
104
  isReachable: boolean | undefined;
127
105
  };
128
106
  enrichSearch: (_search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, data: ReadonlyFlowrAnalysisProvider<import("../../r-bridge/parser").KnownParser>, args: CfgInformationArguments | undefined, prev: CfgInformationSearchContent | undefined) => Promise<CfgInformationSearchContent>;
129
107
  };
130
108
  readonly "query-data": {
131
- enrichElement: (_e: FlowrSearchElement<ParentInformation>, _search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: {
132
- dataflow: DataflowInformation;
133
- normalize: NormalizedAst;
134
- cfg: ControlFlowInformation;
135
- config: FlowrConfigOptions;
136
- }, args: QueryDataElementContent | undefined, prev: QueryDataElementContent | undefined) => QueryDataElementContent;
109
+ enrichElement: (_e: FlowrSearchElement<ParentInformation>, _search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: ReadonlyFlowrAnalysisProvider<import("../../r-bridge/parser").KnownParser>, args: QueryDataElementContent | undefined, prev: QueryDataElementContent | undefined) => QueryDataElementContent;
137
110
  enrichSearch: (_search: FlowrSearchElements<ParentInformation, FlowrSearchElement<ParentInformation>[]>, _data: ReadonlyFlowrAnalysisProvider<import("../../r-bridge/parser").KnownParser>, args: QueryDataSearchContent | undefined, prev: QueryDataSearchContent | undefined) => Required<QueryDataSearchContent>;
138
111
  };
139
112
  };
@@ -147,9 +120,4 @@ export declare function enrichmentContent<E extends Enrichment>(e: FlowrSearchEl
147
120
  /**
148
121
  * Enriches the given search element with the given enrichment type, using the provided analysis data.
149
122
  */
150
- export declare function enrichElement<Element extends FlowrSearchElement<ParentInformation>, E extends Enrichment>(e: Element, s: FlowrSearchElements<ParentInformation>, data: {
151
- dataflow: DataflowInformation;
152
- normalize: NormalizedAst;
153
- cfg: ControlFlowInformation;
154
- config: FlowrConfigOptions;
155
- }, enrichment: E, args?: EnrichmentElementArguments<E>): Promise<Element>;
123
+ export declare function enrichElement<Element extends FlowrSearchElement<ParentInformation>, E extends Enrichment>(e: Element, s: FlowrSearchElements<ParentInformation>, analyzer: ReadonlyFlowrAnalysisProvider, enrichment: E, args?: EnrichmentElementArguments<E>): Promise<Element>;
@@ -5,13 +5,13 @@ exports.enrichmentContent = enrichmentContent;
5
5
  exports.enrichElement = enrichElement;
6
6
  const objects_1 = require("../../util/objects");
7
7
  const vertex_1 = require("../../dataflow/graph/vertex");
8
- const identify_link_to_last_call_relation_1 = require("../../queries/catalog/call-context-query/identify-link-to-last-call-relation");
9
8
  const assert_1 = require("../../util/assert");
10
9
  const dfg_get_origin_1 = require("../../dataflow/origin/dfg-get-origin");
11
10
  const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id");
12
11
  const cfg_simplification_1 = require("../../control-flow/cfg-simplification");
13
12
  const call_context_query_executor_1 = require("../../queries/catalog/call-context-query/call-context-query-executor");
14
13
  const cfg_kind_1 = require("../../project/cfg-kind");
14
+ const identify_link_to_relation_1 = require("../../queries/catalog/call-context-query/identify-link-to-relation");
15
15
  /**
16
16
  * An enumeration that stores the names of the available enrichments that can be applied to a set of search elements.
17
17
  * See {@link FlowrSearchBuilder.with} for more information on how to apply enrichments.
@@ -29,14 +29,16 @@ var Enrichment;
29
29
  */
30
30
  exports.Enrichments = {
31
31
  [Enrichment.CallTargets]: {
32
- enrichElement: (e, _s, data, args, prev) => {
32
+ enrichElement: async (e, _s, analyzer, args, prev) => {
33
33
  // we don't resolve aliases here yet!
34
34
  const content = { targets: [] };
35
- const callVertex = data.dataflow.graph.getVertex(e.node.info.id);
35
+ const df = await analyzer.dataflow();
36
+ const n = await analyzer.normalize();
37
+ const callVertex = df.graph.getVertex(e.node.info.id);
36
38
  if (callVertex?.tag === vertex_1.VertexType.FunctionCall) {
37
- const origins = (0, dfg_get_origin_1.getOriginInDfg)(data.dataflow.graph, callVertex.id);
39
+ const origins = (0, dfg_get_origin_1.getOriginInDfg)(df.graph, callVertex.id);
38
40
  if (!origins || origins.length === 0) {
39
- content.targets = [(0, node_id_1.recoverName)(callVertex.id, data.normalize.idMap)];
41
+ content.targets = [(0, node_id_1.recoverName)(callVertex.id, n.idMap)];
40
42
  }
41
43
  else {
42
44
  // find call targets in user code (which have ids!)
@@ -44,7 +46,7 @@ exports.Enrichments = {
44
46
  switch (o.type) {
45
47
  case 2 /* OriginType.FunctionCallOrigin */:
46
48
  return {
47
- node: data.normalize.idMap.get(o.id),
49
+ node: n.idMap.get(o.id),
48
50
  };
49
51
  case 3 /* OriginType.BuiltInFunctionOrigin */:
50
52
  return o.fn.name;
@@ -53,7 +55,7 @@ exports.Enrichments = {
53
55
  }
54
56
  }).filter(assert_1.isNotUndefined));
55
57
  if (content.targets.length === 0) {
56
- content.targets = [(0, node_id_1.recoverName)(callVertex.id, data.normalize.idMap)];
58
+ content.targets = [(0, node_id_1.recoverName)(callVertex.id, n.idMap)];
57
59
  }
58
60
  }
59
61
  }
@@ -70,19 +72,21 @@ exports.Enrichments = {
70
72
  mapper: ({ targets }) => targets.map(t => t).filter(t => t.node !== undefined)
71
73
  },
72
74
  [Enrichment.LastCall]: {
73
- enrichElement: (e, _s, data, args, prev) => {
75
+ enrichElement: async (e, _s, analyzer, args, prev) => {
74
76
  (0, assert_1.guard)(args && args.length, `${Enrichment.LastCall} enrichment requires at least one argument`);
75
77
  const content = prev ?? { linkedIds: [] };
76
- const vertex = data.dataflow.graph.get(e.node.info.id);
78
+ const df = await analyzer.dataflow();
79
+ const n = await analyzer.normalize();
80
+ const vertex = df.graph.get(e.node.info.id);
77
81
  if (vertex !== undefined && vertex[0].tag === vertex_1.VertexType.FunctionCall) {
78
82
  for (const arg of args) {
79
- const lastCalls = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(vertex[0].id, data.cfg.graph, data.dataflow.graph, {
83
+ const lastCalls = await (0, identify_link_to_relation_1.identifyLinkToRelation)(vertex[0].id, analyzer, {
80
84
  ...arg,
81
85
  callName: (0, call_context_query_executor_1.promoteCallName)(arg.callName),
82
86
  type: 'link-to-last-call',
83
87
  });
84
88
  for (const lastCall of lastCalls) {
85
- content.linkedIds.push({ node: data.normalize.idMap.get(lastCall) });
89
+ content.linkedIds.push({ node: n.idMap.get(lastCall) });
86
90
  }
87
91
  }
88
92
  }
@@ -138,14 +142,14 @@ function enrichmentContent(e, enrichment) {
138
142
  /**
139
143
  * Enriches the given search element with the given enrichment type, using the provided analysis data.
140
144
  */
141
- async function enrichElement(e, s, data, enrichment, args) {
145
+ async function enrichElement(e, s, analyzer, enrichment, args) {
142
146
  const enrichmentData = exports.Enrichments[enrichment];
143
147
  const prev = e?.enrichments;
144
148
  return {
145
149
  ...e,
146
150
  enrichments: {
147
151
  ...prev ?? {},
148
- [enrichment]: await enrichmentData.enrichElement?.(e, s, data, args, prev?.[enrichment])
152
+ [enrichment]: await enrichmentData.enrichElement?.(e, s, analyzer, args, prev?.[enrichment])
149
153
  }
150
154
  };
151
155
  }